mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-11-24 10:46:10 +01:00
Compare commits
1 commit
16d06705b3
...
735c2c8ada
Author | SHA1 | Date | |
---|---|---|---|
735c2c8ada |
109
build/generate-disposable-email.go
Normal file
109
build/generate-disposable-email.go
Normal file
|
@ -0,0 +1,109 @@
|
|||
// Copyright 2024 James Hatfield
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const disposableEmailListURL string = "https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/%s/disposable_email_blocklist.conf"
|
||||
|
||||
var (
|
||||
gitRef *string = flag.String("r", "master", "Git reference of the domain list version")
|
||||
outPat *string = flag.String("o", "modules/setting/disposable_email_domain_data.go", "Output path")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
// generate the source code (array of domains)
|
||||
res, err := generate()
|
||||
if err != nil {
|
||||
log.Fatalf("Generation Error: %v", err)
|
||||
}
|
||||
|
||||
// write result to a file
|
||||
err = os.WriteFile(*outPat, res, 0o644)
|
||||
if err != nil {
|
||||
log.Fatalf("File Write Error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func generate() ([]byte, error) {
|
||||
var err error
|
||||
var url string = fmt.Sprintf(disposableEmailListURL, *gitRef)
|
||||
|
||||
// download the domain list
|
||||
res, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// go through all entries (1 domain per line)
|
||||
scanner := bufio.NewScanner(bytes.NewReader(body))
|
||||
|
||||
var arrDomains []string
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
arrDomains = append(arrDomains, line)
|
||||
}
|
||||
|
||||
// build the string in a readable way
|
||||
var sb strings.Builder
|
||||
|
||||
_, err = sb.WriteString("[]string{\n")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, item := range arrDomains {
|
||||
_, err = sb.WriteString(fmt.Sprintf("\t%q,\n", item))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = sb.WriteString("}")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// insert the values into file
|
||||
final := fmt.Sprintf(hdr, url, sb.String())
|
||||
|
||||
return format.Source([]byte(final))
|
||||
}
|
||||
|
||||
const hdr = `
|
||||
// Copyright 2024 James Hatfield
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Code generated by build/generate-disposable-email.go. DO NOT EDIT
|
||||
// Sourced from %s
|
||||
package setting
|
||||
|
||||
import "sync"
|
||||
|
||||
var DisposableEmailDomains = sync.OnceValue(func() []string {
|
||||
return %s
|
||||
})
|
||||
`
|
3811
modules/setting/disposable_email_domain_data.go
Normal file
3811
modules/setting/disposable_email_domain_data.go
Normal file
File diff suppressed because it is too large
Load diff
|
@ -5,6 +5,7 @@ package setting
|
|||
|
||||
import (
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -37,6 +38,7 @@ var Service = struct {
|
|||
RegisterManualConfirm bool
|
||||
EmailDomainAllowList []glob.Glob
|
||||
EmailDomainBlockList []glob.Glob
|
||||
EmailDomainBlockDisposable bool
|
||||
DisableRegistration bool
|
||||
AllowOnlyInternalRegistration bool
|
||||
AllowOnlyExternalRegistration bool
|
||||
|
@ -156,6 +158,22 @@ func loadServiceFrom(rootCfg ConfigProvider) {
|
|||
}
|
||||
Service.EmailDomainAllowList = CompileEmailGlobList(sec, "EMAIL_DOMAIN_WHITELIST", "EMAIL_DOMAIN_ALLOWLIST")
|
||||
Service.EmailDomainBlockList = CompileEmailGlobList(sec, "EMAIL_DOMAIN_BLOCKLIST")
|
||||
Service.EmailDomainBlockDisposable = sec.Key("EMAIL_DOMAIN_BLOCK_DISPOSABLE").MustBool(false)
|
||||
if Service.EmailDomainBlockDisposable {
|
||||
toAdd := make([]glob.Glob, 0, len(DisposableEmailDomains()))
|
||||
for _, domain := range DisposableEmailDomains() {
|
||||
domain = strings.ToLower(domain)
|
||||
// Only add domains that aren't blocked yet.
|
||||
if !slices.ContainsFunc(Service.EmailDomainBlockList, func(g glob.Glob) bool { return g.Match(domain) }) {
|
||||
if g, err := glob.Compile(domain); err != nil {
|
||||
log.Error("Error in disposable domain %s: %v", domain, err)
|
||||
} else {
|
||||
toAdd = append(toAdd, g)
|
||||
}
|
||||
}
|
||||
}
|
||||
Service.EmailDomainBlockList = append(Service.EmailDomainBlockList, toAdd...)
|
||||
}
|
||||
Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration))
|
||||
Service.ShowMilestonesDashboardPage = sec.Key("SHOW_MILESTONES_DASHBOARD_PAGE").MustBool(true)
|
||||
Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool()
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
package setting
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
|
@ -13,6 +14,15 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func match(globs []glob.Glob, s string) bool {
|
||||
for _, g := range globs {
|
||||
if g.Match(s) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestLoadServices(t *testing.T) {
|
||||
oldService := Service
|
||||
defer func() {
|
||||
|
@ -28,15 +38,6 @@ EMAIL_DOMAIN_BLOCKLIST = d3, *.b
|
|||
require.NoError(t, err)
|
||||
loadServiceFrom(cfg)
|
||||
|
||||
match := func(globs []glob.Glob, s string) bool {
|
||||
for _, g := range globs {
|
||||
if g.Match(s) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
assert.True(t, match(Service.EmailDomainAllowList, "d1"))
|
||||
assert.True(t, match(Service.EmailDomainAllowList, "foo.w"))
|
||||
assert.True(t, match(Service.EmailDomainAllowList, "d2"))
|
||||
|
@ -48,6 +49,97 @@ EMAIL_DOMAIN_BLOCKLIST = d3, *.b
|
|||
assert.False(t, match(Service.EmailDomainBlockList, "d1"))
|
||||
}
|
||||
|
||||
func TestLoadServiceBlockDisposable(t *testing.T) {
|
||||
oldService := Service
|
||||
defer func() {
|
||||
Service = oldService
|
||||
}()
|
||||
|
||||
cfg, err := NewConfigProviderFromData(`
|
||||
[service]
|
||||
EMAIL_DOMAIN_BLOCK_DISPOSABLE = true
|
||||
`)
|
||||
|
||||
require.NoError(t, err)
|
||||
loadServiceFrom(cfg)
|
||||
|
||||
for _, domain := range DisposableEmailDomains() {
|
||||
require.True(t, match(Service.EmailDomainBlockList, domain))
|
||||
}
|
||||
|
||||
require.Len(t, Service.EmailDomainBlockList, len(DisposableEmailDomains()))
|
||||
|
||||
knownGood := [...]string{
|
||||
"aol.com",
|
||||
"gmx.com",
|
||||
"mail.com",
|
||||
"zoho.com",
|
||||
"proton.me",
|
||||
"gmail.com",
|
||||
"yahoo.com",
|
||||
"icloud.com",
|
||||
"outlook.com",
|
||||
"protonmail.com",
|
||||
}
|
||||
|
||||
for _, domain := range knownGood {
|
||||
require.False(t, match(Service.EmailDomainBlockList, domain))
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadServiceBlockDisposableWithExistingGlobs(t *testing.T) {
|
||||
oldService := Service
|
||||
defer func() {
|
||||
Service = oldService
|
||||
}()
|
||||
|
||||
cfg, err := NewConfigProviderFromData(`
|
||||
[service]
|
||||
EMAIL_DOMAIN_BLOCKLIST = *.ru,*.org
|
||||
EMAIL_DOMAIN_BLOCK_DISPOSABLE = true
|
||||
`)
|
||||
|
||||
require.NoError(t, err)
|
||||
loadServiceFrom(cfg)
|
||||
|
||||
for _, domain := range DisposableEmailDomains() {
|
||||
require.True(t, match(Service.EmailDomainBlockList, domain))
|
||||
}
|
||||
|
||||
redundant := 0
|
||||
for _, val := range DisposableEmailDomains() {
|
||||
if strings.HasSuffix(val, ".ru") || strings.HasSuffix(val, ".org") {
|
||||
redundant++
|
||||
}
|
||||
}
|
||||
|
||||
expected := len(DisposableEmailDomains()) - redundant + 2
|
||||
require.Len(t, Service.EmailDomainBlockList, expected)
|
||||
}
|
||||
|
||||
func TestLoadServiceBlockDisposableWithComplementGlobs(t *testing.T) {
|
||||
oldService := Service
|
||||
defer func() {
|
||||
Service = oldService
|
||||
}()
|
||||
|
||||
cfg, err := NewConfigProviderFromData(`
|
||||
[service]
|
||||
EMAIL_DOMAIN_BLOCKLIST = *.random
|
||||
EMAIL_DOMAIN_BLOCK_DISPOSABLE = true
|
||||
`)
|
||||
|
||||
require.NoError(t, err)
|
||||
loadServiceFrom(cfg)
|
||||
|
||||
for _, domain := range DisposableEmailDomains() {
|
||||
require.True(t, match(Service.EmailDomainBlockList, domain))
|
||||
}
|
||||
|
||||
expected := len(DisposableEmailDomains()) + 1
|
||||
require.Len(t, Service.EmailDomainBlockList, expected)
|
||||
}
|
||||
|
||||
func TestLoadServiceVisibilityModes(t *testing.T) {
|
||||
oldService := Service
|
||||
defer func() {
|
||||
|
|
Loading…
Reference in a new issue