经理权限和身份自动赠送
This commit is contained in:
parent
b97e5f0011
commit
9a19267c6a
@ -9,11 +9,13 @@ CREATE TABLE IF NOT EXISTS manager_profiles (
|
||||
contact_info VARCHAR(128) NOT NULL DEFAULT '' COMMENT '联系信息',
|
||||
can_grant_avatar_frame TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心赠送头像框',
|
||||
can_grant_vehicle TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心赠送座驾',
|
||||
can_grant_badge TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心赠送徽章',
|
||||
can_update_user_level TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心升级用户等级',
|
||||
can_add_bd_leader TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心添加 BD Leader',
|
||||
can_add_admin TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心添加 Admin',
|
||||
can_add_superadmin TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心添加 Superadmin',
|
||||
can_block_user TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心封禁用户',
|
||||
can_transfer_user_country TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心转移用户国家',
|
||||
created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建后台管理员 ID',
|
||||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||||
@ -48,9 +50,18 @@ PREPARE stmt FROM @ddl;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @ddl := IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'manager_profiles' AND COLUMN_NAME = 'can_grant_badge') = 0,
|
||||
'ALTER TABLE manager_profiles ADD COLUMN can_grant_badge TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''是否允许在经理中心赠送徽章'' AFTER can_grant_vehicle',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @ddl;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @ddl := IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'manager_profiles' AND COLUMN_NAME = 'can_update_user_level') = 0,
|
||||
'ALTER TABLE manager_profiles ADD COLUMN can_update_user_level TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''是否允许在经理中心升级用户等级'' AFTER can_grant_vehicle',
|
||||
'ALTER TABLE manager_profiles ADD COLUMN can_update_user_level TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''是否允许在经理中心升级用户等级'' AFTER can_grant_badge',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @ddl;
|
||||
@ -93,9 +104,18 @@ PREPARE stmt FROM @ddl;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @ddl := IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'manager_profiles' AND COLUMN_NAME = 'can_transfer_user_country') = 0,
|
||||
'ALTER TABLE manager_profiles ADD COLUMN can_transfer_user_country TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''是否允许在经理中心转移用户国家'' AFTER can_block_user',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @ddl;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
INSERT INTO manager_profiles (
|
||||
app_code, user_id, status, contact_info, can_grant_avatar_frame, can_grant_vehicle,
|
||||
can_update_user_level, can_add_bd_leader, can_add_admin, can_add_superadmin, can_block_user,
|
||||
app_code, user_id, status, contact_info, can_grant_avatar_frame, can_grant_vehicle, can_grant_badge,
|
||||
can_update_user_level, can_add_bd_leader, can_add_admin, can_add_superadmin, can_block_user, can_transfer_user_country,
|
||||
created_by_admin_id, created_at_ms, updated_at_ms
|
||||
)
|
||||
SELECT
|
||||
@ -110,6 +130,8 @@ SELECT
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
MIN(bl.created_at_ms),
|
||||
MAX(bl.updated_at_ms)
|
||||
|
||||
@ -53,11 +53,13 @@ type ManagerListItem struct {
|
||||
Contact string `json:"contact"`
|
||||
CanGrantAvatarFrame bool `json:"canGrantAvatarFrame"`
|
||||
CanGrantVehicle bool `json:"canGrantVehicle"`
|
||||
CanGrantBadge bool `json:"canGrantBadge"`
|
||||
CanUpdateUserLevel bool `json:"canUpdateUserLevel"`
|
||||
CanAddBDLeader bool `json:"canAddBdLeader"`
|
||||
CanAddAdmin bool `json:"canAddAdmin"`
|
||||
CanAddSuperadmin bool `json:"canAddSuperadmin"`
|
||||
CanBlockUser bool `json:"canBlockUser"`
|
||||
CanTransferCountry bool `json:"canTransferUserCountry"`
|
||||
BDLeaderCount int64 `json:"bdLeaderCount"`
|
||||
LastInvitedAtMs int64 `json:"lastInvitedAtMs"`
|
||||
CreatedAtMs int64 `json:"createdAtMs"`
|
||||
@ -600,24 +602,26 @@ func (r *Reader) CreateManagerProfile(ctx context.Context, userID int64, actorID
|
||||
// 不新增第二条身份,也不触碰该经理已经邀请出的 BD Leader/Admin 归属统计。
|
||||
if _, err := r.db.ExecContext(ctx, `
|
||||
INSERT INTO manager_profiles (
|
||||
app_code, user_id, status, contact_info, can_grant_avatar_frame, can_grant_vehicle,
|
||||
can_update_user_level, can_add_bd_leader, can_add_admin, can_add_superadmin, can_block_user,
|
||||
app_code, user_id, status, contact_info, can_grant_avatar_frame, can_grant_vehicle, can_grant_badge,
|
||||
can_update_user_level, can_add_bd_leader, can_add_admin, can_add_superadmin, can_block_user, can_transfer_user_country,
|
||||
created_by_admin_id, created_at_ms, updated_at_ms
|
||||
) VALUES (?, ?, 'active', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
) VALUES (?, ?, 'active', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
status = 'active',
|
||||
contact_info = VALUES(contact_info),
|
||||
can_grant_avatar_frame = VALUES(can_grant_avatar_frame),
|
||||
can_grant_vehicle = VALUES(can_grant_vehicle),
|
||||
can_grant_badge = VALUES(can_grant_badge),
|
||||
can_update_user_level = VALUES(can_update_user_level),
|
||||
can_add_bd_leader = VALUES(can_add_bd_leader),
|
||||
can_add_admin = VALUES(can_add_admin),
|
||||
can_add_superadmin = VALUES(can_add_superadmin),
|
||||
can_block_user = VALUES(can_block_user),
|
||||
can_transfer_user_country = VALUES(can_transfer_user_country),
|
||||
updated_at_ms = VALUES(updated_at_ms)
|
||||
`, appCode, userID, contact, permissions.CanGrantAvatarFrame, permissions.CanGrantVehicle,
|
||||
permissions.CanUpdateUserLevel, permissions.CanAddBDLeader, permissions.CanAddAdmin,
|
||||
permissions.CanAddSuperadmin, permissions.CanBlockUser, actorID, nowMs, nowMs); err != nil {
|
||||
permissions.CanGrantBadge, permissions.CanUpdateUserLevel, permissions.CanAddBDLeader, permissions.CanAddAdmin,
|
||||
permissions.CanAddSuperadmin, permissions.CanBlockUser, permissions.CanTransferCountry, actorID, nowMs, nowMs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items, _, err := r.ListManagers(ctx, listQuery{Keyword: strconv.FormatInt(userID, 10), Page: 1, PageSize: 1})
|
||||
@ -716,15 +720,15 @@ func (r *Reader) ListManagers(ctx context.Context, query listQuery) ([]*ManagerL
|
||||
SELECT mp.user_id, COALESCE(manager.current_display_user_id, ''), COALESCE(manager.username, ''),
|
||||
COALESCE(manager.avatar, ''), `+userCountryRegionIDSQL("manager_region")+`, `+userCountryRegionNameSQL("manager_region")+`,
|
||||
mp.status, COALESCE(mp.contact_info, ''),
|
||||
mp.can_grant_avatar_frame, mp.can_grant_vehicle, mp.can_update_user_level,
|
||||
mp.can_add_bd_leader, mp.can_add_admin, mp.can_add_superadmin, mp.can_block_user,
|
||||
mp.can_grant_avatar_frame, mp.can_grant_vehicle, mp.can_grant_badge, mp.can_update_user_level,
|
||||
mp.can_add_bd_leader, mp.can_add_admin, mp.can_add_superadmin, mp.can_block_user, mp.can_transfer_user_country,
|
||||
COUNT(DISTINCT bl.user_id), COALESCE(MAX(bl.created_at_ms), 0),
|
||||
mp.created_at_ms, mp.updated_at_ms
|
||||
%s
|
||||
GROUP BY mp.user_id, manager.current_display_user_id, manager.username, manager.avatar,
|
||||
manager_region.region_id, manager_region.name, mp.status, mp.contact_info,
|
||||
mp.can_grant_avatar_frame, mp.can_grant_vehicle, mp.can_update_user_level,
|
||||
mp.can_add_bd_leader, mp.can_add_admin, mp.can_add_superadmin, mp.can_block_user,
|
||||
mp.can_grant_avatar_frame, mp.can_grant_vehicle, mp.can_grant_badge, mp.can_update_user_level,
|
||||
mp.can_add_bd_leader, mp.can_add_admin, mp.can_add_superadmin, mp.can_block_user, mp.can_transfer_user_country,
|
||||
mp.created_at_ms, mp.updated_at_ms
|
||||
ORDER BY mp.updated_at_ms DESC, mp.user_id DESC
|
||||
LIMIT ? OFFSET ?
|
||||
@ -748,11 +752,13 @@ func (r *Reader) ListManagers(ctx context.Context, query listQuery) ([]*ManagerL
|
||||
&item.Contact,
|
||||
&item.CanGrantAvatarFrame,
|
||||
&item.CanGrantVehicle,
|
||||
&item.CanGrantBadge,
|
||||
&item.CanUpdateUserLevel,
|
||||
&item.CanAddBDLeader,
|
||||
&item.CanAddAdmin,
|
||||
&item.CanAddSuperadmin,
|
||||
&item.CanBlockUser,
|
||||
&item.CanTransferCountry,
|
||||
&item.BDLeaderCount,
|
||||
&item.LastInvitedAtMs,
|
||||
&item.CreatedAtMs,
|
||||
|
||||
@ -65,54 +65,64 @@ type createManagerRequest struct {
|
||||
TargetUserID flexibleInt64 `json:"targetUserId" binding:"required"`
|
||||
CanGrantAvatarFrame *bool `json:"canGrantAvatarFrame"`
|
||||
CanGrantVehicle *bool `json:"canGrantVehicle"`
|
||||
CanGrantBadge *bool `json:"canGrantBadge"`
|
||||
CanUpdateUserLevel *bool `json:"canUpdateUserLevel"`
|
||||
CanAddBDLeader *bool `json:"canAddBdLeader"`
|
||||
CanAddAdmin *bool `json:"canAddAdmin"`
|
||||
CanAddSuperadmin *bool `json:"canAddSuperadmin"`
|
||||
CanBlockUser *bool `json:"canBlockUser"`
|
||||
CanTransferCountry *bool `json:"canTransferUserCountry"`
|
||||
}
|
||||
|
||||
type updateManagerRequest struct {
|
||||
Contact *string `json:"contact"`
|
||||
CanGrantAvatarFrame *bool `json:"canGrantAvatarFrame"`
|
||||
CanGrantVehicle *bool `json:"canGrantVehicle"`
|
||||
CanGrantBadge *bool `json:"canGrantBadge"`
|
||||
CanUpdateUserLevel *bool `json:"canUpdateUserLevel"`
|
||||
CanAddBDLeader *bool `json:"canAddBdLeader"`
|
||||
CanAddAdmin *bool `json:"canAddAdmin"`
|
||||
CanAddSuperadmin *bool `json:"canAddSuperadmin"`
|
||||
CanBlockUser *bool `json:"canBlockUser"`
|
||||
CanTransferCountry *bool `json:"canTransferUserCountry"`
|
||||
}
|
||||
|
||||
type managerPermissions struct {
|
||||
CanGrantAvatarFrame bool
|
||||
CanGrantVehicle bool
|
||||
CanGrantBadge bool
|
||||
CanUpdateUserLevel bool
|
||||
CanAddBDLeader bool
|
||||
CanAddAdmin bool
|
||||
CanAddSuperadmin bool
|
||||
CanBlockUser bool
|
||||
CanTransferCountry bool
|
||||
}
|
||||
|
||||
func (r createManagerRequest) permissionsWithDefault() managerPermissions {
|
||||
return managerPermissions{
|
||||
CanGrantAvatarFrame: boolDefaultTrue(r.CanGrantAvatarFrame),
|
||||
CanGrantVehicle: boolDefaultTrue(r.CanGrantVehicle),
|
||||
CanGrantBadge: boolDefaultTrue(r.CanGrantBadge),
|
||||
CanUpdateUserLevel: boolDefaultTrue(r.CanUpdateUserLevel),
|
||||
CanAddBDLeader: boolDefaultTrue(r.CanAddBDLeader),
|
||||
CanAddAdmin: boolDefaultTrue(r.CanAddAdmin),
|
||||
CanAddSuperadmin: boolDefaultTrue(r.CanAddSuperadmin),
|
||||
CanBlockUser: boolDefaultTrue(r.CanBlockUser),
|
||||
CanTransferCountry: boolDefaultTrue(r.CanTransferCountry),
|
||||
}
|
||||
}
|
||||
|
||||
func (r updateManagerRequest) appendPermissionAssignments(assignments *[]string, args *[]any) {
|
||||
appendBoolAssignment(assignments, args, "can_grant_avatar_frame", r.CanGrantAvatarFrame)
|
||||
appendBoolAssignment(assignments, args, "can_grant_vehicle", r.CanGrantVehicle)
|
||||
appendBoolAssignment(assignments, args, "can_grant_badge", r.CanGrantBadge)
|
||||
appendBoolAssignment(assignments, args, "can_update_user_level", r.CanUpdateUserLevel)
|
||||
appendBoolAssignment(assignments, args, "can_add_bd_leader", r.CanAddBDLeader)
|
||||
appendBoolAssignment(assignments, args, "can_add_admin", r.CanAddAdmin)
|
||||
appendBoolAssignment(assignments, args, "can_add_superadmin", r.CanAddSuperadmin)
|
||||
appendBoolAssignment(assignments, args, "can_block_user", r.CanBlockUser)
|
||||
appendBoolAssignment(assignments, args, "can_transfer_user_country", r.CanTransferCountry)
|
||||
}
|
||||
|
||||
func appendBoolAssignment(assignments *[]string, args *[]any, column string, value *bool) {
|
||||
|
||||
@ -41,6 +41,7 @@ type UserProfileClient interface {
|
||||
UpdateUserProfile(ctx context.Context, req *userv1.UpdateUserProfileRequest) (*userv1.UpdateUserProfileResponse, error)
|
||||
UpdateUserProfileBackground(ctx context.Context, req *userv1.UpdateUserProfileBackgroundRequest) (*userv1.UpdateUserProfileBackgroundResponse, error)
|
||||
ChangeUserCountry(ctx context.Context, req *userv1.ChangeUserCountryRequest) (*userv1.ChangeUserCountryResponse, error)
|
||||
AdminChangeUserCountry(ctx context.Context, req *userv1.AdminChangeUserCountryRequest) (*userv1.ChangeUserCountryResponse, error)
|
||||
CreateManagerUserBlock(ctx context.Context, req *userv1.CreateManagerUserBlockRequest) (*userv1.CreateManagerUserBlockResponse, error)
|
||||
ListManagerUserBlocks(ctx context.Context, req *userv1.ListManagerUserBlocksRequest) (*userv1.ListManagerUserBlocksResponse, error)
|
||||
UnblockManagerUser(ctx context.Context, req *userv1.UnblockManagerUserRequest) (*userv1.UnblockManagerUserResponse, error)
|
||||
@ -338,6 +339,10 @@ func (c *grpcUserProfileClient) ChangeUserCountry(ctx context.Context, req *user
|
||||
return c.client.ChangeUserCountry(ctx, req)
|
||||
}
|
||||
|
||||
func (c *grpcUserProfileClient) AdminChangeUserCountry(ctx context.Context, req *userv1.AdminChangeUserCountryRequest) (*userv1.ChangeUserCountryResponse, error) {
|
||||
return c.client.AdminChangeUserCountry(ctx, req)
|
||||
}
|
||||
|
||||
func (c *grpcUserProfileClient) CreateManagerUserBlock(ctx context.Context, req *userv1.CreateManagerUserBlockRequest) (*userv1.CreateManagerUserBlockResponse, error) {
|
||||
return c.client.CreateManagerUserBlock(ctx, req)
|
||||
}
|
||||
|
||||
@ -141,6 +141,10 @@ func (f *fakeInviteActivityUserProfileClient) ChangeUserCountry(context.Context,
|
||||
return &userv1.ChangeUserCountryResponse{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeInviteActivityUserProfileClient) AdminChangeUserCountry(context.Context, *userv1.AdminChangeUserCountryRequest) (*userv1.ChangeUserCountryResponse, error) {
|
||||
return &userv1.ChangeUserCountryResponse{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeInviteActivityUserProfileClient) CreateManagerUserBlock(context.Context, *userv1.CreateManagerUserBlockRequest) (*userv1.CreateManagerUserBlockResponse, error) {
|
||||
return &userv1.CreateManagerUserBlockResponse{}, nil
|
||||
}
|
||||
|
||||
@ -124,18 +124,19 @@ type UserHandlers struct {
|
||||
}
|
||||
|
||||
type ManagerHandlers struct {
|
||||
ListManagerGrantResources http.HandlerFunc
|
||||
GrantManagerResource http.HandlerFunc
|
||||
LookupBusinessUsers http.HandlerFunc
|
||||
GetManagerOverview http.HandlerFunc
|
||||
SearchManagerUsers http.HandlerFunc
|
||||
GrantManagerVIP http.HandlerFunc
|
||||
ManagerBlocks http.HandlerFunc
|
||||
ListManagerBlocks http.HandlerFunc
|
||||
CreateManagerBlock http.HandlerFunc
|
||||
UnblockManagerBlock http.HandlerFunc
|
||||
SetManagerUserLevel http.HandlerFunc
|
||||
CreateManagerBDLeader http.HandlerFunc
|
||||
ListManagerGrantResources http.HandlerFunc
|
||||
GrantManagerResource http.HandlerFunc
|
||||
LookupBusinessUsers http.HandlerFunc
|
||||
GetManagerOverview http.HandlerFunc
|
||||
SearchManagerUsers http.HandlerFunc
|
||||
GrantManagerVIP http.HandlerFunc
|
||||
ManagerBlocks http.HandlerFunc
|
||||
ListManagerBlocks http.HandlerFunc
|
||||
CreateManagerBlock http.HandlerFunc
|
||||
UnblockManagerBlock http.HandlerFunc
|
||||
SetManagerUserLevel http.HandlerFunc
|
||||
CreateManagerBDLeader http.HandlerFunc
|
||||
TransferManagerUserCountry http.HandlerFunc
|
||||
}
|
||||
|
||||
type RoomHandlers struct {
|
||||
@ -462,6 +463,7 @@ func (r routes) registerManagerRoutes() {
|
||||
r.profile("/manager-center/blocks/{block_id}/unblock", http.MethodPost, h.UnblockManagerBlock)
|
||||
r.profile("/manager-center/levels", http.MethodPost, h.SetManagerUserLevel)
|
||||
r.profile("/manager-center/bd-leaders", http.MethodPost, h.CreateManagerBDLeader)
|
||||
r.profile("/manager-center/users/country", http.MethodPost, h.TransferManagerUserCountry)
|
||||
r.profile("/business/users/lookup", http.MethodGet, h.LookupBusinessUsers)
|
||||
}
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ func TestListManagerGrantResourcesChecksCapabilityAndFiltersWalletRequest(t *tes
|
||||
if recorder.Code != http.StatusOK {
|
||||
t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String())
|
||||
}
|
||||
if hostClient.lastCapability == nil || hostClient.lastCapability.GetActorUserId() != 42 || hostClient.lastCapability.GetCapability() != "manager_resource_grant" {
|
||||
if hostClient.lastCapability == nil || hostClient.lastCapability.GetActorUserId() != 42 || hostClient.lastCapability.GetCapability() != "manager_grant_badge" {
|
||||
t.Fatalf("manager capability request mismatch: %+v", hostClient.lastCapability)
|
||||
}
|
||||
if walletClient.lastListResources == nil {
|
||||
@ -160,6 +160,75 @@ func TestBusinessUserLookupForwardsSceneAndActor(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchManagerUsersDefaultsSameCountryAndAllowsAllForCountryTransfer(t *testing.T) {
|
||||
profileClient := &fakeUserProfileClient{
|
||||
businessLookupResp: &userv1.BusinessUserLookupResponse{
|
||||
Users: []*userv1.BusinessUserLookupItem{
|
||||
{UserId: 900001, DisplayUserId: "163006", Status: userv1.UserStatus_USER_STATUS_ACTIVE},
|
||||
{UserId: 900002, DisplayUserId: "163007", Status: userv1.UserStatus_USER_STATUS_ACTIVE},
|
||||
},
|
||||
},
|
||||
usersByID: map[int64]*userv1.User{
|
||||
42: {UserId: 42, Status: userv1.UserStatus_USER_STATUS_ACTIVE, Country: "US"},
|
||||
900001: {UserId: 900001, Status: userv1.UserStatus_USER_STATUS_ACTIVE, DisplayUserId: "163006", Country: "US"},
|
||||
900002: {UserId: 900002, Status: userv1.UserStatus_USER_STATUS_ACTIVE, DisplayUserId: "163007", Country: "CA"},
|
||||
},
|
||||
}
|
||||
hostClient := &fakeUserHostClient{}
|
||||
router := newManagerCenterTestRouter(&fakeWalletClient{}, hostClient, profileClient)
|
||||
|
||||
sameCountryReq := httptest.NewRequest(http.MethodGet, "/api/v1/manager-center/users/search?keyword=163&page_size=20", nil)
|
||||
sameCountryReq.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42))
|
||||
sameCountryReq.Header.Set("X-Request-ID", "req-manager-search-same")
|
||||
sameCountryRecorder := httptest.NewRecorder()
|
||||
router.ServeHTTP(sameCountryRecorder, sameCountryReq)
|
||||
|
||||
if sameCountryRecorder.Code != http.StatusOK {
|
||||
t.Fatalf("same-country search status mismatch: got %d body=%s", sameCountryRecorder.Code, sameCountryRecorder.Body.String())
|
||||
}
|
||||
var sameEnvelope struct {
|
||||
Data struct {
|
||||
Items []struct {
|
||||
UserID string `json:"user_id"`
|
||||
} `json:"items"`
|
||||
Total int `json:"total"`
|
||||
} `json:"data"`
|
||||
}
|
||||
if err := json.NewDecoder(sameCountryRecorder.Body).Decode(&sameEnvelope); err != nil {
|
||||
t.Fatalf("decode same-country response failed: %v", err)
|
||||
}
|
||||
if sameEnvelope.Data.Total != 1 || sameEnvelope.Data.Items[0].UserID != "900001" {
|
||||
t.Fatalf("same-country search must filter cross-country users: %+v", sameEnvelope.Data)
|
||||
}
|
||||
|
||||
allReq := httptest.NewRequest(http.MethodGet, "/api/v1/manager-center/users/search?keyword=163&page_size=20&scope=all", nil)
|
||||
allReq.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42))
|
||||
allReq.Header.Set("X-Request-ID", "req-manager-search-all")
|
||||
allRecorder := httptest.NewRecorder()
|
||||
router.ServeHTTP(allRecorder, allReq)
|
||||
|
||||
if allRecorder.Code != http.StatusOK {
|
||||
t.Fatalf("all-country search status mismatch: got %d body=%s", allRecorder.Code, allRecorder.Body.String())
|
||||
}
|
||||
var allEnvelope struct {
|
||||
Data struct {
|
||||
Items []struct {
|
||||
UserID string `json:"user_id"`
|
||||
} `json:"items"`
|
||||
Total int `json:"total"`
|
||||
} `json:"data"`
|
||||
}
|
||||
if err := json.NewDecoder(allRecorder.Body).Decode(&allEnvelope); err != nil {
|
||||
t.Fatalf("decode all-country response failed: %v", err)
|
||||
}
|
||||
if allEnvelope.Data.Total != 2 || allEnvelope.Data.Items[1].UserID != "900002" {
|
||||
t.Fatalf("country transfer search must include cross-country users: %+v", allEnvelope.Data)
|
||||
}
|
||||
if !hostClient.sawCapability("manager_transfer_user_country") {
|
||||
t.Fatalf("scope=all search must check transfer-country capability, saw %#v", hostClient.capabilities)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGrantManagerResourceUsesServerControlledGrantShape(t *testing.T) {
|
||||
walletClient := &fakeWalletClient{}
|
||||
hostClient := &fakeUserHostClient{}
|
||||
@ -441,6 +510,32 @@ func TestCreateManagerBDLeaderRejectsCrossCountryTarget(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransferManagerUserCountryUsesAdminCountryChangeWithoutSameCountryFilter(t *testing.T) {
|
||||
profileClient := &fakeUserProfileClient{usersByID: map[int64]*userv1.User{
|
||||
42: {UserId: 42, Status: userv1.UserStatus_USER_STATUS_ACTIVE, Country: "US", RegionId: 1001},
|
||||
}}
|
||||
hostClient := &fakeUserHostClient{}
|
||||
router := newManagerCenterTestRouter(&fakeWalletClient{}, hostClient, profileClient)
|
||||
body := []byte(`{"command_id":"mgr-country-1","target_user_id":"900001","country":"CA"}`)
|
||||
request := httptest.NewRequest(http.MethodPost, "/api/v1/manager-center/users/country", bytes.NewReader(body))
|
||||
request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42))
|
||||
request.Header.Set("X-Request-ID", "req-manager-country")
|
||||
recorder := httptest.NewRecorder()
|
||||
|
||||
router.ServeHTTP(recorder, request)
|
||||
|
||||
if recorder.Code != http.StatusOK {
|
||||
t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String())
|
||||
}
|
||||
generatedRequestID := assertGeneratedRequestID(t, recorder, "req-manager-country")
|
||||
if req := profileClient.lastAdminCountry; req == nil || req.GetMeta().GetRequestId() != generatedRequestID || req.GetAdminUserId() != 42 || req.GetTargetUserId() != 900001 || req.GetCountry() != "CA" || req.GetReason() != "manager_center_country_transfer" {
|
||||
t.Fatalf("AdminChangeUserCountry request mismatch: %+v", req)
|
||||
}
|
||||
if !hostClient.sawCapability("manager_transfer_user_country") {
|
||||
t.Fatalf("country transfer must check manager_transfer_user_country, saw %#v", hostClient.capabilities)
|
||||
}
|
||||
}
|
||||
|
||||
type fakeGrowthLevelClient struct {
|
||||
lastSet *activityv1.SetUserLevelRequest
|
||||
}
|
||||
|
||||
@ -35,17 +35,18 @@ func New(config Config) *Handler {
|
||||
|
||||
func (h *Handler) ManagerHandlers() httproutes.ManagerHandlers {
|
||||
return httproutes.ManagerHandlers{
|
||||
ListManagerGrantResources: h.listManagerGrantResources,
|
||||
GrantManagerResource: h.grantManagerResource,
|
||||
LookupBusinessUsers: h.lookupBusinessUsers,
|
||||
GetManagerOverview: h.getManagerOverview,
|
||||
SearchManagerUsers: h.searchManagerUsers,
|
||||
GrantManagerVIP: h.grantManagerVIP,
|
||||
ManagerBlocks: h.managerBlocks,
|
||||
ListManagerBlocks: h.listManagerBlocks,
|
||||
CreateManagerBlock: h.createManagerBlock,
|
||||
UnblockManagerBlock: h.unblockManagerBlock,
|
||||
SetManagerUserLevel: h.setManagerUserLevel,
|
||||
CreateManagerBDLeader: h.createManagerBDLeader,
|
||||
ListManagerGrantResources: h.listManagerGrantResources,
|
||||
GrantManagerResource: h.grantManagerResource,
|
||||
LookupBusinessUsers: h.lookupBusinessUsers,
|
||||
GetManagerOverview: h.getManagerOverview,
|
||||
SearchManagerUsers: h.searchManagerUsers,
|
||||
GrantManagerVIP: h.grantManagerVIP,
|
||||
ManagerBlocks: h.managerBlocks,
|
||||
ListManagerBlocks: h.listManagerBlocks,
|
||||
CreateManagerBlock: h.createManagerBlock,
|
||||
UnblockManagerBlock: h.unblockManagerBlock,
|
||||
SetManagerUserLevel: h.setManagerUserLevel,
|
||||
CreateManagerBDLeader: h.createManagerBDLeader,
|
||||
TransferManagerUserCountry: h.transferManagerUserCountry,
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,11 +20,13 @@ const managerCenterCapability = "manager_center"
|
||||
const managerResourceGrantCapability = "manager_resource_grant"
|
||||
const managerGrantAvatarFrameCapability = "manager_grant_avatar_frame"
|
||||
const managerGrantVehicleCapability = "manager_grant_vehicle"
|
||||
const managerGrantBadgeCapability = "manager_grant_badge"
|
||||
const managerUpdateUserLevelCapability = "manager_update_user_level"
|
||||
const managerAddBDLeaderCapability = "manager_add_bd_leader"
|
||||
const managerAddAdminCapability = "manager_add_admin"
|
||||
const managerAddSuperadminCapability = "manager_add_superadmin"
|
||||
const managerBlockUserCapability = "manager_block_user"
|
||||
const managerTransferUserCountryCapability = "manager_transfer_user_country"
|
||||
const managerGrantDayMS int64 = 24 * 60 * 60 * 1000
|
||||
const managerGrantDefaultDurationMS int64 = 7 * managerGrantDayMS
|
||||
|
||||
@ -146,10 +148,16 @@ func (h *Handler) searchManagerUsers(writer http.ResponseWriter, request *http.R
|
||||
return
|
||||
}
|
||||
// 搜索先走已有 business lookup 保持短号/昵称解析一致,再用 BatchGetUsers 拿国家和等级投影做最终过滤。
|
||||
// 只有国家转移入口显式带 scope=all 且经理拥有对应开关时,才允许跨国家搜索;其他动作继续默认同国家。
|
||||
actor, ok := h.requireManagerCenterActor(writer, request)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
scope := strings.ToLower(strings.TrimSpace(request.URL.Query().Get("scope")))
|
||||
allCountries := scope == "all"
|
||||
if allCountries && !h.requireManagerCapability(writer, request, managerTransferUserCountryCapability) {
|
||||
return
|
||||
}
|
||||
pageSize, ok := httpkit.PositiveInt32Query(request, "page_size", 20)
|
||||
if !ok {
|
||||
httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument")
|
||||
@ -193,8 +201,8 @@ func (h *Handler) searchManagerUsers(writer http.ResponseWriter, request *http.R
|
||||
items := make([]managerUserData, 0, len(userIDs))
|
||||
for _, userID := range userIDs {
|
||||
user := usersResp.GetUsers()[userID]
|
||||
// 同国家限制必须放在 gateway 写入口和读入口都做,避免 H5 通过短号枚举跨国家用户。
|
||||
if user == nil || user.GetStatus() != userv1.UserStatus_USER_STATUS_ACTIVE || !sameCountry(actor.GetCountry(), user.GetCountry()) {
|
||||
// 默认搜索必须和写入口一样收敛到同国家;国家转移已单独校验权限,允许在这里跨国家挑选目标。
|
||||
if user == nil || user.GetStatus() != userv1.UserStatus_USER_STATUS_ACTIVE || (!allCountries && !sameCountry(actor.GetCountry(), user.GetCountry())) {
|
||||
continue
|
||||
}
|
||||
items = append(items, managerUserFromProto(user, levels[userID]))
|
||||
@ -671,6 +679,65 @@ func (h *Handler) createManagerBDLeader(writer http.ResponseWriter, request *htt
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) transferManagerUserCountry(writer http.ResponseWriter, request *http.Request) {
|
||||
if h.userProfileClient == nil || h.userHostClient == nil {
|
||||
httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error")
|
||||
return
|
||||
}
|
||||
var body struct {
|
||||
TargetUserID json.RawMessage `json:"target_user_id"`
|
||||
TargetUserIDAlt json.RawMessage `json:"targetUserId"`
|
||||
Country string `json:"country"`
|
||||
CountryCode string `json:"country_code"`
|
||||
CountryCodeAlt string `json:"countryCode"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
if !httpkit.Decode(writer, request, &body) {
|
||||
return
|
||||
}
|
||||
actor, ok := h.requireManagerCenterActor(writer, request)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if !h.requireManagerCapability(writer, request, managerTransferUserCountryCapability) {
|
||||
return
|
||||
}
|
||||
targetUserID, targetOK := rawInt64(body.TargetUserID, body.TargetUserIDAlt)
|
||||
country := strings.ToUpper(strings.TrimSpace(body.Country))
|
||||
if country == "" {
|
||||
country = strings.ToUpper(strings.TrimSpace(body.CountryCode))
|
||||
}
|
||||
if country == "" {
|
||||
country = strings.ToUpper(strings.TrimSpace(body.CountryCodeAlt))
|
||||
}
|
||||
if !targetOK || targetUserID <= 0 || country == "" {
|
||||
httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument")
|
||||
return
|
||||
}
|
||||
reason := strings.TrimSpace(body.Reason)
|
||||
if reason == "" {
|
||||
reason = "manager_center_country_transfer"
|
||||
}
|
||||
// 国家转移是治理动作,不复用同国家目标校验;权限由 manager_profiles 独立开关控制,实际国家/区域事务由 user-service 统一落库和发 outbox。
|
||||
resp, err := h.userProfileClient.AdminChangeUserCountry(request.Context(), &userv1.AdminChangeUserCountryRequest{
|
||||
Meta: httpkit.UserMeta(request, ""),
|
||||
TargetUserId: targetUserID,
|
||||
Country: country,
|
||||
AdminUserId: actor.GetUserId(),
|
||||
Reason: reason,
|
||||
})
|
||||
if err != nil {
|
||||
httpkit.WriteRPCError(writer, request, err)
|
||||
return
|
||||
}
|
||||
httpkit.WriteOK(writer, request, map[string]any{
|
||||
"user": managerUserFromProto(resp.GetUser(), nil),
|
||||
"old_region_id": resp.GetOldRegionId(),
|
||||
"new_region_id": resp.GetNewRegionId(),
|
||||
"region_changed": resp.GetRegionChanged(),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) requireManagerResourceGrantCapability(writer http.ResponseWriter, request *http.Request) bool {
|
||||
return h.requireManagerCapability(writer, request, managerResourceGrantCapability)
|
||||
}
|
||||
@ -743,22 +810,26 @@ func (h *Handler) requireSameCountryTargetWithActor(writer http.ResponseWriter,
|
||||
|
||||
func (h *Handler) managerPermissionOverview(request *http.Request) map[string]bool {
|
||||
permissions := map[string]bool{
|
||||
"can_grant_avatar_frame": false,
|
||||
"can_grant_vehicle": false,
|
||||
"can_update_user_level": false,
|
||||
"can_add_bd_leader": false,
|
||||
"can_add_admin": false,
|
||||
"can_add_superadmin": false,
|
||||
"can_block_user": false,
|
||||
"can_grant_avatar_frame": false,
|
||||
"can_grant_vehicle": false,
|
||||
"can_grant_badge": false,
|
||||
"can_update_user_level": false,
|
||||
"can_add_bd_leader": false,
|
||||
"can_add_admin": false,
|
||||
"can_add_superadmin": false,
|
||||
"can_block_user": false,
|
||||
"can_transfer_user_country": false,
|
||||
}
|
||||
for key, capability := range map[string]string{
|
||||
"can_grant_avatar_frame": managerGrantAvatarFrameCapability,
|
||||
"can_grant_vehicle": managerGrantVehicleCapability,
|
||||
"can_update_user_level": managerUpdateUserLevelCapability,
|
||||
"can_add_bd_leader": managerAddBDLeaderCapability,
|
||||
"can_add_admin": managerAddAdminCapability,
|
||||
"can_add_superadmin": managerAddSuperadminCapability,
|
||||
"can_block_user": managerBlockUserCapability,
|
||||
"can_grant_avatar_frame": managerGrantAvatarFrameCapability,
|
||||
"can_grant_vehicle": managerGrantVehicleCapability,
|
||||
"can_grant_badge": managerGrantBadgeCapability,
|
||||
"can_update_user_level": managerUpdateUserLevelCapability,
|
||||
"can_add_bd_leader": managerAddBDLeaderCapability,
|
||||
"can_add_admin": managerAddAdminCapability,
|
||||
"can_add_superadmin": managerAddSuperadminCapability,
|
||||
"can_block_user": managerBlockUserCapability,
|
||||
"can_transfer_user_country": managerTransferUserCountryCapability,
|
||||
} {
|
||||
resp, err := h.userHostClient.CheckBusinessCapability(request.Context(), &userv1.CheckBusinessCapabilityRequest{
|
||||
Meta: httpkit.UserMeta(request, ""),
|
||||
@ -781,6 +852,8 @@ func managerCapabilityForResourceType(resourceType string) string {
|
||||
return managerGrantAvatarFrameCapability
|
||||
case "vehicle":
|
||||
return managerGrantVehicleCapability
|
||||
case "badge":
|
||||
return managerGrantBadgeCapability
|
||||
default:
|
||||
return managerResourceGrantCapability
|
||||
}
|
||||
|
||||
@ -314,6 +314,7 @@ type fakeUserProfileClient struct {
|
||||
lastUpdate *userv1.UpdateUserProfileRequest
|
||||
lastBackground *userv1.UpdateUserProfileBackgroundRequest
|
||||
lastCountry *userv1.ChangeUserCountryRequest
|
||||
lastAdminCountry *userv1.AdminChangeUserCountryRequest
|
||||
lastCreateBlock *userv1.CreateManagerUserBlockRequest
|
||||
lastListBlocks *userv1.ListManagerUserBlocksRequest
|
||||
lastUnblock *userv1.UnblockManagerUserRequest
|
||||
@ -865,6 +866,21 @@ func (f *fakeUserProfileClient) ChangeUserCountry(_ context.Context, req *userv1
|
||||
}, NextChangeAllowedAtMs: 3600000, OldRegionId: 1001, NewRegionId: 2002, RegionChanged: true}, nil
|
||||
}
|
||||
|
||||
func (f *fakeUserProfileClient) AdminChangeUserCountry(_ context.Context, req *userv1.AdminChangeUserCountryRequest) (*userv1.ChangeUserCountryResponse, error) {
|
||||
f.lastAdminCountry = req
|
||||
if f.countryErr != nil {
|
||||
return nil, f.countryErr
|
||||
}
|
||||
return &userv1.ChangeUserCountryResponse{User: &userv1.User{
|
||||
UserId: req.GetTargetUserId(),
|
||||
DisplayUserId: "100001",
|
||||
Country: req.GetCountry(),
|
||||
RegionId: 2002,
|
||||
Status: userv1.UserStatus_USER_STATUS_ACTIVE,
|
||||
UpdatedAtMs: 3000,
|
||||
}, OldRegionId: 1001, NewRegionId: 2002, RegionChanged: true}, nil
|
||||
}
|
||||
|
||||
func (f *fakeUserProfileClient) CreateManagerUserBlock(_ context.Context, req *userv1.CreateManagerUserBlockRequest) (*userv1.CreateManagerUserBlockResponse, error) {
|
||||
f.lastCreateBlock = req
|
||||
if f.blockErr != nil {
|
||||
|
||||
@ -772,11 +772,13 @@ CREATE TABLE IF NOT EXISTS manager_profiles (
|
||||
contact_info VARCHAR(128) NOT NULL DEFAULT '' COMMENT '联系信息',
|
||||
can_grant_avatar_frame TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心赠送头像框',
|
||||
can_grant_vehicle TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心赠送座驾',
|
||||
can_grant_badge TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心赠送徽章',
|
||||
can_update_user_level TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心升级用户等级',
|
||||
can_add_bd_leader TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心添加 BD Leader',
|
||||
can_add_admin TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心添加 Admin',
|
||||
can_add_superadmin TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心添加 Superadmin',
|
||||
can_block_user TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心封禁用户',
|
||||
can_transfer_user_country TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许在经理中心转移用户国家',
|
||||
created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建后台管理员 ID',
|
||||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||||
|
||||
@ -195,11 +195,13 @@ type ManagerProfile struct {
|
||||
Contact string
|
||||
CanGrantAvatarFrame bool
|
||||
CanGrantVehicle bool
|
||||
CanGrantBadge bool
|
||||
CanUpdateUserLevel bool
|
||||
CanAddBDLeader bool
|
||||
CanAddAdmin bool
|
||||
CanAddSuperadmin bool
|
||||
CanBlockUser bool
|
||||
CanTransferCountry bool
|
||||
CreatedByAdminID int64
|
||||
CreatedAtMs int64
|
||||
UpdatedAtMs int64
|
||||
|
||||
@ -12,11 +12,13 @@ const (
|
||||
CapabilityManagerResourceGrant = "manager_resource_grant"
|
||||
CapabilityManagerGrantAvatarFrame = "manager_grant_avatar_frame"
|
||||
CapabilityManagerGrantVehicle = "manager_grant_vehicle"
|
||||
CapabilityManagerGrantBadge = "manager_grant_badge"
|
||||
CapabilityManagerUpdateUserLevel = "manager_update_user_level"
|
||||
CapabilityManagerAddBDLeader = "manager_add_bd_leader"
|
||||
CapabilityManagerAddAdmin = "manager_add_admin"
|
||||
CapabilityManagerAddSuperadmin = "manager_add_superadmin"
|
||||
CapabilityManagerBlockUser = "manager_block_user"
|
||||
CapabilityManagerTransferCountry = "manager_transfer_user_country"
|
||||
)
|
||||
|
||||
// CheckBusinessCapability 是 App/H5 业务入口的服务端身份边界。
|
||||
@ -42,11 +44,13 @@ func (s *Service) CheckBusinessCapability(ctx context.Context, actorUserID int64
|
||||
case CapabilityManagerResourceGrant,
|
||||
CapabilityManagerGrantAvatarFrame,
|
||||
CapabilityManagerGrantVehicle,
|
||||
CapabilityManagerGrantBadge,
|
||||
CapabilityManagerUpdateUserLevel,
|
||||
CapabilityManagerAddBDLeader,
|
||||
CapabilityManagerAddAdmin,
|
||||
CapabilityManagerAddSuperadmin,
|
||||
CapabilityManagerBlockUser:
|
||||
CapabilityManagerBlockUser,
|
||||
CapabilityManagerTransferCountry:
|
||||
// 细分能力必须同时满足 active 经理身份和对应权限开关;这样 H5 被篡改后直调写接口也会被 user-service 拒绝。
|
||||
ok, err := s.repository.HasActiveManagerCapability(ctx, actorUserID, capability)
|
||||
if err != nil {
|
||||
|
||||
@ -317,16 +317,18 @@ func (r *Repository) HasActiveManagerProfile(ctx context.Context, userID int64)
|
||||
}
|
||||
|
||||
// HasActiveManagerCapability 精确校验经理中心单项能力。
|
||||
// 这里把 legacy 的 manager_resource_grant 收敛成“头像框或座驾任一资源赠送权限”,写入口仍会按真实资源类型再校验一次。
|
||||
// 这里把 legacy 的 manager_resource_grant 收敛成任一资源赠送权限,写入口仍会按真实资源类型再校验一次。
|
||||
func (r *Repository) HasActiveManagerCapability(ctx context.Context, userID int64, capability string) (bool, error) {
|
||||
columnSQL := ""
|
||||
switch capability {
|
||||
case hostservice.CapabilityManagerResourceGrant:
|
||||
columnSQL = "(can_grant_avatar_frame = 1 OR can_grant_vehicle = 1)"
|
||||
columnSQL = "(can_grant_avatar_frame = 1 OR can_grant_vehicle = 1 OR can_grant_badge = 1)"
|
||||
case hostservice.CapabilityManagerGrantAvatarFrame:
|
||||
columnSQL = "can_grant_avatar_frame = 1"
|
||||
case hostservice.CapabilityManagerGrantVehicle:
|
||||
columnSQL = "can_grant_vehicle = 1"
|
||||
case hostservice.CapabilityManagerGrantBadge:
|
||||
columnSQL = "can_grant_badge = 1"
|
||||
case hostservice.CapabilityManagerUpdateUserLevel:
|
||||
columnSQL = "can_update_user_level = 1"
|
||||
case hostservice.CapabilityManagerAddBDLeader:
|
||||
@ -337,6 +339,8 @@ func (r *Repository) HasActiveManagerCapability(ctx context.Context, userID int6
|
||||
columnSQL = "can_add_superadmin = 1"
|
||||
case hostservice.CapabilityManagerBlockUser:
|
||||
columnSQL = "can_block_user = 1"
|
||||
case hostservice.CapabilityManagerTransferCountry:
|
||||
columnSQL = "can_transfer_user_country = 1"
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@ -766,25 +766,27 @@ func (r *Repository) PutManagerProfile(profile hostdomain.ManagerProfile) {
|
||||
|
||||
_, err := r.schema.DB.ExecContext(context.Background(), `
|
||||
INSERT INTO manager_profiles (
|
||||
user_id, status, contact_info, can_grant_avatar_frame, can_grant_vehicle,
|
||||
can_update_user_level, can_add_bd_leader, can_add_admin, can_add_superadmin, can_block_user,
|
||||
user_id, status, contact_info, can_grant_avatar_frame, can_grant_vehicle, can_grant_badge,
|
||||
can_update_user_level, can_add_bd_leader, can_add_admin, can_add_superadmin, can_block_user, can_transfer_user_country,
|
||||
created_by_admin_id, created_at_ms, updated_at_ms
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
status = VALUES(status),
|
||||
contact_info = VALUES(contact_info),
|
||||
can_grant_avatar_frame = VALUES(can_grant_avatar_frame),
|
||||
can_grant_vehicle = VALUES(can_grant_vehicle),
|
||||
can_grant_badge = VALUES(can_grant_badge),
|
||||
can_update_user_level = VALUES(can_update_user_level),
|
||||
can_add_bd_leader = VALUES(can_add_bd_leader),
|
||||
can_add_admin = VALUES(can_add_admin),
|
||||
can_add_superadmin = VALUES(can_add_superadmin),
|
||||
can_block_user = VALUES(can_block_user),
|
||||
can_transfer_user_country = VALUES(can_transfer_user_country),
|
||||
updated_at_ms = VALUES(updated_at_ms)
|
||||
`, profile.UserID, profile.Status, profile.Contact, defaultTrue(profile.CanGrantAvatarFrame),
|
||||
defaultTrue(profile.CanGrantVehicle), defaultTrue(profile.CanUpdateUserLevel),
|
||||
defaultTrue(profile.CanGrantVehicle), defaultTrue(profile.CanGrantBadge), defaultTrue(profile.CanUpdateUserLevel),
|
||||
defaultTrue(profile.CanAddBDLeader), defaultTrue(profile.CanAddAdmin),
|
||||
defaultTrue(profile.CanAddSuperadmin), defaultTrue(profile.CanBlockUser),
|
||||
defaultTrue(profile.CanAddSuperadmin), defaultTrue(profile.CanBlockUser), defaultTrue(profile.CanTransferCountry),
|
||||
profile.CreatedByAdminID, profile.CreatedAtMs, profile.UpdatedAtMs)
|
||||
if err != nil {
|
||||
r.t.Fatalf("seed manager profile %d failed: %v", profile.UserID, err)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user