RuoVea.OmiApi.UserRole 10.0.0.4

dotnet add package RuoVea.OmiApi.UserRole --version 10.0.0.4
                    
NuGet\Install-Package RuoVea.OmiApi.UserRole -Version 10.0.0.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RuoVea.OmiApi.UserRole" Version="10.0.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RuoVea.OmiApi.UserRole" Version="10.0.0.4" />
                    
Directory.Packages.props
<PackageReference Include="RuoVea.OmiApi.UserRole" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add RuoVea.OmiApi.UserRole --version 10.0.0.4
                    
#r "nuget: RuoVea.OmiApi.UserRole, 10.0.0.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package RuoVea.OmiApi.UserRole@10.0.0.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=RuoVea.OmiApi.UserRole&version=10.0.0.4
                    
Install as a Cake Addin
#tool nuget:?package=RuoVea.OmiApi.UserRole&version=10.0.0.4
                    
Install as a Cake Tool

RuoVea.OmiApi.UserRole

用户角色管理 API 组件 —— 提供用户、角色、用户角色关联的完整 CRUD 服务。

RuoVea.OmiApi.UserRole 是一个开箱即用的用户角色管理系统 NuGet 包,包含系统用户管理(增删改查、密码管理、状态控制、角色授权、登录锁定解除)、系统角色管理(增删改查、状态控制、权限数据隔离)和缓存服务。支持多租户(ITenantEntity)、种子数据初始化、JWT 认证、密码加密/强度校验和数据库表自动迁移。基于 SqlSugar ORMDynamicWebApi,注册即自动生成 RESTful API 端点,支持 MySql / SqlServer / PostgreSQL / SQLite / Oracle 等多种数据库。


目录


概览

功能特性

模块 功能
👤 用户管理 增删改查、分页查询、密码修改与重置、登录锁定解除、状态启停、角色授权
🛡️ 角色管理 增删改查、分页查询(含权限过滤)、状态设置、级联删除检查
🔗 用户角色关联管理 批量授权用户角色、批量授权角色用户、按用户Id或角色Id删除关联
💾 缓存服务 Set/Get/Remove 缓存操作、前缀批量删除、缓存存在性检查、异步缓存代理
🏢 多租户支持 SysRole 和 SysUser 实现 ITenantEntity 接口,支持租户数据隔离
🌱 种子数据 预置超级管理员(superAdmin)、系统管理员(admin)、普通用户(ruovea)及对应角色
🗄️ 多库支持 MySql、SqlServer、PostgreSQL、SQLite、Oracle、Dm 等
🧩 自动 API 实现 IApplicationService 即自动映射为 REST 控制器
🔐 密码安全 用户密码使用 IPasswordServer 加密存储,支持密码强度校验,支持加密/明文双模式
🌐 i18n 国际化 通过 .resx 资源文件提供中文本地化错误/提示信息

架构一览

┌──────────────────────────────────────────────────────────────────────┐
│                        NuGet Package                                  │
│  RuoVea.OmiApi.UserRole                                               │
├──────────────────────────────────────────────────────────────────────┤
│  Service Layer (4 Services)                                           │
│  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐   │
│  │  SysUserService  │  │  SysRoleService  │  │SysUserRoleService│   │
│  │  · GetPagesAsync │  │  · GetPagesAsync │  │  (内部服务)       │   │
│  │  · AddUser       │  │  · AddRole       │  │  · GetUserRoles  │   │
│  │  · UpdateUser    │  │  · UpdateRole    │  │  · GetRoleUsers  │   │
│  │  · DeleteUser    │  │  · DeleteRole    │  │  · GrantRoles    │   │
│  │  · ChangePwd     │  │  · SetStatus     │  │  · RemoveByUserId│   │
│  │  · ResetPwd      │  │                  │  └──────────────────┘   │
│  │  · GrantRole     │  └──────────────────┘                          │
│  │  · UnlockLogin   │                                                │
│  │  · SetStatus     │  ┌──────────────────┐                          │
│  └──────────────────┘  │ SysCacheService  │                          │
│                         │  · Set/Get/Remove │                          │
│                         │  · RemoveByPrefix │                          │
│                         │  · Clear         │                          │
│                         └──────────────────┘                          │
├──────────────────────────────────────────────────────────────────────┤
│  Domain Layer (3 Entities)                                            │
│  ┌─────────────────────┐                                             │
│  │  SysUser            │────< SysUserRole >───┐                      │
│  │  · Account/Password │                      │                      │
│  │  · NickName/Phone   │                  ┌─────────────┐            │
│  │  · IsDisable/Status │                  │  SysRole    │            │
│  │  · TenantId (多租户) │                  │  · Name/Code│            │
│  └─────────────────────┘                  │  · Sort     │            │
│                                           │  · IsDisable│            │
│                                           │  · TenantId │            │
│                                           └─────────────┘            │
├──────────────────────────────────────────────────────────────────────┤
│  Infrastructure                                                       │
│  SqlSugar ORM  ·  DynamicWebApi  ·  ExSugar Repo  ·  JWT Bearer      │
│  ExFilter (异常拦截)  ·  ExPws (密码加密)  ·  ExJwtBearer (认证)      │
└──────────────────────────────────────────────────────────────────────┘

领域模型 ER 关系

  SysUser (1) ────< SysUserRole >──── (1) SysRole
  ┌────────┐       ┌───────────┐       ┌───────┐
  │ Id     │───┐   │ Id        │   ┌───│ Id    │
  │ Account│   ├──>│ UserId    │   │   │ Name  │
  │ ...    │   │   │ RoleId    │<──┘   │ Code  │
  │TenantId│   │   │ SysUser   │       │TenantId│
  └────────┘   │   │ SysRole   │       └───────┘
               │   └───────────┘
               │   SysUserRole 是多对多中间表
               │   含 SysUser 和 SysRole 导航属性 (OneToOne)
               └── UserId = SysUser.Id (FK)
               RoleId = SysRole.Id (FK)

支持的 .NET 版本

TFM NuGet 版本
net8.0 8.0.2.17
net10.0 10.0.0.3

安装

NuGet 包管理器

# .NET 8 项目
Install-Package RuoVea.OmiApi.UserRole -Version 8.0.2.17

# .NET 10 项目
Install-Package RuoVea.OmiApi.UserRole -Version 10.0.0.3

.NET CLI

dotnet add package RuoVea.OmiApi.UserRole --version 8.0.2.17

依赖项

本包依赖以下组件(安装时会自动引入):

包名 用途
RuoVea.ExFilter 全局异常拦截与模型验证
RuoVea.ExJwtBearer JWT Bearer 认证配置
RuoVea.ExPws 密码加密与强度校验(IPasswordServer)
RuoVea.OmiApi.Config 系统配置管理(DbInitConfig、Swagger等)
RuoVea.DynamicWebApi 动态 API 控制器生成
RuoVea.ExSugar SqlSugar 仓储模式封装

30 秒快速开始

1. 配置数据库连接 (appsettings.json)

{
  "ConnectionConfigs": [
    {
      "DbType": "Sqlite",
      "ConnectionString": "DataSource=./ruovea.db"
    }
  ],
  "Jwt": {
    "ValidateIssuerSigningKey": true,
    "IssuerSigningKey": "3c1cbc3f546eda35168c3aa3cb91780fbe703f0996c6d123ea96dc85c70bbc0a",
    "ValidateIssuer": true,
    "ValidIssuer": "SecurityDemo.Authentication.JWT",
    "ValidateAudience": true,
    "ValidAudience": "jwtAudience",
    "ValidateLifetime": true,
    "ExpiredTime": 1440,
    "ClockSkew": 5
  },
  "Password": {
    "Strength": "Medium"
  },
  "DbInitConfig": {
    "InitTable": true,
    "InitSeedData": true
  },
  "Swagger": {
    "ApiVersions": [
      {
        "Title": "用户角色管理",
        "Version": "system"
      }
    ]
  }
}

支持的 DbType 值: MySqlSqlServerSqliteOraclePostgreSQLDmKdbndpOpenGaussClickHouse 等。

2. 注册服务 (Program.cs)

// <summary>
// 在 Program.cs 中注册 OmiApi.UserRole 组件服务
// </summary>
var builder = WebApplication.CreateBuilder(args);

// 注册动态 Web API(自动将 Service 映射为 REST 控制器)
builder.Services.AddDynamicWebApi(options =>
{
    options.RemoveControllerPostfixes = new List<string> { "AppService", "Service" };
    options.RemovePrefix = new List<string> { "get", "post" };
});

// 注册 HttpContext 用户身份
builder.Services.AddHttpContextSetup<AspNetUser>();

// 注册 JWT 认证
builder.Services.AddAuthenticationSetup(IdentifyEnum.Jwt, true);

// 注册 SqlSugar ORM
builder.Services.AddSqlSugarSetup();

// 注册 UserRole 模块服务(默认 Scoped 生命周期)
builder.Services.AddOmiSystemSetup();

// 注册请求日志拦截、统一返回、异常处理
builder.Services
    .RequestActionSetup()
    .ResultSetup()
    .ExceptionSetup();

// 注册 Swagger
builder.Services.AddSwaggerSetup();

// 初始化数据库表结构和种子数据
builder.Services.AddSystemInitSetup();

// 跨域配置
builder.Services.AddCors(option =>
{
    option.AddDefaultPolicy(builder =>
    {
        builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
    });
});

var app = builder.Build();

app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.Run();

3. 启动并访问 Swagger

启动项目后,访问 https://localhost:xxxx/swagger,即可看到 "用户角色管理" 分组下的全部 RESTful API 端点。


核心场景

场景一:创建用户并授权角色

// <summary>
// 创建新用户 —— 异步写法。创建成功后,为用户批量授权角色。
// </summary>
public async Task<bool> CreateUserWithRolesAsync(SysUserService userService)
{
    // Step 1: 创建用户
    var userInput = new AddUserInput
    {
        Account  = "zhangsan",
        Password = "P@ssw0rd!2024",
        NickName = "张三",
        RealName = "张三丰",
        Phone    = "13800138000",
        Email    = "zhangsan@example.com",
        Sex      = Gender.Male,
        IsDisable = YesOrNot.N,
        Remark   = "市场部新员工"
    };

    var userId = await userService.AddUser(userInput);
    if (userId <= 0)
    {
        return false;
    }

    // Step 2: 为用户授权角色
    await userService.GrantRole(new UserRolesInput
    {
        UserId   = userId,
        RoleIds  = new List<long> { 2, 3 } // 授权角色 ID 列表
    });

    return true;
}

// <summary>
// 创建新用户 —— 同步写法。⚠️ 仅推荐在 Console/测试环境使用。
// </summary>
public bool CreateUserWithRoles(SysUserService userService)
{
    var userInput = new AddUserInput
    {
        Account  = "zhangsan",
        Password = "P@ssw0rd!2024",
        NickName = "张三",
        Phone    = "13800138000"
    };

    var userId = userService.AddUser(userInput).GetAwaiter().GetResult();
    if (userId <= 0) return false;

    userService.GrantRole(new UserRolesInput
    {
        UserId   = userId,
        RoleIds  = new List<long> { 2, 3 }
    }).GetAwaiter().GetResult();

    return true;
}
创建用户 + 授权角色流程:

  Step 1: 创建用户
    ├─ 校验 Account 唯一性(account_exists 检查)
    ├─ IPasswordServer 加密密码
    └─ INSERT SysUser

  Step 2: 授权用户角色
    ├─ 删除 UserId 的现有角色关联(DELETE SysUserRole)
    ├─ 检查每个 RoleId 是否存在(record_not_exists)
    └─ 批量 INSERT SysUserRole (UserId, RoleId)

场景二:修改密码与重置密码

// <summary>
// 用户自主修改密码 —— 需验证旧密码。
// </summary>
public async Task<bool> ChangeMyPasswordAsync(SysUserService userService)
{
    var input = new ChangePwdInput
    {
        Password    = "OldP@ssw0rd",
        NewPassword = "NewP@ssw0rd!2024"
    };

    // 内部校验:
    // 1. 旧密码是否正确 (password_error)
    // 2. 新旧密码不能相同 (new_password_same_as_old)
    // 3. 新密码强度校验(由 IPasswordServer 校验)
    // 4. 新密码加密后 UPDATE SysUser.Password
    return await userService.ChangePwd(input);
}

// <summary>
// 管理员重置用户密码 —— 无需旧密码验证。
// </summary>
public async Task<bool> ResetUserPasswordAsync(SysUserService userService)
{
    var input = new ResetPwdUserInput
    {
        Id       = 1001,
        Password = "Default@123456"
    };

    // 内部操作:
    // 1. 检查用户是否存在 (account_not_exists)
    // 2. IPasswordServer 加密新密码
    // 3. UPDATE SysUser SET Password = 加密后的密码
    return await userService.ResetPwd(input);
}
密码修改流程 (ChangePwd):

  开始
    │
    ├─ 1. 根据 JWT Token 获取当前登录用户
    │     若未登录 → 抛出认证异常
    │
    ├─ 2. IPasswordServer.Verify(输入的旧密码, 存储的加密密码)
    │     匹配失败 → 抛出 password_error
    │
    ├─ 3. 新密码 == 旧密码?
    │     是 → 抛出 new_password_same_as_old
    │
    ├─ 4. IPasswordServer.ValidateStrength(新密码)
    │     不满足强度要求 → 抛出校验失败
    │
    └─ 5. UPDATE SysUser SET Password = IPasswordServer.Encrypt(新密码)
    │
  结束

场景三:用户状态管理与登录解锁

// <summary>
// 设置用户启用/停用状态 —— 含安全保护检查。
// </summary>
public async Task<bool> ToggleUserStatusAsync(SysUserService userService, long userId, bool disable)
{
    var input = new UserInput
    {
        Id        = userId,
        IsDisable = disable ? YesOrNot.Y : YesOrNot.N
    };

    // ⚠️ 安全检查:
    // 1. prohibit_modify_self_status - 禁止修改本人账号状态
    // 2. prohibit_modify_super_admin_status - 禁止修改超级管理员状态
    // 3. 检查用户是否存在 (record_not_exists)
    return await userService.SetStatus(input);
}

// <summary>
// 解除用户登录锁定 —— 将 LastLoginTime 置空.
// </summary>
public async Task<bool> UnlockUserAsync(SysUserService userService, long userId)
{
    var input = new UnlockLoginInput
    {
        Id = userId
    };

    // 内部操作:
    // 1. 校验用户是否存在
    // 2. UPDATE SysUser SET LastLoginTime = NULL
    //    (某些认证流程会将 LastLoginTime 设为未来时间来实现临时锁定)
    return await userService.UnlockLogin(input);
}

场景四:角色管理与权限数据隔离

// <summary>
// 创建角色 —— 数据权限自动隔离。
// 内部自动设置 Creator 为当前登录用户。
// </summary>
public async Task<long> CreateRoleAsync(SysRoleService roleService)
{
    var input = new AddRoleInput
    {
        Name     = "内容编辑",
        Code     = "content_editor",
        Sort     = 100,
        Remark   = "负责内容的审核与发布",
        IsDisable = YesOrNot.N
    };

    return await roleService.AddRole(input);
}

// <summary>
// 分页查询角色 —— 非超管/系统管理员只能看到自己创建或已拥有的角色。
// </summary>
public async Task<PageResult<RoleOutput>> SearchRolesAsync(SysRoleService roleService)
{
    var param = new PageRoleInput
    {
        PageNo    = 1,
        PageSize  = 10,
        Name      = "管理",          // 角色名称模糊搜索
        IsDisable = YesOrNot.N       // 仅启用角色
    };

    // 权限数据隔离逻辑(内部):
    // - 超级管理员 (superAdmin) → 查看所有角色
    // - 系统管理员 (admin)     → 查看所有角色
    // - 普通用户               → 仅查看自己创建的或已拥有的角色
    return await roleService.GetPagesAsync(param);
}

// <summary>
// 删除角色 —— 级联检查。
// </summary>
public async Task DeleteRoleAsync(SysRoleService roleService, long roleId)
{
    var input = new DeleteRoleInput { Id = roleId };

    // ⚠️ 安全检查:
    // 1. prohibit_delete_admin - 禁止删除系统管理员角色
    // 2. role_has_accounts     - 角色下存在关联用户时禁止删除
    // 3. record_not_exists     - 角色不存在

    await roleService.DeleteRole(input);
}
角色删除检查流程:

  DELETE 请求
    │
    ├─ 角色是否存在?
    │   否 → 抛出 record_not_exists
    │
    ├─ 是否为系统管理员角色?
    │   是 → 抛出 prohibit_delete_admin
    │
    ├─ 是否有用户关联该角色?
    │   SELECT COUNT(*) FROM SysUserRole WHERE RoleId = @id
    │   有 → 抛出 role_has_accounts
    │
    └─ DELETE SysRole WHERE Id = @id

场景五:缓存服务操作

// <summary>
// 缓存读写操作 —— 异步写法。
// </summary>
public async Task CacheOperationsAsync(SysCacheService cacheService)
{
    // 设置缓存(带过期时间)
    await cacheService.Set("user:info:1001", new { Name = "张三", Role = "编辑" }, TimeSpan.FromMinutes(30));

    // 获取缓存
    var cached = await cacheService.GetValue("user:info:1001");

    // 检查缓存是否存在
    bool exists = await cacheService.Exists("user:info:1001");

    // 获取指定前缀的键名集合
    var keys = await cacheService.GetKeysByPrefixKey("user:info:");

    // 批量删除指定前缀的缓存
    await cacheService.RemoveByPrefixKey("user:info:");

    // 清除单个缓存
    await cacheService.Remove("user:info:1001");

    // 清空所有缓存
    await cacheService.Clear();
}

// <summary>
// 缓存操作 —— 同步写法。
// ⚠️ 注意:在 ASP.NET 上下文中可能导致死锁,仅推荐在 Console/测试环境使用。
// </summary>
public void CacheOperations(SysCacheService cacheService)
{
    cacheService.Set("key", "value", TimeSpan.FromMinutes(10)).GetAwaiter().GetResult();
    var value = cacheService.GetValue("key").GetAwaiter().GetResult();
    cacheService.Remove("key").GetAwaiter().GetResult();
}

配置选项详解

数据库连接配置 (ConnectionConfigs)

{
  "ConnectionConfigs": [
    {
      "DbType": "Sqlite",
      "ConnectionString": "DataSource=./ruovea.db",

      "EnableUnderLine": false,
      "EnableDiffLog": false,
      "IsEncrypt": false,
      "DbSecurity": "",
      "IsDeleteFilter": true,
      "IsUserIdFilter": false,
      "IsTenantIdFilter": false,
      "CommandTimeOut": 30
    }
  ]
}
参数 类型 默认值 说明
DbType string 必填 数据库类型
ConnectionString string 必填 连接字符串
EnableUnderLine bool false 驼峰转下划线
EnableDiffLog bool false 启用库表差异日志
IsEncrypt bool false 连接字符串是否加密
DbSecurity string "" 解密密钥(IsEncrypt=true 时使用)
IsDeleteFilter bool true ⚠️ 全局软删除过滤(实体需继承 IDeletedEntity
IsUserIdFilter bool false 按创建者过滤(实体需继承 ICreatorFilterEntityBase
IsTenantIdFilter bool false 按租户过滤(实体需继承 ITenantIdFilter
CommandTimeOut int 30 SQL 命令超时时间(秒)

表初始化配置 (DbInitConfig)

{
  "DbInitConfig": {
    "InitTable": true,
    "InitSeedData": true
  }
}
参数 类型 默认值 说明
InitTable bool false 启动时自动检查并创建缺失的数据表(CodeFirst)
InitSeedData bool false 是否写入种子数据(超级管理员、系统管理员、普通用户及对应角色)

性能提醒: AddSystemInitSetup 在后台执行表检查和种子数据写入。生产环境首次启动后建议将 InitTableInitSeedData 设为 false,避免每次启动都执行 IsAnyTable 检查。

JWT 认证配置 (Jwt)

{
  "Jwt": {
    "ValidateIssuerSigningKey": true,
    "IssuerSigningKey": "your-secret-key-at-least-16-chars",
    "ValidateIssuer": true,
    "ValidIssuer": "SecurityDemo.Authentication.JWT",
    "ValidateAudience": true,
    "ValidAudience": "jwtAudience",
    "ValidateLifetime": true,
    "ExpiredTime": 1440,
    "ClockSkew": 5
  }
}
参数 类型 默认值 说明
ValidateIssuerSigningKey bool true 是否验证密钥
IssuerSigningKey string 必填 ⚠️ 签名密钥,长度须大于16字符
ValidateIssuer bool true 是否验证签发方
ValidIssuer string 签发方标识
ValidateAudience bool true 是否验证签收方
ValidAudience string 签收方标识
ValidateLifetime bool true 是否验证过期时间
ExpiredTime long 1440 Token 过期时间(分钟),默认 24 小时
ClockSkew long 5 过期时间容错值(秒)

密码配置 (Password)

{
  "Password": {
    "Strength": "Medium",
    "Encrypted": true
  }
}
参数 类型 默认值 说明
Strength string Medium 密码强度要求(Low / Medium / High)
Encrypted bool true 是否启用密码加密存储(false 时明文存储)

⚠️ 安全提醒: Encrypted 设置为 false 时密码以明文存储,仅建议在开发环境使用。生产环境务必启用加密。

DI 注册配置

// <summary>
// AddOmiSystemSetup —— 三种重载,适应不同配置来源。
// 注册服务: JWT、密码配置、SysCacheService、SysRoleService、SysUserRoleService、
//          SysUserService、IPasswordServer
// </summary>

// 重载 1:自动从全局 AppSettings.Configuration 读取
builder.Services.AddOmiSystemSetup();

// 重载 2:传入自定义 IConfiguration
builder.Services.AddOmiSystemSetup(configuration.GetSection("MyUserRole"));

// 重载 3:通过 Action 委托配置
builder.Services.AddOmiSystemSetup(options =>
{
    options.InitTable    = true;
    options.InitSeedData = true;
});

// 自定义服务生命周期
builder.Services.AddOmiSystemSetup(ServiceLifetime.Singleton);

// 初始化数据库表结构(SysRole / SysUser / SysUserRole)
builder.Services.AddSystemInitSetup();
参数 类型 默认值 说明
serviceLifetime ServiceLifetime Scoped 注册 4 个服务的生命周期
config IConfiguration 自定义配置节
config (Action) Action<DbInitConfig> 代码内配置

⚠️ 线程安全: 切换为 Singleton 生命周期时,确保注入的 SugarRepository<T>ISqlSugarClient 本身支持并发访问。SqlSugar 的 SqlSugarClient 是线程安全的,但仓储的某些操作依赖请求上下文(如 Creator 自动填充、ICurrentUser 身份解析),单例模式下可能导致用户信息串扰。

种子数据说明

InitSeedData = true 时,AddSystemInitSetup 会写入以下预置数据:

角色 Code 说明
超级管理员 superAdmin 拥有系统全部权限
系统管理员 admin 拥有管理权限
用户 Account 默认密码 关联角色 说明
超级管理员 superAdmin IPasswordServer 加密 superAdmin 系统最高权限用户
系统管理员 admin IPasswordServer 加密 admin 日常管理用户
普通用户 ruovea IPasswordServer 加密 普通业务用户

API 接口速览

所有接口自动归入 Swagger "system" 分组,默认路由前缀由 DynamicWebApi 配置决定。

SysUserService — 用户管理

HTTP 方法 说明
GET GetPagesAsync 分页查询用户列表
GET UserList 获取用户列表
GET GetAllAsync 获取全部用户简要列表(仅 ID、账号、姓名)
GET GetBaseInfo 查看用户基本信息
GET GetOwnRoleList 获取用户拥有角色集合
POST AddUser 增加用户(自动去重 Account、加密密码)
PUT UpdateUser 更新用户信息
PUT UpdateBaseInfo 更新用户基本信息
PUT SetStatus 设置用户状态(启停用)
DELETE DeleteUser 删除用户(安全校验:禁止删除自己、禁止删除超管)
POST GrantRole 授权用户角色(先删后插)
POST ChangePwd 修改当前用户密码(需验证旧密码)
POST ResetPwd 重置用户密码(管理员操作,无需旧密码)
POST UnlockLogin 解除登录锁定

SysRoleService — 角色管理

HTTP 方法 说明
GET GetPagesAsync 分页查询角色列表(含权限数据隔离)
GET GetList 获取角色列表
POST AddRole 增加角色(Name/Code 唯一性校验)
PUT UpdateRole 更新角色信息
PUT SetStatus 设置角色状态(启停用)
DELETE DeleteRole 删除角色(安全校验:禁止删除管理员角色、检查关联用户)

SysUserRoleService — 用户角色关联(内部服务)

HTTP 方法 说明
(内部调用) 获取用户角色列表
(内部调用) 获取角色下的用户列表
(内部调用) 批量授权用户角色(先删后插)
(内部调用) 按用户 Id 删除关联
(内部调用) 按角色 Id 删除关联

此服务为内部服务,不对外暴露 HTTP 端点,由 SysUserServiceSysRoleService 调用。

SysCacheService — 缓存管理

HTTP 方法 说明
GET GetValue 根据键名获取缓存值
GET GetKeysByPrefixKey 根据键名前缀获取键名集合
DELETE Remove 删除指定缓存
DELETE RemoveByPrefixKey 根据键名前缀批量删除缓存
DELETE Clear 清空所有缓存

错误处理与日志

错误码速查

组件内部使用 i18n 国际化资源管理错误信息,支持中文本地化:

错误码 含义 触发场景
account_exists 账号已存在 创建用户时 Account 重复
account_not_exists 账号不存在 根据 Account 查询用户时无匹配记录
data_exists 数据已存在 创建重复的角色名称或编码
dict_status_error 字典状态错误 字典数据状态异常
illegal_operation_self 非法操作,禁止删除自己 用户尝试删除自身账号
new_password_same_as_old 新密码不能与旧密码相同 修改密码时新旧密码一致
password_error 旧密码输入错误 修改密码时旧密码验证失败
prohibit_delete_admin 禁止删除系统管理员角色 尝试删除 admin 角色
prohibit_delete_super_admin 禁止删除超级管理员 尝试删除 superAdmin 用户
prohibit_modify_self_status 禁止修改本人账号状态 用户尝试启用/停用自身账号
prohibit_modify_super_admin_status 禁止修改超级管理员状态 尝试修改 superAdmin 的状态
record_not_exists 记录不存在 根据 ID 查询/更新时记录缺失
role_has_accounts 此角色下面存在账号禁止删除 删除角色时有关联用户
no_permission 没有权限 越权操作
organization_exists 已有相同组织机构,编码或名称相同 机构重名
organization_has_users 该机构下有用户禁止删除 删除机构时有关联用户
position_exists 已存在同名或同编码职位 职位重名
position_has_users 该职位下有用户禁止删除 删除职位时有关联用户
position_not_exists 职位不存在 职位查询无匹配

异常处理示例

// <summary>
// 安全创建用户 —— 捕获账号重复、参数验证和密码强度异常。
// </summary>
public async Task<(bool Success, string Message)> SafeCreateUserAsync(
    SysUserService userService, AddUserInput input)
{
    try
    {
        var result = await userService.AddUser(input);
        return (result > 0, "用户创建成功");
    }
    catch (ArgumentException ex) when (ex.Message.Contains("account_exists"))
    {
        // 账号已存在
        return (false, $"账号 '{input.Account}' 已被注册");
    }
    catch (ArgumentException ex)
    {
        // 其他业务校验失败
        return (false, $"业务校验失败: {ex.Message}");
    }
    catch (AggregateException ex)
    {
        // 字段级验证失败(密码强度、必填字段等)
        return (false, $"字段验证失败: {ex.Message}");
    }
}

// <summary>
// 安全删除角色 —— 捕获级联检查异常。
// </summary>
public async Task<(bool Success, string Message)> SafeDeleteRoleAsync(
    SysRoleService roleService, long roleId)
{
    try
    {
        await roleService.DeleteRole(new DeleteRoleInput { Id = roleId });
        return (true, "角色删除成功");
    }
    catch (ArgumentException ex) when (ex.Message.Contains("prohibit_delete_admin"))
    {
        return (false, "系统管理员角色禁止删除");
    }
    catch (ArgumentException ex) when (ex.Message.Contains("role_has_accounts"))
    {
        return (false, "该角色下存在关联用户,请先解除所有用户授权后再删除");
    }
    catch (Exception ex)
    {
        return (false, $"删除失败: {ex.Message}");
    }
}

// <summary>
// 同步写法 —— 安全修改用户状态。
// ⚠️ 仅推荐在非 ASP.NET 上下文使用。
// </summary>
public (bool Success, string Message) SafeSetUserStatus(SysUserService userService, long userId, bool disable)
{
    try
    {
        userService.SetStatus(new UserInput
        {
            Id        = userId,
            IsDisable = disable ? YesOrNot.Y : YesOrNot.N
        }).GetAwaiter().GetResult();

        return (true, disable ? "用户已停用" : "用户已启用");
    }
    catch (Exception ex)
    {
        return (false, ex.Message);
    }
}

日志集成

组件不直接输出日志,依赖调用方集成的日志框架。推荐在 Program.cs 中配置 Serilog 或 NLog 来捕获:

// SqlSugar 的 SQL 日志可通过 AOP 事件捕获
builder.Services.AddSqlSugarSetup(); // 内部配置了 SQL 执行日志

// ExFilter 的全局异常拦截会自动记录异常日志
builder.Services.RequestActionSetup()   // 请求日志拦截
               .ExceptionSetup();       // 异常捕获与记录

版本迁移指南

从 8.0.2.x 升级到 10.0.0.x

变更项 说明
TFM 升级 net8.0net10.0,需同步升级所有依赖包到 10.0.* 版本
包版本对齐 RuoVea.ExFilterRuoVea.ExJwtBearerRuoVea.ExPwsRuoVea.OmiApi.ConfigRuoVea.DynamicWebApiRuoVea.ExSugar 均需升至对应 10.0.*
API 兼容 所有公开 API 向后兼容,无需修改业务代码
数据库 表结构无变更,无需执行迁移脚本
密码加密 IPasswordServer 接口不变,加密算法向后兼容

API 变更历史

版本 变更
8.0.2.17 稳定版本
8.0.2.16 修复多字段查询时 SqlSugar 因重复参数 @value 键报错的问题
8.0.2.15 组件版本升级,图表数据缓存
8.0.2.14 表结构初始化处理
更早版本 初始发布

常见问题

Q: 如何切换数据库?

修改 appsettings.json 中的 DbTypeConnectionString,然后重新运行。AddSystemInitSetup 会自动为新数据库创建表结构。

// MySql 示例
{ "DbType": "MySql", "ConnectionString": "Server=localhost;Database=ruovea;Uid=root;Pwd=123456;" }

// SqlServer 示例
{ "DbType": "SqlServer", "ConnectionString": "Server=.;Database=ruovea;Trusted_Connection=True;" }

// PostgreSQL 示例
{ "DbType": "PostgreSQL", "ConnectionString": "Host=localhost;Database=ruovea;Username=postgres;Password=123456;" }

Q: 如何自定义 API 路由前缀?

AddDynamicWebApi 中配置 DefaultApiPrefix

builder.Services.AddDynamicWebApi(options =>
{
    options.DefaultApiPrefix = "/openapi/api";
    options.RemoveControllerPostfixes = new List<string> { "AppService", "Service" };
    options.RemovePrefix = new List<string> { "get", "post" };
});

Q: 如何实现多租户数据隔离?

SysUserSysRole 实体实现了 ITenantEntity 接口。在 ConnectionConfigs 中启用 IsTenantIdFilter: true,SqlSugar 会自动在查询中追加 TenantId 过滤条件。同时需要在 ICurrentUser 实现中返回当前租户 ID。

{
  "ConnectionConfigs": [
    {
      "DbType": "MySql",
      "ConnectionString": "...",
      "IsTenantIdFilter": true
    }
  ]
}

Q: ⚠️ 种子数据的默认密码是什么?如何修改?

种子数据中所有用户的密码均使用 IPasswordServer 加密后写入,默认密码由配置中的 Password 配置节控制。如需修改种子用户的默认密码,请修改 AddSystemInitSetup 初始化逻辑中传入的密码明文,或在初始化后通过 ResetPwd 接口重置。

Q: ❗ 为什么 GetPagesAsync 返回的角色列表与预期不符?

角色查询会自动执行权限数据隔离

  • 超级管理员(superAdmin)和系统管理员(admin)可以查看所有角色
  • 普通用户只能查看自己创建的或已拥有的角色

如果登录用户不是超管/系统管理员,查询结果为当前用户权限范围内的角色,并非全部角色。

Q: ChangePwdResetPwd 有什么区别?

方法 使用场景 是否需要旧密码 权限要求
ChangePwd 用户自主修改密码 需要 需要登录(JWT Token)
ResetPwd 管理员重置他人密码 不需要 管理员权限

Q: 删除用户/角色时被阻止怎么办?

组件内置了安全保护检查:

  • 删除用户被阻止:检查是否为 prohibit_delete_super_admin(禁止删除超管)或 illegal_operation_self(禁止删除自己)
  • 删除角色被阻止:检查是否为 prohibit_delete_admin(禁止删除管理员角色)或 role_has_accounts(角色下有关联用户)

对于 role_has_accounts,请先通过 SysUserRoleService 解除所有用户与角色的关联,再执行角色删除。

Q: 缓存服务的底层实现是什么?

SysCacheService 是基于 ICacheService(SqlSugar 提供的缓存抽象)实现的,底层可使用 Redis、MemoryCache 或自定义缓存提供程序。缓存键名建议使用 : 分隔的命名空间前缀(如 user:info:1001role:list),便于通过 RemoveByPrefixKey 批量清理。


许可证

本项目基于 Apache 2.0 License 开源发布。


Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on RuoVea.OmiApi.UserRole:

Package Downloads
RuoVea.OmiUserRole

用户角色管理

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.0.4 95 6/26/2026
10.0.0.3 112 6/24/2026
10.0.0.2 122 5/28/2026
10.0.0.1 116 3/23/2026
10.0.0 131 1/27/2026
9.0.0.2 128 5/28/2026
9.0.0.1 122 3/23/2026
9.0.0 142 1/27/2026
8.0.2.18 98 6/26/2026
8.0.2.17 120 6/24/2026
8.0.2.16 119 5/28/2026
8.0.1.15 129 3/23/2026
8.0.1.14 143 1/27/2026
8.0.1.13 140 1/13/2026
7.0.2.16 120 5/28/2026
7.0.1.15 128 3/23/2026
7.0.1.14 147 1/27/2026
6.0.2.16 122 5/28/2026
6.0.2.15 137 3/23/2026
6.0.2.14 149 1/27/2026
Loading failed