forked from NYANDEV/forgejo
[GITEA] add option for banning dots in usernames
Refs: https://codeberg.org/forgejo/forgejo/pulls/676 Author: Panagiotis "Ivory" Vasilopoulos <git@n0toose.net> Date: Mon Jun 12 13:57:01 2023 +0200 Co-authored-by: Gusted <postmaster@gusted.xyz> (cherry picked from commit fabdda5c6e84017bf75ab5f9ab6cc0e583b70d09) (cherry picked from commit d2c7f45621028d37944659db096bc92c031dd8e7) (cherry picked from commit dfdbaba3d6b7abf1c542b0ea41b7812b729cc217) (cherry picked from commit a3cda092b8897e4d669cfcf2cb8b16236e3c9b32) (cherry picked from commit f0fdb5905c3b22bec043530da15d2c52f6bc41c9) (cherry picked from commit 9697e48c1f8b23d3dd1da246b525b63c3756353d) (cherry picked from commit 46e31009a86db18a9b5bd8e2f535b198df90c437) (cherry picked from commit 5bb2c54b6f55499937396339bcacd3b4d8fb6b5e) (cherry picked from commit 682f9d24e13b83d89bd6b86324960f1b4fc72eeb) (cherry picked from commit 18634810057ef88fd01b54cec33bd4bd04c53221) (cherry picked from commit 4f1b7c4ddbc4099aa9b6fda1e0145d37f638e567) (cherry picked from commit 6afe70bbf1290e604fc476ee27901d1722ac1272) (cherry picked from commit 5cec1d9c2d2a731fa44f761e6c90f0d20ab3ccc4) Conflicts: templates/admin/config.tmpl https://codeberg.org/forgejo/forgejo/pulls/1512 (cherry picked from commit de2d172473217e3437238fd9c691edc8d8524e1a) (cherry picked from commit 37a3172dd9e2646157ec49ca46f94b9b0012b061) (cherry picked from commit 92dfca0c5a8a8d4fd8a93b5468ba593283fc9452) (cherry picked from commit a713d59b0cbeaf2fe023be1daa42165cd0df3b1d) (cherry picked from commit e7bd71a6188ed4abbabf8b64b439e588c1c1f5f7) (cherry picked from commit 69f3e952c495ecf8af5e7fc8cca6f3ba31fd3da2)
This commit is contained in:
parent
769e24d5a8
commit
83fbb7b566
7 changed files with 57 additions and 5 deletions
|
@ -810,6 +810,11 @@ LEVEL = Info
|
||||||
;; Every new user will have restricted permissions depending on this setting
|
;; Every new user will have restricted permissions depending on this setting
|
||||||
;DEFAULT_USER_IS_RESTRICTED = false
|
;DEFAULT_USER_IS_RESTRICTED = false
|
||||||
;;
|
;;
|
||||||
|
;; Users will be able to use dots when choosing their username. Disabling this is
|
||||||
|
;; helpful if your usersare having issues with e.g. RSS feeds or advanced third-party
|
||||||
|
;; extensions that use strange regex patterns.
|
||||||
|
; ALLOW_DOTS_IN_USERNAMES = true
|
||||||
|
;;
|
||||||
;; Either "public", "limited" or "private", default is "public"
|
;; Either "public", "limited" or "private", default is "public"
|
||||||
;; Limited is for users visible only to signed users
|
;; Limited is for users visible only to signed users
|
||||||
;; Private is for users visible only to members of their organizations
|
;; Private is for users visible only to members of their organizations
|
||||||
|
|
|
@ -68,6 +68,7 @@ var Service = struct {
|
||||||
DefaultKeepEmailPrivate bool
|
DefaultKeepEmailPrivate bool
|
||||||
DefaultAllowCreateOrganization bool
|
DefaultAllowCreateOrganization bool
|
||||||
DefaultUserIsRestricted bool
|
DefaultUserIsRestricted bool
|
||||||
|
AllowDotsInUsernames bool
|
||||||
EnableTimetracking bool
|
EnableTimetracking bool
|
||||||
DefaultEnableTimetracking bool
|
DefaultEnableTimetracking bool
|
||||||
DefaultEnableDependencies bool
|
DefaultEnableDependencies bool
|
||||||
|
@ -180,6 +181,7 @@ func loadServiceFrom(rootCfg ConfigProvider) {
|
||||||
Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool()
|
Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool()
|
||||||
Service.DefaultAllowCreateOrganization = sec.Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").MustBool(true)
|
Service.DefaultAllowCreateOrganization = sec.Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").MustBool(true)
|
||||||
Service.DefaultUserIsRestricted = sec.Key("DEFAULT_USER_IS_RESTRICTED").MustBool(false)
|
Service.DefaultUserIsRestricted = sec.Key("DEFAULT_USER_IS_RESTRICTED").MustBool(false)
|
||||||
|
Service.AllowDotsInUsernames = sec.Key("ALLOW_DOTS_IN_USERNAMES").MustBool(true)
|
||||||
Service.EnableTimetracking = sec.Key("ENABLE_TIMETRACKING").MustBool(true)
|
Service.EnableTimetracking = sec.Key("ENABLE_TIMETRACKING").MustBool(true)
|
||||||
if Service.EnableTimetracking {
|
if Service.EnableTimetracking {
|
||||||
Service.DefaultEnableTimetracking = sec.Key("DEFAULT_ENABLE_TIMETRACKING").MustBool(true)
|
Service.DefaultEnableTimetracking = sec.Key("DEFAULT_ENABLE_TIMETRACKING").MustBool(true)
|
||||||
|
|
|
@ -117,13 +117,20 @@ func IsValidExternalTrackerURLFormat(uri string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
validUsernamePattern = regexp.MustCompile(`^[\da-zA-Z][-.\w]*$`)
|
validUsernamePatternWithDots = regexp.MustCompile(`^[\da-zA-Z][-.\w]*$`)
|
||||||
invalidUsernamePattern = regexp.MustCompile(`[-._]{2,}|[-._]$`) // No consecutive or trailing non-alphanumeric chars
|
validUsernamePatternWithoutDots = regexp.MustCompile(`^[\da-zA-Z][-\w]*$`)
|
||||||
|
|
||||||
|
// No consecutive or trailing non-alphanumeric chars, catches both cases
|
||||||
|
invalidUsernamePattern = regexp.MustCompile(`[-._]{2,}|[-._]$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsValidUsername checks if username is valid
|
// IsValidUsername checks if username is valid
|
||||||
func IsValidUsername(name string) bool {
|
func IsValidUsername(name string) bool {
|
||||||
// It is difficult to find a single pattern that is both readable and effective,
|
// It is difficult to find a single pattern that is both readable and effective,
|
||||||
// but it's easier to use positive and negative checks.
|
// but it's easier to use positive and negative checks.
|
||||||
return validUsernamePattern.MatchString(name) && !invalidUsernamePattern.MatchString(name)
|
if setting.Service.AllowDotsInUsernames {
|
||||||
|
return validUsernamePatternWithDots.MatchString(name) && !invalidUsernamePattern.MatchString(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return validUsernamePatternWithoutDots.MatchString(name) && !invalidUsernamePattern.MatchString(name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,8 @@ func Test_IsValidExternalTrackerURLFormat(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsValidUsername(t *testing.T) {
|
func TestIsValidUsernameAllowDots(t *testing.T) {
|
||||||
|
setting.Service.AllowDotsInUsernames = true
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
arg string
|
arg string
|
||||||
want bool
|
want bool
|
||||||
|
@ -185,3 +186,31 @@ func TestIsValidUsername(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsValidUsernameBanDots(t *testing.T) {
|
||||||
|
setting.Service.AllowDotsInUsernames = false
|
||||||
|
defer func() {
|
||||||
|
setting.Service.AllowDotsInUsernames = true
|
||||||
|
}()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
arg string
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{arg: "a", want: true},
|
||||||
|
{arg: "abc", want: true},
|
||||||
|
{arg: "0.b-c", want: false},
|
||||||
|
{arg: "a.b-c_d", want: false},
|
||||||
|
{arg: ".abc", want: false},
|
||||||
|
{arg: "abc.", want: false},
|
||||||
|
{arg: "a..bc", want: false},
|
||||||
|
{arg: "a...bc", want: false},
|
||||||
|
{arg: "a.-bc", want: false},
|
||||||
|
{arg: "a._bc", want: false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.arg, func(t *testing.T) {
|
||||||
|
assert.Equalf(t, tt.want, IsValidUsername(tt.arg), "IsValidUsername[AllowDotsInUsernames=false](%v)", tt.arg)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/translation"
|
"code.gitea.io/gitea/modules/translation"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
"code.gitea.io/gitea/modules/validation"
|
"code.gitea.io/gitea/modules/validation"
|
||||||
|
@ -135,7 +136,11 @@ func Validate(errs binding.Errors, data map[string]any, f Form, l translation.Lo
|
||||||
case validation.ErrRegexPattern:
|
case validation.ErrRegexPattern:
|
||||||
data["ErrorMsg"] = trName + l.Tr("form.regex_pattern_error", errs[0].Message)
|
data["ErrorMsg"] = trName + l.Tr("form.regex_pattern_error", errs[0].Message)
|
||||||
case validation.ErrUsername:
|
case validation.ErrUsername:
|
||||||
data["ErrorMsg"] = trName + l.Tr("form.username_error")
|
if setting.Service.AllowDotsInUsernames {
|
||||||
|
data["ErrorMsg"] = trName + l.Tr("form.username_error")
|
||||||
|
} else {
|
||||||
|
data["ErrorMsg"] = trName + l.Tr("form.username_error_no_dots")
|
||||||
|
}
|
||||||
case validation.ErrInvalidGroupTeamMap:
|
case validation.ErrInvalidGroupTeamMap:
|
||||||
data["ErrorMsg"] = trName + l.Tr("form.invalid_group_team_map_error", errs[0].Message)
|
data["ErrorMsg"] = trName + l.Tr("form.invalid_group_team_map_error", errs[0].Message)
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -294,6 +294,7 @@ default_allow_create_organization = Allow Creation of Organizations by Default
|
||||||
default_allow_create_organization_popup = Allow new user accounts to create organizations by default.
|
default_allow_create_organization_popup = Allow new user accounts to create organizations by default.
|
||||||
default_enable_timetracking = Enable Time Tracking by Default
|
default_enable_timetracking = Enable Time Tracking by Default
|
||||||
default_enable_timetracking_popup = Enable time tracking for new repositories by default.
|
default_enable_timetracking_popup = Enable time tracking for new repositories by default.
|
||||||
|
allow_dots_in_usernames = Allow users to use dots in their usernames. Doesn't affect existing accounts.
|
||||||
no_reply_address = Hidden Email Domain
|
no_reply_address = Hidden Email Domain
|
||||||
no_reply_address_helper = Domain name for users with a hidden email address. For example, the username 'joe' will be logged in Git as 'joe@noreply.example.org' if the hidden email domain is set to 'noreply.example.org'.
|
no_reply_address_helper = Domain name for users with a hidden email address. For example, the username 'joe' will be logged in Git as 'joe@noreply.example.org' if the hidden email domain is set to 'noreply.example.org'.
|
||||||
password_algorithm = Password Hash Algorithm
|
password_algorithm = Password Hash Algorithm
|
||||||
|
@ -533,6 +534,7 @@ include_error = ` must contain substring "%s".`
|
||||||
glob_pattern_error = ` glob pattern is invalid: %s.`
|
glob_pattern_error = ` glob pattern is invalid: %s.`
|
||||||
regex_pattern_error = ` regex pattern is invalid: %s.`
|
regex_pattern_error = ` regex pattern is invalid: %s.`
|
||||||
username_error = ` can only contain alphanumeric chars ('0-9','a-z','A-Z'), dash ('-'), underscore ('_') and dot ('.'). It cannot begin or end with non-alphanumeric chars, and consecutive non-alphanumeric chars are also forbidden.`
|
username_error = ` can only contain alphanumeric chars ('0-9','a-z','A-Z'), dash ('-'), underscore ('_') and dot ('.'). It cannot begin or end with non-alphanumeric chars, and consecutive non-alphanumeric chars are also forbidden.`
|
||||||
|
username_error_no_dots = ` can only contain alphanumeric chars ('0-9','a-z','A-Z'), dash ('-') and underscore ('_'). It cannot begin or end with non-alphanumeric chars, and consecutive non-alphanumeric chars are also forbidden.`
|
||||||
invalid_group_team_map_error = ` mapping is invalid: %s`
|
invalid_group_team_map_error = ` mapping is invalid: %s`
|
||||||
unknown_error = Unknown error:
|
unknown_error = Unknown error:
|
||||||
captcha_incorrect = The CAPTCHA code is incorrect.
|
captcha_incorrect = The CAPTCHA code is incorrect.
|
||||||
|
|
|
@ -159,6 +159,8 @@
|
||||||
<dd>{{if .Service.DefaultKeepEmailPrivate}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
|
<dd>{{if .Service.DefaultKeepEmailPrivate}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
|
||||||
<dt>{{ctx.Locale.Tr "admin.config.default_allow_create_organization"}}</dt>
|
<dt>{{ctx.Locale.Tr "admin.config.default_allow_create_organization"}}</dt>
|
||||||
<dd>{{if .Service.DefaultAllowCreateOrganization}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
|
<dd>{{if .Service.DefaultAllowCreateOrganization}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
|
||||||
|
<dt>{{ctx.Locale.Tr "admin.config.allow_dots_in_usernames"}}</dt>
|
||||||
|
<dd>{{if .Service.AllowDotsInUsernames}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
|
||||||
<dt>{{ctx.Locale.Tr "admin.config.enable_timetracking"}}</dt>
|
<dt>{{ctx.Locale.Tr "admin.config.enable_timetracking"}}</dt>
|
||||||
<dd>{{if .Service.EnableTimetracking}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
|
<dd>{{if .Service.EnableTimetracking}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
|
||||||
{{if .Service.EnableTimetracking}}
|
{{if .Service.EnableTimetracking}}
|
||||||
|
|
Loading…
Reference in a new issue