namespace Admin.NET.Plugin.AiDOP.Entity.S8; /// /// S8-ACTION-PERMISSION-1:异常单「动作 ↔ 角色」授权行。 /// /// 身份是 (tenant_id, action_code, role_id),不含 factory —— /// 工厂从来不是隔离维度(真库 factory_ref_id = 1000 横跨两个租户)。 /// /// 为什么 S8 自己存一份,而不是继续用 SysRoleMenu: /// 平台那条链的语义是「这个角色能看见哪个菜单按钮」,租户校验只覆盖菜单、不覆盖角色, /// 于是别家租户的角色可以把 S8 能力带进本租户(见 /// 的取证)。本表把「谁能对异常单做什么」这个问题收回 S8 自己回答, /// tenant_id 是行上的一等字段,跨租户在结构上就不成立。 /// /// 只存 Action ↔ Role,不存 Action ↔ User:角色成员继续由平台的角色管理维护, /// S8 不再造第二套「谁属于哪个角色」。 /// [SugarTable("ado_s8_exception_action_role", "S8 异常动作角色授权")] [SugarIndex("uk_s8_action_role", nameof(TenantId), OrderByType.Asc, nameof(ActionCode), OrderByType.Asc, nameof(RoleId), OrderByType.Asc, IsUnique = true)] public class AdoS8ExceptionActionRole { [SugarColumn(ColumnName = "id", IsPrimaryKey = true, IsIdentity = true, ColumnDataType = "bigint")] public long Id { get; set; } /// 租户。唯一安全边界 [SugarColumn(ColumnName = "tenant_id", ColumnDataType = "bigint")] public long TenantId { get; set; } /// 动作码,取值必须在 S8ExceptionActionCatalog 内;不在目录 = 未知动作 = 拒绝。 [SugarColumn(ColumnName = "action_code", Length = 64)] public string ActionCode { get; set; } = string.Empty; /// 被授权的角色(SysRole.Id)。写入时校验该角色属于 [SugarColumn(ColumnName = "role_id", ColumnDataType = "bigint")] public long RoleId { get; set; } [SugarColumn(ColumnName = "created_at")] public DateTime CreatedAt { get; set; } = DateTime.Now; [SugarColumn(ColumnName = "created_by", Length = 64, IsNullable = true)] public string? CreatedBy { get; set; } }