2026-07-09 18:15:57 +08:00

577 lines
24 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}