Files
iotlcm/admin-svr/server/internal/logic/agent/agent_role_save_test.go
T

128 lines
6.5 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 agent
import (
"context"
"testing"
_ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcfg"
_ "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/logic/memorydb"
_ "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/logic/system"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/contexts"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model"
)
// 复现生产形态:dept 100 同时存在模板角色 18(is_pass=1)和普通角色 79(运营人员,is_pass=0)。
// 给 79 勾权限保存时,旧逻辑强制把 in.IsPass 置 1 再查重,必然报
// 「每个机构只能配置一个下级管理员角色」,导致普通角色永远改不了。
func TestSaveTemplateRoleAllowsOrdinaryRoleWithTemplateConfigured(t *testing.T) {
setupRoleSaveTestDB(t)
ctx := contexts.Set(context.Background(), &model.Context{User: &model.Identity{BaseClaims: model.BaseClaims{
ID: 1,
TenantId: "000000",
DeptId: 100,
Roles: []model.Role{{RoleId: 1}},
}}})
// 模板已配置为 18,机构 100 已有 is_pass=1 的 18
mustExecRole(t, ctx, `INSERT INTO sys_dept (dept_id, tenant_id, parent_id, dept_type, status, dept_role) VALUES (100,'000000',0,1,'0',1)`)
mustExecRole(t, ctx, `INSERT INTO sys_role (role_id, tenant_id, dept_id, role_name, role_key, status, data_scope, is_pass, created_dept) VALUES
(1,'000000',100,'超级管理员','admin','0','1',0,100),
(18,'000000',100,'代理商','dl','0','4',1,100),
(79,'000000',100,'运营人员','yunying','0','4',0,100)`)
mustExecRole(t, ctx, `INSERT INTO sys_role_menu (tenant_id, role_id, menu_id, data_scope) VALUES ('000000',18,100,'0')`)
mustExecRole(t, ctx, `INSERT INTO sys_config (config_id, tenant_id, config_key, config_value) VALUES (1,'000000','agent.role.template.role_id','18')`)
// 编辑普通角色 79:勾一个菜单
_, err := NewAgentRole().saveTemplateRole(ctx, &model.AgentRoleSaveParam{
RoleId: 79,
DeptId: 100,
RoleName: "运营人员",
RoleKey: "yunying",
Status: "0",
DataScope: "4",
MenuIds: []int64{100},
})
if err != nil {
t.Fatalf("已配置模板时普通角色必须能保存,实际报错: %v", err)
}
// 关键断言:79 不能被悄悄改成 is_pass=1
var isPass int
v, qErr := g.DB().GetValue(ctx, `SELECT is_pass FROM sys_role WHERE role_id = 79`)
if qErr != nil {
t.Fatalf("query is_pass failed: %v", qErr)
}
isPass = v.Int()
if isPass != 0 {
t.Fatalf("普通角色 79 的 is_pass 被改成了 %d,应保持 0", isPass)
}
// 模板 18 的 is_pass 也不能被动到
v18, _ := g.DB().GetValue(ctx, `SELECT is_pass FROM sys_role WHERE role_id = 18`)
if v18.Int() != 1 {
t.Fatalf("模板角色 18 的 is_pass 变成了 %d,应保持 1", v18.Int())
}
}
// 未配置平台模板时,原有「本级唯一 is_pass=1 角色」限制必须保留。
func TestSaveTemplateRoleKeepsLegacyUniquenessWithoutTemplate(t *testing.T) {
setupRoleSaveTestDB(t)
ctx := contexts.Set(context.Background(), &model.Context{User: &model.Identity{BaseClaims: model.BaseClaims{
ID: 1, TenantId: "000000", DeptId: 200,
}}})
mustExecRole(t, ctx, `INSERT INTO sys_dept (dept_id, tenant_id, parent_id, dept_type, status, dept_role) VALUES (200,'000000',0,1,'0',1)`)
mustExecRole(t, ctx, `INSERT INTO sys_role (role_id, tenant_id, dept_id, role_name, role_key, status, data_scope, is_pass, created_dept) VALUES
(1,'000000',200,'超级管理员','admin','0','1',0,200),
(90,'000000',200,'已有的下发角色','dl','0','4',1,200)`)
// 没有 sys_config 模板参数 → 走 legacy 分支
_, err := NewAgentRole().saveTemplateRole(ctx, &model.AgentRoleSaveParam{
RoleId: 0,
DeptId: 200,
RoleName: "第二个下发角色",
RoleKey: "dl2",
Status: "0",
DataScope: "4",
MenuIds: []int64{},
IsPass: 1,
})
if err == nil {
t.Fatal("未配置模板时,第二个 is_pass=1 角色必须被拒绝")
}
if err.Error() != "每个机构只能配置一个下级管理员角色" {
t.Fatalf("错误信息不符,实际: %v", err)
}
}
func setupRoleSaveTestDB(t *testing.T) {
t.Helper()
if err := gdb.SetConfig(gdb.Config{
"default": gdb.ConfigGroup{
{Type: "sqlite", Link: "sqlite::@file(:memory:)", Debug: false},
},
}); err != nil {
t.Fatalf("configure sqlite failed: %v", err)
}
_ = g.Cfg().GetAdapter().(*gcfg.AdapterFile).Set("database.memorydb.link", "")
ctx := context.Background()
t.Cleanup(func() { _ = g.DB().Close(ctx) })
mustExecRole(t, ctx, `CREATE TABLE sys_dept (dept_id INTEGER PRIMARY KEY, tenant_id TEXT, parent_id INTEGER, dept_type INTEGER, status TEXT DEFAULT '0', dept_role INTEGER, order_num INTEGER DEFAULT 0, ancestors TEXT, dept_name TEXT, deleted_at DATETIME)`)
mustExecRole(t, ctx, `CREATE TABLE sys_config (config_id INTEGER PRIMARY KEY, tenant_id TEXT, config_name TEXT, config_key TEXT, config_value TEXT, config_type TEXT, created_dept INTEGER, created_by INTEGER, created_at DATETIME, updated_by INTEGER, updated_at DATETIME, remark TEXT)`)
mustExecRole(t, ctx, `CREATE TABLE sys_role (
role_id INTEGER PRIMARY KEY AUTOINCREMENT, tenant_id TEXT, dept_id INTEGER, role_name TEXT, role_key TEXT, role_sort INTEGER, data_scope TEXT,
menu_check_strictly INTEGER, dept_check_strictly INTEGER, status TEXT, is_pass INTEGER, created_dept INTEGER, created_by INTEGER, created_at DATETIME, updated_by INTEGER, updated_at DATETIME, deleted_by INTEGER, deleted_at DATETIME, remark TEXT)`)
mustExecRole(t, ctx, `CREATE TABLE sys_role_menu (tenant_id TEXT, role_id INTEGER, menu_id INTEGER, data_scope TEXT)`)
mustExecRole(t, ctx, `CREATE TABLE sys_role_dept (tenant_id TEXT, role_id INTEGER, dept_id INTEGER)`)
mustExecRole(t, ctx, `CREATE TABLE sys_user_role (tenant_id TEXT DEFAULT '000000', user_id INTEGER, role_id INTEGER)`)
mustExecRole(t, ctx, `CREATE TABLE sys_menu (menu_id INTEGER PRIMARY KEY, menu_name TEXT, parent_id INTEGER, level INTEGER, tree TEXT, order_num INTEGER DEFAULT 0, path TEXT, component TEXT, query_param TEXT, is_frame INTEGER, is_cache INTEGER, menu_type TEXT, visible TEXT, status TEXT DEFAULT '0', perms TEXT, icon TEXT, created_dept INTEGER, created_by INTEGER, created_at DATETIME, updated_by INTEGER, updated_at DATETIME, remark TEXT)`)
mustExecRole(t, ctx, `INSERT INTO sys_menu (menu_id, menu_name, parent_id, status) VALUES (100,'卡片信息',0,'0')`)
}
func mustExecRole(t *testing.T, ctx context.Context, sql string) {
t.Helper()
if _, err := g.DB().Exec(ctx, sql); err != nil {
t.Fatalf("execute sql failed: %v\nsql=%s", err, sql)
}
}