diff --git "a/\350\265\265\346\254\243/0701.\345\210\233\345\273\272\351\241\271\347\233\256\357\274\214\346\224\276\345\205\245\350\247\243\345\206\263\346\226\271\346\241\210.md" "b/\350\265\265\346\254\243/0701.\345\210\233\345\273\272\351\241\271\347\233\256\357\274\214\346\224\276\345\205\245\350\247\243\345\206\263\346\226\271\346\241\210.md" new file mode 100644 index 0000000000000000000000000000000000000000..601bddaba1cdfbe3f3f5180d3dd9f81f523020db --- /dev/null +++ "b/\350\265\265\346\254\243/0701.\345\210\233\345\273\272\351\241\271\347\233\256\357\274\214\346\224\276\345\205\245\350\247\243\345\206\263\346\226\271\346\241\210.md" @@ -0,0 +1,61 @@ +## 创建项目,放入解决方案 +```c# +dotnet new webapi -n Admin2024.Api +dotnet new classlib -n Admin2024.Application +dotnet new classlib -n Admin2024.Application.Contracts +dotnet new classlib -n Admin2024.Domain +dotnet new classlib -n Admin2024.Infrastructure +dotnet new classlib -n Admin2024.EntityFrameworkCore + +dotnet new sln -n Admin2024 + +dotnet sln add Admin2024.Api +dotnet sln add Admin2024.Application +dotnet sln add Admin2024.Application.Contracts +dotnet sln add Admin2024.Domain +dotnet sln add Admin2024.Infrastructure +dotnet sln add Admin2024.EntityFrameworkCore +``` + +操作Domain文件: +- 新建文件夹Entity--BaseEntity.cs +- 在Entity中新建文件夹System--AppUser.cs AppRole.cs AppUserRole.cs AppPermission.cs AppRolePermission.cs AppOperation.cs AppResource.cs +- 新建文件夹Interface(与Entity同级)--IRepository.cs + +具体代码见文件夹*work* + + +## RBAC +### RBAC是什么 +基于角色(Role)的访问控制,通过将*权限*分配给*角色*,再将*角色*分配给*用户*,从而实现对系统资源的访问控制。 + +核心概念: +- 角色(Role):角色是指在系统中具有一组相关权限的抽象概念,代表了用户在特定上下文中的身份或职能,例如管理员、普通用户等; +- 权限(Permission):权限是指对系统资源进行操作的许可,如读取、写入、修改等。权限可以被分配给角色; +- 用户(User):用户是具有特定角色和权限的实体,可以登录系统并执行操作,每个用户可以别分配一个或多个角色; +- 分配(Assignment):分配是指将角色与用户关联起来,以赋予用户相应的权限。 + +RBAC认为授权实际上是who、what和how三元组之间的关系,也就是who对what进行how的操作,也就是“主体”对“客体”的操作。 +- who:权限的拥有者或主体(如:User,Role) +- what:操作或对象(operation,object) +- how:具体的权限(Privilege,正向授权与负向授权) + +### RBAC流程图 +![alt text](img/RBAC流程图.png) + + +### RBAC各模块功能 +![alt text](img/RBAC各模块功能图.png) + + +### RBAC访问控制流程 +![alt text](img/RBAC访问控制流程图.png) + + +### 数据库设计及相关表结构 +#### 主外键关联的 +![alt text](img/主外键关联表.png) + + +#### 非主外键(虚拟) +![alt text](img/非主外键图.png) \ No newline at end of file diff --git "a/\350\265\265\346\254\243/0702.\345\241\253\345\205\205\351\203\250\345\210\206\351\242\206\345\237\237\345\256\236\344\275\223\347\232\204\350\241\214\344\270\272\357\274\214\345\256\214\346\210\220\351\200\232\347\224\250\344\273\223\345\202\250\346\216\245\345\217\243.md" "b/\350\265\265\346\254\243/0702.\345\241\253\345\205\205\351\203\250\345\210\206\351\242\206\345\237\237\345\256\236\344\275\223\347\232\204\350\241\214\344\270\272\357\274\214\345\256\214\346\210\220\351\200\232\347\224\250\344\273\223\345\202\250\346\216\245\345\217\243.md" new file mode 100644 index 0000000000000000000000000000000000000000..86f12d14daa2c815bca15fdf13daf46d768693b8 --- /dev/null +++ "b/\350\265\265\346\254\243/0702.\345\241\253\345\205\205\351\203\250\345\210\206\351\242\206\345\237\237\345\256\236\344\275\223\347\232\204\350\241\214\344\270\272\357\274\214\345\256\214\346\210\220\351\200\232\347\224\250\344\273\223\345\202\250\346\216\245\345\217\243.md" @@ -0,0 +1,321 @@ +BaseEntity.cs: +```c# +namespace Admin2024.Domain.Entity; + +public abstract class BaseEntity +{ + //主键Id + public Guid Id { get; set; } + //是否启用/激活 + public bool IsActived { get; set; } + //是否删除 + public bool IsDeleted { get; set; } + //创建时间 + public DateTime CreatedAt { get; set; } + //创建人 + public Guid CreatedBy { get; set; } + //最后更新时间 + public DateTime UpdatedAt { get; set; } + //最后更新人 + public Guid UpdatedBy { get; set; } + //显示顺序,数字越大越靠前 + public int DisplayOrder { get; set; } + //备注 + public string? Remarks { get; set; } +} +``` + + +AppUser.cs: +```c# +namespace Admin2024.Domain.Entity.System +{ + /// + /// 应用用户实体类,继承自基础实体类BaseEntity,代表系统中的一个用户。 + /// + public class AppUser : BaseEntity + { + // 用户的角色集合,用于存储用户所拥有的角色。 + private List _appRoles = new List(); + + // 用户名,用于唯一标识一个用户。 + public string Username { get; set; } = null!; + + // 用户密码,用于验证用户身份。 + public string Password { get; set; } = null!; + + // 随机加密字符串,用于密码加密。 + public string Salt { get; set; } = null!; + + // 用户昵称,用于显示给其他用户看到的名称。 + public string Nickname { get; set; } = null!; + + // 用户头像地址,用于显示用户头像。 + public string Avatar { get; set; } = null!; + + // 用户手机号码,用于用户身份验证和联系用户。 + public string Telephone { get; set; } = null!; + + // 用户微信号,用于绑定微信登录。 + public string Weixin { get; set; } = null!; + + // 用户QQ号,用于绑定QQ登录。 + public string QQ { get; set; } = null!; + + // 设置用户密码 + public void SetPassword(string password) + { + this.Password = password; + } + + // 为用户分配角色。 + //"appRole"待分配的角色 + public void AllocateRole(AppRole appRole) + { + _appRoles.Add(appRole); + } + + // 移除用户的一个角色 + //"appRole"待移除的角色 + public void RemoveRole(AppRole appRole) + { + _appRoles.Remove(appRole); + } + + // 通过角色名移除用户的一个角色 + //"roleName"待移除的角色名 + public void RemoveRole(string roleName) + { + var role = _appRoles.FirstOrDefault(x => x.RoleName == roleName); + if (role != null) + { + _appRoles.Remove(role); + } + } + + // 检查用户是否具有权限 + //始终返回true,表示具有权限。实际应用中应根据角色权限进行具体实现 + public bool HasPermssion() + { + return true; + } + } +} +``` + +AppRole.cs: +```c# +namespace Admin2024.Domain.Entity.System +{ + /// + /// 应用角色实体类,继承自基础实体类BaseEntity,定义系统中的角色及其权限。 + /// + public class AppRole : BaseEntity + { + // 角色关联的权限列表。 + private List _appPermission = new List(); + + // 角色名称,用于标识角色的唯一名称。 + public string RoleName { get; set; } = null!; + + // 角色描述,对角色的简短说明。 + public string? Description { get; set; } + + /// + /// 角色构造函数,无参构造。 + /// + public AppRole() + { + } + + /// + /// 角色构造函数,带角色名和描述的构造。 + /// + /// 角色名称。 + /// 角色描述。 + public AppRole(string roleName, string description) + { + RoleName = roleName; + Description = description; + } + + /// + /// 分配权限给角色。 + /// + /// 待分配的权限实例。 + public void AllocatePermission(AppPermission appPermission) + { + _appPermission.Add(appPermission); + } + + /// + /// 从角色中移除权限。 + /// + /// 待移除的权限实例。 + public void RemovePermission(AppPermission appPermission) + { + _appPermission.Remove(appPermission); + } + + /// + /// 判断角色是否拥有指定资源和操作的权限。 + /// + /// 资源实例。 + /// 操作实例。 + /// 如果拥有权限则返回true,否则返回false。 + public bool HasPermission(AppResource appResource, AppOperation appOperation) + { + return _appPermission.Any(x => x.AppResourceId == appResource.Id + && x.AppOperationId == appOperation.Id); + } + + /// + /// 根据资源ID和操作ID判断角色是否拥有指定权限。 + /// + /// 资源ID。 + /// 操作ID。 + /// 如果拥有权限则返回true,否则返回false。 + public bool HasPermission(Guid resourceId, Guid operationId) + { + return _appPermission.Any(x => x.AppResourceId == resourceId + && x.AppOperationId == operationId); + } + } +} +``` + +AppUserRole.cs: +```c# +namespace Admin2024.Domain.Entity.System; + +public class AppUserRole : BaseEntity +{ + public Guid AppUserId { get; set; } + public Guid AppRoleId { get; set; } +} +``` + +AppPermission.cs: +```c# +namespace Admin2024.Domain.Entity.System +{ + /// + /// 应用权限基类,继承自 ,包含了应用资源标识和操作标识。 + /// + public class AppPermission : BaseEntity + { + // 获取或设置应用资源的唯一标识。 + public Guid AppResourceId { get; set; } + + // 获取或设置应用操作的唯一标识。 + public Guid AppOperationId { get; set; } + + // 初始化一个 实例。 + public AppPermission() + { + // 默认构造函数,通常用于数据库映射或其他框架初始化。 + } + + /// + /// 初始化一个 实例,指定应用资源标识和操作标识。 + /// + /// 应用资源的唯一标识。 + /// 应用操作的唯一标识。 + public AppPermission(Guid appResourceId, Guid appOperationId) + { + AppResourceId = appResourceId; + AppOperationId = appOperationId; + } + } +} +``` + +AppRolePermission.cs: +```c# +namespace Admin2024.Domain.Entity.System +{ + + // "AppRolePermission" 类表示应用角色与权限之间的关联信息 + public class AppRolePermission : BaseEntity + { + /// + /// 获取或设置应用角色的唯一标识。 + /// + public Guid AppRoleId { get; set; } + + /// + /// 获取或设置应用权限的唯一标识。 + /// + public Guid AppPermissionId { get; set; } + } +} +``` + +AppOperation.cs: +```c# +namespace Admin2024.Domain.Entity.System +{ + /// + /// 类表示应用程序中的一个操作项, + /// 继承自 ,包含操作名称和描述信息。 + /// + public class AppOperation : BaseEntity + { + // 获取或设置操作的名称 + public string OperationName { get; set; } = null!; + + /// 获取或设置操作的描述信息 + public string? Descript { get; set; } + } +} +``` + +AppResource.cs: +```c# +namespace Admin2024.Domain.Entity.System; + +public class AppResource : BaseEntity +{ + //资源名称 + public string ResourceName { get; set; } = null!; + //资源的访问URL + public string Url { get; set; } = null!; +} +``` + +IRepository.cs: +```c# +using Admin2024.Domain.Entity; + +namespace Admin2024.Domain.Interface; + +/// +/// 定义了对实体类型T进行基本CRUD操作的接口。 +/// T必须继承自BaseEntity以确保具有基础的实体属性与行为。 +/// +/// 实体类型,继承自BaseEntity。 +public interface IRepository where T : BaseEntity +{ + // 异步根据ID获取单个实体。 + Task GetByIdAsync(Guid id); + + // 异步获取所有实体的列表。 + Task> GetListAsync(); + + // 异步创建一个新的实体。 + // 返回已创建并可能包含新分配ID的实体对象。 + Task CreateAsync(T entity); + + // 异步更新指定ID的实体。 + // 返回已更新的实体对象,如果更新成功。 + Task UpdateAsync(Guid id, T entity); + + // 异步根据ID删除实体。 + // 如果删除成功则返回被删除的实体,否则返回null。 + Task DeleteAsync(Guid id); + + // 异步根据实体实例删除实体。 + // 如果删除成功则返回被删除的实体,否则返回null。 + Task DeleteAsync(T entity); +} +``` \ No newline at end of file diff --git "a/\350\265\265\346\254\243/0703.flunt API.md" "b/\350\265\265\346\254\243/0703.flunt API.md" new file mode 100644 index 0000000000000000000000000000000000000000..36254a08a23cfe6103cb9fdbc7bc4a4ffb5a81fa --- /dev/null +++ "b/\350\265\265\346\254\243/0703.flunt API.md" @@ -0,0 +1,99 @@ +Fluent API(流畅 API)是 Entity Framework Core 提供的一种配置数据库模型的方法,它允许开发者通过链式调用方法来定义实体类与数据库之间的映射关系,而不需要使用传统的属性标记(attributes)或 XML 配置文件。这种方式使得配置更加直观和易于理解。 + +### Fluent API 的优势和用法: + +1. **可读性和可维护性**: + - Fluent API 使用链式调用来配置实体,使得配置代码更加紧凑和可读性更高,特别是在配置复杂关系或者索引时,相比使用属性标记或者 XML 配置,更易于维护和理解。 + +2. **灵活性**: + - Fluent API 提供了丰富的方法来配置实体的各个方面,如表名、列名、主键、外键关系、索引、约束等,可以精确地控制实体在数据库中的映射。 + +3. **集中式配置**: + - 使用 Fluent API 可以将所有与数据库映射相关的配置集中在一个类中,通常是一个继承自 `IEntityTypeConfiguration` 的配置类,这样有助于代码组织和维护。 + +4. **不侵入性**: + - Fluent API 的配置不会侵入到实体类本身,这意味着你可以保持实体类的纯粹性,不需要引入和依赖于特定的 ORM 特性。 + +### 示例和常见用法: + +下面是一些使用 Fluent API 配置实体映射的示例,假设我们有一个 `Product` 实体和一个 `Category` 实体,它们之间是一对多的关系: + +```c# +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +public class Product +{ + public int ProductId { get; set; } + public string Name { get; set; } + public decimal Price { get; set; } + + public int CategoryId { get; set; } + public Category Category { get; set; } +} + +public class Category +{ + public int CategoryId { get; set; } + public string Name { get; set; } + + public ICollection Products { get; set; } +} + +public class ProductConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + // 表名 + builder.ToTable("Products"); + + // 主键 + builder.HasKey(p => p.ProductId); + + // 列配置 + builder.Property(p => p.Name) + .HasColumnName("ProductName") + .HasMaxLength(100) + .IsRequired(); + + builder.Property(p => p.Price) + .HasColumnType("decimal(18,2)") + .IsRequired(); + + // 外键关系 + builder.HasOne(p => p.Category) + .WithMany(c => c.Products) + .HasForeignKey(p => p.CategoryId); + } +} + +public class CategoryConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + // 表名 + builder.ToTable("Categories"); + + // 主键 + builder.HasKey(c => c.CategoryId); + + // 列配置 + builder.Property(c => c.Name) + .HasMaxLength(50) + .IsRequired(); + + // 导航属性配置 + builder.HasMany(c => c.Products) + .WithOne(p => p.Category) + .HasForeignKey(p => p.CategoryId); + } +} +``` + +在上面的示例中,我们展示了如何使用 Fluent API 配置 `Product` 和 `Category` 实体的映射关系和表结构: + +- `ProductConfiguration` 和 `CategoryConfiguration` 类实现了 `IEntityTypeConfiguration` 接口,并在 `Configure` 方法中使用 Fluent API 来配置实体的映射关系。 +- 通过 `builder.ToTable` 方法指定了实体在数据库中对应的表名。 +- 使用 `builder.HasKey` 方法配置了主键。 +- 使用 `builder.Property` 方法配置了各个属性的列名、数据类型、最大长度等信息。 +- 使用 `builder.HasOne`、`builder.WithMany` 和 `builder.HasForeignKey` 方法配置了实体之间的关系,如外键关系。 diff --git "a/\350\265\265\346\254\243/0704.\345\256\214\346\210\220\346\234\215\345\212\241\345\261\202\346\216\245\345\217\243\345\217\212Dto\357\274\214\345\234\250\346\216\247\345\210\266\345\231\250\350\260\203\347\224\250\345\257\271\345\272\224\346\234\215\345\212\241.md" "b/\350\265\265\346\254\243/0704.\345\256\214\346\210\220\346\234\215\345\212\241\345\261\202\346\216\245\345\217\243\345\217\212Dto\357\274\214\345\234\250\346\216\247\345\210\266\345\231\250\350\260\203\347\224\250\345\257\271\345\272\224\346\234\215\345\212\241.md" new file mode 100644 index 0000000000000000000000000000000000000000..fd98da16291b7186ea7145aec2a4af802b2319e9 --- /dev/null +++ "b/\350\265\265\346\254\243/0704.\345\256\214\346\210\220\346\234\215\345\212\241\345\261\202\346\216\245\345\217\243\345\217\212Dto\357\274\214\345\234\250\346\216\247\345\210\266\345\231\250\350\260\203\347\224\250\345\257\271\345\272\224\346\234\215\345\212\241.md" @@ -0,0 +1,174 @@ +Admin2024.Api--UsersController.cs: +```c# + +``` + +Adminn2024.Application.Cotracts-->新建文件夹AppUser + +新建文件AppUserDto.cs: +```c# +namespace Admin2024.Application.Contracts.AppUser; + +public class AppUserDto +{ + public Guid Id { get; set; } + public string Username { get; set; } = null!; + public string Password { get; set; } = null!; +} +``` + +新建文件CreateAppUserDto.cs: +```c# +namespace Admin2024.Application.Contracts.AppUser; + +public class CreateAppUserDto +{ + public string Username { get; set; } = null!; + public string Password { get; set; } = null!; + public string ConfirmPassword { get; set; } = null!; +} +``` + +新建文件IAppUserAppService.cs: +```c# +/* 此接口定义了应用用户管理的服务接口, + 包含用户注册、登录、登出、禁用、删除、更新、密码修改及角色分配等功能。 +*/ + + +namespace Admin2024.Application.Contracts.AppUser +{ + public interface IAppUserAppService + { + // 注册新用户 + // "createAppUserDto" 包含新用户信息的数据传输对象 + // 注册成功后的用户信息,如果失败则返回null + Task Registry(CreateAppUserDto createAppUserDto); + + // 用户登录 + void Login(string username, string password); + + // 用户登出 + // "token" 用户的认证令牌 + void Logout(string token); + + // 禁用用户账号 + void DisableUser(); + + // 删除用户账号 + void Delete(); + + // 更新用户信息 + // "updateAppUserDto" 包含更新信息的数据传输对象 + void Update(UpdateAppUserDto updateAppUserDto); + + // 修改用户密码 + void ModifyPassword(string password); + + // 为用户分配角色 + void AllcateRoleToUser(); + } +} +``` + +新建文件UpdateAppUserDto.cs: +```c# +namespace Admin2024.Application.Contracts.AppUser; + +public class UpdateAppUserDto +{ + +} +``` + +Admin2024.Application--新建文件夹AppUser + +新建文件AppUserAppService.cs: +```c# +using Admin2024.Application.Contracts.AppUser; +using Admin2024.Domain.Entity.System; +using Admin2024.Domain.Interface; + +namespace Admin2024.Application.User; + +public class AppUserAppService : IAppUserAppService +{ + private readonly IRepository _appRepository; + + public AppUserAppService(IRepository appRepository) + { + _appRepository = appRepository; + } + + public void AllcateRoleToUser() + { + throw new NotImplementedException(); + } + + public void Delete() + { + throw new NotImplementedException(); + } + + public void DisableUser() + { + throw new NotImplementedException(); + } + + public void Login(string username, string password) + { + throw new NotImplementedException(); + } + + public void Logout(string token) + { + throw new NotImplementedException(); + } + + public void ModifyPassword(string password) + { + throw new NotImplementedException(); + } + + public async Task Registry(CreateAppUserDto createAppUserDto) + { + if (createAppUserDto.Password == createAppUserDto.ConfirmPassword) + { + var appUser = new AppUser + { + Username = createAppUserDto.Username, + Password = createAppUserDto.Password, + Salt = "哈", + Nickname = "哈哈", + Telephone = "123456", + QQ = "654321", + Weixin = "13579", + Avatar = "没有头像" + }; + appUser.Registry(); + var res = await _appRepository.CreateAsync(appUser); + var dto = new AppUserDto + { + Id = res.Id, + Username = res.Username, + Password = res.Password + }; + return dto; + } + return null; + } + + public void Update(UpdateAppUserDto updateAppUserDto) + { + throw new NotImplementedException(); + } +} +``` + + + +```c# +dotnet ef migrations add 名 -p 迁移文件 -s 启动文件 + +dotnet ef database update -p 迁移文件 -s 启动文件 +``` \ No newline at end of file diff --git "a/\350\265\265\346\254\243/0705.postgresql\345\234\250\346\234\215\345\212\241\345\231\250\344\270\212\347\232\204\345\256\211\350\243\205\345\222\214\351\205\215\347\275\256.md" "b/\350\265\265\346\254\243/0705.postgresql\345\234\250\346\234\215\345\212\241\345\231\250\344\270\212\347\232\204\345\256\211\350\243\205\345\222\214\351\205\215\347\275\256.md" new file mode 100644 index 0000000000000000000000000000000000000000..0c7e0fe1eb9af7df0a818b41e4e39daad7e0d146 --- /dev/null +++ "b/\350\265\265\346\254\243/0705.postgresql\345\234\250\346\234\215\345\212\241\345\231\250\344\270\212\347\232\204\345\256\211\350\243\205\345\222\214\351\205\215\347\275\256.md" @@ -0,0 +1,79 @@ +**以阿里云的云服务器ECS、Ubuntu操作系统为例。** +## 1. 域名解析 +- 阿里云中点控制台,选择域名 +- 在域名列表中选择需要解析的域名,点击解析 +- 添加记录,然后填入服务器公网IP,公网IP在云服务器ECS->实例 + +## 2. 开启SSH服务(可选) +1. 安装SSH + ``` + sudo apt-get install ssh + ``` +2. 配置允许root用户远程登录 + - 修改/etc/ssh/sshd_config文件 + ``` + vim /etc/ssh/sshd_config + + + #PermitRootLogin prohibit-password + PermitRootLogin yes + ``` + +3. 重启服务 + ``` + sudo service ssh restart + ``` + +## 3. 远程连接服务器 + +**可通过阿里云直接远程连接,也可以在任意终端工具连接(例如Tabby、Windows PowerShell等)** +**通过终端工具连接需要输入命令`ssh root@域名`,然后输入密码进入** + +## 4. 安装和启动PostgreSQL + +- 使用 apt update 命令获取包的最新版本 + ``` + $ sudo apt update + ``` +- 安装PostgreSQL + ``` + $ sudo apt install postgresql -y + ``` +- 启动PostgreSQL + ``` + + $ sudo systemctl start postgresql + + + $ sudo systemctl status postgresql + ``` + +## 5. 配置 PostgreSQL 允许远程连接 +- 编辑postgresql.conf文件 + ``` + vim /etc/postgresql/(版本号)/main/postgresql.conf + ``` + **找到listen_adresses行,去掉前面#注释,将localhost改为*,表示 PostgreSQL 将监听所有可用的网络接口。具体来说,这意味着 PostgreSQL 将会监听服务器上所有网络接口的连接请求,需要注意的是,开放所有网络接口可能会增加安全风险,因此在配置时需要注意网络安全性,确保采取适当的安全措施(例如防火墙、访问控制等)以保护数据库的安全。** + +- 编辑 pg hba.conf 文件的 IPv4 本地连接部分 + ``` + vim /etc/postgresql/(版本号)/main/pg_hba.conf + ``` + + **在IPv4中添加一行`host all all 0.0.0.0/0 md5`** + **表示允许来自任意 IP 地址(0.0.0.0/0)的所有用户(all)连接到所有的数据库(all),并通过md5验证方式进行身份验证** + +- 重启PostgreSQL服务 + ``` + sudo systemctl restart postgresql + ``` + +- 防火墙中添加允许5432端口 + ``` + sudo ufw allow 5432/tcp + ``` + +## 6. 阿里云中安全组添加入口访问规则 +- 阿里云中点控制台,选择云服务器ECS +- 网络与安全中选择安全组,创建安全组 +- 可快速添加也可以手动添加,端口范围选择PostgreSQL(5432) \ No newline at end of file diff --git "a/\350\265\265\346\254\243/img/RBAC\345\220\204\346\250\241\345\235\227\345\212\237\350\203\275\345\233\276.png" "b/\350\265\265\346\254\243/img/RBAC\345\220\204\346\250\241\345\235\227\345\212\237\350\203\275\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..ab49bcd29e7ca6c8b1ad04eedca4b73ac2b1ab11 Binary files /dev/null and "b/\350\265\265\346\254\243/img/RBAC\345\220\204\346\250\241\345\235\227\345\212\237\350\203\275\345\233\276.png" differ diff --git "a/\350\265\265\346\254\243/img/RBAC\346\265\201\347\250\213\345\233\276.png" "b/\350\265\265\346\254\243/img/RBAC\346\265\201\347\250\213\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..519acbe9a67d07556381e2e2b284866a79f9c1c5 Binary files /dev/null and "b/\350\265\265\346\254\243/img/RBAC\346\265\201\347\250\213\345\233\276.png" differ diff --git "a/\350\265\265\346\254\243/img/RBAC\350\256\277\351\227\256\346\216\247\345\210\266\346\265\201\347\250\213\345\233\276.png" "b/\350\265\265\346\254\243/img/RBAC\350\256\277\351\227\256\346\216\247\345\210\266\346\265\201\347\250\213\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..f9ae5f29210ee0eeb153c2363327d76d58ab153f Binary files /dev/null and "b/\350\265\265\346\254\243/img/RBAC\350\256\277\351\227\256\346\216\247\345\210\266\346\265\201\347\250\213\345\233\276.png" differ diff --git "a/\350\265\265\346\254\243/img/\344\270\273\345\244\226\351\224\256\345\205\263\350\201\224\350\241\250.png" "b/\350\265\265\346\254\243/img/\344\270\273\345\244\226\351\224\256\345\205\263\350\201\224\350\241\250.png" new file mode 100644 index 0000000000000000000000000000000000000000..afd307e3e85ea1a2eff0cd77dc75dc4f9cdcd089 Binary files /dev/null and "b/\350\265\265\346\254\243/img/\344\270\273\345\244\226\351\224\256\345\205\263\350\201\224\350\241\250.png" differ diff --git "a/\350\265\265\346\254\243/img/\351\235\236\344\270\273\345\244\226\351\224\256\345\233\276.png" "b/\350\265\265\346\254\243/img/\351\235\236\344\270\273\345\244\226\351\224\256\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..43706baccef4cf6cdb82e802195d6fec35124251 Binary files /dev/null and "b/\350\265\265\346\254\243/img/\351\235\236\344\270\273\345\244\226\351\224\256\345\233\276.png" differ