fix: don't drop oidc_id when updating users

This commit is contained in:
Jannis Mattheis
2026-07-24 11:01:31 +02:00
parent ad137d69ad
commit d09ea4e169
2 changed files with 33 additions and 16 deletions

View File

@@ -445,35 +445,32 @@ func (a *UserAPI) ChangePassword(ctx *gin.Context) {
// $ref: "#/definitions/Error"
func (a *UserAPI) UpdateUserByID(ctx *gin.Context) {
withID(ctx, "id", func(id uint) {
var user *model.UpdateUserExternal
if err := ctx.Bind(&user); err == nil {
oldUser, err := a.DB.GetUserByID(id)
var updatedUser *model.UpdateUserExternal
if err := ctx.Bind(&updatedUser); err == nil {
dbUser, err := a.DB.GetUserByID(id)
if success := successOrAbort(ctx, 500, err); !success {
return
}
if oldUser != nil {
if dbUser != nil {
adminCount, err := a.DB.CountUser(&model.User{Admin: true})
if success := successOrAbort(ctx, 500, err); !success {
return
}
if !user.Admin && oldUser.Admin && adminCount == 1 {
if !updatedUser.Admin && dbUser.Admin && adminCount == 1 {
ctx.AbortWithError(400, errors.New("cannot delete last admin"))
return
}
internal := &model.User{
ID: oldUser.ID,
Name: user.Name,
Admin: user.Admin,
Pass: oldUser.Pass,
CreatedAt: oldUser.CreatedAt,
dbUser.Name = updatedUser.Name
dbUser.Admin = updatedUser.Admin
if updatedUser.Pass != "" {
dbUser.Pass = password.CreatePassword(updatedUser.Pass, a.PasswordStrength)
}
if user.Pass != "" {
internal.Pass = password.CreatePassword(user.Pass, a.PasswordStrength)
}
if success := successOrAbort(ctx, 500, a.DB.UpdateUser(internal)); !success {
if success := successOrAbort(ctx, 500, a.DB.UpdateUser(dbUser)); !success {
return
}
ctx.JSON(200, toExternalUser(internal))
ctx.JSON(200, toExternalUser(dbUser))
} else {
ctx.AbortWithError(404, errors.New("user does not exist"))
}

View File

@@ -392,6 +392,26 @@ func (s *UserSuite) Test_UpdateUserByID_UpdatePassword() {
assert.True(s.T(), password.ComparePassword(user.Pass, []byte("new")))
}
func (s *UserSuite) Test_UpdateUserByID_PreservesOIDCID() {
oidcID := "https://issuer.example.com#subject"
s.db.CreateUser(&model.User{ID: 2, Name: "nico", OIDCID: &oidcID})
s.ctx.Params = gin.Params{{Key: "id", Value: "2"}}
s.ctx.Request = httptest.NewRequest("POST", "/user/2", strings.NewReader(`{"name": "tom", "pass": "", "admin": true}`))
s.ctx.Request.Header.Set("Content-Type", "application/json")
s.a.UpdateUserByID(s.ctx)
assert.Equal(s.T(), 200, s.recorder.Code)
user, err := s.db.GetUserByID(2)
assert.NoError(s.T(), err)
assert.NotNil(s.T(), user)
if assert.NotNil(s.T(), user.OIDCID) {
assert.Equal(s.T(), oidcID, *user.OIDCID)
}
}
func (s *UserSuite) Test_UpdatePassword() {
s.db.CreateUser(&model.User{ID: 1, Name: "jmattheis", Pass: password.CreatePassword("old", 5)})