satellite/admin: secure accidental user email change

It currently is possible to create a violation with regards to
the uniqueness of the user account emails that is used for the
login.
When an update via the admin API is made, it currently is possible
to set the accounts email to an already occupied email address.
This will result in very flacky login behaviour, as well as creating
a lot of other related issues.

This small change adds a check to ensure the email is not attached to
any account.

Change-Id: I167be673082d59ef32cafe41047fce9f5ae534d0
This commit is contained in:
Stefan Benten 2023-06-02 00:09:13 +02:00 committed by Storj Robot
parent 2e3ed973de
commit 11324111e3
2 changed files with 18 additions and 0 deletions

View File

@ -296,6 +296,17 @@ func (server *Server) updateUser(w http.ResponseWriter, r *http.Request) {
updateRequest.ShortName = &shortNamePtr updateRequest.ShortName = &shortNamePtr
} }
if input.Email != "" { if input.Email != "" {
existingUser, err := server.db.Console().Users().GetByEmail(ctx, input.Email)
if err != nil && !errors.Is(sql.ErrNoRows, err) {
sendJSONError(w, "failed to check for user email",
err.Error(), http.StatusInternalServerError)
return
}
if existingUser != nil {
sendJSONError(w, fmt.Sprintf("user with email already exists %s", input.Email),
"", http.StatusConflict)
return
}
updateRequest.Email = &input.Email updateRequest.Email = &input.Email
} }
if len(input.PasswordHash) > 0 { if len(input.PasswordHash) > 0 {

View File

@ -262,6 +262,13 @@ func TestUserUpdate(t *testing.T) {
responseBody := assertReq(ctx, t, link, http.MethodPut, body, http.StatusNotFound, "", planet.Satellites[0].Config.Console.AuthToken) responseBody := assertReq(ctx, t, link, http.MethodPut, body, http.StatusNotFound, "", planet.Satellites[0].Config.Console.AuthToken)
require.Contains(t, string(responseBody), "does not exist") require.Contains(t, string(responseBody), "does not exist")
}) })
t.Run("Email already used", func(t *testing.T) {
link := fmt.Sprintf("http://"+address.String()+"/api/users/%s", "alice+2@mail.test")
body := `{"email":"alice+2@mail.test", "shortName":"Newbie"}`
responseBody := assertReq(ctx, t, link, http.MethodPut, body, http.StatusConflict, "", planet.Satellites[0].Config.Console.AuthToken)
require.Contains(t, string(responseBody), "already exists")
})
}) })
} }