Smail/backend/services/accountgroup/service_test.go
smail 9fa25d5ce5
Some checks are pending
Security Checks / security (push) Waiting to run
补充分组权限回归用例
覆盖管理员所属分组范围、默认分组回退、管理员多分组和普通用户单分组约束。
2026-10-02 03:53:35 +08:00

138 lines
4.4 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 accountgroup
import (
"testing"
"git.pcux.cn/xuans/Smail/models"
"git.pcux.cn/xuans/Smail/services/access"
_ "modernc.org/sqlite"
"xorm.io/xorm"
)
func TestCanAccessExcludesSuperAdminFromAdminScope(t *testing.T) {
engine, err := xorm.NewEngine("sqlite", ":memory:")
if err != nil {
t.Fatal(err)
}
defer engine.Close()
if err := engine.Sync2(new(models.User), new(models.AccountGroupMember)); err != nil {
t.Fatal(err)
}
superAdmin := models.User{Account: "superadmin", Name: "超级管理员", Role: string(access.RoleSuperAdmin)}
admin := models.User{Account: "admin", Name: "分组管理员", Role: string(access.RoleAdmin), IsAdmin: 1}
member := models.User{Account: "member", Name: "普通用户", Role: string(access.RoleUser)}
if _, err := engine.Insert(&superAdmin, &admin, &member); err != nil {
t.Fatal(err)
}
if _, err := engine.Insert(
&models.AccountGroupMember{UserID: admin.ID, GroupID: 1},
&models.AccountGroupMember{UserID: member.ID, GroupID: 1},
); err != nil {
t.Fatal(err)
}
if CanAccess(engine, admin.ID, access.RoleAdmin, superAdmin.ID) {
t.Fatal("管理员不应访问超级管理员账户")
}
if !CanAccess(engine, admin.ID, access.RoleAdmin, member.ID) {
t.Fatal("管理员应访问同组普通用户账户")
}
}
func TestMembershipScopeGuardLimitsAdminToOwnedGroups(t *testing.T) {
engine, err := xorm.NewEngine("sqlite", ":memory:")
if err != nil {
t.Fatal(err)
}
defer engine.Close()
if err := engine.Sync2(new(models.User), new(models.AccountGroup), new(models.AccountGroupMember)); err != nil {
t.Fatal(err)
}
admin := models.User{Account: "admin", Name: "分组管理员", Role: string(access.RoleAdmin), IsAdmin: 1}
superAdmin := models.User{Account: "superadmin", Name: "超级管理员", Role: string(access.RoleSuperAdmin)}
if _, err := engine.Insert(&admin, &superAdmin); err != nil {
t.Fatal(err)
}
if _, err := engine.Insert(
&models.AccountGroup{ID: 1, Name: "一组"},
&models.AccountGroup{ID: 2, Name: "二组"},
&models.AccountGroupMember{UserID: admin.ID, GroupID: 1},
); err != nil {
t.Fatal(err)
}
tx := engine.NewSession()
defer tx.Close()
if err := tx.Begin(); err != nil {
t.Fatal(err)
}
defer tx.Rollback()
if err := MembershipScopeGuard(admin.ID, access.RoleAdmin, []int{1})(tx); err != nil {
t.Fatalf("管理员应能管理所属分组:%v", err)
}
if err := MembershipScopeGuard(admin.ID, access.RoleAdmin, []int{2})(tx); err != ErrDenied {
t.Fatalf("管理员不应管理其他分组,得到:%v", err)
}
if err := MembershipScopeGuard(superAdmin.ID, access.RoleSuperAdmin, []int{2})(tx); err != nil {
t.Fatalf("超级管理员应能管理全部分组:%v", err)
}
}
func TestMembershipScopeGuardUsesDefaultGroupWhenAdminHasNoMembership(t *testing.T) {
engine, err := xorm.NewEngine("sqlite", ":memory:")
if err != nil {
t.Fatal(err)
}
defer engine.Close()
if err := engine.Sync2(new(models.User), new(models.AccountGroupMember)); err != nil {
t.Fatal(err)
}
admin := models.User{Account: "admin", Name: "默认分组管理员", Role: string(access.RoleAdmin), IsAdmin: 1}
if _, err := engine.Insert(&admin); err != nil {
t.Fatal(err)
}
tx := engine.NewSession()
defer tx.Close()
if err := tx.Begin(); err != nil {
t.Fatal(err)
}
defer tx.Rollback()
if err := MembershipScopeGuard(admin.ID, access.RoleAdmin, []int{0})(tx); err != nil {
t.Fatalf("无明确分组的管理员应能管理默认分组:%v", err)
}
if err := MembershipScopeGuard(admin.ID, access.RoleAdmin, []int{1})(tx); err != ErrDenied {
t.Fatalf("无明确分组的管理员不应管理其他分组,得到:%v", err)
}
}
func TestValidateMembershipKeepsAdminMultiGroupAndUserSingleGroupRules(t *testing.T) {
engine, err := xorm.NewEngine("sqlite", ":memory:")
if err != nil {
t.Fatal(err)
}
defer engine.Close()
if err := engine.Sync2(new(models.AccountGroup)); err != nil {
t.Fatal(err)
}
if _, err := engine.Insert(&models.AccountGroup{ID: 1, Name: "一组"}, &models.AccountGroup{ID: 2, Name: "二组"}); err != nil {
t.Fatal(err)
}
tx := engine.NewSession()
defer tx.Close()
if ids, err := ValidateMembership(tx, access.RoleAdmin, []int{1, 2}); err != nil || len(ids) != 2 {
t.Fatalf("管理员应允许多个分组,ids=%v err=%v", ids, err)
}
if _, err := ValidateMembership(tx, access.RoleUser, []int{1, 2}); err != ErrInvalid {
t.Fatalf("普通用户不应允许多个分组,得到:%v", err)
}
}