feat: 网关管理模块 + RBAC权限认证 + 组织架构 + 审计日志
- 网关管理:GatewayEntity/Service/Controller CRUD + 测试连接;设备 GatewayId 外键关联 - JWT 认证:登录签发 Token(权限编码写入 Claims)、RequirePermission 权限过滤器、CurrentUser 上下文 - RBAC:用户/角色/权限实体与 CRUD,预定义 4 角色 + 6 权限种子(admin/admin123) - 组织架构:sys_org 固定层级树(公司/实验室/部门/班组白夜班),层级校验,用户挂 OrgId/岗位/技能标签 - 数据权限:角色 DataScope(全部/本组织及下级),用户列表按组织子树过滤 - 防锁死保护:禁止删/禁自己,保证至少一名活跃管理员,角色摘除 user:manage 前校验 - 审计日志:AuditRecorder 接入设备增删改/指令下发/登录登出/组织变更,AuditController 查询 - 设备指令下发按网关表取连接参数;设备列表支持 gatewayId/productId 筛选 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
using Model.Entity.System;
|
||||
using ORM;
|
||||
|
||||
namespace Service.Implement
|
||||
{
|
||||
/// <summary>
|
||||
/// RBAC 数据种子:预定义 4 个系统角色 + 6 个权限 + 默认管理员账号(admin/admin123)
|
||||
/// 幂等:按 Code 查存在性,存在则跳过;可重复执行
|
||||
/// </summary>
|
||||
public static class DataSeeder
|
||||
{
|
||||
/// <summary>数据范围:1=全部, 2=本实验室</summary>
|
||||
public const byte DataScopeAll = 1;
|
||||
public const byte DataScopeLab = 2;
|
||||
|
||||
/// <summary>6 个系统权限编码</summary>
|
||||
public static readonly (string Code, string Name, string Group)[] Permissions =
|
||||
{
|
||||
("device:view", "查看设备", "device"),
|
||||
("device:edit", "编辑设备", "device"),
|
||||
("device:control", "控制设备", "device"),
|
||||
("alert:confirm", "确认告警", "alert"),
|
||||
("inspection:manage", "巡检管理", "inspection"),
|
||||
("user:manage", "用户管理", "user")
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 4 个预定义角色:超级管理员(全部) / 实验室管理员(本实验室) / 设备操作员(本实验室) / 维修工程师(本实验室)
|
||||
/// 权限矩阵严格按需求文档
|
||||
/// </summary>
|
||||
public static readonly (string Code, string Name, byte DataScope, string[] Permissions)[] Roles =
|
||||
{
|
||||
("superadmin", "超级管理员", DataScopeAll, new[] { "device:view", "device:edit", "device:control", "alert:confirm", "inspection:manage", "user:manage" }),
|
||||
("labadmin", "实验室管理员", DataScopeLab, new[] { "device:view", "device:edit", "device:control", "alert:confirm", "inspection:manage" }),
|
||||
("operator", "设备操作员", DataScopeLab, new[] { "device:view", "inspection:manage" }),
|
||||
("maintengineer", "维修工程师", DataScopeLab, new[] { "device:view", "device:edit", "device:control", "alert:confirm" })
|
||||
};
|
||||
|
||||
public static void Seed()
|
||||
{
|
||||
try
|
||||
{
|
||||
var db = SqlSugarContext.DbContext;
|
||||
var now = DateTime.Now;
|
||||
|
||||
// 1. 权限种子
|
||||
var permIdByCode = new Dictionary<string, long>();
|
||||
foreach (var (code, name, group) in Permissions)
|
||||
{
|
||||
var existing = db.Queryable<PermissionEntity>().Where(x => x.Code == code).First();
|
||||
if (existing != null) { permIdByCode[code] = existing.Id; continue; }
|
||||
var perm = new PermissionEntity
|
||||
{
|
||||
Code = code, Name = name, Group = group, IsSystem = 1,
|
||||
Sort = Array.FindIndex(Permissions, p => p.Code == code),
|
||||
CreateTime = now
|
||||
};
|
||||
var id = db.Insertable(perm).ExecuteReturnSnowflakeId();
|
||||
permIdByCode[code] = id;
|
||||
}
|
||||
|
||||
// 2. 角色种子 + 角色-权限关联
|
||||
foreach (var (code, name, scope, perms) in Roles)
|
||||
{
|
||||
var role = db.Queryable<RoleEntity>().Where(x => x.Code == code).First();
|
||||
long roleId;
|
||||
if (role == null)
|
||||
{
|
||||
role = new RoleEntity
|
||||
{
|
||||
Code = code, Name = name, DataScope = scope, IsSystem = 1,
|
||||
Sort = Array.FindIndex(Roles, r => r.Code == code),
|
||||
Remark = "系统预定义角色",
|
||||
CreateTime = now
|
||||
};
|
||||
roleId = db.Insertable(role).ExecuteReturnSnowflakeId();
|
||||
}
|
||||
else
|
||||
{
|
||||
roleId = role.Id;
|
||||
}
|
||||
|
||||
// 补齐角色-权限关联(只加不删,避免覆盖管理员自定义调整)
|
||||
foreach (var permCode in perms)
|
||||
{
|
||||
if (!permIdByCode.TryGetValue(permCode, out var permId)) continue;
|
||||
var linkExists = db.Queryable<RolePermissionEntity>()
|
||||
.Where(x => x.RoleId == roleId && x.PermissionId == permId).Any();
|
||||
if (!linkExists)
|
||||
{
|
||||
db.Insertable(new RolePermissionEntity { RoleId = roleId, PermissionId = permId, CreateTime = now }).ExecuteCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 默认管理员账号(admin/admin123,挂在超级管理员角色)
|
||||
var adminExists = db.Queryable<UserEntity>().Where(x => x.UserName == "admin" && x.IsDel == 0).Any();
|
||||
if (!adminExists)
|
||||
{
|
||||
var superAdmin = db.Queryable<RoleEntity>().Where(x => x.Code == "superadmin").First();
|
||||
var admin = new UserEntity
|
||||
{
|
||||
UserName = "admin",
|
||||
PasswordHash = PasswordHelper.Hash("admin123"),
|
||||
RealName = "系统管理员",
|
||||
IsEnabled = 1,
|
||||
Remark = "系统默认管理员(首次登录后请修改密码)",
|
||||
CreateTime = now
|
||||
};
|
||||
var adminId = db.Insertable(admin).ExecuteReturnSnowflakeId();
|
||||
if (superAdmin != null)
|
||||
{
|
||||
db.Insertable(new UserRoleEntity { UserId = adminId, RoleId = superAdmin.Id, CreateTime = now }).ExecuteCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// 种子失败不阻断启动(例如表刚建好并发场景),下次启动会重试
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user