package grpc import ( "context" "hyapp/pkg/xerr" hostservice "hyapp/services/user-service/internal/service/host" userv1 "hyapp.local/api/proto/user/v1" ) // 这个文件保持薄传输层:只做 proto 与业务层的数据转换和错误映射。 // 角色授权、区域校验、幂等和事务都在业务层/持久化层,避免不同入口行为分叉。 // SearchAgencies 查询当前用户同国家可加入 Agency。 func (s *Server) SearchAgencies(ctx context.Context, req *userv1.SearchAgenciesRequest) (*userv1.SearchAgenciesResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) agencies, err := s.hostSvc.SearchAgencies(ctx, req.GetUserId(), req.GetKeyword(), req.GetPageSize()) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &userv1.SearchAgenciesResponse{Agencies: make([]*userv1.Agency, 0, len(agencies))} for _, agency := range agencies { resp.Agencies = append(resp.Agencies, toProtoAgency(agency)) } return resp, nil } // ApplyToAgency 创建用户加入 Agency 的待处理申请。 func (s *Server) ApplyToAgency(ctx context.Context, req *userv1.ApplyToAgencyRequest) (*userv1.ApplyToAgencyResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) // command_id 和 user_id 来自 App 调用约定;当前阶段没有在传输层注入认证上下文。 application, err := s.hostSvc.ApplyToAgency(ctx, hostservice.ApplyToAgencyInput{ CommandID: req.GetCommandId(), UserID: req.GetUserId(), AgencyID: req.GetAgencyId(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.ApplyToAgencyResponse{Application: toProtoAgencyApplication(application)}, nil } // ReviewAgencyApplication 审核用户加入 Agency 申请。 func (s *Server) ReviewAgencyApplication(ctx context.Context, req *userv1.ReviewAgencyApplicationRequest) (*userv1.ReviewAgencyApplicationResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) // reviewer_user_id 只是传入业务层的操作者;是否为 Agency 拥有者在持久化层锁内确认。 result, err := s.hostSvc.ReviewAgencyApplication(ctx, hostservice.ReviewAgencyApplicationInput{ CommandID: req.GetCommandId(), ReviewerUserID: req.GetReviewerUserId(), ApplicationID: req.GetApplicationId(), Decision: req.GetDecision(), Reason: req.GetReason(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.ReviewAgencyApplicationResponse{ Application: toProtoAgencyApplication(result.Application), HostProfile: toProtoHostProfile(result.HostProfile), Membership: toProtoAgencyMembership(result.Membership), }, nil } // KickAgencyHost 结束普通 Host 的 Agency 归属,并按领域规则返回移除后的 Host 身份状态。 func (s *Server) KickAgencyHost(ctx context.Context, req *userv1.KickAgencyHostRequest) (*userv1.KickAgencyHostResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) // 传输层不判断拥有者和成员关系,防止未来 HTTP/任务入口复制一份不一致规则。 result, err := s.hostSvc.KickAgencyHost(ctx, hostservice.KickAgencyHostInput{ CommandID: req.GetCommandId(), OperatorUserID: req.GetOperatorUserId(), AgencyID: req.GetAgencyId(), HostUserID: req.GetHostUserId(), Reason: req.GetReason(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.KickAgencyHostResponse{ Membership: toProtoAgencyMembership(result.Membership), HostProfile: toProtoHostProfile(result.HostProfile), }, nil } // InviteAgency 创建用户成为 Agency owner 的待确认邀请,目标接受后才创建关系事实。 func (s *Server) InviteAgency(ctx context.Context, req *userv1.InviteAgencyRequest) (*userv1.InviteAgencyResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) // 邀请人的 BD 身份和目标用户的区域/身份冲突都由业务事务校验。 invitation, err := s.hostSvc.InviteAgency(ctx, hostservice.InviteAgencyInput{ CommandID: req.GetCommandId(), InviterUserID: req.GetInviterUserId(), TargetUserID: req.GetTargetUserId(), AgencyName: req.GetAgencyName(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.InviteAgencyResponse{Invitation: toProtoRoleInvitation(invitation)}, nil } // InviteBD 创建用户成为普通 BD 的待确认邀请,只有 BD 负责人可调用。 func (s *Server) InviteBD(ctx context.Context, req *userv1.InviteBDRequest) (*userv1.InviteBDResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) // BD 负责人授权在持久化层内基于 bd_leader_profiles 当前事实判断。 invitation, err := s.hostSvc.InviteBD(ctx, hostservice.InviteBDInput{ CommandID: req.GetCommandId(), InviterUserID: req.GetInviterUserId(), TargetUserID: req.GetTargetUserId(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.InviteBDResponse{Invitation: toProtoRoleInvitation(invitation)}, nil } // InviteHost 创建用户加入 Agency 的待确认邀请,只有 active Agency owner 可调用。 func (s *Server) InviteHost(ctx context.Context, req *userv1.InviteHostRequest) (*userv1.InviteHostResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) // 发起人是否拥有 active Agency、目标是否同区和是否已有归属都在持久化事务内锁定判断。 invitation, err := s.hostSvc.InviteHost(ctx, hostservice.InviteHostInput{ CommandID: req.GetCommandId(), InviterUserID: req.GetInviterUserId(), TargetUserID: req.GetTargetUserId(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.InviteHostResponse{Invitation: toProtoRoleInvitation(invitation)}, nil } // ListBDLeaderBDs 返回当前 BD Leader 直属 BD 列表。 func (s *Server) ListBDLeaderBDs(ctx context.Context, req *userv1.ListBDLeaderBDsRequest) (*userv1.ListBDLeaderBDsResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) profiles, err := s.hostSvc.ListBDLeaderBDs(ctx, hostservice.ListBDLeaderBDsCommand{ LeaderUserID: req.GetLeaderUserId(), Status: req.GetStatus(), PageSize: int(req.GetPageSize()), }) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &userv1.ListBDLeaderBDsResponse{BdProfiles: make([]*userv1.BDProfile, 0, len(profiles))} for _, profile := range profiles { resp.BdProfiles = append(resp.BdProfiles, toProtoBDProfile(profile)) } return resp, nil } // ListBDLeaderAgencies 返回当前 BD Leader 团队下的 Agency 列表。 func (s *Server) ListBDLeaderAgencies(ctx context.Context, req *userv1.ListBDLeaderAgenciesRequest) (*userv1.ListBDLeaderAgenciesResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) agencies, err := s.hostSvc.ListBDLeaderAgencies(ctx, hostservice.ListBDLeaderAgenciesCommand{ LeaderUserID: req.GetLeaderUserId(), Status: req.GetStatus(), PageSize: int(req.GetPageSize()), }) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &userv1.ListBDLeaderAgenciesResponse{Agencies: make([]*userv1.Agency, 0, len(agencies))} for _, agency := range agencies { resp.Agencies = append(resp.Agencies, toProtoAgency(agency)) } return resp, nil } // ListBDAgencies 返回当前 BD 自己拓展的 Agency 列表。 func (s *Server) ListBDAgencies(ctx context.Context, req *userv1.ListBDAgenciesRequest) (*userv1.ListBDAgenciesResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) agencies, err := s.hostSvc.ListBDAgencies(ctx, hostservice.ListBDAgenciesCommand{ BDUserID: req.GetBdUserId(), Status: req.GetStatus(), PageSize: int(req.GetPageSize()), }) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &userv1.ListBDAgenciesResponse{Agencies: make([]*userv1.Agency, 0, len(agencies))} for _, agency := range agencies { resp.Agencies = append(resp.Agencies, toProtoAgency(agency)) } return resp, nil } // ListManagerTeamAgencies 返回经理团队树内全部有效 Agency;经理停用时由业务层返回 PermissionDenied。 func (s *Server) ListManagerTeamAgencies(ctx context.Context, req *userv1.ListManagerTeamAgenciesRequest) (*userv1.ListManagerTeamAgenciesResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) result, err := s.hostSvc.ListManagerTeamAgencies(ctx, hostservice.ListManagerTeamAgenciesCommand{ ManagerUserID: req.GetManagerUserId(), PageSize: int(req.GetPageSize()), }) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &userv1.ListManagerTeamAgenciesResponse{ Agencies: make([]*userv1.ManagerTeamAgency, 0, len(result.Agencies)), TotalBdLeaders: int32(result.TotalBDLeaders), TotalBds: int32(result.TotalBDs), Truncated: result.Truncated, } for _, agency := range result.Agencies { resp.Agencies = append(resp.Agencies, &userv1.ManagerTeamAgency{ AgencyId: agency.AgencyID, OwnerUserId: agency.OwnerUserID, ParentBdUserId: agency.ParentBDUserID, }) } return resp, nil } // ListRoleInvitations 返回目标用户收到的角色邀请消息。 func (s *Server) ListRoleInvitations(ctx context.Context, req *userv1.ListRoleInvitationsRequest) (*userv1.ListRoleInvitationsResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) // 查询只接受 target_user_id,不允许调用方按 inviter 任意枚举别人的消息。 invitations, err := s.hostSvc.ListRoleInvitations(ctx, hostservice.ListRoleInvitationsCommand{ TargetUserID: req.GetTargetUserId(), Status: req.GetStatus(), PageSize: int(req.GetPageSize()), }) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &userv1.ListRoleInvitationsResponse{Invitations: make([]*userv1.RoleInvitation, 0, len(invitations))} for _, invitation := range invitations { resp.Invitations = append(resp.Invitations, toProtoRoleInvitation(invitation)) } return resp, nil } // GetRoleInvitation 返回一条邀请事实,用于 action-confirm 以 user-service 的 owner 状态修复确认消息。 func (s *Server) GetRoleInvitation(ctx context.Context, req *userv1.GetRoleInvitationRequest) (*userv1.GetRoleInvitationResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) // actor_user_id 必须是邀请发起人或目标用户;权限判断下沉到业务层,避免内部调用绕过边界。 invitation, err := s.hostSvc.GetRoleInvitation(ctx, req.GetActorUserId(), req.GetInvitationId()) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.GetRoleInvitationResponse{Invitation: toProtoRoleInvitation(invitation)}, nil } // ProcessRoleInvitation 处理 Host、Agency 或 BD 邀请。 func (s *Server) ProcessRoleInvitation(ctx context.Context, req *userv1.ProcessRoleInvitationRequest) (*userv1.ProcessRoleInvitationResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) // actor_user_id 的含义由动作决定:取消是邀请人,接受/拒绝是目标用户。 result, err := s.hostSvc.ProcessRoleInvitation(ctx, hostservice.ProcessRoleInvitationInput{ CommandID: req.GetCommandId(), ActorUserID: req.GetActorUserId(), InvitationID: req.GetInvitationId(), Action: req.GetAction(), Reason: req.GetReason(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.ProcessRoleInvitationResponse{ Invitation: toProtoRoleInvitation(result.Invitation), HostProfile: toProtoHostProfile(result.HostProfile), Agency: toProtoAgency(result.Agency), Membership: toProtoAgencyMembership(result.Membership), BdProfile: toProtoBDProfile(result.BDProfile), }, nil } // GetHostProfile 返回当前用户主播身份事实。 func (s *Server) GetHostProfile(ctx context.Context, req *userv1.GetHostProfileRequest) (*userv1.GetHostProfileResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) profile, err := s.hostSvc.GetHostProfile(ctx, req.GetUserId()) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.GetHostProfileResponse{HostProfile: toProtoHostProfile(profile)}, nil } // BatchGetHostProfiles 一次返回多个用户的主播身份事实,缺失用户不返回占位对象。 func (s *Server) BatchGetHostProfiles(ctx context.Context, req *userv1.BatchGetHostProfilesRequest) (*userv1.BatchGetHostProfilesResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) profiles, err := s.hostSvc.BatchGetHostProfiles(ctx, req.GetUserIds()) if err != nil { return nil, xerr.ToGRPCError(err) } result := make(map[int64]*userv1.HostProfile, len(profiles)) for userID, profile := range profiles { // map key 固定使用 user_id,调用方按原 target 顺序重新组装业务快照。 result[userID] = toProtoHostProfile(profile) } return &userv1.BatchGetHostProfilesResponse{HostProfiles: result}, nil } // GetBDProfile 按调用方声明的角色返回普通 BD 或 BD Leader 身份事实。 func (s *Server) GetBDProfile(ctx context.Context, req *userv1.GetBDProfileRequest) (*userv1.GetBDProfileResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) profile, err := s.hostSvc.GetBDProfile(ctx, req.GetUserId(), req.GetRole()) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.GetBDProfileResponse{BdProfile: toProtoBDProfile(profile)}, nil } // GetCoinSellerProfile 返回当前用户币商身份事实。 func (s *Server) GetCoinSellerProfile(ctx context.Context, req *userv1.GetCoinSellerProfileRequest) (*userv1.GetCoinSellerProfileResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) profile, err := s.hostSvc.GetCoinSellerProfile(ctx, req.GetUserId()) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.GetCoinSellerProfileResponse{CoinSellerProfile: toProtoCoinSellerProfile(profile)}, nil } // ListActiveCoinSellersInMyRegion 返回当前用户同区域启用币商。 func (s *Server) ListActiveCoinSellersInMyRegion(ctx context.Context, req *userv1.ListActiveCoinSellersInMyRegionRequest) (*userv1.ListActiveCoinSellersInMyRegionResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) items, err := s.hostSvc.ListActiveCoinSellersInMyRegion(ctx, req.GetUserId()) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &userv1.ListActiveCoinSellersInMyRegionResponse{CoinSellers: make([]*userv1.CoinSellerListItem, 0, len(items))} for _, item := range items { resp.CoinSellers = append(resp.CoinSellers, toProtoCoinSellerListItem(item)) } return resp, nil } // CreateSubCoinSeller 处理父币商在 H5 币商中心搜索直开直属子币商。 func (s *Server) CreateSubCoinSeller(ctx context.Context, req *userv1.CreateSubCoinSellerRequest) (*userv1.CreateSubCoinSellerResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) result, err := s.hostSvc.CreateSubCoinSeller(ctx, hostservice.CreateSubCoinSellerInput{ CommandID: req.GetCommandId(), ParentUserID: req.GetParentUserId(), ChildUserID: req.GetChildUserId(), RequestID: req.GetMeta().GetRequestId(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.CreateSubCoinSellerResponse{ Relation: toProtoCoinSellerSubRelation(result.Relation), Child: toProtoCoinSellerListItem(result.Child), }, nil } // SubmitSubCoinSellerApplication 处理父币商邀请子币商申请;提交后等待后台审批,不立即创建关系。 func (s *Server) SubmitSubCoinSellerApplication(ctx context.Context, req *userv1.SubmitSubCoinSellerApplicationRequest) (*userv1.SubmitSubCoinSellerApplicationResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) result, err := s.hostSvc.SubmitSubCoinSellerApplication(ctx, hostservice.SubmitSubCoinSellerApplicationInput{ CommandID: req.GetCommandId(), ParentUserID: req.GetParentUserId(), TargetUserID: req.GetTargetUserId(), RequestID: req.GetMeta().GetRequestId(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.SubmitSubCoinSellerApplicationResponse{ Application: toProtoCoinSellerSubApplication(result.Application), }, nil } // ListSubCoinSellers 返回父币商直属子币商分页列表。 func (s *Server) ListSubCoinSellers(ctx context.Context, req *userv1.ListSubCoinSellersRequest) (*userv1.ListSubCoinSellersResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) result, err := s.hostSvc.ListSubCoinSellers(ctx, hostservice.ListSubCoinSellersCommand{ ParentUserID: req.GetParentUserId(), Page: int(req.GetPage()), PageSize: int(req.GetPageSize()), }) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &userv1.ListSubCoinSellersResponse{ Children: make([]*userv1.CoinSellerListItem, 0, len(result.Items)), Total: result.Total, Page: int32(result.Page), PageSize: int32(result.PageSize), } for _, item := range result.Items { resp.Children = append(resp.Children, toProtoCoinSellerListItem(item)) } return resp, nil } // CheckCoinSellerSubRelation 校验父子币商关系和父级权限,供 gateway 子币商库存转账前调用。 func (s *Server) CheckCoinSellerSubRelation(ctx context.Context, req *userv1.CheckCoinSellerSubRelationRequest) (*userv1.CheckCoinSellerSubRelationResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) child, err := s.hostSvc.CheckCoinSellerSubRelation(ctx, hostservice.CheckCoinSellerSubRelationCommand{ ParentUserID: req.GetParentUserId(), ChildUserID: req.GetChildUserId(), }) if err != nil { return &userv1.CheckCoinSellerSubRelationResponse{Allowed: false, Reason: string(xerr.CodeOf(err))}, xerr.ToGRPCError(err) } return &userv1.CheckCoinSellerSubRelationResponse{Allowed: true, Child: toProtoCoinSellerListItem(child)}, nil } // GetUserRoleSummary 返回 App 入口显隐所需的角色摘要,替代 gateway 多角色 fanout。 func (s *Server) GetUserRoleSummary(ctx context.Context, req *userv1.GetUserRoleSummaryRequest) (*userv1.GetUserRoleSummaryResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) summary, err := s.hostSvc.GetUserRoleSummary(ctx, req.GetUserId()) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.GetUserRoleSummaryResponse{Summary: toProtoUserRoleSummary(summary)}, nil } // GetAgency 返回 Agency 当前事实。 func (s *Server) GetAgency(ctx context.Context, req *userv1.GetAgencyRequest) (*userv1.GetAgencyResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) agency, err := s.hostSvc.GetAgency(ctx, req.GetAgencyId()) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.GetAgencyResponse{Agency: toProtoAgency(agency)}, nil } // UpdateAgencyProfile 修改 Agency 独立资料;用户资料和 Agency 资料不会互相回写。 func (s *Server) UpdateAgencyProfile(ctx context.Context, req *userv1.UpdateAgencyProfileRequest) (*userv1.UpdateAgencyProfileResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) agency, err := s.hostSvc.UpdateAgencyProfile(ctx, hostservice.UpdateAgencyProfileInput{ CommandID: req.GetCommandId(), OperatorUserID: req.GetOperatorUserId(), AgencyID: req.GetAgencyId(), Name: req.Name, Avatar: req.Avatar, RequestID: req.GetMeta().GetRequestId(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.UpdateAgencyProfileResponse{Agency: toProtoAgency(agency)}, nil } // CheckBusinessCapability 返回 H5/App 业务入口可用性,具体身份规则由 host service 统一判断。 func (s *Server) CheckBusinessCapability(ctx context.Context, req *userv1.CheckBusinessCapabilityRequest) (*userv1.CheckBusinessCapabilityResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) allowed, reason, err := s.hostSvc.CheckBusinessCapability(ctx, req.GetActorUserId(), req.GetCapability()) if err != nil { return nil, xerr.ToGRPCError(err) } return &userv1.CheckBusinessCapabilityResponse{Allowed: allowed, Reason: reason}, nil } // GetAgencyMembers 返回 Agency 成员关系事实列表。 func (s *Server) GetAgencyMembers(ctx context.Context, req *userv1.GetAgencyMembersRequest) (*userv1.GetAgencyMembersResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) memberships, err := s.hostSvc.ListAgencyMembers(ctx, req.GetAgencyId(), req.GetStatus()) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &userv1.GetAgencyMembersResponse{Memberships: make([]*userv1.AgencyMembership, 0, len(memberships))} for _, membership := range memberships { resp.Memberships = append(resp.Memberships, toProtoAgencyMembership(membership)) } return resp, nil } // GetAgencyApplications 返回 Agency 申请事实列表。 func (s *Server) GetAgencyApplications(ctx context.Context, req *userv1.GetAgencyApplicationsRequest) (*userv1.GetAgencyApplicationsResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) applications, err := s.hostSvc.ListAgencyApplications(ctx, req.GetAgencyId(), req.GetStatus()) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &userv1.GetAgencyApplicationsResponse{Applications: make([]*userv1.AgencyApplication, 0, len(applications))} for _, application := range applications { resp.Applications = append(resp.Applications, toProtoAgencyApplication(application)) } return resp, nil }