feat: support merchant team roles and permissions
This commit is contained in:
@@ -35,3 +35,97 @@ func TestCreateAPIClientEnforcesPerMerchantLimit(t *testing.T) {
|
||||
t.Fatalf("expected per-merchant limit error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMerchantCustomRoleIsScopedAndCanCreateEmployee(t *testing.T) {
|
||||
db := newServiceTestDB(t)
|
||||
merchantA := model.Merchant{Code: "team-merchant-a", Name: "团队商户 A", Status: model.MerchantStatusActive}
|
||||
merchantB := model.Merchant{Code: "team-merchant-b", Name: "团队商户 B", Status: model.MerchantStatusActive}
|
||||
actor := model.User{Username: "team-owner", PasswordHash: "hash", Role: model.RoleMerchant, Status: 1}
|
||||
if err := db.Create(&merchantA).Error; err != nil {
|
||||
t.Fatalf("create merchant A: %v", err)
|
||||
}
|
||||
if err := db.Create(&merchantB).Error; err != nil {
|
||||
t.Fatalf("create merchant B: %v", err)
|
||||
}
|
||||
if err := db.Create(&actor).Error; err != nil {
|
||||
t.Fatalf("create actor: %v", err)
|
||||
}
|
||||
|
||||
svc := NewMerchantService(db, nil, NewTenantService(db))
|
||||
role, err := svc.CreateRole(merchantA.ID, MerchantRoleInput{
|
||||
Code: "after-sales",
|
||||
Name: "客服",
|
||||
Permissions: []string{model.PermissionOrdersManage},
|
||||
}, actor.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("create custom role: %v", err)
|
||||
}
|
||||
|
||||
member, err := svc.AddMember(merchantA.ID, AddMemberInput{
|
||||
Username: "merchant-a-support",
|
||||
Password: "password123",
|
||||
Nickname: "客服小李",
|
||||
Role: role.Code,
|
||||
}, actor.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("create employee: %v", err)
|
||||
}
|
||||
if member.User == nil || member.User.Username != "merchant-a-support" || member.Role != "after-sales" {
|
||||
t.Fatalf("unexpected member: %+v", member)
|
||||
}
|
||||
if !member.IsDefault {
|
||||
t.Fatal("new employee should default to the merchant that created it")
|
||||
}
|
||||
|
||||
if _, err := svc.AddMember(merchantB.ID, AddMemberInput{
|
||||
Username: "merchant-b-support",
|
||||
Password: "password123",
|
||||
Role: role.Code,
|
||||
}, actor.ID); err == nil {
|
||||
t.Fatal("expected merchant A role to be rejected for merchant B")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultMerchantRolesCanBeEdited(t *testing.T) {
|
||||
db := newServiceTestDB(t)
|
||||
merchant := model.Merchant{Code: "default-roles", Name: "默认角色商户", Status: model.MerchantStatusActive}
|
||||
actor := model.User{Username: "default-role-owner", PasswordHash: "hash", Role: model.RoleMerchant, Status: 1}
|
||||
if err := db.Create(&merchant).Error; err != nil {
|
||||
t.Fatalf("create merchant: %v", err)
|
||||
}
|
||||
if err := db.Create(&actor).Error; err != nil {
|
||||
t.Fatalf("create actor: %v", err)
|
||||
}
|
||||
if err := createDefaultMerchantRoles(db, merchant.ID); err != nil {
|
||||
t.Fatalf("create default roles: %v", err)
|
||||
}
|
||||
|
||||
svc := NewMerchantService(db, nil, NewTenantService(db))
|
||||
roles, err := svc.ListRoles(merchant.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("list roles: %v", err)
|
||||
}
|
||||
var finance model.MerchantRole
|
||||
var hasSupport bool
|
||||
for _, role := range roles {
|
||||
if role.Code == model.MemberRoleFinance {
|
||||
finance = role
|
||||
}
|
||||
if role.Code == "support" && role.Name == "客服" {
|
||||
hasSupport = true
|
||||
}
|
||||
}
|
||||
if finance.ID == 0 || !hasSupport {
|
||||
t.Fatalf("expected editable finance and support roles, got %+v", roles)
|
||||
}
|
||||
updated, err := svc.UpdateRole(merchant.ID, finance.ID, MerchantRoleInput{
|
||||
Name: "财务主管",
|
||||
Permissions: []string{model.PermissionWalletView},
|
||||
}, actor.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("update finance role: %v", err)
|
||||
}
|
||||
if updated.Name != "财务主管" || updated.Permissions != model.PermissionWalletView {
|
||||
t.Fatalf("unexpected updated role: %+v", updated)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user