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 TenantMemberApi struct { DB *sql.DB Members dbi.Factory[iam.TenantMemberStore] } type AddTenantMemberReq struct { TenantID core.ID UserID core.ID Status iam.MemberStatus } type AddTenantMemberRes struct{} type SetTenantMemberStatusReq struct { TenantID core.ID UserID core.ID Status iam.MemberStatus } type SetTenantMemberStatusRes struct{} type RemoveTenantMemberReq struct { TenantID core.ID UserID core.ID } type RemoveTenantMemberRes struct{} type GetTenantMemberReq struct { TenantID core.ID UserID core.ID } type ListTenantMembersReq struct { TenantID core.ID Page core.PageReq } type ListTenantMembersRes core.Page[iam.TenantMember] type ListUserTenantsReq struct { UserID core.ID Page core.PageReq } type ListUserTenantsRes core.Page[iam.TenantMember] func (s *TenantMemberApi) Add(ctx context.Context, req AddTenantMemberReq) (*AddTenantMemberRes, error) { return dbi.ReadWrite(ctx, s.DB, func(tx dbi.DBI) (*AddTenantMemberRes, error) { status := req.Status if status == "" { status = iam.MemberInvited } return &AddTenantMemberRes{}, s.Members(tx).Add(ctx, req.TenantID, req.UserID, status) }) } func (s *TenantMemberApi) SetStatus(ctx context.Context, req SetTenantMemberStatusReq) (*SetTenantMemberStatusRes, error) { return dbi.ReadWrite(ctx, s.DB, func(tx dbi.DBI) (*SetTenantMemberStatusRes, error) { return &SetTenantMemberStatusRes{}, s.Members(tx).SetStatus(ctx, req.TenantID, req.UserID, req.Status) }) } func (s *TenantMemberApi) Remove(ctx context.Context, req RemoveTenantMemberReq) (*RemoveTenantMemberRes, error) { return dbi.ReadWrite(ctx, s.DB, func(tx dbi.DBI) (*RemoveTenantMemberRes, error) { return &RemoveTenantMemberRes{}, s.Members(tx).Remove(ctx, req.TenantID, req.UserID) }) } func (s *TenantMemberApi) Get(ctx context.Context, req GetTenantMemberReq) (*iam.TenantMember, error) { return dbi.ReadOnly(ctx, s.DB, func(tx dbi.DBI) (*iam.TenantMember, error) { return s.Members(tx).Get(ctx, req.TenantID, req.UserID) }) } func (s *TenantMemberApi) ListByTenant(ctx context.Context, req ListTenantMembersReq) (*ListTenantMembersRes, error) { page, err := dbi.ReadOnly(ctx, s.DB, func(tx dbi.DBI) (core.Page[iam.TenantMember], error) { return s.Members(tx).ListByTenant(ctx, req.TenantID, req.Page) }) if err != nil { return nil, err } res := ListTenantMembersRes(page) return &res, nil } func (s *TenantMemberApi) ListByUser(ctx context.Context, req ListUserTenantsReq) (*ListUserTenantsRes, error) { page, err := dbi.ReadOnly(ctx, s.DB, func(tx dbi.DBI) (core.Page[iam.TenantMember], error) { return s.Members(tx).ListByUser(ctx, req.UserID, req.Page) }) if err != nil { return nil, err } res := ListUserTenantsRes(page) return &res, nil } func TenantMemberRoutes(svc *TenantMemberApi) []routes.Route { return []routes.Route{ routes.RPC("/tenant-members/add", svc.Add), routes.RPC("/tenant-members/set-status", svc.SetStatus), routes.RPC("/tenant-members/remove", svc.Remove), routes.RPC("/tenant-members/get", svc.Get), routes.RPC("/tenant-members/list-by-tenant", svc.ListByTenant), routes.RPC("/tenant-members/list-by-user", svc.ListByUser), } }