Reviewing the upload queue is now a per-user flag (reviews_uploads), not part of the admin role: several people can hold it, a moderator can have it, and an admin may not. Only admins grant or revoke it; existing admins keep it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
169 lines
4.9 KiB
Go
169 lines
4.9 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
|
|
"pipu/api/internal/api/gen"
|
|
)
|
|
|
|
// ListUsers реализует gen.StrictServerInterface.
|
|
func (h *Handler) ListUsers(ctx context.Context, req gen.ListUsersRequestObject) (gen.ListUsersResponseObject, error) {
|
|
p, err := principal(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var (
|
|
q, cursor string
|
|
role *Role
|
|
)
|
|
if req.Params.Q != nil {
|
|
q = *req.Params.Q
|
|
}
|
|
if req.Params.Cursor != nil {
|
|
cursor = *req.Params.Cursor
|
|
}
|
|
if req.Params.Role != nil {
|
|
r := Role(*req.Params.Role)
|
|
role = &r
|
|
}
|
|
users, next, err := h.svc.ListUsers(ctx, p, q, role, cursor, req.Params.Limit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
items := make([]gen.AdminUser, 0, len(users))
|
|
for _, u := range users {
|
|
items = append(items, AdminUserDTO(u))
|
|
}
|
|
return gen.ListUsers200JSONResponse{Items: items, NextCursor: optional(next)}, nil
|
|
}
|
|
|
|
// CreateUser реализует gen.StrictServerInterface.
|
|
func (h *Handler) CreateUser(ctx context.Context, req gen.CreateUserRequestObject) (gen.CreateUserResponseObject, error) {
|
|
p, err := principal(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
in := CreateUserInput{Username: req.Body.Username, Role: Role(req.Body.Role)}
|
|
if req.Body.ReviewsUploads != nil {
|
|
in.ReviewsUploads = *req.Body.ReviewsUploads
|
|
}
|
|
if req.Body.DisplayName != nil {
|
|
in.DisplayName = *req.Body.DisplayName
|
|
}
|
|
u, password, err := h.svc.CreateUser(ctx, p, in)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return gen.CreateUser201JSONResponse{User: AdminUserDTO(u), TemporaryPassword: password}, nil
|
|
}
|
|
|
|
// UpdateUser реализует gen.StrictServerInterface.
|
|
func (h *Handler) UpdateUser(ctx context.Context, req gen.UpdateUserRequestObject) (gen.UpdateUserResponseObject, error) {
|
|
p, err := principal(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
patch := UserPatch{DisplayName: req.Body.DisplayName, IsBlocked: req.Body.IsBlocked, ReviewsUploads: req.Body.ReviewsUploads}
|
|
if req.Body.Role != nil {
|
|
r := Role(*req.Body.Role)
|
|
patch.Role = &r
|
|
}
|
|
u, err := h.svc.UpdateUser(ctx, p, req.Id, patch)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return gen.UpdateUser200JSONResponse(AdminUserDTO(u)), nil
|
|
}
|
|
|
|
// DeleteUser реализует gen.StrictServerInterface.
|
|
func (h *Handler) DeleteUser(ctx context.Context, req gen.DeleteUserRequestObject) (gen.DeleteUserResponseObject, error) {
|
|
p, err := principal(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := h.svc.DeleteUser(ctx, p, req.Id); err != nil {
|
|
return nil, err
|
|
}
|
|
return gen.DeleteUser204Response{}, nil
|
|
}
|
|
|
|
// ResetUserPassword реализует gen.StrictServerInterface.
|
|
func (h *Handler) ResetUserPassword(ctx context.Context, req gen.ResetUserPasswordRequestObject) (gen.ResetUserPasswordResponseObject, error) {
|
|
p, err := principal(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
password, err := h.svc.ResetPassword(ctx, p, req.Id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return gen.ResetUserPassword200JSONResponse{TemporaryPassword: password}, nil
|
|
}
|
|
|
|
// ResetUserRecommendations реализует gen.StrictServerInterface.
|
|
func (h *Handler) ResetUserRecommendations(ctx context.Context, req gen.ResetUserRecommendationsRequestObject) (gen.ResetUserRecommendationsResponseObject, error) {
|
|
p, err := principal(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := h.svc.ResetRecommendations(ctx, p, req.Id); err != nil {
|
|
return nil, err
|
|
}
|
|
return gen.ResetUserRecommendations204Response{}, nil
|
|
}
|
|
|
|
// ListAudit реализует gen.StrictServerInterface.
|
|
func (h *Handler) ListAudit(ctx context.Context, req gen.ListAuditRequestObject) (gen.ListAuditResponseObject, error) {
|
|
p, err := principal(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cursor := ""
|
|
if req.Params.Cursor != nil {
|
|
cursor = *req.Params.Cursor
|
|
}
|
|
records, next, err := h.svc.ListAudit(ctx, p, cursor, req.Params.Limit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
items := make([]gen.AuditEntry, 0, len(records))
|
|
for _, r := range records {
|
|
e := gen.AuditEntry{
|
|
Id: r.ID, Action: r.Action, TargetType: r.TargetType, TargetId: r.TargetID, CreatedAt: r.CreatedAt,
|
|
}
|
|
if r.ActorID != nil && r.ActorUsername != nil {
|
|
e.Actor = &gen.AuditActor{Id: *r.ActorID, Username: *r.ActorUsername}
|
|
}
|
|
if r.Payload != nil {
|
|
payload := r.Payload
|
|
e.Payload = &payload
|
|
}
|
|
items = append(items, e)
|
|
}
|
|
return gen.ListAudit200JSONResponse{Items: items, NextCursor: optional(next)}, nil
|
|
}
|
|
|
|
// AdminUserDTO переводит пользователя в схему AdminUser.
|
|
func AdminUserDTO(u User) gen.AdminUser {
|
|
return gen.AdminUser{
|
|
Id: u.ID,
|
|
Username: u.Username,
|
|
DisplayName: u.DisplayName,
|
|
Role: gen.Role(u.Role),
|
|
ReviewsUploads: u.ReviewsUploads,
|
|
Locale: u.Locale,
|
|
IsBlocked: u.IsBlocked,
|
|
MustChangePassword: u.MustChangePassword,
|
|
MustChangeCredentials: u.MustChangeCredentials,
|
|
CreatedAt: u.CreatedAt,
|
|
LastLoginAt: u.LastLoginAt,
|
|
}
|
|
}
|
|
|
|
func optional(s string) *string {
|
|
if s == "" {
|
|
return nil
|
|
}
|
|
return &s
|
|
}
|