You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: add configurable cooldown to claim usernames (go-gitea#6422)
Add a new option that allows instances to set a cooldown period to claim
old usernames. In the context of public instances this can be used to
prevent old usernames to be claimed after they are free and allow
graceful migration (by making use of the redirect feature) to a new
username. The granularity of this cooldown is a day. By default this
feature is disabled and thus no cooldown period.
The `CreatedUnix` column is added the `user_redirect` table, for
existing redirects the timestamp is simply zero as we simply do not know
when they were created and are likely already over the cooldown period
if the instance configures one.
Users can always reclaim their 'old' user name again within the cooldown
period. Users can also always reclaim 'old' names of organization they
currently own within the cooldown period.
Creating and renaming users as an admin user are not affected by the
cooldown period for moderation and user support reasons.
To avoid abuse of the cooldown feature, such that a user holds a lot of
usernames, a new option is added `MAX_USER_REDIRECTS` which sets a limit
to the amount of user redirects a user may have, by default this is
disabled. If a cooldown period is set then the default is 5. This
feature operates independently of the cooldown period feature.
Added integration and unit testing.
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6422
Reviewed-by: Earl Warren <[email protected]>
Reviewed-by: 0ko <[email protected]>
Reviewed-by: Otto <[email protected]>
Co-authored-by: Gusted <[email protected]>
Co-committed-by: Gusted <[email protected]>
// NOTE: It's not possible to combine these two queries into one due to a limitation of MySQL.
116
+
keepIDs:=make([]int64, n)
117
+
iferr:=db.GetEngine(ctx).SQL("SELECT id FROM user_redirect WHERE redirect_user_id = ? ORDER BY created_unix DESC LIMIT "+strconv.FormatInt(n, 10), userID).Find(&keepIDs); err!=nil {
// Only check for a cooldown period if UsernameCooldownPeriod is a positive number.
141
+
ifsetting.Service.UsernameCooldownPeriod<=0 {
142
+
returntrue, time.Time{}, nil
143
+
}
144
+
145
+
userRedirect, err:=GetUserRedirect(ctx, username)
146
+
iferr!=nil {
147
+
ifIsErrUserRedirectNotExist(err) {
148
+
returntrue, time.Time{}, nil
149
+
}
150
+
returnfalse, time.Time{}, err
151
+
}
152
+
153
+
// Allow reclaiming of user's own username.
154
+
ifuserRedirect.RedirectUserID==doerID {
155
+
returntrue, time.Time{}, nil
156
+
}
157
+
158
+
// We do not know if the redirect user id was for an organization, so
159
+
// unconditionally execute the following query to retrieve all users that
160
+
// are part of the "Owner" team. If the redirect user ID is not an organization
161
+
// the returned list would be empty.
162
+
ownerTeamUIDs:= []int64{}
163
+
iferr:=db.GetEngine(ctx).SQL("SELECT uid FROM team_user INNER JOIN team ON team_user.`team_id` = team.`id` WHERE team.`org_id` = ? AND team.`name` = 'Owners'", userRedirect.RedirectUserID).Find(&ownerTeamUIDs); err!=nil {
164
+
returnfalse, time.Time{}, err
165
+
}
166
+
167
+
ifslices.Contains(ownerTeamUIDs, doerID) {
168
+
returntrue, time.Time{}, nil
169
+
}
170
+
171
+
// Multiply the value of UsernameCooldownPeriod by the amount of seconds in a day.
Copy file name to clipboardExpand all lines: options/locale/locale_en-US.ini
+5Lines changed: 5 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -630,6 +630,7 @@ lang_select_error = Select a language from the list.
630
630
631
631
username_been_taken = The username is already taken.
632
632
username_change_not_local_user = Non-local users are not allowed to change their username.
633
+
username_claiming_cooldown = The username cannot be claimed, because its cooldown period is not yet over. It can be claimed on %[1]s.
633
634
repo_name_been_taken = The repository name is already used.
634
635
repository_force_private = Force Private is enabled: private repositories cannot be made public.
635
636
repository_files_already_exist = Files already exist for this repository. Contact the system administrator.
@@ -765,6 +766,8 @@ update_profile_success = Your profile has been updated.
765
766
change_username = Your username has been changed.
766
767
change_username_prompt = Note: Changing your username also changes your account URL.
767
768
change_username_redirect_prompt = The old username will redirect until someone claims it.
769
+
change_username_redirect_prompt.with_cooldown.one = The old username will be available to everyone after a cooldown period of %[1]d day, you can still reclaim the old username during the cooldown period.
770
+
change_username_redirect_prompt.with_cooldown.few = The old username will be available to everyone after a cooldown period of %[1]d days, you can still reclaim the old username during the cooldown period.
settings.update_setting_success = Organization settings have been updated.
2884
2887
settings.change_orgname_prompt = Note: Changing the organization name will also change your organization's URL and free the old name.
2885
2888
settings.change_orgname_redirect_prompt = The old name will redirect until it is claimed.
2889
+
settings.change_orgname_redirect_prompt.with_cooldown.one = The old username will be available to everyone after a cooldown period of %[1]d day, you can still reclaim the old username during the cooldown period.
2890
+
settings.change_orgname_redirect_prompt.with_cooldown.few = The old username will be available to everyone after a cooldown period of %[1]d days, you can still reclaim the old username during the cooldown period.
2886
2891
settings.update_avatar_success = The organization's avatar has been updated.
2887
2892
settings.delete = Delete organization
2888
2893
settings.delete_account = Delete this organization
0 commit comments