Skip to content

Commit

Permalink
[GITEA] add option for banning dots in usernames
Browse files Browse the repository at this point in the history
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 fabdda5)
(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)
  • Loading branch information
n0toose authored and earl-warren committed Sep 18, 2023
1 parent 3058a54 commit 5cec1d9
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 5 deletions.
5 changes: 5 additions & 0 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,11 @@ LEVEL = Info
;; Every new user will have restricted permissions depending on this setting
;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"
;; Limited is for users visible only to signed users
;; Private is for users visible only to members of their organizations
Expand Down
2 changes: 2 additions & 0 deletions modules/setting/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ var Service = struct {
DefaultKeepEmailPrivate bool
DefaultAllowCreateOrganization bool
DefaultUserIsRestricted bool
AllowDotsInUsernames bool
EnableTimetracking bool
DefaultEnableTimetracking bool
DefaultEnableDependencies bool
Expand Down Expand Up @@ -180,6 +181,7 @@ func loadServiceFrom(rootCfg ConfigProvider) {
Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool()
Service.DefaultAllowCreateOrganization = sec.Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").MustBool(true)
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)
if Service.EnableTimetracking {
Service.DefaultEnableTimetracking = sec.Key("DEFAULT_ENABLE_TIMETRACKING").MustBool(true)
Expand Down
13 changes: 10 additions & 3 deletions modules/validation/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,20 @@ func IsValidExternalTrackerURLFormat(uri string) bool {
}

var (
validUsernamePattern = regexp.MustCompile(`^[\da-zA-Z][-.\w]*$`)
invalidUsernamePattern = regexp.MustCompile(`[-._]{2,}|[-._]$`) // No consecutive or trailing non-alphanumeric chars
validUsernamePatternWithDots = regexp.MustCompile(`^[\da-zA-Z][-.\w]*$`)
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
func IsValidUsername(name string) bool {
// It is difficult to find a single pattern that is both readable and effective,
// 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)
}
31 changes: 30 additions & 1 deletion modules/validation/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
arg string
want bool
Expand Down Expand Up @@ -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)
})
}
}
7 changes: 6 additions & 1 deletion modules/web/middleware/binding.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"reflect"
"strings"

"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/validation"
Expand Down Expand Up @@ -135,7 +136,11 @@ func Validate(errs binding.Errors, data map[string]any, f Form, l translation.Lo
case validation.ErrRegexPattern:
data["ErrorMsg"] = trName + l.Tr("form.regex_pattern_error", errs[0].Message)
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:
data["ErrorMsg"] = trName + l.Tr("form.invalid_group_team_map_error", errs[0].Message)
default:
Expand Down
2 changes: 2 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,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_enable_timetracking = Enable Time Tracking 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_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
Expand Down Expand Up @@ -532,6 +533,7 @@ include_error = ` must contain substring "%s".`
glob_pattern_error = ` glob 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_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`
unknown_error = Unknown error:
captcha_incorrect = The CAPTCHA code is incorrect.
Expand Down
2 changes: 2 additions & 0 deletions templates/admin/config.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@
<dd>{{if .Service.DefaultKeepEmailPrivate}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
<dt>{{.locale.Tr "admin.config.default_allow_create_organization"}}</dt>
<dd>{{if .Service.DefaultAllowCreateOrganization}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
<dt>{{.locale.Tr "admin.config.allow_dots_in_usernames"}}</dt>
<dd>{{if .Service.AllowDotsInUsernames}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
<dt>{{.locale.Tr "admin.config.enable_timetracking"}}</dt>
<dd>{{if .Service.EnableTimetracking}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
{{if .Service.EnableTimetracking}}
Expand Down

0 comments on commit 5cec1d9

Please sign in to comment.