Files
pocket-id/backend/internal/controller/user_group_controller.go
2026-07-10 16:31:45 -05:00

162 lines
5.7 KiB
Go

package controller
import (
"context"
"net/http"
"github.com/danielgtaylor/huma/v2"
"github.com/pocket-id/pocket-id/backend/internal/dto"
"github.com/pocket-id/pocket-id/backend/internal/middleware"
"github.com/pocket-id/pocket-id/backend/internal/service"
"github.com/pocket-id/pocket-id/backend/internal/utils"
httpapi "github.com/pocket-id/pocket-id/backend/internal/utils/huma"
)
type userGroupListInput struct {
utils.ListRequestOptions
Search string `query:"search" required:"false"`
}
type userGroupIDInput struct {
ID string `path:"id"`
}
type userGroupCreateInput struct {
Body dto.UserGroupCreateDto
}
type userGroupUpdateInput struct {
ID string `path:"id"`
Body dto.UserGroupCreateDto
}
type userGroupUsersInput struct {
ID string `path:"id"`
Body dto.UserGroupUpdateUsersDto
}
type userGroupClientsInput struct {
ID string `path:"id"`
Body dto.UserGroupUpdateAllowedOidcClientsDto
}
// NewUserGroupController registers user group management routes
func NewUserGroupController(api huma.API, authMiddleware *middleware.AuthMiddleware, userGroupService *service.UserGroupService) {
controller := &UserGroupController{UserGroupService: userGroupService}
auth := authMiddleware.Huma(api)
listOperation := userGroupOperation("list-user-groups", http.MethodGet, "/api/user-groups", "List user groups")
auth(&listOperation)
httpapi.Register(api, listOperation, controller.list)
getOperation := userGroupOperation("get-user-group", http.MethodGet, "/api/user-groups/{id}", "Get user group by ID")
auth(&getOperation)
httpapi.Register(api, getOperation, controller.get)
createOperation := userGroupOperation("create-user-group", http.MethodPost, "/api/user-groups", "Create user group")
createOperation.DefaultStatus = http.StatusCreated
auth(&createOperation)
httpapi.Register(api, createOperation, controller.create)
updateOperation := userGroupOperation("update-user-group", http.MethodPut, "/api/user-groups/{id}", "Update user group")
auth(&updateOperation)
httpapi.Register(api, updateOperation, controller.update)
deleteOperation := userGroupOperation("delete-user-group", http.MethodDelete, "/api/user-groups/{id}", "Delete user group")
deleteOperation.DefaultStatus = http.StatusNoContent
auth(&deleteOperation)
httpapi.Register(api, deleteOperation, controller.delete)
usersOperation := userGroupOperation("update-user-group-users", http.MethodPut, "/api/user-groups/{id}/users", "Update users in a group")
auth(&usersOperation)
httpapi.Register(api, usersOperation, controller.updateUsers)
clientsOperation := userGroupOperation("update-user-group-allowed-oidc-clients", http.MethodPut, "/api/user-groups/{id}/allowed-oidc-clients", "Update allowed OIDC clients")
auth(&clientsOperation)
httpapi.Register(api, clientsOperation, controller.updateAllowedOIDCClients)
}
func userGroupOperation(id, method, path, summary string) huma.Operation {
return huma.Operation{OperationID: id, Method: method, Path: path, Summary: summary, Tags: []string{"User Groups"}}
}
type UserGroupController struct {
UserGroupService *service.UserGroupService
}
func (ugc *UserGroupController) list(ctx context.Context, input *userGroupListInput) (*httpapi.BodyOutput[dto.Paginated[dto.UserGroupMinimalDto]], error) {
groups, pagination, err := ugc.UserGroupService.List(ctx, input.Search, input.ListRequestOptions)
if err != nil {
return nil, err
}
groupsDTO := make([]dto.UserGroupMinimalDto, len(groups))
for i, group := range groups {
if err := dto.MapStruct(group, &groupsDTO[i]); err != nil {
return nil, err
}
groupsDTO[i].UserCount, err = ugc.UserGroupService.GetUserCountOfGroup(ctx, group.ID)
if err != nil {
return nil, err
}
}
return &httpapi.BodyOutput[dto.Paginated[dto.UserGroupMinimalDto]]{Body: dto.Paginated[dto.UserGroupMinimalDto]{Data: groupsDTO, Pagination: pagination}}, nil
}
func (ugc *UserGroupController) get(ctx context.Context, input *userGroupIDInput) (*httpapi.BodyOutput[dto.UserGroupDto], error) {
group, err := ugc.UserGroupService.Get(ctx, input.ID)
if err != nil {
return nil, err
}
return mapUserGroup(group)
}
func (ugc *UserGroupController) create(ctx context.Context, input *userGroupCreateInput) (*httpapi.BodyOutput[dto.UserGroupDto], error) {
group, err := ugc.UserGroupService.Create(ctx, input.Body)
if err != nil {
return nil, err
}
return mapUserGroup(group)
}
func (ugc *UserGroupController) update(ctx context.Context, input *userGroupUpdateInput) (*httpapi.BodyOutput[dto.UserGroupDto], error) {
group, err := ugc.UserGroupService.Update(ctx, input.ID, input.Body)
if err != nil {
return nil, err
}
return mapUserGroup(group)
}
func (ugc *UserGroupController) delete(ctx context.Context, input *userGroupIDInput) (*httpapi.EmptyOutput, error) {
if err := ugc.UserGroupService.Delete(ctx, input.ID); err != nil {
return nil, err
}
return &httpapi.EmptyOutput{}, nil
}
func (ugc *UserGroupController) updateUsers(ctx context.Context, input *userGroupUsersInput) (*httpapi.BodyOutput[dto.UserGroupDto], error) {
group, err := ugc.UserGroupService.UpdateUsers(ctx, input.ID, input.Body.UserIDs)
if err != nil {
return nil, err
}
return mapUserGroup(group)
}
func (ugc *UserGroupController) updateAllowedOIDCClients(ctx context.Context, input *userGroupClientsInput) (*httpapi.BodyOutput[dto.UserGroupDto], error) {
group, err := ugc.UserGroupService.UpdateAllowedOidcClient(ctx, input.ID, input.Body)
if err != nil {
return nil, err
}
return mapUserGroup(group)
}
func mapUserGroup(group any) (*httpapi.BodyOutput[dto.UserGroupDto], error) {
var output dto.UserGroupDto
if err := dto.MapStruct(group, &output); err != nil {
return nil, err
}
return &httpapi.BodyOutput[dto.UserGroupDto]{Body: output}, nil
}