package main import ( "context" "database/sql" "atlas9.dev/c/core" "atlas9.dev/c/core/dbi" "atlas9.dev/c/core/iam" "atlas9.dev/c/core/routes" ) type MemberApi struct { DB *sql.DB Members dbi.Factory[iam.MemberStore] } type AddMemberReq struct { GroupID core.ID UserID core.ID } type AddMemberRes struct{} type RemoveMemberReq struct { GroupID core.ID UserID core.ID } type RemoveMemberRes struct{} type ListMembersReq struct { GroupID core.ID Page core.PageReq } type ListMembersRes core.Page[core.ID] type ListUserGroupsReq struct { UserID core.ID Page core.PageReq } type ListUserGroupsRes core.Page[core.ID] func (s *MemberApi) Add(ctx context.Context, req AddMemberReq) (*AddMemberRes, error) { return dbi.ReadWrite(ctx, s.DB, func(tx dbi.DBI) (*AddMemberRes, error) { return &AddMemberRes{}, s.Members(tx).Add(ctx, req.GroupID, req.UserID) }) } func (s *MemberApi) Remove(ctx context.Context, req RemoveMemberReq) (*RemoveMemberRes, error) { return dbi.ReadWrite(ctx, s.DB, func(tx dbi.DBI) (*RemoveMemberRes, error) { return &RemoveMemberRes{}, s.Members(tx).Remove(ctx, req.GroupID, req.UserID) }) } func (s *MemberApi) ListMembers(ctx context.Context, req ListMembersReq) (*ListMembersRes, error) { page, err := dbi.ReadOnly(ctx, s.DB, func(tx dbi.DBI) (core.Page[core.ID], error) { return s.Members(tx).ListMembers(ctx, req.GroupID, req.Page) }) if err != nil { return nil, err } res := ListMembersRes(page) return &res, nil } func (s *MemberApi) ListUserGroups(ctx context.Context, req ListUserGroupsReq) (*ListUserGroupsRes, error) { page, err := dbi.ReadOnly(ctx, s.DB, func(tx dbi.DBI) (core.Page[core.ID], error) { return s.Members(tx).ListGroups(ctx, req.UserID, req.Page) }) if err != nil { return nil, err } res := ListUserGroupsRes(page) return &res, nil } func MemberRoutes(svc *MemberApi) []routes.Route { return []routes.Route{ routes.RPC("/members/add", svc.Add), routes.RPC("/members/remove", svc.Remove), routes.RPC("/members/list", svc.ListMembers), routes.RPC("/members/list-user-groups", svc.ListUserGroups), } }