增加用户的manager身份

This commit is contained in:
zhx 2026-05-25 23:41:50 +08:00
parent 245412ae95
commit ad4a755998
13 changed files with 75 additions and 130 deletions

View File

@ -442,7 +442,7 @@ func (x *CoinSellerProfile) GetUpdatedAtMs() int64 {
}
// UserRoleSummary 是 App 我的页和入口显隐使用的轻量角色摘要。
// 它把 host、Agency、BD 和币商身份收敛到一次 user-service RPC避免 gateway 随角色扩张继续 fanout。
// 它把 host、Agency、manager、BD 和币商身份收敛到一次 user-service RPC避免 gateway 随角色扩张继续 fanout。
type UserRoleSummary struct {
state protoimpl.MessageState `protogen:"open.v1"`
UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
@ -457,6 +457,7 @@ type UserRoleSummary struct {
BdStatus string `protobuf:"bytes,10,opt,name=bd_status,json=bdStatus,proto3" json:"bd_status,omitempty"`
CoinSellerStatus string `protobuf:"bytes,11,opt,name=coin_seller_status,json=coinSellerStatus,proto3" json:"coin_seller_status,omitempty"`
PendingRoleInvitations int64 `protobuf:"varint,12,opt,name=pending_role_invitations,json=pendingRoleInvitations,proto3" json:"pending_role_invitations,omitempty"`
IsManager bool `protobuf:"varint,13,opt,name=is_manager,json=isManager,proto3" json:"is_manager,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -575,6 +576,13 @@ func (x *UserRoleSummary) GetPendingRoleInvitations() int64 {
return 0
}
func (x *UserRoleSummary) GetIsManager() bool {
if x != nil {
return x.IsManager
}
return false
}
// AgencyMembership 是 host 与 Agency 的有时效关系事实。
type AgencyMembership struct {
state protoimpl.MessageState `protogen:"open.v1"`
@ -3689,7 +3697,7 @@ const file_proto_user_v1_host_proto_rawDesc = "" +
"\x13merchant_asset_type\x18\x03 \x01(\tR\x11merchantAssetType\x12+\n" +
"\x12created_by_user_id\x18\x04 \x01(\x03R\x0fcreatedByUserId\x12\"\n" +
"\rcreated_at_ms\x18\x05 \x01(\x03R\vcreatedAtMs\x12\"\n" +
"\rupdated_at_ms\x18\x06 \x01(\x03R\vupdatedAtMs\"\x95\x03\n" +
"\rupdated_at_ms\x18\x06 \x01(\x03R\vupdatedAtMs\"\xb4\x03\n" +
"\x0fUserRoleSummary\x12\x17\n" +
"\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x17\n" +
"\ais_host\x18\x02 \x01(\bR\x06isHost\x12\x1b\n" +
@ -3705,7 +3713,9 @@ const file_proto_user_v1_host_proto_rawDesc = "" +
"\tbd_status\x18\n" +
" \x01(\tR\bbdStatus\x12,\n" +
"\x12coin_seller_status\x18\v \x01(\tR\x10coinSellerStatus\x128\n" +
"\x18pending_role_invitations\x18\f \x01(\x03R\x16pendingRoleInvitations\"\xaa\x03\n" +
"\x18pending_role_invitations\x18\f \x01(\x03R\x16pendingRoleInvitations\x12\x1d\n" +
"\n" +
"is_manager\x18\r \x01(\bR\tisManager\"\xaa\x03\n" +
"\x10AgencyMembership\x12#\n" +
"\rmembership_id\x18\x01 \x01(\x03R\fmembershipId\x12\x1b\n" +
"\tagency_id\x18\x02 \x01(\x03R\bagencyId\x12 \n" +

View File

@ -57,7 +57,7 @@ message CoinSellerProfile {
}
// UserRoleSummary App 使
// hostAgencyBD user-service RPC gateway fanout
// hostAgencymanagerBD user-service RPC gateway fanout
message UserRoleSummary {
int64 user_id = 1;
bool is_host = 2;
@ -71,6 +71,7 @@ message UserRoleSummary {
string bd_status = 10;
string coin_seller_status = 11;
int64 pending_role_invitations = 12;
bool is_manager = 13;
}
// AgencyMembership host Agency

View File

@ -2717,7 +2717,10 @@ definitions:
description: 用户是否拥有 active host profile。
is_agent:
type: boolean
description: 用户是否拥有 active agency owner 身份。
description: 用户是否拥有 Agency 入口身份active Agency owner 或 Agency 来源主播都可能为 true。
is_manager:
type: boolean
description: 用户是否拥有经理中心身份;首版等价于 active Agency owner。
is_bd:
type: boolean
description: 用户是否拥有 active BD 或 BD Leader 身份。
@ -2732,6 +2735,7 @@ definitions:
required:
- is_host
- is_agency
- is_manager
- is_bd
- is_bd_leader
- is_coin_seller
@ -2741,6 +2745,8 @@ definitions:
type: boolean
is_agency:
type: boolean
is_manager:
type: boolean
is_bd:
type: boolean
is_bd_leader:
@ -3170,6 +3176,7 @@ definitions:
type: string
enum:
- host-center
- manager-center
- bd-center
- bd-leader-center
- agency-center

View File

@ -49,6 +49,7 @@ Authorization: Bearer <access_token>
"roles": {
"is_host": true,
"is_agency": false,
"is_manager": false,
"is_bd": false,
"is_bd_leader": false,
"is_coin_seller": false,
@ -116,6 +117,7 @@ Authorization: Bearer <access_token>
| `apply_host` | `roles.is_host == false` |
| `host_center` | `roles.is_host == true` |
| `agency_center` | `roles.is_agency == true` |
| `manager_center` | `roles.is_manager == true` |
| `bd_center` | `roles.is_bd == true` |
| `bd_leader_center` | `roles.is_bd_leader == true` |
| `coin_seller_center` | `roles.is_coin_seller == true` |

View File

@ -247,12 +247,12 @@ func (s *Store) seedMenus() error {
{ParentID: &gameID, Title: "游戏列表", Code: "game-list", Path: "/games", Icon: "sports_esports", PermissionCode: "game:view", Sort: 70, Visible: true},
{ParentID: &geoID, Title: "国家管理", Code: "host-org-countries", Path: "/host/countries", Icon: "public", PermissionCode: "country:view", Sort: 70, Visible: true},
{ParentID: &geoID, Title: "区域管理", Code: "host-org-regions", Path: "/host/regions", Icon: "map", PermissionCode: "region:view", Sort: 71, Visible: true},
{ParentID: &hostOrgID, Title: "经理列表", Code: "host-org-managers", Path: "/host/managers", Icon: "users", PermissionCode: "agency:view", Sort: 80, Visible: true},
{ParentID: &hostOrgID, Title: "Manager列表", Code: "host-org-managers", Path: "/host/managers", Icon: "users", PermissionCode: "agency:view", Sort: 80, Visible: true},
{ParentID: &hostOrgID, Title: "Agency 列表", Code: "host-org-agencies", Path: "/host/agencies", Icon: "apartment", PermissionCode: "agency:view", Sort: 81, Visible: true},
{ParentID: &hostOrgID, Title: "BD Leader 列表", Code: "host-org-bd-leaders", Path: "/host/bd-leaders", Icon: "shield", PermissionCode: "bd:view", Sort: 82, Visible: true},
{ParentID: &hostOrgID, Title: "BD 列表", Code: "host-org-bds", Path: "/host/bds", Icon: "team", PermissionCode: "bd:view", Sort: 83, Visible: true},
{ParentID: &hostOrgID, Title: "主播列表", Code: "host-org-hosts", Path: "/host/hosts", Icon: "users", PermissionCode: "host:view", Sort: 84, Visible: true},
{ParentID: &hostOrgID, Title: "币商列表", Code: "host-org-coin-sellers", Path: "/host/coin-sellers", Icon: "wallet", PermissionCode: "coin-seller:view", Sort: 85, Visible: true},
{ParentID: &hostOrgID, Title: "Host 列表", Code: "host-org-hosts", Path: "/host/hosts", Icon: "users", PermissionCode: "host:view", Sort: 84, Visible: true},
{ParentID: &hostOrgID, Title: "Coin Saller列表", Code: "host-org-coin-sellers", Path: "/host/coin-sellers", Icon: "wallet", PermissionCode: "coin-seller:view", Sort: 85, Visible: true},
}
for _, menu := range children {
if _, err := s.syncDefaultMenu(s.db, menu); err != nil {

View File

@ -34,6 +34,7 @@ func TestGetMyOverviewComposesProfileWalletVIPStatsRolesAndEntries(t *testing.T)
UserId: 42,
IsHost: true,
IsAgency: true,
IsManager: true,
IsBd: true,
IsBdLeader: true,
IsCoinSeller: true,
@ -81,7 +82,7 @@ func TestGetMyOverviewComposesProfileWalletVIPStatsRolesAndEntries(t *testing.T)
t.Fatalf("profile stats mismatch: %+v", stats)
}
roles := data["roles"].(map[string]any)
if roles["is_host"] != true || roles["is_agency"] != true || roles["is_bd"] != true || roles["is_bd_leader"] != true || roles["is_coin_seller"] != true || roles["agency_id"] != float64(7001) {
if roles["is_host"] != true || roles["is_agency"] != true || roles["is_manager"] != true || roles["is_bd"] != true || roles["is_bd_leader"] != true || roles["is_coin_seller"] != true || roles["agency_id"] != float64(7001) {
t.Fatalf("roles data mismatch: %+v", roles)
}
wallet := data["wallet"].(map[string]any)
@ -106,6 +107,7 @@ func TestGetMyOverviewComposesProfileWalletVIPStatsRolesAndEntries(t *testing.T)
!overviewEntryVisible(entries, "task") ||
!overviewEntryVisible(entries, "host_center") ||
!overviewEntryVisible(entries, "agency_center") ||
!overviewEntryVisible(entries, "manager_center") ||
!overviewEntryVisible(entries, "bd_center") ||
!overviewEntryVisible(entries, "bd_leader_center") ||
!overviewEntryVisible(entries, "coin_seller_center") ||
@ -136,7 +138,7 @@ func TestGetMyOverviewProjectsOrdinaryUserEntriesAndZeroWallet(t *testing.T) {
t.Fatalf("missing stats should be zero projection: %+v", stats)
}
roles := data["roles"].(map[string]any)
if roles["is_host"] != false || roles["is_bd"] != false || roles["is_coin_seller"] != false {
if roles["is_host"] != false || roles["is_manager"] != false || roles["is_bd"] != false || roles["is_coin_seller"] != false {
t.Fatalf("ordinary roles mismatch: %+v", roles)
}
entries := data["entries"].([]any)
@ -162,11 +164,11 @@ func TestGetMyOverviewDegradesOptionalUpstreamFailures(t *testing.T) {
t.Fatalf("profile stats degradation mismatch: %+v", stats)
}
roles := data["roles"].(map[string]any)
if roles["unavailable"] != true || roles["is_host"] != false || roles["is_bd"] != false || roles["is_coin_seller"] != false {
if roles["unavailable"] != true || roles["is_host"] != false || roles["is_manager"] != false || roles["is_bd"] != false || roles["is_coin_seller"] != false {
t.Fatalf("roles degradation mismatch: %+v", roles)
}
entries := data["entries"].([]any)
if overviewEntryVisible(entries, "host_center") || overviewEntryVisible(entries, "bd_center") || overviewEntryVisible(entries, "coin_seller_center") {
if overviewEntryVisible(entries, "host_center") || overviewEntryVisible(entries, "manager_center") || overviewEntryVisible(entries, "bd_center") || overviewEntryVisible(entries, "coin_seller_center") {
t.Fatalf("degraded roles must not expose privileged entries: %+v", entries)
}
}

View File

@ -2427,20 +2427,14 @@ func TestGetAppVersionReturnsLatestVersionAndUpdateDecision(t *testing.T) {
func TestGetMyHostIdentityCombinesActiveHostAndBDProfiles(t *testing.T) {
hostClient := &fakeUserHostClient{
hostProfile: &userv1.HostProfile{
UserId: 42,
Status: "active",
Source: "admin_create_agency",
},
bdProfile: &userv1.BDProfile{
UserId: 42,
Status: "active",
Role: "bd_leader",
},
profile: &userv1.CoinSellerProfile{
UserId: 42,
Status: "active",
MerchantAssetType: "COIN_SELLER_COIN",
roleSummary: &userv1.UserRoleSummary{
UserId: 42,
IsHost: true,
IsAgency: true,
IsManager: true,
IsBd: true,
IsBdLeader: true,
IsCoinSeller: true,
},
}
handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{})
@ -2456,14 +2450,8 @@ func TestGetMyHostIdentityCombinesActiveHostAndBDProfiles(t *testing.T) {
if recorder.Code != http.StatusOK {
t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String())
}
if hostClient.lastHost == nil || hostClient.lastHost.GetUserId() != 42 || hostClient.lastHost.GetMeta().GetRequestId() != assertGeneratedRequestID(t, recorder, "req-host-identity") {
t.Fatalf("host identity host request mismatch: %+v", hostClient.lastHost)
}
if hostClient.lastBD == nil || hostClient.lastBD.GetUserId() != 42 {
t.Fatalf("host identity bd request mismatch: %+v", hostClient.lastBD)
}
if hostClient.last == nil || hostClient.last.GetUserId() != 42 {
t.Fatalf("host identity coin seller request mismatch: %+v", hostClient.last)
if hostClient.lastRoleSummary == nil || hostClient.lastRoleSummary.GetUserId() != 42 || hostClient.lastRoleSummary.GetMeta().GetRequestId() != assertGeneratedRequestID(t, recorder, "req-host-identity") {
t.Fatalf("host identity role summary request mismatch: %+v", hostClient.lastRoleSummary)
}
var response httpkit.ResponseEnvelope
if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil {
@ -2473,6 +2461,7 @@ func TestGetMyHostIdentityCombinesActiveHostAndBDProfiles(t *testing.T) {
if response.Code != httpkit.CodeOK || !ok ||
data["is_host"] != true ||
data["is_agent"] != true ||
data["is_manager"] != true ||
data["is_bd"] != true ||
data["is_bd_leader"] != true ||
data["is_coin_seller"] != true {
@ -2481,11 +2470,7 @@ func TestGetMyHostIdentityCombinesActiveHostAndBDProfiles(t *testing.T) {
}
func TestGetMyHostIdentityTreatsMissingProfilesAsFalse(t *testing.T) {
hostClient := &fakeUserHostClient{
hostErr: xerr.ToGRPCError(xerr.New(xerr.NotFound, "host profile not found")),
bdErr: xerr.ToGRPCError(xerr.New(xerr.NotFound, "bd profile not found")),
err: xerr.ToGRPCError(xerr.New(xerr.NotFound, "coin seller profile not found")),
}
hostClient := &fakeUserHostClient{}
handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{})
handler.SetUserHostClient(hostClient)
router := handler.Routes(auth.NewVerifier("secret"))
@ -2507,6 +2492,7 @@ func TestGetMyHostIdentityTreatsMissingProfilesAsFalse(t *testing.T) {
if response.Code != httpkit.CodeOK || !ok ||
data["is_host"] != false ||
data["is_agent"] != false ||
data["is_manager"] != false ||
data["is_bd"] != false ||
data["is_bd_leader"] != false ||
data["is_coin_seller"] != false {

View File

@ -1,26 +1,17 @@
package userapi
import (
"hyapp/services/gateway-service/internal/transport/http/httpkit"
"net/http"
userv1 "hyapp.local/api/proto/user/v1"
"hyapp/pkg/xerr"
"hyapp/services/gateway-service/internal/auth"
)
const (
hostIdentityActiveStatus = "active"
hostIdentityAgencyInvitation = "agency_invitation"
hostIdentityAdminCreateAgency = "admin_create_agency"
hostIdentityBDRole = "bd"
hostIdentityBDLeaderRole = "bd_leader"
hostIdentityCoinSellerAsset = "COIN_SELLER_COIN"
"hyapp/services/gateway-service/internal/transport/http/httpkit"
)
type userHostIdentityData struct {
IsHost bool `json:"is_host"`
IsAgent bool `json:"is_agent"`
IsManager bool `json:"is_manager"`
IsBD bool `json:"is_bd"`
IsBDLeader bool `json:"is_bd_leader"`
IsCoinSeller bool `json:"is_coin_seller"`
@ -32,50 +23,24 @@ func (h *Handler) getMyHostIdentity(writer http.ResponseWriter, request *http.Re
httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error")
return
}
userID := auth.UserIDFromContext(request.Context())
identity := userHostIdentityData{}
hostResp, err := h.userHostClient.GetHostProfile(request.Context(), &userv1.GetHostProfileRequest{
resp, err := h.userHostClient.GetUserRoleSummary(request.Context(), &userv1.GetUserRoleSummaryRequest{
Meta: httpkit.UserMeta(request, ""),
UserId: userID,
UserId: auth.UserIDFromContext(request.Context()),
})
if err != nil {
if xerr.ReasonFromGRPC(err) != xerr.NotFound {
httpkit.WriteRPCError(writer, request, err)
return
}
} else {
applyHostIdentity(&identity, hostResp.GetHostProfile())
httpkit.WriteRPCError(writer, request, err)
return
}
bdResp, err := h.userHostClient.GetBDProfile(request.Context(), &userv1.GetBDProfileRequest{
Meta: httpkit.UserMeta(request, ""),
UserId: userID,
summary := resp.GetSummary()
httpkit.WriteOK(writer, request, userHostIdentityData{
IsHost: summary.GetIsHost(),
IsAgent: summary.GetIsAgency(),
IsManager: summary.GetIsManager(),
IsBD: summary.GetIsBd(),
IsBDLeader: summary.GetIsBdLeader(),
IsCoinSeller: summary.GetIsCoinSeller(),
})
if err != nil {
if xerr.ReasonFromGRPC(err) != xerr.NotFound {
httpkit.WriteRPCError(writer, request, err)
return
}
} else {
applyBDIdentity(&identity, bdResp.GetBdProfile())
}
coinSellerResp, err := h.userHostClient.GetCoinSellerProfile(request.Context(), &userv1.GetCoinSellerProfileRequest{
Meta: httpkit.UserMeta(request, ""),
UserId: userID,
})
if err != nil {
if xerr.ReasonFromGRPC(err) != xerr.NotFound {
httpkit.WriteRPCError(writer, request, err)
return
}
} else {
applyCoinSellerIdentity(&identity, coinSellerResp.GetCoinSellerProfile())
}
httpkit.WriteOK(writer, request, identity)
}
// getMyRoleSummary 返回我的页入口显隐所需的完整角色摘要。
@ -96,6 +61,7 @@ func (h *Handler) getMyRoleSummary(writer http.ResponseWriter, request *http.Req
httpkit.WriteOK(writer, request, overviewRolesData{
IsHost: summary.GetIsHost(),
IsAgency: summary.GetIsAgency(),
IsManager: summary.GetIsManager(),
IsBD: summary.GetIsBd(),
IsBDLeader: summary.GetIsBdLeader(),
IsCoinSeller: summary.GetIsCoinSeller(),
@ -107,39 +73,3 @@ func (h *Handler) getMyRoleSummary(writer http.ResponseWriter, request *http.Req
PendingRoleInvitations: summary.GetPendingRoleInvitations(),
})
}
func applyHostIdentity(identity *userHostIdentityData, profile *userv1.HostProfile) {
if profile == nil || profile.GetStatus() != hostIdentityActiveStatus {
return
}
identity.IsHost = true
switch profile.GetSource() {
case hostIdentityAgencyInvitation, hostIdentityAdminCreateAgency:
identity.IsAgent = true
}
}
func applyBDIdentity(identity *userHostIdentityData, profile *userv1.BDProfile) {
if profile == nil || profile.GetStatus() != hostIdentityActiveStatus {
return
}
switch profile.GetRole() {
case hostIdentityBDLeaderRole:
identity.IsBD = true
identity.IsBDLeader = true
case hostIdentityBDRole:
identity.IsBD = true
}
}
func applyCoinSellerIdentity(identity *userHostIdentityData, profile *userv1.CoinSellerProfile) {
if profile == nil ||
profile.GetStatus() != hostIdentityActiveStatus ||
profile.GetMerchantAssetType() != hostIdentityCoinSellerAsset {
return
}
identity.IsCoinSeller = true
}

View File

@ -35,6 +35,7 @@ type overviewWalletData struct {
type overviewRolesData struct {
IsHost bool `json:"is_host"`
IsAgency bool `json:"is_agency"`
IsManager bool `json:"is_manager"`
IsBD bool `json:"is_bd"`
IsBDLeader bool `json:"is_bd_leader"`
IsCoinSeller bool `json:"is_coin_seller"`
@ -183,6 +184,7 @@ func (h *Handler) getOverviewRoles(ctx context.Context, request *http.Request, u
return overviewRolesData{
IsHost: summary.GetIsHost(),
IsAgency: summary.GetIsAgency(),
IsManager: summary.GetIsManager(),
IsBD: summary.GetIsBd(),
IsBDLeader: summary.GetIsBdLeader(),
IsCoinSeller: summary.GetIsCoinSeller(),
@ -245,10 +247,11 @@ func overviewEntries(roles overviewRolesData) []overviewEntryData {
{Key: "apply_host", Visible: !roles.IsHost, Enabled: true, Route: "/host/apply", IconKey: "host_apply", Order: 50},
{Key: "host_center", Visible: roles.IsHost, Enabled: roles.IsHost, Route: "/host", IconKey: "host_center", Order: 60},
{Key: "agency_center", Visible: roles.IsAgency, Enabled: roles.IsAgency, Route: "/agency", IconKey: "agency", Order: 70},
{Key: "bd_center", Visible: roles.IsBD, Enabled: roles.IsBD, Route: "/bd", IconKey: "bd", Order: 80},
{Key: "bd_leader_center", Visible: roles.IsBDLeader, Enabled: roles.IsBDLeader, Route: "/bd-leader", IconKey: "bd_leader", Order: 90},
{Key: "coin_seller_center", Visible: roles.IsCoinSeller, Enabled: roles.IsCoinSeller, Route: "/coin-seller", IconKey: "coin_seller", Order: 100},
{Key: "settings", Visible: true, Enabled: true, Route: "/settings", IconKey: "settings", Order: 110},
{Key: "language", Visible: true, Enabled: true, Route: "/language", IconKey: "language", Order: 120},
{Key: "manager_center", Visible: roles.IsManager, Enabled: roles.IsManager, Route: "/manager-center", IconKey: "manager_center", Order: 80},
{Key: "bd_center", Visible: roles.IsBD, Enabled: roles.IsBD, Route: "/bd", IconKey: "bd", Order: 90},
{Key: "bd_leader_center", Visible: roles.IsBDLeader, Enabled: roles.IsBDLeader, Route: "/bd-leader", IconKey: "bd_leader", Order: 100},
{Key: "coin_seller_center", Visible: roles.IsCoinSeller, Enabled: roles.IsCoinSeller, Route: "/coin-seller", IconKey: "coin_seller", Order: 110},
{Key: "settings", Visible: true, Enabled: true, Route: "/settings", IconKey: "settings", Order: 120},
{Key: "language", Visible: true, Enabled: true, Route: "/language", IconKey: "language", Order: 130},
}
}

View File

@ -184,6 +184,7 @@ type UserRoleSummary struct {
UserID int64
IsHost bool
IsAgency bool
IsManager bool
IsBD bool
IsBDLeader bool
IsCoinSeller bool

View File

@ -579,7 +579,7 @@ func TestGetUserRoleSummaryAggregatesRolesAndPendingInvitations(t *testing.T) {
if err != nil {
t.Fatalf("GetUserRoleSummary failed: %v", err)
}
if !summary.IsHost || !summary.IsAgency || !summary.IsBD || !summary.IsBDLeader || !summary.IsCoinSeller || summary.AgencyID != 933 || summary.BDID != 931 {
if !summary.IsHost || !summary.IsAgency || !summary.IsManager || !summary.IsBD || !summary.IsBDLeader || !summary.IsCoinSeller || summary.AgencyID != 933 || summary.BDID != 931 {
t.Fatalf("role summary mismatch: %+v", summary)
}
pending, err := svc.GetUserRoleSummary(ctx, 932)

View File

@ -118,6 +118,8 @@ func (r *Repository) GetUserRoleSummary(ctx context.Context, userID int64) (host
summary.IsHost = hostStatus == hostdomain.HostStatusActive
if ownerAgencyID > 0 {
summary.AgencyID = ownerAgencyID
// 经理中心首版授权边界是 active Agency owner普通 Agency 成员只展示 Agency 入口,不具备 manager 身份。
summary.IsManager = true
} else {
summary.AgencyID = hostAgencyID
}

View File

@ -351,6 +351,7 @@ func toProtoUserRoleSummary(summary hostdomain.UserRoleSummary) *userv1.UserRole
UserId: summary.UserID,
IsHost: summary.IsHost,
IsAgency: summary.IsAgency,
IsManager: summary.IsManager,
IsBd: summary.IsBD,
IsBdLeader: summary.IsBDLeader,
IsCoinSeller: summary.IsCoinSeller,