fix(auth): allow admins to change any username including their own
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m6s
ci / ts / ts (packages + web) (push) Successful in 2m59s
ci / api / api (push) Successful in 49s
ci / db / db (push) Successful in 1m17s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m25s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m6s
ci / ts / ts (packages + web) (push) Successful in 2m59s
ci / api / api (push) Successful in 49s
ci / db / db (push) Successful in 1m17s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m25s
This commit is contained in:
1 parent
b0cbd0f149
commit
c34272d508
16 files changed
+431
-266
No files matched your search
@@ -150,13 +150,14 @@ func displayName(s string) (*string, error) {
|
||||
|
||||
// UserPatch — изменения пользователя из админки. nil — не менять.
|
||||
type UserPatch struct {
|
||||
Username *string
|
||||
DisplayName *string
|
||||
Role *Role
|
||||
IsBlocked *bool
|
||||
ReviewsUploads *bool
|
||||
}
|
||||
|
||||
// UpdateUser меняет имя, роль и блокировку с проверкой прав по каждому изменению.
|
||||
// UpdateUser меняет логин, имя, роль и блокировку с проверкой прав по каждому изменению.
|
||||
func (s *Service) UpdateUser(ctx context.Context, p Principal, id uuid.UUID, patch UserPatch) (User, error) {
|
||||
if patch.Role != nil && !patch.Role.Valid() {
|
||||
return User{}, apperr.Validation("role", CodeRoleInvalid, "unknown role", nil)
|
||||
@@ -178,6 +179,19 @@ func (s *Service) UpdateUser(ctx context.Context, p Principal, id uuid.UUID, pat
|
||||
})
|
||||
}
|
||||
|
||||
if patch.Username != nil {
|
||||
if p.Role != RoleAdmin {
|
||||
return forbidden()
|
||||
}
|
||||
username := NormalizeUsername(*patch.Username)
|
||||
if err := ValidateUsername("username", username); err != nil {
|
||||
return err
|
||||
}
|
||||
if username != target.Username {
|
||||
upd.Username = &username
|
||||
audit("user.username_change", map[string]any{"from": target.Username, "to": username})
|
||||
}
|
||||
}
|
||||
if patch.DisplayName != nil {
|
||||
if !CanManageUser(actor, tgt, UserEdit) {
|
||||
return forbidden()
|
||||
@@ -247,6 +261,9 @@ func (s *Service) UpdateUser(ctx context.Context, p Principal, id uuid.UUID, pat
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if errors.Is(err, ErrUsernameTaken) {
|
||||
return User{}, apperr.Validation("username", CodeUsernameTaken, "username is taken", nil)
|
||||
}
|
||||
return out, err
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user