loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

federation with allow lists (#5393)

## Description

This addresses Issue #5379.
The email validation was extended.
Additionally to checking whether the email domain is in the block list or in the allow list now we also check if the email domain is the servers own FQDN.
Tests have been written for the correct function of the allow list and if the local FQDN is admitted as email domain.

Edit: Clarifications, Typos

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
- [x] in their respective `*_test.go` for unit tests.

### Documentation

- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] I want the title to show in the release notes with a link to this pull request.

Co-authored-by: Michael Jerger <michael.jerger@meissa-gmbh.de>
Co-authored-by: patdyn <erik.seiert@meissa-gmbh.de>
Co-authored-by: Mirco <mirco.zachmann@meissa.de>
Co-authored-by: jerger <jerger@noreply.codeberg.org>
Co-authored-by: zam <mirco.zachmann@meissa.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5393
Reviewed-by: jerger <jerger@noreply.codeberg.org>
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: patdyn <patdyn@noreply.codeberg.org>
Co-committed-by: patdyn <patdyn@noreply.codeberg.org>

authored by

patdyn
Michael Jerger
patdyn
Mirco
jerger
patdyn
and committed by
Earl Warren
9eebadce ffd19ec8

+135 -6
+25 -1
modules/setting/service.go
··· 1 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 + // Copyright 2025 The Forgejo Authors. All rights reserved 2 3 // SPDX-License-Identifier: MIT 3 4 4 5 package setting 5 6 6 7 import ( 8 + "net/url" 7 9 "regexp" 8 10 "slices" 9 11 "strings" ··· 145 147 loadServiceFrom(CfgProvider) 146 148 } 147 149 150 + func appURLAsGlob(fqdn string) (glob.Glob, error) { 151 + localFqdn, err := url.ParseRequestURI(fqdn) 152 + if err != nil { 153 + log.Error("Error in EmailDomainAllowList: %v", err) 154 + return nil, err 155 + } 156 + appFqdn, err := glob.Compile(localFqdn.Hostname(), ',') 157 + if err != nil { 158 + log.Error("Error in EmailDomainAllowList: %v", err) 159 + return nil, err 160 + } 161 + return appFqdn, nil 162 + } 163 + 148 164 func loadServiceFrom(rootCfg ConfigProvider) { 149 165 sec := rootCfg.Section("service") 150 166 Service.ActiveCodeLives = sec.Key("ACTIVE_CODE_LIVE_MINUTES").MustInt(180) ··· 164 180 if sec.HasKey("EMAIL_DOMAIN_WHITELIST") { 165 181 deprecatedSetting(rootCfg, "service", "EMAIL_DOMAIN_WHITELIST", "service", "EMAIL_DOMAIN_ALLOWLIST", "1.21") 166 182 } 167 - Service.EmailDomainAllowList = CompileEmailGlobList(sec, "EMAIL_DOMAIN_WHITELIST", "EMAIL_DOMAIN_ALLOWLIST") 183 + emailDomainAllowList := CompileEmailGlobList(sec, "EMAIL_DOMAIN_WHITELIST", "EMAIL_DOMAIN_ALLOWLIST") 184 + 185 + if len(emailDomainAllowList) > 0 && Federation.Enabled { 186 + appURL, err := appURLAsGlob(AppURL) 187 + if err == nil { 188 + emailDomainAllowList = append(emailDomainAllowList, appURL) 189 + } 190 + } 191 + Service.EmailDomainAllowList = emailDomainAllowList 168 192 Service.EmailDomainBlockList = CompileEmailGlobList(sec, "EMAIL_DOMAIN_BLOCKLIST") 169 193 Service.EmailDomainBlockDisposable = sec.Key("EMAIL_DOMAIN_BLOCK_DISPOSABLE").MustBool(false) 170 194 if Service.EmailDomainBlockDisposable {
+2 -1
modules/setting/setting.go
··· 1 1 // Copyright 2014 The Gogs Authors. All rights reserved. 2 2 // Copyright 2017 The Gitea Authors. All rights reserved. 3 + // Copyright 2025 The Forgejo Authors. All rights reserved 3 4 // SPDX-License-Identifier: MIT 4 5 5 6 package setting ··· 210 211 initAllLoggers() 211 212 212 213 loadDBSetting(CfgProvider) 214 + loadFederationFrom(CfgProvider) 213 215 loadServiceFrom(CfgProvider) 214 216 loadOAuth2ClientFrom(CfgProvider) 215 217 loadCacheFrom(CfgProvider) ··· 224 226 LoadQueueSettings() 225 227 loadProjectFrom(CfgProvider) 226 228 loadMimeTypeMapFrom(CfgProvider) 227 - loadFederationFrom(CfgProvider) 228 229 loadF3From(CfgProvider) 229 230 } 230 231
+83
modules/setting/setting_test.go
··· 1 1 // Copyright 2020 The Gitea Authors. All rights reserved. 2 + // Copyright 2025 The Forgejo Authors. All rights reserved 2 3 // SPDX-License-Identifier: MIT 3 4 4 5 package setting ··· 9 10 "code.gitea.io/gitea/modules/json" 10 11 11 12 "github.com/stretchr/testify/assert" 13 + "github.com/stretchr/testify/require" 12 14 ) 13 15 14 16 func TestMakeAbsoluteAssetURL(t *testing.T) { ··· 30 32 jsonBytes := MakeManifestData(`Example App '\"`, "https://example.com", "https://example.com/foo/bar") 31 33 assert.True(t, json.Valid(jsonBytes)) 32 34 } 35 + 36 + func TestLoadServiceDomainListsForFederation(t *testing.T) { 37 + oldAppURL := AppURL 38 + oldFederation := Federation 39 + oldService := Service 40 + 41 + defer func() { 42 + AppURL = oldAppURL 43 + Federation = oldFederation 44 + Service = oldService 45 + }() 46 + 47 + cfg, err := NewConfigProviderFromData(` 48 + [federation] 49 + ENABLED = true 50 + [service] 51 + EMAIL_DOMAIN_ALLOWLIST = *.allow.random 52 + EMAIL_DOMAIN_BLOCKLIST = *.block.random 53 + `) 54 + 55 + require.NoError(t, err) 56 + loadServerFrom(cfg) 57 + loadFederationFrom(cfg) 58 + loadServiceFrom(cfg) 59 + 60 + assert.True(t, match(Service.EmailDomainAllowList, "d1.allow.random")) 61 + assert.True(t, match(Service.EmailDomainAllowList, "localhost")) 62 + } 63 + 64 + func TestLoadServiceDomainListsNoFederation(t *testing.T) { 65 + oldAppURL := AppURL 66 + oldFederation := Federation 67 + oldService := Service 68 + 69 + defer func() { 70 + AppURL = oldAppURL 71 + Federation = oldFederation 72 + Service = oldService 73 + }() 74 + 75 + cfg, err := NewConfigProviderFromData(` 76 + [federation] 77 + ENABLED = false 78 + [service] 79 + EMAIL_DOMAIN_ALLOWLIST = *.allow.random 80 + EMAIL_DOMAIN_BLOCKLIST = *.block.random 81 + `) 82 + 83 + require.NoError(t, err) 84 + loadServerFrom(cfg) 85 + loadFederationFrom(cfg) 86 + loadServiceFrom(cfg) 87 + 88 + assert.True(t, match(Service.EmailDomainAllowList, "d1.allow.random")) 89 + } 90 + 91 + func TestLoadServiceDomainListsFederationEmptyAllowList(t *testing.T) { 92 + oldAppURL := AppURL 93 + oldFederation := Federation 94 + oldService := Service 95 + 96 + defer func() { 97 + AppURL = oldAppURL 98 + Federation = oldFederation 99 + Service = oldService 100 + }() 101 + 102 + cfg, err := NewConfigProviderFromData(` 103 + [federation] 104 + ENABLED = true 105 + [service] 106 + EMAIL_DOMAIN_BLOCKLIST = *.block.random 107 + `) 108 + 109 + require.NoError(t, err) 110 + loadServerFrom(cfg) 111 + loadFederationFrom(cfg) 112 + loadServiceFrom(cfg) 113 + 114 + assert.Empty(t, Service.EmailDomainAllowList) 115 + }
+19 -4
modules/validation/email.go
··· 1 1 // Copyright 2016 The Gogs Authors. All rights reserved. 2 2 // Copyright 2020 The Gitea Authors. All rights reserved. 3 + // Copyright 2024 The Forgejo Authors. All rights reserved 3 4 // SPDX-License-Identifier: MIT 4 5 5 6 package validation ··· 100 101 } 101 102 102 103 func IsEmailDomainAllowed(email string) bool { 103 - if len(setting.Service.EmailDomainAllowList) == 0 { 104 - return !isEmailDomainListed(setting.Service.EmailDomainBlockList, email) 105 - } 104 + return isEmailDomainAllowedInternal( 105 + email, 106 + setting.Service.EmailDomainAllowList, 107 + setting.Service.EmailDomainBlockList) 108 + } 106 109 107 - return isEmailDomainListed(setting.Service.EmailDomainAllowList, email) 110 + func isEmailDomainAllowedInternal( 111 + email string, 112 + emailDomainAllowList []glob.Glob, 113 + emailDomainBlockList []glob.Glob, 114 + ) bool { 115 + var result bool 116 + 117 + if len(emailDomainAllowList) == 0 { 118 + result = !isEmailDomainListed(emailDomainBlockList, email) 119 + } else { 120 + result = isEmailDomainListed(emailDomainAllowList, email) 121 + } 122 + return result 108 123 } 109 124 110 125 // isEmailDomainListed checks whether the domain of an email address
+6
modules/validation/email_test.go
··· 1 1 // Copyright 2017 The Gitea Authors. All rights reserved. 2 + // Copyright 2024 The Forgejo Authors. All rights reserved 2 3 // SPDX-License-Identifier: MIT 3 4 4 5 package validation ··· 65 66 }) 66 67 } 67 68 } 69 + 70 + func TestEmailDomainAllowList(t *testing.T) { 71 + res := IsEmailDomainAllowed("someuser@localhost.localdomain") 72 + assert.True(t, res) 73 + }