From 6772e89c837a0a8cedc9edffbe94d02b7a7f7ea9 Mon Sep 17 00:00:00 2001 From: AndrewBezold Date: Wed, 27 May 2020 20:05:40 -0400 Subject: [PATCH 01/20] Add redirect for user --- models/error.go | 15 ++++++++ models/models.go | 1 + models/user.go | 18 ++++++++- models/user_redirect.go | 56 ++++++++++++++++++++++++++++ modules/context/context.go | 21 +++++++++++ modules/context/repo.go | 15 ++++++-- options/locale/locale_cs-CZ.ini | 2 - options/locale/locale_de-DE.ini | 2 - options/locale/locale_en-US.ini | 2 - options/locale/locale_es-ES.ini | 2 - options/locale/locale_fa-IR.ini | 2 - options/locale/locale_fr-FR.ini | 2 - options/locale/locale_id-ID.ini | 1 - options/locale/locale_it-IT.ini | 2 - options/locale/locale_ja-JP.ini | 2 - options/locale/locale_ko-KR.ini | 1 - options/locale/locale_lv-LV.ini | 2 - options/locale/locale_ml-IN.ini | 1 - options/locale/locale_nl-NL.ini | 1 - options/locale/locale_pl-PL.ini | 2 - options/locale/locale_pt-BR.ini | 2 - options/locale/locale_pt-PT.ini | 2 - options/locale/locale_ru-RU.ini | 2 - options/locale/locale_sv-SE.ini | 2 - options/locale/locale_tr-TR.ini | 2 - options/locale/locale_uk-UA.ini | 2 - options/locale/locale_zh-CN.ini | 2 - options/locale/locale_zh-TW.ini | 2 - routers/api/v1/api.go | 14 +++++-- routers/api/v1/user/key.go | 10 +++-- routers/api/v1/user/user.go | 16 ++++++-- routers/repo/http.go | 11 +++++- routers/user/profile.go | 6 ++- templates/user/settings/profile.tmpl | 1 - 34 files changed, 164 insertions(+), 60 deletions(-) create mode 100644 models/user_redirect.go diff --git a/models/error.go b/models/error.go index e9343cbe7c680..3de78df60c22f 100644 --- a/models/error.go +++ b/models/error.go @@ -146,6 +146,21 @@ func (err ErrUserNotExist) Error() string { return fmt.Sprintf("user does not exist [uid: %d, name: %s, keyid: %d]", err.UID, err.Name, err.KeyID) } +// ErrUserRedirectNotExist represents a "UserRedirectNotExist" kind of error. +type ErrUserRedirectNotExist struct { + Name string +} + +// IsErrUserRedirectNotExist check if an error is an ErrUserRedirectNotExist. +func IsErrUserRedirectNotExist(err error) bool { + _, ok := err.(ErrUserRedirectNotExist) + return ok +} + +func (err ErrUserRedirectNotExist) Error() string { + return fmt.Sprintf("user redirect does not exist [name: %s]", err.Name) +} + // ErrUserProhibitLogin represents a "ErrUserProhibitLogin" kind of error. type ErrUserProhibitLogin struct { UID int64 diff --git a/models/models.go b/models/models.go index 7f12d6260ad07..13b2880d1c2da 100644 --- a/models/models.go +++ b/models/models.go @@ -125,6 +125,7 @@ func init() { new(Task), new(LanguageStat), new(EmailHash), + new(UserRedirect), ) gonicNames := []string{"SSL", "UID"} diff --git a/models/user.go b/models/user.go index 0ecb1b9a48e9a..3405e3736fda2 100644 --- a/models/user.go +++ b/models/user.go @@ -976,6 +976,10 @@ func CreateUser(u *User) (err error) { return ErrUserAlreadyExist{u.Name} } + if err = deleteUserRedirect(sess, u.Name); err != nil { + return err + } + u.Email = strings.ToLower(u.Email) isExist, err = sess. Where("email=?", u.Email). @@ -1084,6 +1088,7 @@ func VerifyActiveEmailCode(code, email string) *EmailAddress { // ChangeUserName changes all corresponding setting from old user name to new one. func ChangeUserName(u *User, newUserName string) (err error) { + oldUserName := u.Name if err = IsUsableUsername(newUserName); err != nil { return err } @@ -1101,15 +1106,24 @@ func ChangeUserName(u *User, newUserName string) (err error) { return err } - if _, err = sess.Exec("UPDATE `repository` SET owner_name=? WHERE owner_name=?", newUserName, u.Name); err != nil { + if _, err = sess.Exec("UPDATE `repository` SET owner_name=? WHERE owner_name=?", newUserName, oldUserName); err != nil { return fmt.Errorf("Change repo owner name: %v", err) } // Do not fail if directory does not exist - if err = os.Rename(UserPath(u.Name), UserPath(newUserName)); err != nil && !os.IsNotExist(err) { + if err = os.Rename(UserPath(oldUserName), UserPath(newUserName)); err != nil && !os.IsNotExist(err) { return fmt.Errorf("Rename user directory: %v", err) } + // If there was previously a redirect at this location, remove it. + if err = deleteUserRedirect(sess, newUserName); err != nil { + return fmt.Errorf("delete user redirect: %v", err) + } + + if err := NewUserRedirect(DBContext{sess}, u.ID, oldUserName, newUserName); err != nil { + return err + } + return sess.Commit() } diff --git a/models/user_redirect.go b/models/user_redirect.go new file mode 100644 index 0000000000000..7a479970324d3 --- /dev/null +++ b/models/user_redirect.go @@ -0,0 +1,56 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package models + +import "strings" + +// UserRedirect represents that a user name should be redirected to another +type UserRedirect struct { + ID int64 `xorm:"pk autoincr"` + LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"` + RedirectUserID int64 // userID to redirect to +} + +// LookupUserRedirect look up if a user has a redirect name +func LookupUserRedirect(userName string) (int64, error) { + userName = strings.ToLower(userName) + redirect := &UserRedirect{LowerName: userName} + if has, err := x.Get(redirect); err != nil { + return 0, err + } else if !has { + return 0, ErrUserRedirectNotExist{Name: userName} + } + return redirect.RedirectUserID, nil +} + +// NewUserRedirect create a new user redirect +func NewUserRedirect(ctx DBContext, ID int64, oldUserName, newUserName string) error { + oldUserName = strings.ToLower(oldUserName) + newUserName = strings.ToLower(newUserName) + + if err := deleteUserRedirect(ctx.e, newUserName); err != nil { + return err + } + + if _, err := ctx.e.Insert(&UserRedirect{ + LowerName: oldUserName, + RedirectUserID: ID, + }); err != nil { + return err + } + return nil +} + +// deleteUserRedirect delete any redirect from the specified user name to +// anything else +func deleteUserRedirect(e Engine, userName string) error { + userName = strings.ToLower(userName) + _, err := e.Delete(&UserRedirect{LowerName: userName}) + return err +} + +func DeleteUserRedirect(userName string) error { + return deleteUserRedirect(x, userName) +} diff --git a/modules/context/context.go b/modules/context/context.go index b26528f6b207f..a1e5ea2af59f7 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -6,6 +6,7 @@ package context import ( + "fmt" "html" "html/template" "io" @@ -84,6 +85,26 @@ func (ctx *Context) IsUserRepoReaderAny() bool { return ctx.Repo.HasAccess() } +// RedirectToUser redirect to a differently-named user +func RedirectToUser(ctx *Context, userName string, redirectUserID int64) { + user, err := models.GetUserByID(redirectUserID) + if err != nil { + ctx.ServerError("GetUserByID", err) + return + } + + redirectPath := strings.Replace( + ctx.Req.URL.Path, + fmt.Sprintf("%s", userName), + user.Name, + 1, + ) + if ctx.Req.URL.RawQuery != "" { + redirectPath += "?" + ctx.Req.URL.RawQuery + } + ctx.Redirect(path.Join(setting.AppSubURL, redirectPath)) +} + // HasAPIError returns true if error occurs in form validation. func (ctx *Context) HasAPIError() bool { hasErr, ok := ctx.Data["HasError"] diff --git a/modules/context/repo.go b/modules/context/repo.go index 5ebed0eb7ea0c..d8a36e2c5ac89 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -388,11 +388,18 @@ func RepoAssignment() macaron.Handler { owner, err = models.GetUserByName(userName) if err != nil { if models.IsErrUserNotExist(err) { - if ctx.Query("go-get") == "1" { - EarlyResponseForGoGetMeta(ctx) - return + redirectUserID, err := models.LookupUserRedirect(userName) + if err == nil { + RedirectToUser(ctx, userName, redirectUserID) + } else if models.IsErrUserRedirectNotExist(err) { + if ctx.Query("go-get") == "1" { + EarlyResponseForGoGetMeta(ctx) + return + } + ctx.NotFound("GetUserByName", nil) + } else { + ctx.ServerError("LookupUserRedirect", err) } - ctx.NotFound("GetUserByName", nil) } else { ctx.ServerError("GetUserByName", err) } diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index 333dd9bd769a1..4dc7f6b5ee89a 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -425,7 +425,6 @@ update_theme=Aktualizovat motiv vzhledu update_profile=Aktualizovat profil update_profile_success=Váš profil byl aktualizován. change_username=Vaše uživatelské jméno bylo změněno. -change_username_prompt=Poznámka: změna uživatelského jména změní také URL účtu. continue=Pokračovat cancel=Zrušit language=Jazyk @@ -1759,7 +1758,6 @@ settings.visibility.private=Soukromá (viditelné jen členům organizace) settings.update_settings=Upravit nastavení settings.update_setting_success=Nastavení organizace bylo upraveno. -settings.change_orgname_prompt=Poznámka: změna názvu organizace změní i její URL. settings.update_avatar_success=Avatar organizace byl aktualizován. settings.delete=Smazat organizaci settings.delete_account=Smazat tuto organizaci diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index 369dca10c5dd7..889de41a13051 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -425,7 +425,6 @@ update_theme=Theme ändern update_profile=Profil aktualisieren update_profile_success=Dein Profil wurde aktualisiert. change_username=Dein Benutzername wurde geändert. -change_username_prompt=Hinweis: Wenn du deinen Benutzernamen änderst, wird auch deine Konto-URL geändert. continue=Weiter cancel=Abbrechen language=Sprache @@ -1759,7 +1758,6 @@ settings.visibility.private=Privat (nur für Organisationsmitglieder sichtbar) settings.update_settings=Einstellungen speichern settings.update_setting_success=Organisationseinstellungen wurden aktualisiert. -settings.change_orgname_prompt=Hinweis: Die Änderung des Organisationsnamens ändert auch ihre URL. settings.update_avatar_success=Der Organisationsavatar wurde aktualisiert. settings.delete=Organisation löschen settings.delete_account=Diese Organisation löschen diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 6227ceb2a2861..71d3d1dda7f52 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -426,7 +426,6 @@ update_theme = Update Theme update_profile = Update Profile update_profile_success = Your profile has been updated. change_username = Your username has been changed. -change_username_prompt = Note: username changes also change your account URL. continue = Continue cancel = Cancel language = Language @@ -1760,7 +1759,6 @@ settings.visibility.private = Private (Visible only to organization members) settings.update_settings = Update Settings settings.update_setting_success = Organization settings have been updated. -settings.change_orgname_prompt = Note: changing the organization name also changes the organization's URL. settings.update_avatar_success = The organization's avatar has been updated. settings.delete = Delete Organization settings.delete_account = Delete This Organization diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini index 3db2c9aca3bbc..0e3c8e25903dc 100644 --- a/options/locale/locale_es-ES.ini +++ b/options/locale/locale_es-ES.ini @@ -425,7 +425,6 @@ update_theme=Actualizar tema update_profile=Actualizar perfil update_profile_success=Tu perfil ha sido actualizado. change_username=Su nombre de usuario ha sido cambiado. -change_username_prompt=Nota: los cambios de nombre de usuario también cambian la URL de su cuenta. continue=Continuar cancel=Cancelar language=Idioma @@ -1759,7 +1758,6 @@ settings.visibility.private=Privado (Visible sólo para miembros de la organizac settings.update_settings=Actualizar configuración settings.update_setting_success=Configuración de la organización se han actualizado. -settings.change_orgname_prompt=Nota: cambiar el nombre de la organización también cambia la URL de la organización. settings.update_avatar_success=Se ha actualizado el avatar de la organización. settings.delete=Eliminar organización settings.delete_account=Eliminar esta organización diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini index 39913935e42f5..5fed375b106e7 100644 --- a/options/locale/locale_fa-IR.ini +++ b/options/locale/locale_fa-IR.ini @@ -425,7 +425,6 @@ update_theme=بروز رسانی پوسته update_profile=بروز‌رسانی نمایه update_profile_success=نمایه شما بروزرسانی شد. change_username=نام کاربری شما تغییر کرد. -change_username_prompt=توجه: تغییر نام‌کاربری، نشانی URL حساب شما را نیز تغییر می‌دهد. continue=ادامه cancel=انصراف language=زبان @@ -1762,7 +1761,6 @@ settings.visibility.private=خصوصی (پدیدار برای کاربران ع settings.update_settings=به‌ روزرسانی تنظیمات settings.update_setting_success=تنظیمات این سازمان به‌روز شد. -settings.change_orgname_prompt=نکته: به‌یاد داشته باشید تغییر نام سازمان موجب تعییر نشانی‌ها آن نیز می‌شود. settings.update_avatar_success=آواتار این سازمان به‌روز شد. settings.delete=حذف سازمان settings.delete_account=حذف این سازمان diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index f23d8b3858ce1..613f2004aedb5 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -425,7 +425,6 @@ update_theme=Mise à jour du thème update_profile=Valider les modifications update_profile_success=Votre profil a été mis à jour. change_username=Votre nom d'utilisateur a été modifié. -change_username_prompt=Remarque : changer votre nom d'utilisateur change également l'URL de votre compte. continue=Continuer cancel=Annuler language=Langues @@ -1759,7 +1758,6 @@ settings.visibility.private=Privé (Visible uniquement aux membres de l’organi settings.update_settings=Valider settings.update_setting_success=Les paramètres de l'organisation ont été mis à jour. -settings.change_orgname_prompt=NB: changer le nom de l'organisation changera aussi son URL. settings.update_avatar_success=L'avatar de l'organisation a été mis à jour. settings.delete=Supprimer l'organisation settings.delete_account=Supprimer cette organisation diff --git a/options/locale/locale_id-ID.ini b/options/locale/locale_id-ID.ini index 4eda61741e3c1..6e5bdf7e85fa7 100644 --- a/options/locale/locale_id-ID.ini +++ b/options/locale/locale_id-ID.ini @@ -425,7 +425,6 @@ update_theme=Perbarui Tema update_profile=Perbarui Profil update_profile_success=Profil anda telah diperbarui. change_username=Nama pengguna Anda telah diganti. -change_username_prompt=Catatan: Perubahan nama pengguna juga mengubah URL akun Anda. continue=Lanjutkan cancel=Batalkan language=Bahasa diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini index 9e711f3b95292..8efcd504f0af6 100644 --- a/options/locale/locale_it-IT.ini +++ b/options/locale/locale_it-IT.ini @@ -425,7 +425,6 @@ update_theme=Aggiorna tema update_profile=Aggiorna Profilo update_profile_success=Il tuo profilo è stato aggiornato. change_username=Il tuo nome utente è stato modificato. -change_username_prompt=Nota: i cambiamenti al nome utente vanno a modificare anche l'URL del tuo account. continue=Continua cancel=Annulla language=Lingua @@ -1759,7 +1758,6 @@ settings.visibility.private=Privato (Visibile solo ai membri dell'organizzazione settings.update_settings=Aggiorna Impostazioni settings.update_setting_success=Le impostazioni dell'organizzazione sono state aggiornate. -settings.change_orgname_prompt=Nota: cambiare il nome dell'organizzazione cambia anche il relativo URL. settings.update_avatar_success=L'avatar dell'organizzazione è stato aggiornato. settings.delete=Elimina organizzazione settings.delete_account=Elimina questa organizzazione diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 5db64b7caed58..6e97d8fffa412 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -425,7 +425,6 @@ update_theme=テーマを更新 update_profile=プロフィール更新 update_profile_success=プロフィールを更新しました。 change_username=ユーザー名を変更しました。 -change_username_prompt=注: ユーザー名を変更すると、アカウントのURLも変わります。 continue=続行 cancel=キャンセル language=言語 @@ -1759,7 +1758,6 @@ settings.visibility.private=プライベート (組織メンバーにのみ表 settings.update_settings=設定の更新 settings.update_setting_success=組織の設定を更新しました。 -settings.change_orgname_prompt=注: 組織の名称を変更すると、組織のURLも変わります。 settings.update_avatar_success=組織のアバターを更新しました。 settings.delete=組織を削除 settings.delete_account=この組織を削除 diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini index 1a40455b4db66..d853949f0f63e 100644 --- a/options/locale/locale_ko-KR.ini +++ b/options/locale/locale_ko-KR.ini @@ -425,7 +425,6 @@ update_theme=테마 갱신 update_profile=프로필 업데이트 update_profile_success=프로필이 업데이트 되었습니다. change_username=사용자 이름 변경 되었습니다. -change_username_prompt=사용자 이름 및 계정 URL 정보가 변경되었습니다. continue=계속하기 cancel=취소 language=언어 diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini index 24a1d7dcd134a..51192eadca335 100644 --- a/options/locale/locale_lv-LV.ini +++ b/options/locale/locale_lv-LV.ini @@ -425,7 +425,6 @@ update_theme=Mainīt motīvu update_profile=Mainīt profilu update_profile_success=Jūsu profila informācija tika saglabāta. change_username=Lietotājvārds mainīts. -change_username_prompt=Piezīme: Šī darbība izmainīs norādes uz šo kontu. continue=Turpināt cancel=Atcelt language=Valoda @@ -1759,7 +1758,6 @@ settings.visibility.private=Privāta (redzama tikai organizācijas dalībniekiem settings.update_settings=Mainīt iestatījumus settings.update_setting_success=Organizācijas iestatījumi tika saglabāti. -settings.change_orgname_prompt=Ņemiet vērā: Mainot organizācijas nosaukumu tiks izmainītas šīs organizācijas saites. settings.update_avatar_success=Organizācijas attēls tika saglabāts. settings.delete=Dzēst organizāciju settings.delete_account=Dzēst šo organizāciju diff --git a/options/locale/locale_ml-IN.ini b/options/locale/locale_ml-IN.ini index 5bf177314fc75..2e427711c0b1a 100644 --- a/options/locale/locale_ml-IN.ini +++ b/options/locale/locale_ml-IN.ini @@ -425,7 +425,6 @@ update_theme=പ്രമേയം പുതുക്കുക update_profile=പ്രോഫൈല്‍ പരിഷ്കരിക്കുക update_profile_success=നിങ്ങളുടെ പ്രൊഫൈൽ പരിഷ്കരിച്ചിരിക്കുന്നു. change_username=നിങ്ങളുടെ ഉപയോക്തൃനാമം മാറ്റി. -change_username_prompt=കുറിപ്പ്: ഉപയോക്തൃനാമത്തിലെ മാറ്റം നിങ്ങളുടെ അക്കൗണ്ട് URLഉം മാറ്റുന്നു. continue=തുടരുക cancel=റദ്ദാക്കുക language=ഭാഷ diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini index 55d0907890990..9b0f35978bffa 100644 --- a/options/locale/locale_nl-NL.ini +++ b/options/locale/locale_nl-NL.ini @@ -425,7 +425,6 @@ update_theme=Thema bijwerken update_profile=Profiel bijwerken update_profile_success=Je profiel is bijgewerkt. change_username=Je gebruikersnaam is gewijzigd. -change_username_prompt=Let op: Als je je gebruikersnaam aanpast, verandert je account-URL ook. continue=Doorgaan cancel=Annuleren language=Taal diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini index ae08da2697a41..eb32a114fed70 100644 --- a/options/locale/locale_pl-PL.ini +++ b/options/locale/locale_pl-PL.ini @@ -425,7 +425,6 @@ update_theme=Zaktualizuj motyw update_profile=Zaktualizuj profil update_profile_success=Twój profil został zaktualizowany. change_username=Twój nick został zmieniony. -change_username_prompt=Informacja: zmiana nazwy użytkownika zmienia również adres URL Twojego konta. continue=Kontynuuj cancel=Anuluj language=Język @@ -1759,7 +1758,6 @@ settings.visibility.private=Prywatne (widoczne tylko dla użytkowników organiza settings.update_settings=Aktualizuj ustawienia settings.update_setting_success=Ustawienia organizacji zostały zaktualizowane. -settings.change_orgname_prompt=Uwaga: zmiana nazwy organizacji zmieni również adres URL tej organizacji. settings.update_avatar_success=Awatar organizacji został zaktualizowany. settings.delete=Usuń organizację settings.delete_account=Usuń tą organizację diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index 1da63c9289cb7..6b6a009a26926 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -425,7 +425,6 @@ update_theme=Atualizar o tema update_profile=Atualizar o perfil update_profile_success=Seu perfil foi atualizado. change_username=Seu nome de usuário foi alterado. -change_username_prompt=Nota: as alterações de nome de usuário também mudam sua URL da conta. continue=Continuar cancel=Cancelar language=Idioma @@ -1759,7 +1758,6 @@ settings.visibility.private=Privada (Visível apenas para membros da organizaç settings.update_settings=Atualizar Configurações settings.update_setting_success=Configurações da organização foram atualizadas. -settings.change_orgname_prompt=Nota: alterar o nome da organização também altera a URL da mesma. settings.update_avatar_success=O avatar da organização foi atualizado. settings.delete=Excluir organização settings.delete_account=Excluir esta organização diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index 3a970227d3aa6..e38890d4345b4 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -425,7 +425,6 @@ update_theme=Substituir tema update_profile=Modificar perfil update_profile_success=O seu perfil foi modificado. change_username=Seu nome de utilizador foi alterado. -change_username_prompt=Nota: alterações do nome de utilizador também alteram o URL de sua conta. continue=Continuar cancel=Cancelar language=Idioma @@ -1759,7 +1758,6 @@ settings.visibility.private=Privada (visível apenas para os membros da organiza settings.update_settings=Modificar configurações settings.update_setting_success=As configurações da organização foram modificadas. -settings.change_orgname_prompt=Nota: alterar o nome da organização altera também o URL da organização. settings.update_avatar_success=O avatar da organização foi modificado. settings.delete=Eliminar organização settings.delete_account=Eliminar esta organização diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index 0f3bd8895cfbc..717459ed51de3 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -425,7 +425,6 @@ update_theme=Обновить тему update_profile=Обновить профиль update_profile_success=Ваш профиль успешно обновлен. change_username=Ваше имя пользователя было изменено. -change_username_prompt=Примечание: изменения имени пользователя также изменяют URL-адрес учетной записи. continue=Далее cancel=Отмена language=Язык @@ -1759,7 +1758,6 @@ settings.visibility.private=Частный (Видимый только для settings.update_settings=Обновить настройки settings.update_setting_success=Настройки организации обновлены. -settings.change_orgname_prompt=Это изменение изменит ссылки на организацию. settings.update_avatar_success=Аватар организации обновлен. settings.delete=Удалить организацию settings.delete_account=Удалить эту организацию diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini index b5e2308bc832b..8290d1cd675e8 100644 --- a/options/locale/locale_sv-SE.ini +++ b/options/locale/locale_sv-SE.ini @@ -425,7 +425,6 @@ update_theme=Ändra tema update_profile=Uppdatera profil update_profile_success=Din profil har uppdaterats. change_username=Ditt användarnamn har ändrats. -change_username_prompt=OBS: ändringar av användarnamn ändrar även kontots URL. continue=Fortsätt cancel=Avbryt language=Språk @@ -1759,7 +1758,6 @@ settings.visibility.private=Privat (synlig endast för organisationens medlemmar settings.update_settings=Uppdatera inställningar settings.update_setting_success=Organisationsinställningarna har uppdaterats. -settings.change_orgname_prompt=Notera: ändring av organisationsnamnet ändrar även organisationens URL. settings.update_avatar_success=Organisationens avatar har uppdateras. settings.delete=Tag bort organisation settings.delete_account=Tag bort denna organisation diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index d084c5c27466c..11e0414c71877 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -425,7 +425,6 @@ update_theme=Temayı Güncelle update_profile=Profili Güncelle update_profile_success=Profil resminiz güncellendi. change_username=Kullanıcı adınız değiştirildi. -change_username_prompt=Not: Kullanıcı adı değişiklikleri hesap URL'nizi de değiştirir. continue=Devam Et cancel=İptal language=Dil @@ -1759,7 +1758,6 @@ settings.visibility.private=Özel (Sadece organizasyon üyeleri görebilir) settings.update_settings=Ayarları Güncelle settings.update_setting_success=Organizasyon ayarları güncellendi. -settings.change_orgname_prompt=Not: Organizasyon adını değiştirmek, kuruluşun URL’sini de değiştirir. settings.update_avatar_success=Organizasyonun resmi güncellendi. settings.delete=Organizasyonu Sil settings.delete_account=Bu Organizasyonu Sil diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini index a4e867d2adf43..b2faf108349b0 100644 --- a/options/locale/locale_uk-UA.ini +++ b/options/locale/locale_uk-UA.ini @@ -425,7 +425,6 @@ update_theme=Оновити тему update_profile=Оновити профіль update_profile_success=Профіль успішно оновлено. change_username=Ваше Ім'я кристувача було змінено. -change_username_prompt=Примітка. Зміни в імені також змінюють URL-адресу облікового запису. continue=Продовжити cancel=Відмінити language=Мова @@ -1759,7 +1758,6 @@ settings.visibility.private=Приватний (Видимий лише член settings.update_settings=Оновити налаштування settings.update_setting_success=Налаштування організації оновлені. -settings.change_orgname_prompt=Ця зміна змінить посилання на організацію. settings.update_avatar_success=Аватар організації оновлений. settings.delete=Видалити організацію settings.delete_account=Видалити цю організацію diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 94a71abf148ae..1fe89394a481d 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -425,7 +425,6 @@ update_theme=更新主题 update_profile=更新信息 update_profile_success=您的资料信息已经更新 change_username=您的用户名已更改。 -change_username_prompt=注意:更改账号名将同时改变账号的URL continue=继续操作 cancel=取消操作 language=界面语言 @@ -1759,7 +1758,6 @@ settings.visibility.private=私有 (仅对组织成员可见) settings.update_settings=更新组织设置 settings.update_setting_success=组织设置已更新。 -settings.change_orgname_prompt=注意:修改组织名称将会同时修改对应的URL。 settings.update_avatar_success=组织头像已经更新。 settings.delete=删除组织 settings.delete_account=删除当前组织 diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini index 04a3445a71b7a..1aef487e45c02 100644 --- a/options/locale/locale_zh-TW.ini +++ b/options/locale/locale_zh-TW.ini @@ -425,7 +425,6 @@ update_theme=更新主題 update_profile=更新訊息 update_profile_success=您的個人資料已被更新 change_username=您的使用者名稱已更改。 -change_username_prompt=注意:使用者名更改也會更改您的帳戶的 URL。 continue=繼續操作 cancel=取消操作 language=語言 @@ -1759,7 +1758,6 @@ settings.visibility.private=私有(只有組織成員才能看到) settings.update_settings=更新組織設定 settings.update_setting_success=組織設定已更新。 -settings.change_orgname_prompt=注意:修改組織名稱將會同時修改對應的 URL。 settings.update_avatar_success=組織大頭貼已經更新。 settings.delete=刪除組織 settings.delete_account=刪除當前組織 diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 0567c3560c782..61e6587b7ba8a 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -127,9 +127,15 @@ func repoAssignment() macaron.Handler { owner, err = models.GetUserByName(userName) if err != nil { if models.IsErrUserNotExist(err) { - ctx.NotFound() + if redirectUserID, err := models.LookupUserRedirect(userName); err == nil { + context.RedirectToUser(ctx.Context, userName, redirectUserID) + } else if models.IsErrUserRedirectNotExist(err) { + ctx.NotFound("GetUserByName", err) + } else { + ctx.ServerError("LookupUserRedirect", err) + } } else { - ctx.Error(http.StatusInternalServerError, "GetUserByName", err) + ctx.ServerError("GetUserByName", err) } return } @@ -146,10 +152,10 @@ func repoAssignment() macaron.Handler { } else if models.IsErrRepoRedirectNotExist(err) { ctx.NotFound() } else { - ctx.Error(http.StatusInternalServerError, "LookupRepoRedirect", err) + ctx.ServerError("LookupRepoRedirect", err) } } else { - ctx.Error(http.StatusInternalServerError, "GetRepositoryByName", err) + ctx.ServerError("GetRepositoryByName", err) } return } diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go index 033b29f420da2..6a38b62d156c1 100644 --- a/routers/api/v1/user/key.go +++ b/routers/api/v1/user/key.go @@ -41,12 +41,16 @@ func appendPrivateInformation(apiKey *api.PublicKey, key *models.PublicKey, defa // GetUserByParamsName get user by name func GetUserByParamsName(ctx *context.APIContext, name string) *models.User { - user, err := models.GetUserByName(ctx.Params(name)) + user, err := models.GetUserByName(name) if err != nil { if models.IsErrUserNotExist(err) { - ctx.NotFound() + if redirectUserID, err := models.LookupUserRedirect(name); err == nil { + context.RedirectToUser(ctx.Context, name, redirectUserID) + } else { + ctx.NotFound("GetUserByName", err) + } } else { - ctx.Error(http.StatusInternalServerError, "GetUserByName", err) + ctx.ServerError("GetUserByName", err) } return nil } diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go index aaca53093eee0..892037e4cf64e 100644 --- a/routers/api/v1/user/user.go +++ b/routers/api/v1/user/user.go @@ -105,9 +105,13 @@ func GetInfo(ctx *context.APIContext) { u, err := models.GetUserByName(ctx.Params(":username")) if err != nil { if models.IsErrUserNotExist(err) { - ctx.NotFound() + if redirectUserID, err := models.LookupUserRedirect(ctx.Params(":username")); err == nil { + context.RedirectToUser(ctx.Context, ctx.Params(":username"), redirectUserID) + } else { + ctx.NotFound("GetUserByName", err) + } } else { - ctx.Error(http.StatusInternalServerError, "GetUserByName", err) + ctx.ServerError("GetUserByName", err) } return } @@ -152,9 +156,13 @@ func GetUserHeatmapData(ctx *context.APIContext) { user, err := models.GetUserByName(ctx.Params(":username")) if err != nil { if models.IsErrUserNotExist(err) { - ctx.Status(http.StatusNotFound) + if redirectUserID, err := models.LookupUserRedirect(ctx.Params(":username")); err == nil { + context.RedirectToUser(ctx.Context, ctx.Params(":username"), redirectUserID) + } else { + ctx.NotFound("GetUserByName", err) + } } else { - ctx.Error(http.StatusInternalServerError, "GetUserByName", err) + ctx.ServerError("GetUserByName", err) } return } diff --git a/routers/repo/http.go b/routers/repo/http.go index 1eec033882a48..4e5d145aae784 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -101,7 +101,15 @@ func HTTP(ctx *context.Context) { owner, err := models.GetUserByName(username) if err != nil { - ctx.NotFoundOrServerError("GetUserByName", models.IsErrUserNotExist, err) + if models.IsErrUserNotExist(err) { + if redirectUserID, err := models.LookupUserRedirect(username); err == nil { + context.RedirectToUser(ctx, username, redirectUserID) + } else { + ctx.NotFound("GetUserByName", err) + } + } else { + ctx.ServerError("GetUserByName", err) + } return } @@ -109,6 +117,7 @@ func HTTP(ctx *context.Context) { repo, err := models.GetRepositoryByName(owner.ID, reponame) if err != nil { if models.IsErrRepoNotExist(err) { + log.Trace("routers/repo/http.go:HTTP") if redirectRepoID, err := models.LookupRepoRedirect(owner.ID, reponame); err == nil { context.RedirectToRepo(ctx, redirectRepoID) return diff --git a/routers/user/profile.go b/routers/user/profile.go index 82fab4ad87278..4bc39692fbf9c 100644 --- a/routers/user/profile.go +++ b/routers/user/profile.go @@ -22,7 +22,11 @@ func GetUserByName(ctx *context.Context, name string) *models.User { user, err := models.GetUserByName(name) if err != nil { if models.IsErrUserNotExist(err) { - ctx.NotFound("GetUserByName", nil) + if redirectUserID, err := models.LookupUserRedirect(name); err == nil { + context.RedirectToUser(ctx, name, redirectUserID) + } else { + ctx.NotFound("GetUserByName", err) + } } else { ctx.ServerError("GetUserByName", err) } diff --git a/templates/user/settings/profile.tmpl b/templates/user/settings/profile.tmpl index b170c6757961e..3a6081abf454c 100644 --- a/templates/user/settings/profile.tmpl +++ b/templates/user/settings/profile.tmpl @@ -11,7 +11,6 @@
{{.CsrfTokenHtml}}
- {{if not .SignedUser.IsLocal}}

{{$.i18n.Tr "settings.password_username_disabled"}}

From 1524fef39140c336b8a7e99e1b096c95e56b9bf0 Mon Sep 17 00:00:00 2001 From: AndrewBezold Date: Wed, 27 May 2020 20:34:49 -0400 Subject: [PATCH 02/20] Add redirect for orgs --- models/org.go | 4 ++++ modules/context/org.go | 9 ++++++++- routers/api/v1/api.go | 11 +++++++++-- templates/org/settings/options.tmpl | 1 - 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/models/org.go b/models/org.go index 58afc5cb59502..2e81d9984e68e 100644 --- a/models/org.go +++ b/models/org.go @@ -152,6 +152,10 @@ func CreateOrganization(org, owner *User) (err error) { return ErrUserAlreadyExist{org.Name} } + if err = DeleteUserRedirect(org.Name); err != nil { + return err + } + org.LowerName = strings.ToLower(org.Name) if org.Rands, err = GetUserSalt(); err != nil { return err diff --git a/modules/context/org.go b/modules/context/org.go index 9b87fba9fd0bc..f61a39c666b95 100644 --- a/modules/context/org.go +++ b/modules/context/org.go @@ -54,7 +54,14 @@ func HandleOrgAssignment(ctx *Context, args ...bool) { ctx.Org.Organization, err = models.GetUserByName(orgName) if err != nil { if models.IsErrUserNotExist(err) { - ctx.NotFound("GetUserByName", err) + redirectUserID, err := models.LookupUserRedirect(orgName) + if err == nil { + RedirectToUser(ctx, orgName, redirectUserID) + } else if models.IsErrUserRedirectNotExist(err) { + ctx.NotFound("GetUserByName", err) + } else { + ctx.ServerError("LookupUserRedirect", err) + } } else { ctx.ServerError("GetUserByName", err) } diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 61e6587b7ba8a..b1ccf64f7f809 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -392,9 +392,16 @@ func orgAssignment(args ...bool) macaron.Handler { ctx.Org.Organization, err = models.GetOrgByName(ctx.Params(":org")) if err != nil { if models.IsErrOrgNotExist(err) { - ctx.NotFound() + redirectUserID, err := models.LookupUserRedirect(ctx.Params(":orgname")) + if err == nil { + context.RedirectToUser(ctx.Context, ctx.Params(":orgname"), redirectUserID) + } else if models.IsErrUserRedirectNotExist(err) { + ctx.NotFound("GetOrgByName", err) + } else { + ctx.ServerError("LookupUserRedirect", err) + } } else { - ctx.Error(http.StatusInternalServerError, "GetOrgByName", err) + ctx.ServerError("GetOrgByName", err) } return } diff --git a/templates/org/settings/options.tmpl b/templates/org/settings/options.tmpl index d58c77ad10a2e..c35304dd76f5c 100644 --- a/templates/org/settings/options.tmpl +++ b/templates/org/settings/options.tmpl @@ -13,7 +13,6 @@ {{.CsrfTokenHtml}}
-
From b4ecccfb08b7dd47670e8c0d67358241ab6f86a4 Mon Sep 17 00:00:00 2001 From: AndrewBezold Date: Wed, 27 May 2020 20:53:15 -0400 Subject: [PATCH 03/20] Add user redirect test --- models/fixtures/user_redirect.yml | 4 ++ models/user_redirect_test.go | 69 +++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 models/fixtures/user_redirect.yml create mode 100644 models/user_redirect_test.go diff --git a/models/fixtures/user_redirect.yml b/models/fixtures/user_redirect.yml new file mode 100644 index 0000000000000..8ff79933983eb --- /dev/null +++ b/models/fixtures/user_redirect.yml @@ -0,0 +1,4 @@ +- + id: 1 + lower_name: olduser1 + redirect_user_id: 1 diff --git a/models/user_redirect_test.go b/models/user_redirect_test.go new file mode 100644 index 0000000000000..eea2ac466958e --- /dev/null +++ b/models/user_redirect_test.go @@ -0,0 +1,69 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package models + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestLookupUserRedirect(t *testing.T) { + assert.NoError(t, PrepareTestDatabase()) + + userID, err := LookupUserRedirect("olduser1") + assert.NoError(t, err) + assert.EqualValues(t, 1, userID) + + _, err = LookupUserRedirect("doesnotexist") + assert.True(t, IsErrUserRedirectNotExist(err)) +} + +func TestNewUserRedirect(t *testing.T) { + // redirect to a completely new name + assert.NoError(t, PrepareTestDatabase()) + + user := AssertExistsAndLoadBean(t, &User{ID: 1}).(*User) + assert.NoError(t, NewUserRedirect(DefaultDBContext(), user.ID, user.Name, "newusername")) + + AssertExistsAndLoadBean(t, &UserRedirect{ + LowerName: user.LowerName, + RedirectUserID: user.ID, + }) + AssertExistsAndLoadBean(t, &UserRedirect{ + LowerName: "olduser1", + RedirectUserID: user.ID, + }) +} + +func TestNewUserRedirect2(t *testing.T) { + // redirect to previously used name + assert.NoError(t, PrepareTestDatabase()) + + user := AssertExistsAndLoadBean(t, &User{ID: 1}).(*User) + assert.NoError(t, NewUserRedirect(DefaultDBContext(), user.ID, user.Name, "olduser1")) + + AssertExistsAndLoadBean(t, &UserRedirect{ + LowerName: user.LowerName, + RedirectUserID: user.ID, + }) + AssertNotExistsBean(t, &UserRedirect{ + LowerName: "olduser1", + RedirectUserID: user.ID, + }) +} + +func TestNewUserRedirect3(t *testing.T) { + // redirect for a previously-unredirected user + assert.NoError(t, PrepareTestDatabase()) + + user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User) + assert.NoError(t, NewUserRedirect(DefaultDBContext(), user.ID, user.Name, "newusername")) + + AssertExistsAndLoadBean(t, &UserRedirect{ + LowerName: user.LowerName, + RedirectUserID: user.ID, + }) +} From 415698084c72eecd9cfbe4b9bced7b56b571203f Mon Sep 17 00:00:00 2001 From: AndrewBezold Date: Wed, 27 May 2020 21:31:29 -0400 Subject: [PATCH 04/20] Appease linter --- modules/context/context.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/context/context.go b/modules/context/context.go index a1e5ea2af59f7..0d806533cba36 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -6,7 +6,6 @@ package context import ( - "fmt" "html" "html/template" "io" @@ -95,7 +94,7 @@ func RedirectToUser(ctx *Context, userName string, redirectUserID int64) { redirectPath := strings.Replace( ctx.Req.URL.Path, - fmt.Sprintf("%s", userName), + userName, user.Name, 1, ) From 911270345ddd71c0cf2d66e064f5d72d67b3261c Mon Sep 17 00:00:00 2001 From: AndrewBezold Date: Wed, 27 May 2020 21:35:53 -0400 Subject: [PATCH 05/20] Add comment to DeleteUserRedirect function --- models/user_redirect.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/models/user_redirect.go b/models/user_redirect.go index 7a479970324d3..4ae98c364a6cf 100644 --- a/models/user_redirect.go +++ b/models/user_redirect.go @@ -51,6 +51,8 @@ func deleteUserRedirect(e Engine, userName string) error { return err } +// DeleteUserRedirect delete any redirect from the specified user name to +// anything else func DeleteUserRedirect(userName string) error { return deleteUserRedirect(x, userName) } From aecbb0dcadf0bc66d07ccc964c4f1e42c89bab8b Mon Sep 17 00:00:00 2001 From: AndrewBezold Date: Thu, 28 May 2020 17:38:01 -0400 Subject: [PATCH 06/20] Fix locale changes --- options/locale/locale_cs-CZ.ini | 2 ++ options/locale/locale_de-DE.ini | 2 ++ options/locale/locale_es-ES.ini | 2 ++ options/locale/locale_fa-IR.ini | 2 ++ options/locale/locale_fr-FR.ini | 2 ++ options/locale/locale_id-ID.ini | 1 + options/locale/locale_it-IT.ini | 2 ++ options/locale/locale_ja-JP.ini | 2 ++ options/locale/locale_ko-KR.ini | 1 + options/locale/locale_lv-LV.ini | 2 ++ options/locale/locale_ml-IN.ini | 1 + options/locale/locale_nl-NL.ini | 1 + options/locale/locale_pl-PL.ini | 2 ++ options/locale/locale_pt-BR.ini | 2 ++ options/locale/locale_pt-PT.ini | 2 ++ options/locale/locale_ru-RU.ini | 2 ++ options/locale/locale_sv-SE.ini | 2 ++ options/locale/locale_tr-TR.ini | 2 ++ options/locale/locale_uk-UA.ini | 2 ++ options/locale/locale_zh-CN.ini | 2 ++ options/locale/locale_zh-TW.ini | 2 ++ 21 files changed, 38 insertions(+) diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index 4dc7f6b5ee89a..333dd9bd769a1 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -425,6 +425,7 @@ update_theme=Aktualizovat motiv vzhledu update_profile=Aktualizovat profil update_profile_success=Váš profil byl aktualizován. change_username=Vaše uživatelské jméno bylo změněno. +change_username_prompt=Poznámka: změna uživatelského jména změní také URL účtu. continue=Pokračovat cancel=Zrušit language=Jazyk @@ -1758,6 +1759,7 @@ settings.visibility.private=Soukromá (viditelné jen členům organizace) settings.update_settings=Upravit nastavení settings.update_setting_success=Nastavení organizace bylo upraveno. +settings.change_orgname_prompt=Poznámka: změna názvu organizace změní i její URL. settings.update_avatar_success=Avatar organizace byl aktualizován. settings.delete=Smazat organizaci settings.delete_account=Smazat tuto organizaci diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index 889de41a13051..369dca10c5dd7 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -425,6 +425,7 @@ update_theme=Theme ändern update_profile=Profil aktualisieren update_profile_success=Dein Profil wurde aktualisiert. change_username=Dein Benutzername wurde geändert. +change_username_prompt=Hinweis: Wenn du deinen Benutzernamen änderst, wird auch deine Konto-URL geändert. continue=Weiter cancel=Abbrechen language=Sprache @@ -1758,6 +1759,7 @@ settings.visibility.private=Privat (nur für Organisationsmitglieder sichtbar) settings.update_settings=Einstellungen speichern settings.update_setting_success=Organisationseinstellungen wurden aktualisiert. +settings.change_orgname_prompt=Hinweis: Die Änderung des Organisationsnamens ändert auch ihre URL. settings.update_avatar_success=Der Organisationsavatar wurde aktualisiert. settings.delete=Organisation löschen settings.delete_account=Diese Organisation löschen diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini index 0e3c8e25903dc..3db2c9aca3bbc 100644 --- a/options/locale/locale_es-ES.ini +++ b/options/locale/locale_es-ES.ini @@ -425,6 +425,7 @@ update_theme=Actualizar tema update_profile=Actualizar perfil update_profile_success=Tu perfil ha sido actualizado. change_username=Su nombre de usuario ha sido cambiado. +change_username_prompt=Nota: los cambios de nombre de usuario también cambian la URL de su cuenta. continue=Continuar cancel=Cancelar language=Idioma @@ -1758,6 +1759,7 @@ settings.visibility.private=Privado (Visible sólo para miembros de la organizac settings.update_settings=Actualizar configuración settings.update_setting_success=Configuración de la organización se han actualizado. +settings.change_orgname_prompt=Nota: cambiar el nombre de la organización también cambia la URL de la organización. settings.update_avatar_success=Se ha actualizado el avatar de la organización. settings.delete=Eliminar organización settings.delete_account=Eliminar esta organización diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini index 5fed375b106e7..39913935e42f5 100644 --- a/options/locale/locale_fa-IR.ini +++ b/options/locale/locale_fa-IR.ini @@ -425,6 +425,7 @@ update_theme=بروز رسانی پوسته update_profile=بروز‌رسانی نمایه update_profile_success=نمایه شما بروزرسانی شد. change_username=نام کاربری شما تغییر کرد. +change_username_prompt=توجه: تغییر نام‌کاربری، نشانی URL حساب شما را نیز تغییر می‌دهد. continue=ادامه cancel=انصراف language=زبان @@ -1761,6 +1762,7 @@ settings.visibility.private=خصوصی (پدیدار برای کاربران ع settings.update_settings=به‌ روزرسانی تنظیمات settings.update_setting_success=تنظیمات این سازمان به‌روز شد. +settings.change_orgname_prompt=نکته: به‌یاد داشته باشید تغییر نام سازمان موجب تعییر نشانی‌ها آن نیز می‌شود. settings.update_avatar_success=آواتار این سازمان به‌روز شد. settings.delete=حذف سازمان settings.delete_account=حذف این سازمان diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index 613f2004aedb5..f23d8b3858ce1 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -425,6 +425,7 @@ update_theme=Mise à jour du thème update_profile=Valider les modifications update_profile_success=Votre profil a été mis à jour. change_username=Votre nom d'utilisateur a été modifié. +change_username_prompt=Remarque : changer votre nom d'utilisateur change également l'URL de votre compte. continue=Continuer cancel=Annuler language=Langues @@ -1758,6 +1759,7 @@ settings.visibility.private=Privé (Visible uniquement aux membres de l’organi settings.update_settings=Valider settings.update_setting_success=Les paramètres de l'organisation ont été mis à jour. +settings.change_orgname_prompt=NB: changer le nom de l'organisation changera aussi son URL. settings.update_avatar_success=L'avatar de l'organisation a été mis à jour. settings.delete=Supprimer l'organisation settings.delete_account=Supprimer cette organisation diff --git a/options/locale/locale_id-ID.ini b/options/locale/locale_id-ID.ini index 6e5bdf7e85fa7..4eda61741e3c1 100644 --- a/options/locale/locale_id-ID.ini +++ b/options/locale/locale_id-ID.ini @@ -425,6 +425,7 @@ update_theme=Perbarui Tema update_profile=Perbarui Profil update_profile_success=Profil anda telah diperbarui. change_username=Nama pengguna Anda telah diganti. +change_username_prompt=Catatan: Perubahan nama pengguna juga mengubah URL akun Anda. continue=Lanjutkan cancel=Batalkan language=Bahasa diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini index 8efcd504f0af6..9e711f3b95292 100644 --- a/options/locale/locale_it-IT.ini +++ b/options/locale/locale_it-IT.ini @@ -425,6 +425,7 @@ update_theme=Aggiorna tema update_profile=Aggiorna Profilo update_profile_success=Il tuo profilo è stato aggiornato. change_username=Il tuo nome utente è stato modificato. +change_username_prompt=Nota: i cambiamenti al nome utente vanno a modificare anche l'URL del tuo account. continue=Continua cancel=Annulla language=Lingua @@ -1758,6 +1759,7 @@ settings.visibility.private=Privato (Visibile solo ai membri dell'organizzazione settings.update_settings=Aggiorna Impostazioni settings.update_setting_success=Le impostazioni dell'organizzazione sono state aggiornate. +settings.change_orgname_prompt=Nota: cambiare il nome dell'organizzazione cambia anche il relativo URL. settings.update_avatar_success=L'avatar dell'organizzazione è stato aggiornato. settings.delete=Elimina organizzazione settings.delete_account=Elimina questa organizzazione diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 6e97d8fffa412..5db64b7caed58 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -425,6 +425,7 @@ update_theme=テーマを更新 update_profile=プロフィール更新 update_profile_success=プロフィールを更新しました。 change_username=ユーザー名を変更しました。 +change_username_prompt=注: ユーザー名を変更すると、アカウントのURLも変わります。 continue=続行 cancel=キャンセル language=言語 @@ -1758,6 +1759,7 @@ settings.visibility.private=プライベート (組織メンバーにのみ表 settings.update_settings=設定の更新 settings.update_setting_success=組織の設定を更新しました。 +settings.change_orgname_prompt=注: 組織の名称を変更すると、組織のURLも変わります。 settings.update_avatar_success=組織のアバターを更新しました。 settings.delete=組織を削除 settings.delete_account=この組織を削除 diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini index d853949f0f63e..1a40455b4db66 100644 --- a/options/locale/locale_ko-KR.ini +++ b/options/locale/locale_ko-KR.ini @@ -425,6 +425,7 @@ update_theme=테마 갱신 update_profile=프로필 업데이트 update_profile_success=프로필이 업데이트 되었습니다. change_username=사용자 이름 변경 되었습니다. +change_username_prompt=사용자 이름 및 계정 URL 정보가 변경되었습니다. continue=계속하기 cancel=취소 language=언어 diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini index 51192eadca335..24a1d7dcd134a 100644 --- a/options/locale/locale_lv-LV.ini +++ b/options/locale/locale_lv-LV.ini @@ -425,6 +425,7 @@ update_theme=Mainīt motīvu update_profile=Mainīt profilu update_profile_success=Jūsu profila informācija tika saglabāta. change_username=Lietotājvārds mainīts. +change_username_prompt=Piezīme: Šī darbība izmainīs norādes uz šo kontu. continue=Turpināt cancel=Atcelt language=Valoda @@ -1758,6 +1759,7 @@ settings.visibility.private=Privāta (redzama tikai organizācijas dalībniekiem settings.update_settings=Mainīt iestatījumus settings.update_setting_success=Organizācijas iestatījumi tika saglabāti. +settings.change_orgname_prompt=Ņemiet vērā: Mainot organizācijas nosaukumu tiks izmainītas šīs organizācijas saites. settings.update_avatar_success=Organizācijas attēls tika saglabāts. settings.delete=Dzēst organizāciju settings.delete_account=Dzēst šo organizāciju diff --git a/options/locale/locale_ml-IN.ini b/options/locale/locale_ml-IN.ini index 2e427711c0b1a..5bf177314fc75 100644 --- a/options/locale/locale_ml-IN.ini +++ b/options/locale/locale_ml-IN.ini @@ -425,6 +425,7 @@ update_theme=പ്രമേയം പുതുക്കുക update_profile=പ്രോഫൈല്‍ പരിഷ്കരിക്കുക update_profile_success=നിങ്ങളുടെ പ്രൊഫൈൽ പരിഷ്കരിച്ചിരിക്കുന്നു. change_username=നിങ്ങളുടെ ഉപയോക്തൃനാമം മാറ്റി. +change_username_prompt=കുറിപ്പ്: ഉപയോക്തൃനാമത്തിലെ മാറ്റം നിങ്ങളുടെ അക്കൗണ്ട് URLഉം മാറ്റുന്നു. continue=തുടരുക cancel=റദ്ദാക്കുക language=ഭാഷ diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini index 9b0f35978bffa..55d0907890990 100644 --- a/options/locale/locale_nl-NL.ini +++ b/options/locale/locale_nl-NL.ini @@ -425,6 +425,7 @@ update_theme=Thema bijwerken update_profile=Profiel bijwerken update_profile_success=Je profiel is bijgewerkt. change_username=Je gebruikersnaam is gewijzigd. +change_username_prompt=Let op: Als je je gebruikersnaam aanpast, verandert je account-URL ook. continue=Doorgaan cancel=Annuleren language=Taal diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini index eb32a114fed70..ae08da2697a41 100644 --- a/options/locale/locale_pl-PL.ini +++ b/options/locale/locale_pl-PL.ini @@ -425,6 +425,7 @@ update_theme=Zaktualizuj motyw update_profile=Zaktualizuj profil update_profile_success=Twój profil został zaktualizowany. change_username=Twój nick został zmieniony. +change_username_prompt=Informacja: zmiana nazwy użytkownika zmienia również adres URL Twojego konta. continue=Kontynuuj cancel=Anuluj language=Język @@ -1758,6 +1759,7 @@ settings.visibility.private=Prywatne (widoczne tylko dla użytkowników organiza settings.update_settings=Aktualizuj ustawienia settings.update_setting_success=Ustawienia organizacji zostały zaktualizowane. +settings.change_orgname_prompt=Uwaga: zmiana nazwy organizacji zmieni również adres URL tej organizacji. settings.update_avatar_success=Awatar organizacji został zaktualizowany. settings.delete=Usuń organizację settings.delete_account=Usuń tą organizację diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index 6b6a009a26926..1da63c9289cb7 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -425,6 +425,7 @@ update_theme=Atualizar o tema update_profile=Atualizar o perfil update_profile_success=Seu perfil foi atualizado. change_username=Seu nome de usuário foi alterado. +change_username_prompt=Nota: as alterações de nome de usuário também mudam sua URL da conta. continue=Continuar cancel=Cancelar language=Idioma @@ -1758,6 +1759,7 @@ settings.visibility.private=Privada (Visível apenas para membros da organizaç settings.update_settings=Atualizar Configurações settings.update_setting_success=Configurações da organização foram atualizadas. +settings.change_orgname_prompt=Nota: alterar o nome da organização também altera a URL da mesma. settings.update_avatar_success=O avatar da organização foi atualizado. settings.delete=Excluir organização settings.delete_account=Excluir esta organização diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index e38890d4345b4..3a970227d3aa6 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -425,6 +425,7 @@ update_theme=Substituir tema update_profile=Modificar perfil update_profile_success=O seu perfil foi modificado. change_username=Seu nome de utilizador foi alterado. +change_username_prompt=Nota: alterações do nome de utilizador também alteram o URL de sua conta. continue=Continuar cancel=Cancelar language=Idioma @@ -1758,6 +1759,7 @@ settings.visibility.private=Privada (visível apenas para os membros da organiza settings.update_settings=Modificar configurações settings.update_setting_success=As configurações da organização foram modificadas. +settings.change_orgname_prompt=Nota: alterar o nome da organização altera também o URL da organização. settings.update_avatar_success=O avatar da organização foi modificado. settings.delete=Eliminar organização settings.delete_account=Eliminar esta organização diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index 717459ed51de3..0f3bd8895cfbc 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -425,6 +425,7 @@ update_theme=Обновить тему update_profile=Обновить профиль update_profile_success=Ваш профиль успешно обновлен. change_username=Ваше имя пользователя было изменено. +change_username_prompt=Примечание: изменения имени пользователя также изменяют URL-адрес учетной записи. continue=Далее cancel=Отмена language=Язык @@ -1758,6 +1759,7 @@ settings.visibility.private=Частный (Видимый только для settings.update_settings=Обновить настройки settings.update_setting_success=Настройки организации обновлены. +settings.change_orgname_prompt=Это изменение изменит ссылки на организацию. settings.update_avatar_success=Аватар организации обновлен. settings.delete=Удалить организацию settings.delete_account=Удалить эту организацию diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini index 8290d1cd675e8..b5e2308bc832b 100644 --- a/options/locale/locale_sv-SE.ini +++ b/options/locale/locale_sv-SE.ini @@ -425,6 +425,7 @@ update_theme=Ändra tema update_profile=Uppdatera profil update_profile_success=Din profil har uppdaterats. change_username=Ditt användarnamn har ändrats. +change_username_prompt=OBS: ändringar av användarnamn ändrar även kontots URL. continue=Fortsätt cancel=Avbryt language=Språk @@ -1758,6 +1759,7 @@ settings.visibility.private=Privat (synlig endast för organisationens medlemmar settings.update_settings=Uppdatera inställningar settings.update_setting_success=Organisationsinställningarna har uppdaterats. +settings.change_orgname_prompt=Notera: ändring av organisationsnamnet ändrar även organisationens URL. settings.update_avatar_success=Organisationens avatar har uppdateras. settings.delete=Tag bort organisation settings.delete_account=Tag bort denna organisation diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index 11e0414c71877..d084c5c27466c 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -425,6 +425,7 @@ update_theme=Temayı Güncelle update_profile=Profili Güncelle update_profile_success=Profil resminiz güncellendi. change_username=Kullanıcı adınız değiştirildi. +change_username_prompt=Not: Kullanıcı adı değişiklikleri hesap URL'nizi de değiştirir. continue=Devam Et cancel=İptal language=Dil @@ -1758,6 +1759,7 @@ settings.visibility.private=Özel (Sadece organizasyon üyeleri görebilir) settings.update_settings=Ayarları Güncelle settings.update_setting_success=Organizasyon ayarları güncellendi. +settings.change_orgname_prompt=Not: Organizasyon adını değiştirmek, kuruluşun URL’sini de değiştirir. settings.update_avatar_success=Organizasyonun resmi güncellendi. settings.delete=Organizasyonu Sil settings.delete_account=Bu Organizasyonu Sil diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini index b2faf108349b0..a4e867d2adf43 100644 --- a/options/locale/locale_uk-UA.ini +++ b/options/locale/locale_uk-UA.ini @@ -425,6 +425,7 @@ update_theme=Оновити тему update_profile=Оновити профіль update_profile_success=Профіль успішно оновлено. change_username=Ваше Ім'я кристувача було змінено. +change_username_prompt=Примітка. Зміни в імені також змінюють URL-адресу облікового запису. continue=Продовжити cancel=Відмінити language=Мова @@ -1758,6 +1759,7 @@ settings.visibility.private=Приватний (Видимий лише член settings.update_settings=Оновити налаштування settings.update_setting_success=Налаштування організації оновлені. +settings.change_orgname_prompt=Ця зміна змінить посилання на організацію. settings.update_avatar_success=Аватар організації оновлений. settings.delete=Видалити організацію settings.delete_account=Видалити цю організацію diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 1fe89394a481d..94a71abf148ae 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -425,6 +425,7 @@ update_theme=更新主题 update_profile=更新信息 update_profile_success=您的资料信息已经更新 change_username=您的用户名已更改。 +change_username_prompt=注意:更改账号名将同时改变账号的URL continue=继续操作 cancel=取消操作 language=界面语言 @@ -1758,6 +1759,7 @@ settings.visibility.private=私有 (仅对组织成员可见) settings.update_settings=更新组织设置 settings.update_setting_success=组织设置已更新。 +settings.change_orgname_prompt=注意:修改组织名称将会同时修改对应的URL。 settings.update_avatar_success=组织头像已经更新。 settings.delete=删除组织 settings.delete_account=删除当前组织 diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini index 1aef487e45c02..04a3445a71b7a 100644 --- a/options/locale/locale_zh-TW.ini +++ b/options/locale/locale_zh-TW.ini @@ -425,6 +425,7 @@ update_theme=更新主題 update_profile=更新訊息 update_profile_success=您的個人資料已被更新 change_username=您的使用者名稱已更改。 +change_username_prompt=注意:使用者名更改也會更改您的帳戶的 URL。 continue=繼續操作 cancel=取消操作 language=語言 @@ -1758,6 +1759,7 @@ settings.visibility.private=私有(只有組織成員才能看到) settings.update_settings=更新組織設定 settings.update_setting_success=組織設定已更新。 +settings.change_orgname_prompt=注意:修改組織名稱將會同時修改對應的 URL。 settings.update_avatar_success=組織大頭貼已經更新。 settings.delete=刪除組織 settings.delete_account=刪除當前組織 From b4eea727028d6f783ce7f2bb2be362d0b07901e4 Mon Sep 17 00:00:00 2001 From: AndrewBezold Date: Thu, 28 May 2020 18:57:24 -0400 Subject: [PATCH 07/20] Fix GetUserByParams --- routers/api/v1/user/key.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go index 6a38b62d156c1..e3b1da99842a1 100644 --- a/routers/api/v1/user/key.go +++ b/routers/api/v1/user/key.go @@ -59,7 +59,7 @@ func GetUserByParamsName(ctx *context.APIContext, name string) *models.User { // GetUserByParams returns user whose name is presented in URL paramenter. func GetUserByParams(ctx *context.APIContext) *models.User { - return GetUserByParamsName(ctx, ":username") + return GetUserByParamsName(ctx, ctx.Params(":username")) } func composePublicKeysAPILink() string { From 14fa02b4d72efb2a7b0c9fe69d2d9680f9cb501e Mon Sep 17 00:00:00 2001 From: AndrewBezold Date: Thu, 28 May 2020 19:23:20 -0400 Subject: [PATCH 08/20] Fix orgAssignment --- routers/api/v1/api.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index b1ccf64f7f809..fe3f13f3075c0 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -392,9 +392,9 @@ func orgAssignment(args ...bool) macaron.Handler { ctx.Org.Organization, err = models.GetOrgByName(ctx.Params(":org")) if err != nil { if models.IsErrOrgNotExist(err) { - redirectUserID, err := models.LookupUserRedirect(ctx.Params(":orgname")) + redirectUserID, err := models.LookupUserRedirect(ctx.Params(":org")) if err == nil { - context.RedirectToUser(ctx.Context, ctx.Params(":orgname"), redirectUserID) + context.RedirectToUser(ctx.Context, ctx.Params(":org"), redirectUserID) } else if models.IsErrUserRedirectNotExist(err) { ctx.NotFound("GetOrgByName", err) } else { From 387ddec5d3239ad32da4cfd267569ede1f07b23e Mon Sep 17 00:00:00 2001 From: AndrewBezold Date: Tue, 9 Jun 2020 10:30:39 -0400 Subject: [PATCH 09/20] Remove debug logging --- routers/repo/http.go | 1 - 1 file changed, 1 deletion(-) diff --git a/routers/repo/http.go b/routers/repo/http.go index 4e5d145aae784..260dc26d780af 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -117,7 +117,6 @@ func HTTP(ctx *context.Context) { repo, err := models.GetRepositoryByName(owner.ID, reponame) if err != nil { if models.IsErrRepoNotExist(err) { - log.Trace("routers/repo/http.go:HTTP") if redirectRepoID, err := models.LookupRepoRedirect(owner.ID, reponame); err == nil { context.RedirectToRepo(ctx, redirectRepoID) return From 0167007c1e0c99695799f85bfaacc7cdb5e59757 Mon Sep 17 00:00:00 2001 From: AndrewBezold Date: Tue, 9 Jun 2020 23:29:24 -0400 Subject: [PATCH 10/20] Add redirect prompt --- options/locale/locale_en-US.ini | 4 ++++ templates/org/settings/options.tmpl | 2 ++ templates/user/settings/profile.tmpl | 2 ++ web_src/js/index.js | 6 ++++++ 4 files changed, 14 insertions(+) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 71d3d1dda7f52..2e79d30a058f8 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -426,6 +426,8 @@ update_theme = Update Theme update_profile = Update Profile update_profile_success = Your profile has been updated. change_username = Your username has been changed. +change_username_prompt = Note: username changes also change your account URL. +change_username_redirect_prompt = The old username will redirect until it is claimed. continue = Continue cancel = Cancel language = Language @@ -1759,6 +1761,8 @@ settings.visibility.private = Private (Visible only to organization members) settings.update_settings = Update Settings settings.update_setting_success = Organization settings have been updated. +settings.change_orgname_prompt = Note: changing the organization name also changes the organization's URL. +settings.change_orgname_redirect_prompt = The old name will redirect until it is claimed. settings.update_avatar_success = The organization's avatar has been updated. settings.delete = Delete Organization settings.delete_account = Delete This Organization diff --git a/templates/org/settings/options.tmpl b/templates/org/settings/options.tmpl index c35304dd76f5c..b1464d60925a6 100644 --- a/templates/org/settings/options.tmpl +++ b/templates/org/settings/options.tmpl @@ -13,6 +13,8 @@ {{.CsrfTokenHtml}}
+
diff --git a/templates/user/settings/profile.tmpl b/templates/user/settings/profile.tmpl index 3a6081abf454c..bfa1ea7701a4b 100644 --- a/templates/user/settings/profile.tmpl +++ b/templates/user/settings/profile.tmpl @@ -11,6 +11,8 @@ {{.CsrfTokenHtml}}
+ {{if not .SignedUser.IsLocal}}

{{$.i18n.Tr "settings.password_username_disabled"}}

diff --git a/web_src/js/index.js b/web_src/js/index.js index efe1663a76adb..8abf8be07f0a1 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -1634,10 +1634,13 @@ function initOrganization() { if ($('.organization.settings.options').length > 0) { $('#org_name').on('keyup', function () { const $prompt = $('#org-name-change-prompt'); + const $prompt_redirect = $('#org-name-change-redirect-prompt'); if ($(this).val().toString().toLowerCase() !== $(this).data('org-name').toString().toLowerCase()) { $prompt.show(); + $prompt_redirect.show(); } else { $prompt.hide(); + $prompt_redirect.hide(); } }); } @@ -1653,10 +1656,13 @@ function initUserSettings() { if ($('.user.settings.profile').length > 0) { $('#username').on('keyup', function () { const $prompt = $('#name-change-prompt'); + const $prompt_redirect = $('#name-change-redirect-prompt'); if ($(this).val().toString().toLowerCase() !== $(this).data('name').toString().toLowerCase()) { $prompt.show(); + $prompt_redirect.show(); } else { $prompt.hide(); + $prompt_redirect.hide(); } }); } From b4ac0d6402a277f900ded411dc32a697c49dee3e Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 23 Jan 2021 16:02:42 +0100 Subject: [PATCH 11/20] Dont Export DeleteUserRedirect & only use it within a session --- models/org.go | 8 ++++---- models/user_redirect.go | 6 ------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/models/org.go b/models/org.go index 699959e24a45c..ee867eec887f4 100644 --- a/models/org.go +++ b/models/org.go @@ -152,10 +152,6 @@ func CreateOrganization(org, owner *User) (err error) { return ErrUserAlreadyExist{org.Name} } - if err = DeleteUserRedirect(org.Name); err != nil { - return err - } - org.LowerName = strings.ToLower(org.Name) if org.Rands, err = GetUserSalt(); err != nil { return err @@ -175,6 +171,10 @@ func CreateOrganization(org, owner *User) (err error) { return err } + if err = deleteUserRedirect(sess, org.Name); err != nil { + return err + } + if _, err = sess.Insert(org); err != nil { return fmt.Errorf("insert organization: %v", err) } diff --git a/models/user_redirect.go b/models/user_redirect.go index 4ae98c364a6cf..60e2578b30ad9 100644 --- a/models/user_redirect.go +++ b/models/user_redirect.go @@ -50,9 +50,3 @@ func deleteUserRedirect(e Engine, userName string) error { _, err := e.Delete(&UserRedirect{LowerName: userName}) return err } - -// DeleteUserRedirect delete any redirect from the specified user name to -// anything else -func DeleteUserRedirect(userName string) error { - return deleteUserRedirect(x, userName) -} From 988075bb7aba8c2987d0b55526179ca9fa02ed88 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 23 Jan 2021 16:10:06 +0100 Subject: [PATCH 12/20] Unexport newUserRedirect --- models/user.go | 2 +- models/user_redirect.go | 8 ++++---- models/user_redirect_test.go | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/models/user.go b/models/user.go index 4aa14ac2aaeec..6f5e90d522f3d 100644 --- a/models/user.go +++ b/models/user.go @@ -1009,7 +1009,7 @@ func ChangeUserName(u *User, newUserName string) (err error) { return fmt.Errorf("delete user redirect: %v", err) } - if err := NewUserRedirect(DBContext{sess}, u.ID, oldUserName, newUserName); err != nil { + if err := newUserRedirect(sess, u.ID, oldUserName, newUserName); err != nil { return err } diff --git a/models/user_redirect.go b/models/user_redirect.go index 60e2578b30ad9..a280b256e6b0e 100644 --- a/models/user_redirect.go +++ b/models/user_redirect.go @@ -25,16 +25,16 @@ func LookupUserRedirect(userName string) (int64, error) { return redirect.RedirectUserID, nil } -// NewUserRedirect create a new user redirect -func NewUserRedirect(ctx DBContext, ID int64, oldUserName, newUserName string) error { +// newUserRedirect create a new user redirect +func newUserRedirect(e Engine, ID int64, oldUserName, newUserName string) error { oldUserName = strings.ToLower(oldUserName) newUserName = strings.ToLower(newUserName) - if err := deleteUserRedirect(ctx.e, newUserName); err != nil { + if err := deleteUserRedirect(e, newUserName); err != nil { return err } - if _, err := ctx.e.Insert(&UserRedirect{ + if _, err := e.Insert(&UserRedirect{ LowerName: oldUserName, RedirectUserID: ID, }); err != nil { diff --git a/models/user_redirect_test.go b/models/user_redirect_test.go index eea2ac466958e..791c920bcf05d 100644 --- a/models/user_redirect_test.go +++ b/models/user_redirect_test.go @@ -26,7 +26,7 @@ func TestNewUserRedirect(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) user := AssertExistsAndLoadBean(t, &User{ID: 1}).(*User) - assert.NoError(t, NewUserRedirect(DefaultDBContext(), user.ID, user.Name, "newusername")) + assert.NoError(t, newUserRedirect(x, user.ID, user.Name, "newusername")) AssertExistsAndLoadBean(t, &UserRedirect{ LowerName: user.LowerName, @@ -43,7 +43,7 @@ func TestNewUserRedirect2(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) user := AssertExistsAndLoadBean(t, &User{ID: 1}).(*User) - assert.NoError(t, NewUserRedirect(DefaultDBContext(), user.ID, user.Name, "olduser1")) + assert.NoError(t, newUserRedirect(x, user.ID, user.Name, "olduser1")) AssertExistsAndLoadBean(t, &UserRedirect{ LowerName: user.LowerName, @@ -60,7 +60,7 @@ func TestNewUserRedirect3(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User) - assert.NoError(t, NewUserRedirect(DefaultDBContext(), user.ID, user.Name, "newusername")) + assert.NoError(t, newUserRedirect(x, user.ID, user.Name, "newusername")) AssertExistsAndLoadBean(t, &UserRedirect{ LowerName: user.LowerName, From adb0bcaa760a2286cc704b8d9ff06c67ea73acd6 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 23 Jan 2021 16:24:49 +0100 Subject: [PATCH 13/20] cleanup --- models/user_redirect.go | 2 +- routers/api/v1/api.go | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/models/user_redirect.go b/models/user_redirect.go index a280b256e6b0e..1da8b440888ea 100644 --- a/models/user_redirect.go +++ b/models/user_redirect.go @@ -13,7 +13,7 @@ type UserRedirect struct { RedirectUserID int64 // userID to redirect to } -// LookupUserRedirect look up if a user has a redirect name +// LookupUserRedirect look up userID if a user has a redirect name func LookupUserRedirect(userName string) (int64, error) { userName = strings.ToLower(userName) redirect := &UserRedirect{LowerName: userName} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 3a9693292aaf7..876f48ca5cca3 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -139,10 +139,10 @@ func repoAssignment() macaron.Handler { } else if models.IsErrUserRedirectNotExist(err) { ctx.NotFound("GetUserByName", err) } else { - ctx.ServerError("LookupUserRedirect", err) + ctx.Error(http.StatusInternalServerError, "LookupUserRedirect", err) } } else { - ctx.ServerError("GetUserByName", err) + ctx.Error(http.StatusInternalServerError, "GetUserByName", err) } return } @@ -159,10 +159,10 @@ func repoAssignment() macaron.Handler { } else if models.IsErrRepoRedirectNotExist(err) { ctx.NotFound() } else { - ctx.ServerError("LookupRepoRedirect", err) + ctx.Error(http.StatusInternalServerError, "LookupRepoRedirect", err) } } else { - ctx.ServerError("GetRepositoryByName", err) + ctx.Error(http.StatusInternalServerError, "GetRepositoryByName", err) } return } @@ -405,10 +405,10 @@ func orgAssignment(args ...bool) macaron.Handler { } else if models.IsErrUserRedirectNotExist(err) { ctx.NotFound("GetOrgByName", err) } else { - ctx.ServerError("LookupUserRedirect", err) + ctx.Error(http.StatusInternalServerError, "LookupUserRedirect", err) } } else { - ctx.ServerError("GetOrgByName", err) + ctx.Error(http.StatusInternalServerError, "GetOrgByName", err) } return } From 690953542ff453e58a0091c2a45021b2c67505aa Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 23 Jan 2021 16:41:46 +0100 Subject: [PATCH 14/20] Fix & Dedub API code --- routers/api/v1/user/helper.go | 36 +++++++++++++++++++++++++++++++++++ routers/api/v1/user/key.go | 23 ---------------------- routers/api/v1/user/user.go | 27 ++++---------------------- 3 files changed, 40 insertions(+), 46 deletions(-) create mode 100644 routers/api/v1/user/helper.go diff --git a/routers/api/v1/user/helper.go b/routers/api/v1/user/helper.go new file mode 100644 index 0000000000000..fcdac257edc8d --- /dev/null +++ b/routers/api/v1/user/helper.go @@ -0,0 +1,36 @@ +// Copyright 2021 The Gitea Authors. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package user + +import ( + "net/http" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/context" +) + +// GetUserByParamsName get user by name +func GetUserByParamsName(ctx *context.APIContext, name string) *models.User { + username := ctx.Params(name) + user, err := models.GetUserByName(username) + if err != nil { + if models.IsErrUserNotExist(err) { + if redirectUserID, err := models.LookupUserRedirect(username); err == nil { + context.RedirectToUser(ctx.Context, username, redirectUserID) + } else { + ctx.NotFound("GetUserByName", err) + } + } else { + ctx.Error(http.StatusInternalServerError, "GetUserByName", err) + } + return nil + } + return user +} + +// GetUserByParams returns user whose name is presented in URL (":username"). +func GetUserByParams(ctx *context.APIContext) *models.User { + return GetUserByParamsName(ctx, ":username") +} diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go index 64b4e571f49dd..fa16df1836350 100644 --- a/routers/api/v1/user/key.go +++ b/routers/api/v1/user/key.go @@ -39,29 +39,6 @@ func appendPrivateInformation(apiKey *api.PublicKey, key *models.PublicKey, defa return apiKey, nil } -// GetUserByParamsName get user by name -func GetUserByParamsName(ctx *context.APIContext, name string) *models.User { - user, err := models.GetUserByName(name) - if err != nil { - if models.IsErrUserNotExist(err) { - if redirectUserID, err := models.LookupUserRedirect(name); err == nil { - context.RedirectToUser(ctx.Context, name, redirectUserID) - } else { - ctx.NotFound("GetUserByName", err) - } - } else { - ctx.ServerError("GetUserByName", err) - } - return nil - } - return user -} - -// GetUserByParams returns user whose name is presented in URL paramenter. -func GetUserByParams(ctx *context.APIContext) *models.User { - return GetUserByParamsName(ctx, ctx.Params(":username")) -} - func composePublicKeysAPILink() string { return setting.AppURL + "api/v1/user/keys/" } diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go index ac418f37994f3..ecc149fe52d32 100644 --- a/routers/api/v1/user/user.go +++ b/routers/api/v1/user/user.go @@ -107,17 +107,8 @@ func GetInfo(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - u, err := models.GetUserByName(ctx.Params(":username")) - if err != nil { - if models.IsErrUserNotExist(err) { - if redirectUserID, err := models.LookupUserRedirect(ctx.Params(":username")); err == nil { - context.RedirectToUser(ctx.Context, ctx.Params(":username"), redirectUserID) - } else { - ctx.NotFound("GetUserByName", err) - } - } else { - ctx.ServerError("GetUserByName", err) - } + u := GetUserByParams(ctx) + if ctx.Written() { return } @@ -157,18 +148,8 @@ func GetUserHeatmapData(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - // Get the user to throw an error if it does not exist - user, err := models.GetUserByName(ctx.Params(":username")) - if err != nil { - if models.IsErrUserNotExist(err) { - if redirectUserID, err := models.LookupUserRedirect(ctx.Params(":username")); err == nil { - context.RedirectToUser(ctx.Context, ctx.Params(":username"), redirectUserID) - } else { - ctx.NotFound("GetUserByName", err) - } - } else { - ctx.ServerError("GetUserByName", err) - } + user := GetUserByParams(ctx) + if ctx.Written() { return } From 68c7c786ca33a45ef964d268e321a43ead24f93d Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 23 Jan 2021 16:47:05 +0100 Subject: [PATCH 15/20] Format Template --- templates/org/settings/options.tmpl | 6 ++++-- templates/user/settings/profile.tmpl | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/templates/org/settings/options.tmpl b/templates/org/settings/options.tmpl index 7ce7545d9b7e2..09bf5e0caa16e 100644 --- a/templates/org/settings/options.tmpl +++ b/templates/org/settings/options.tmpl @@ -13,8 +13,10 @@ {{.CsrfTokenHtml}}
- +
diff --git a/templates/user/settings/profile.tmpl b/templates/user/settings/profile.tmpl index d4ee63873d85e..ee3cc589041a8 100644 --- a/templates/user/settings/profile.tmpl +++ b/templates/user/settings/profile.tmpl @@ -11,8 +11,10 @@ {{.CsrfTokenHtml}}
- + {{if not .SignedUser.IsLocal}}

{{$.i18n.Tr "settings.password_username_disabled"}}

From 51f1194e19e3fbd0f56de158e9393164bdd7461e Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 23 Jan 2021 16:58:37 +0100 Subject: [PATCH 16/20] Add Migration & rm dublicat --- models/migrations/migrations.go | 2 ++ models/migrations/v167.go | 24 ++++++++++++++++++++++++ models/user.go | 7 +------ 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 models/migrations/v167.go diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index f62bba2a71906..3227f6f75451b 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -279,6 +279,8 @@ var migrations = []Migration{ NewMigration("Convert hook task type from char(16) to varchar(16) and trim the column", convertHookTaskTypeToVarcharAndTrim), // v166 -> v167 NewMigration("Where Password is Valid with Empty String delete it", recalculateUserEmptyPWD), + // v167 -> v168 + NewMigration("Add user redirect", addUserRedirect), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v167.go b/models/migrations/v167.go new file mode 100644 index 0000000000000..fd91f226abbd9 --- /dev/null +++ b/models/migrations/v167.go @@ -0,0 +1,24 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package migrations + +import ( + "fmt" + + "xorm.io/xorm" +) + +func addUserRedirect(x *xorm.Engine) (err error) { + type UserRedirect struct { + ID int64 `xorm:"pk autoincr"` + LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"` + RedirectUserID int64 + } + + if err := x.Sync2(new(UserRedirect)); err != nil { + return fmt.Errorf("Sync2: %v", err) + } + return nil +} diff --git a/models/user.go b/models/user.go index 6f5e90d522f3d..d0a4e88ef9798 100644 --- a/models/user.go +++ b/models/user.go @@ -1004,12 +1004,7 @@ func ChangeUserName(u *User, newUserName string) (err error) { return fmt.Errorf("Rename user directory: %v", err) } - // If there was previously a redirect at this location, remove it. - if err = deleteUserRedirect(sess, newUserName); err != nil { - return fmt.Errorf("delete user redirect: %v", err) - } - - if err := newUserRedirect(sess, u.ID, oldUserName, newUserName); err != nil { + if err = newUserRedirect(sess, u.ID, oldUserName, newUserName); err != nil { return err } From 10d3ec95b51a4715c4f11ee2b1de15603eaf481a Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 23 Jan 2021 17:38:55 +0100 Subject: [PATCH 17/20] Refactor: unexport newRepoRedirect() & rm dedub del exec --- models/repo.go | 11 +++-------- models/repo_redirect.go | 8 ++++---- models/repo_redirect_test.go | 6 +++--- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/models/repo.go b/models/repo.go index b11671e1fc09b..62d64fbee9183 100644 --- a/models/repo.go +++ b/models/repo.go @@ -1312,8 +1312,8 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error return fmt.Errorf("delete repo redirect: %v", err) } - if err := NewRepoRedirect(DBContext{sess}, oldOwner.ID, repo.ID, repo.Name, repo.Name); err != nil { - return fmt.Errorf("NewRepoRedirect: %v", err) + if err := newRepoRedirect(sess, oldOwner.ID, repo.ID, repo.Name, repo.Name); err != nil { + return fmt.Errorf("newRepoRedirect: %v", err) } return sess.Commit() @@ -1361,12 +1361,7 @@ func ChangeRepositoryName(doer *User, repo *Repository, newRepoName string) (err return fmt.Errorf("sess.Begin: %v", err) } - // If there was previously a redirect at this location, remove it. - if err = deleteRepoRedirect(sess, repo.OwnerID, newRepoName); err != nil { - return fmt.Errorf("delete repo redirect: %v", err) - } - - if err := NewRepoRedirect(DBContext{sess}, repo.Owner.ID, repo.ID, oldRepoName, newRepoName); err != nil { + if err := newRepoRedirect(sess, repo.Owner.ID, repo.ID, oldRepoName, newRepoName); err != nil { return err } diff --git a/models/repo_redirect.go b/models/repo_redirect.go index 182b6b41a2cf7..afbfeb499e11a 100644 --- a/models/repo_redirect.go +++ b/models/repo_redirect.go @@ -28,16 +28,16 @@ func LookupRepoRedirect(ownerID int64, repoName string) (int64, error) { return redirect.RedirectRepoID, nil } -// NewRepoRedirect create a new repo redirect -func NewRepoRedirect(ctx DBContext, ownerID, repoID int64, oldRepoName, newRepoName string) error { +// newRepoRedirect create a new repo redirect +func newRepoRedirect(e Engine, ownerID, repoID int64, oldRepoName, newRepoName string) error { oldRepoName = strings.ToLower(oldRepoName) newRepoName = strings.ToLower(newRepoName) - if err := deleteRepoRedirect(ctx.e, ownerID, newRepoName); err != nil { + if err := deleteRepoRedirect(e, ownerID, newRepoName); err != nil { return err } - if _, err := ctx.e.Insert(&RepoRedirect{ + if _, err := e.Insert(&RepoRedirect{ OwnerID: ownerID, LowerName: oldRepoName, RedirectRepoID: repoID, diff --git a/models/repo_redirect_test.go b/models/repo_redirect_test.go index 44ec2b4e942b6..4c3184a0fd479 100644 --- a/models/repo_redirect_test.go +++ b/models/repo_redirect_test.go @@ -26,7 +26,7 @@ func TestNewRepoRedirect(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) - assert.NoError(t, NewRepoRedirect(DefaultDBContext(), repo.OwnerID, repo.ID, repo.Name, "newreponame")) + assert.NoError(t, newRepoRedirect(x, repo.OwnerID, repo.ID, repo.Name, "newreponame")) AssertExistsAndLoadBean(t, &RepoRedirect{ OwnerID: repo.OwnerID, @@ -45,7 +45,7 @@ func TestNewRepoRedirect2(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) - assert.NoError(t, NewRepoRedirect(DefaultDBContext(), repo.OwnerID, repo.ID, repo.Name, "oldrepo1")) + assert.NoError(t, newRepoRedirect(x, repo.OwnerID, repo.ID, repo.Name, "oldrepo1")) AssertExistsAndLoadBean(t, &RepoRedirect{ OwnerID: repo.OwnerID, @@ -64,7 +64,7 @@ func TestNewRepoRedirect3(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) repo := AssertExistsAndLoadBean(t, &Repository{ID: 2}).(*Repository) - assert.NoError(t, NewRepoRedirect(DefaultDBContext(), repo.OwnerID, repo.ID, repo.Name, "newreponame")) + assert.NoError(t, newRepoRedirect(x, repo.OwnerID, repo.ID, repo.Name, "newreponame")) AssertExistsAndLoadBean(t, &RepoRedirect{ OwnerID: repo.OwnerID, From 4c7f0f0ffd5ad086f283af3d097e3e1c63e3bd3b Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sun, 24 Jan 2021 00:59:18 +0100 Subject: [PATCH 18/20] if this fails we'll need to re-rename the user directory --- models/user.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/models/user.go b/models/user.go index d0a4e88ef9798..6667346eeb87f 100644 --- a/models/user.go +++ b/models/user.go @@ -1008,7 +1008,14 @@ func ChangeUserName(u *User, newUserName string) (err error) { return err } - return sess.Commit() + if err = sess.Commit(); err != nil { + if err2 := os.Rename(UserPath(newUserName), UserPath(oldUserName)); err2 != nil && !os.IsNotExist(err2) { + return err2 + } + return err + } + + return nil } // checkDupEmail checks whether there are the same email with the user From 7d3849fea5591fe0a8b81fdc0abb8df56e37e1ec Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sun, 24 Jan 2021 01:10:34 +0100 Subject: [PATCH 19/20] fmt --- models/user.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/user.go b/models/user.go index 6667346eeb87f..c1df2e48b2c9d 100644 --- a/models/user.go +++ b/models/user.go @@ -1014,7 +1014,7 @@ func ChangeUserName(u *User, newUserName string) (err error) { } return err } - + return nil } From f11bb7ef481d47deab163209f99ce825e5b9af1f Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sun, 24 Jan 2021 12:37:46 +0100 Subject: [PATCH 20/20] Update models/user.go Co-authored-by: zeripath --- models/user.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/models/user.go b/models/user.go index c1df2e48b2c9d..8147c9f62610b 100644 --- a/models/user.go +++ b/models/user.go @@ -1010,7 +1010,8 @@ func ChangeUserName(u *User, newUserName string) (err error) { if err = sess.Commit(); err != nil { if err2 := os.Rename(UserPath(newUserName), UserPath(oldUserName)); err2 != nil && !os.IsNotExist(err2) { - return err2 + log.Critical("Unable to rollback directory change during failed username change from: %s to: %s. DB Error: %v. Filesystem Error: %v", oldUserName, newUserName, err, err2) + return fmt.Errorf("failed to rollback directory change during failed username change from: %s to: %s. DB Error: %w. Filesystem Error: %v", oldUserName, newUserName, err, err2) } return err }