mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
[MM-34725] app/user: check if username or email is in use before patching a user (#17392)
* app/user: check if username or email is in use before patching a user * reflect review comments * fix tests
This commit is contained in:
committed by
GitHub
parent
3ea75332e7
commit
3a13987ee1
@@ -178,11 +178,17 @@ func (a *App) PatchBot(botUserId string, botPatch *model.BotPatch) (*model.Bot,
|
||||
if nErr != nil {
|
||||
var appErr *model.AppError
|
||||
var invErr *store.ErrInvalidInput
|
||||
var conErr *store.ErrConflict
|
||||
switch {
|
||||
case errors.As(nErr, &appErr):
|
||||
return nil, appErr
|
||||
case errors.As(nErr, &invErr):
|
||||
return nil, model.NewAppError("PatchBot", "app.user.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
|
||||
return nil, model.NewAppError("PatchBot", "app.user.update.find.app_error", nil, nErr.Error(), http.StatusBadRequest)
|
||||
case errors.As(nErr, &conErr):
|
||||
if cErr, ok := nErr.(*store.ErrConflict); ok && cErr.Resource == "Username" {
|
||||
return nil, model.NewAppError("PatchBot", "app.user.save.username_exists.app_error", nil, nErr.Error(), http.StatusBadRequest)
|
||||
}
|
||||
return nil, model.NewAppError("PatchBot", "app.user.save.email_exists.app_error", nil, nErr.Error(), http.StatusBadRequest)
|
||||
default:
|
||||
return nil, model.NewAppError("PatchBot", "app.user.update.finding.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ func TestPatchBot(t *testing.T) {
|
||||
|
||||
_, err = th.App.PatchBot(bot.UserId, botPatch)
|
||||
require.NotNil(t, err)
|
||||
require.Equal(t, "app.user.update.find.app_error", err.Id)
|
||||
require.Equal(t, "app.user.save.username_exists.app_error", err.Id)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
18
app/user.go
18
app/user.go
@@ -1281,15 +1281,13 @@ func (a *App) UpdateUser(user *model.User, sendNotifications bool) (*model.User,
|
||||
}
|
||||
}
|
||||
|
||||
if _, appErr := a.GetUserByEmail(user.Email); appErr == nil {
|
||||
return nil, model.NewAppError("UpdateUser", "store.sql_user.update.email_taken.app_error", nil, "user_id="+user.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
// Don't set new eMail on user account if email verification is required, this will be done as a post-verification action
|
||||
// to avoid users being able to set non-controlled eMails as their account email
|
||||
|
||||
if *a.Config().EmailSettings.RequireEmailVerification {
|
||||
newEmail = user.Email
|
||||
// Don't set new eMail on user account if email verification is required, this will be done as a post-verification action
|
||||
// to avoid users being able to set non-controlled eMails as their account email
|
||||
if _, appErr := a.GetUserByEmail(newEmail); appErr == nil {
|
||||
return nil, model.NewAppError("UpdateUser", "app.user.save.email_exists.app_error", nil, "user_id="+user.Id, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
// When a bot is created, prev.Email will be an autogenerated faked email,
|
||||
// which will not match a CLI email input during bot to user conversions.
|
||||
@@ -1305,11 +1303,17 @@ func (a *App) UpdateUser(user *model.User, sendNotifications bool) (*model.User,
|
||||
if err != nil {
|
||||
var appErr *model.AppError
|
||||
var invErr *store.ErrInvalidInput
|
||||
var conErr *store.ErrConflict
|
||||
switch {
|
||||
case errors.As(err, &appErr):
|
||||
return nil, appErr
|
||||
case errors.As(err, &invErr):
|
||||
return nil, model.NewAppError("UpdateUser", "app.user.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
|
||||
case errors.As(err, &conErr):
|
||||
if cErr, ok := err.(*store.ErrConflict); ok && cErr.Resource == "Username" {
|
||||
return nil, model.NewAppError("UpdateUser", "app.user.save.username_exists.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
return nil, model.NewAppError("UpdateUser", "app.user.save.email_exists.app_error", nil, "", http.StatusBadRequest)
|
||||
default:
|
||||
return nil, model.NewAppError("UpdateUser", "app.user.update.finding.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
@@ -471,7 +471,7 @@ func TestUpdateUserEmail(t *testing.T) {
|
||||
user.Email = newEmail
|
||||
user3, err := th.App.UpdateUser(user, false)
|
||||
require.NotNil(t, err)
|
||||
assert.Equal(t, err.Id, "store.sql_user.update.email_taken.app_error")
|
||||
assert.Equal(t, err.Id, "app.user.save.email_exists.app_error")
|
||||
assert.Nil(t, user3)
|
||||
})
|
||||
|
||||
@@ -514,7 +514,7 @@ func TestUpdateUserEmail(t *testing.T) {
|
||||
user.Email = newEmail
|
||||
user3, err := th.App.UpdateUser(user, false)
|
||||
require.NotNil(t, err)
|
||||
assert.Equal(t, err.Id, "store.sql_user.update.email_taken.app_error")
|
||||
assert.Equal(t, err.Id, "app.user.save.email_exists.app_error")
|
||||
assert.Nil(t, user3)
|
||||
})
|
||||
}
|
||||
@@ -1457,3 +1457,37 @@ func TestDeactivateMfa(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPatchUser(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
testUser := th.CreateUser()
|
||||
defer th.App.PermanentDeleteUser(testUser)
|
||||
|
||||
t.Run("Patch with a username already exists", func(t *testing.T) {
|
||||
_, err := th.App.PatchUser(testUser.Id, &model.UserPatch{
|
||||
Username: model.NewString(th.BasicUser.Username),
|
||||
}, true)
|
||||
|
||||
require.NotNil(t, err)
|
||||
require.Equal(t, "app.user.save.username_exists.app_error", err.Id)
|
||||
})
|
||||
|
||||
t.Run("Patch with a email already exists", func(t *testing.T) {
|
||||
_, err := th.App.PatchUser(testUser.Id, &model.UserPatch{
|
||||
Email: model.NewString(th.BasicUser.Email),
|
||||
}, true)
|
||||
|
||||
require.NotNil(t, err)
|
||||
require.Equal(t, "app.user.save.email_exists.app_error", err.Id)
|
||||
})
|
||||
|
||||
t.Run("Patch username with a new username", func(t *testing.T) {
|
||||
_, err := th.App.PatchUser(testUser.Id, &model.UserPatch{
|
||||
Username: model.NewString(model.NewId()),
|
||||
}, true)
|
||||
|
||||
require.Nil(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -147,10 +147,6 @@
|
||||
"id": "system.message.name",
|
||||
"translation": "Система"
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "Тази ел.поща вече е заета. Моля, изберете друга."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "Не може да се намери съществуващ профил, отговарящ на вашите идентификационни данни. Този екип може да изисква покана от собственика на екипа, за да се присъедините."
|
||||
|
||||
@@ -4842,10 +4842,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "Konnte kein Konto mit den angegeben Zugangsdaten finden. Dieses Team erfordert eventuell eine Einladung vom Teambesitzer, um beizutreten."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "Diese E-Mail-Adresse wird bereits genutzt. Bitte eine andere wählen."
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "System"
|
||||
|
||||
@@ -9102,10 +9102,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "Unable to find an existing account matching your credentials. This team may require an invite from the team owner to join."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "This email is already taken. Please choose another."
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "System"
|
||||
|
||||
@@ -4842,10 +4842,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "No se puede encontrar una cuenta existente con tus credenciales. Es posible que requieras una invitación por parte del dueño del equipo para poder unirte."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "Este correo electrónico ya está siendo utilizado. Por favor escoge otro."
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "Sistema"
|
||||
|
||||
@@ -4842,10 +4842,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "Impossible de trouver un compte existant correspondant à vos identifiants. Cette équipe nécessite peut-être une invitation de la part du propriétaire pour pouvoir la rejoindre."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "Cette adresse e-mail est déjà utilisée. Veuillez en choisir une autre."
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "Système"
|
||||
|
||||
@@ -4842,10 +4842,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "Non è stato possibile trovare un account con le credenziali fornite. Potrebbe essere necessario disporre di un invito da parte del proprietario del gruppo per l'accesso."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "Questo indirizzo email è già in uso. Sceglierne un altro."
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "Sistema"
|
||||
|
||||
@@ -4837,10 +4837,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "あなたの認証情報に合致する既存のアカウントを見付けられませんでした。このチームに参加するには、チームのオーナーから招待を受ける必要があります。"
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "この電子メールアドレスは既に使用されています。他の電子メールアドレスを指定してください。"
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "システム"
|
||||
|
||||
@@ -4837,10 +4837,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "We couldn't find an existing account matching your credentials. This team may require an invite from the team owner to join."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "This email is already taken. Please choose another."
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "시스템"
|
||||
|
||||
@@ -4842,10 +4842,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "We kunnen geen bestaand account vinden met de gebruikersnaam voor dit team. Het kan zijn dat een uitnodiging voor het team nodig is om lid te worden."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "Dit e-mail adres is reeds in gebruik. Kies aub een andere."
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "Systeem"
|
||||
|
||||
@@ -4847,10 +4847,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "Nie można znaleźć istniejącego konta pasującego do poświadczeń. Ten zespół może wymagać zaproszenia od właściciela zespołu do dołączenia."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "Ten adres e-mail jest już zajęty. Proszę wybrać inny."
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "System"
|
||||
|
||||
@@ -4842,10 +4842,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "Não foi possível encontrar uma conta correspondente a suas credenciais. Esta equipe pode exigir um convite do dono da equipe para participar."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "Este email já foi utilizado. Por favor escolha outro."
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "Sistema"
|
||||
|
||||
@@ -4847,10 +4847,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "Nu s-a putut găsi un cont existent care să corespundă acreditărilor dvs. Această echipă poate solicita o invitație din partea proprietarului echipei să se alăture."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "Acest e-mail este deja luate. Vă rugăm să alegeţi o altă."
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "Sistem"
|
||||
|
||||
@@ -4847,10 +4847,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "Не удалось найти действительную учетную запись с соответствующими учетными данными. Эта команда может требовать приглашения от владельца команды для присоединения."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "Этот e-mail уже зарегистрирован, выберите другой."
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "Система"
|
||||
|
||||
@@ -147,10 +147,6 @@
|
||||
"id": "system.message.name",
|
||||
"translation": "System"
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "Den här e-postadressen används redan. Välj en annan."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "Kan inte hitta ett existerande konto som matchar din autentisering. Denna grupp kan behöva en inbjudan av ägaren till gruppen för att gå med."
|
||||
|
||||
@@ -4842,10 +4842,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "Bu takım için kimlik doğrulama bilgilerinizle eşleşen var olan bir hesap bulunamadı. Bu takıma katılmak için takım yöneticisinin çağrı göndermesi gerekiyor olabilir."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "Bu e-posta adresi zaten alınmış. Lütfen başka bir adres seçin."
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "Sistem"
|
||||
|
||||
@@ -4847,10 +4847,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "Не вдалося знайти дійсний обліковий запис з відповідними обліковими даними. Ця команда може вимагати запрошення від власника команди для приєднання."
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "Цей e-mail вже зареєстрований, виберіть інший."
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "Система"
|
||||
|
||||
@@ -4837,10 +4837,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "未找到符合您的凭证的帐号。此团队或许需要从团队拥有者获得邀请才可加入。"
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "该邮箱已被使用。请重新选择。"
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "系统"
|
||||
|
||||
@@ -4837,10 +4837,6 @@
|
||||
"id": "store.sql_user.get_for_login.app_error",
|
||||
"translation": "找不到符合您的認證之帳號,此團隊需要從團隊擁有者取得邀請才可加入。"
|
||||
},
|
||||
{
|
||||
"id": "store.sql_user.update.email_taken.app_error",
|
||||
"translation": "這個電子郵件已經被使用。請選擇其他的。"
|
||||
},
|
||||
{
|
||||
"id": "system.message.name",
|
||||
"translation": "系統"
|
||||
|
||||
@@ -210,10 +210,10 @@ func (us SqlUserStore) Update(user *model.User, trustedUpdateData bool) (*model.
|
||||
count, err := us.GetMaster().Update(user)
|
||||
if err != nil {
|
||||
if IsUniqueConstraintError(err, []string{"Email", "users_email_key", "idx_users_email_unique"}) {
|
||||
return nil, store.NewErrInvalidInput("User", "id", user.Id)
|
||||
return nil, store.NewErrConflict("Email", err, user.Email)
|
||||
}
|
||||
if IsUniqueConstraintError(err, []string{"Username", "users_username_key", "idx_users_username_unique"}) {
|
||||
return nil, store.NewErrInvalidInput("User", "id", user.Id)
|
||||
return nil, store.NewErrConflict("Username", err, user.Username)
|
||||
}
|
||||
return nil, errors.Wrapf(err, "failed to update User with userId=%s", user.Id)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user