feat(users): admin promote/demote endpoints
POST /users/{id}/promote and /demote set a user's role (admin/user), admin-only
(403 otherwise). Mirrors the verify endpoints: SetRole use case + repo method,
validated role. Unit, admin-flow, and integration tests included.
This commit is contained in:
@@ -32,6 +32,9 @@ func (s stubRepo) GetByID(context.Context, uuid.UUID) (*domain.User, error) {
|
||||
func (s stubRepo) SetVerified(context.Context, uuid.UUID, bool) error {
|
||||
return usecase.ErrUserNotFound
|
||||
}
|
||||
func (s stubRepo) SetRole(context.Context, uuid.UUID, domain.Role) error {
|
||||
return usecase.ErrUserNotFound
|
||||
}
|
||||
|
||||
type stubHasher struct {
|
||||
hashErr error
|
||||
|
||||
@@ -15,4 +15,5 @@ var (
|
||||
ErrInvalidCredentials = errors.New("invalid email or password")
|
||||
ErrPasswordTooShort = errors.New("password too short")
|
||||
ErrPasswordTooLong = errors.New("password too long")
|
||||
ErrInvalidRole = errors.New("invalid role")
|
||||
)
|
||||
|
||||
@@ -25,6 +25,9 @@ type UserRepository interface {
|
||||
// SetVerified toggles the verified flag, returning ErrUserNotFound if no
|
||||
// such user exists.
|
||||
SetVerified(ctx context.Context, id uuid.UUID, verified bool) error
|
||||
// SetRole changes a user's role, returning ErrUserNotFound if no such user
|
||||
// exists.
|
||||
SetRole(ctx context.Context, id uuid.UUID, role domain.Role) error
|
||||
}
|
||||
|
||||
// PasswordHasher hashes and verifies passwords. The bcrypt adapter satisfies it.
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package usecase
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/emil28092005/SciMesh/users/internal/domain"
|
||||
)
|
||||
|
||||
// SetRole promotes or demotes a user. Only an admin may call this (enforced in
|
||||
// the transport layer); the use case validates the target role and applies it.
|
||||
type SetRole struct {
|
||||
users UserRepository
|
||||
}
|
||||
|
||||
func NewSetRole(users UserRepository) *SetRole {
|
||||
return &SetRole{users: users}
|
||||
}
|
||||
|
||||
// Execute assigns role to the user, returning ErrInvalidRole for an unknown role
|
||||
// or ErrUserNotFound if the user does not exist.
|
||||
func (uc *SetRole) Execute(ctx context.Context, id uuid.UUID, role domain.Role) error {
|
||||
if !role.Valid() {
|
||||
return ErrInvalidRole
|
||||
}
|
||||
return uc.users.SetRole(ctx, id, role)
|
||||
}
|
||||
Reference in New Issue
Block a user