diff --git a/internal/api/admin.go b/internal/api/admin.go index f8188d578..a7bce5fed 100644 --- a/internal/api/admin.go +++ b/internal/api/admin.go @@ -155,6 +155,14 @@ func (a *API) adminUserUpdate(w http.ResponseWriter, r *http.Request) error { if err != nil { return err } + + if params.Email != user.GetEmail() { + if user, err := models.IsDuplicatedEmail(db, params.Email, user.Aud, nil); err != nil { + return apierrors.NewInternalServerError("Database error checking email").WithInternalError(err) + } else if user != nil { + return apierrors.NewUnprocessableEntityError(apierrors.ErrorCodeEmailExists, DuplicateEmailMsg) + } + } } if params.Phone != "" { @@ -214,7 +222,7 @@ func (a *API) adminUserUpdate(w http.ResponseWriter, r *http.Request) error { } var identities []models.Identity - if params.Email != "" { + if params.Email != "" && user.GetEmail() != params.Email { if identity, terr := models.FindIdentityByIdAndProvider(tx, user.ID.String(), "email"); terr != nil && !models.IsNotFoundError(terr) { return terr } else if identity == nil { @@ -250,7 +258,7 @@ func (a *API) adminUserUpdate(w http.ResponseWriter, r *http.Request) error { } } - if params.Phone != "" { + if params.Phone != "" && user.GetPhone() != params.Phone { if identity, terr := models.FindIdentityByIdAndProvider(tx, user.ID.String(), "phone"); terr != nil && !models.IsNotFoundError(terr) { return terr } else if identity == nil { diff --git a/internal/api/admin_test.go b/internal/api/admin_test.go index c72694f78..d6dad3ada 100644 --- a/internal/api/admin_test.go +++ b/internal/api/admin_test.go @@ -494,6 +494,31 @@ func (ts *AdminTestSuite) TestAdminUserUpdate() { } } +func (ts *AdminTestSuite) TestAdminUserUpdateDuplicateEmailFailed() { + u1, err := models.NewUser("", "", "", ts.Config.JWT.Aud, nil) + require.NoError(ts.T(), err) + require.NoError(ts.T(), ts.API.db.Create(u1)) + + u2, err := models.NewUser("", "test@example.com", "test", ts.Config.JWT.Aud, nil) + require.NoError(ts.T(), err) + require.NoError(ts.T(), ts.API.db.Create(u2)) + + ts.Run("update user with duplicate email", func() { + var buffer bytes.Buffer + require.NoError(ts.T(), json.NewEncoder(&buffer).Encode(map[string]any{ + "email": u2.Email, + })) + + // Setup request + w := httptest.NewRecorder() + req := httptest.NewRequest(http.MethodPut, fmt.Sprintf("/admin/users/%s", u1.ID), &buffer) + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", ts.token)) + + ts.API.handler.ServeHTTP(w, req) + require.Equal(ts.T(), http.StatusUnprocessableEntity, w.Code) + }) +} + func (ts *AdminTestSuite) TestAdminUserUpdatePasswordFailed() { u, err := models.NewUser("12345678", "test1@example.com", "test", ts.Config.JWT.Aud, nil) require.NoError(ts.T(), err, "Error making new user")