feat:添加数据权限搭建,准备完成数据权限过滤

This commit is contained in:
橙子
2023-05-21 21:43:11 +08:00
parent 95a91a10b3
commit ad6bd8f39b
15 changed files with 206 additions and 83 deletions

View File

@@ -11,6 +11,7 @@ namespace Yi.Framework.Infrastructure.Ddd.Repositories
/// 注释一下严格意义这里应该protected但是我认为 简易程度 与 耦合程度 中是需要进行衡量的
/// </summary>
ISugarQueryable<T> _DbQueryable { get; }
ISqlSugarClient _Db { get; }
//单查
Task<T> GetByIdAsync(dynamic id);
Task<T> GetSingleAsync(Expression<Func<T, bool>> whereExpression);

View File

@@ -19,7 +19,7 @@ namespace Yi.Framework.Infrastructure.Sqlsugar.Repositories
/// </summary>
public ISugarQueryable<T> _DbQueryable => AsQueryable();
protected ISqlSugarClient _Db { get { return Context; } set { } }
public ISqlSugarClient _Db { get { return Context; }}
public async Task<List<T>> GetPageListAsync(Expression<Func<T, bool>> whereExpression, IPagedAndSortedResultRequestDto page)
{

View File

@@ -13,7 +13,7 @@ using Yi.Framework.Infrastructure.Data.Entities;
namespace Yi.Framework.Infrastructure.Sqlsugar
{
public class SqlSugarDbContext
public class SqlSugarDbContext
{
/// <summary>
/// SqlSugar 客户端
@@ -81,69 +81,79 @@ namespace Yi.Framework.Infrastructure.Sqlsugar
},
db =>
{
db.Aop.DataExecuting = (oldValue, entityInfo) =>
{
switch (entityInfo.OperationType)
{
case DataFilterType.UpdateByObject:
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModificationTime)))
{
entityInfo.SetValue(DateTime.Now);
}
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModifierId)))
{
if (_currentUser != null)
{
entityInfo.SetValue(_currentUser.Id);
}
}
break;
case DataFilterType.InsertByObject:
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreationTime)))
{
entityInfo.SetValue(DateTime.Now);
}
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreatorId)))
{
if (_currentUser != null)
{
entityInfo.SetValue(_currentUser.Id);
}
}
//插入时需要租户id,先预留
if (entityInfo.PropertyName.Equals(nameof(IMultiTenant.TenantId)))
{
//if (this.CurrentTenant is not null)
//{
// entityInfo.SetValue(this.CurrentTenant.Id);
//}
}
break;
}
};
db.Aop.OnLogExecuting = (s, p) =>
{
StringBuilder sb = new StringBuilder();
//sb.Append("执行SQL:" + s.ToString());
//foreach (var i in p)
//{
// sb.Append($"\r\n参数:{i.ParameterName},参数值:{i.Value}");
//}
sb.Append($"\r\n 完整SQL{UtilMethods.GetSqlString(DbType.MySql, s, p)}");
logger?.LogDebug(sb.ToString());
};
db.Aop.DataExecuting = DataExecuting;
db.Aop.OnLogExecuting = OnLogExecuting;
//扩展
OnSqlSugarClientConfig(db);
});
}
//上下文对象扩展
/// <summary>
/// 上下文对象扩展
/// </summary>
/// <param name="sqlSugarClient"></param>
protected virtual void OnSqlSugarClientConfig(ISqlSugarClient sqlSugarClient)
{
}
/// <summary>
/// 数据
/// </summary>
/// <param name="oldValue"></param>
/// <param name="entityInfo"></param>
protected virtual void DataExecuting(object oldValue, DataFilterModel entityInfo)
{
switch (entityInfo.OperationType)
{
case DataFilterType.UpdateByObject:
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModificationTime)))
{
entityInfo.SetValue(DateTime.Now);
}
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModifierId)))
{
if (_currentUser != null)
{
entityInfo.SetValue(_currentUser.Id);
}
}
break;
case DataFilterType.InsertByObject:
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreationTime)))
{
entityInfo.SetValue(DateTime.Now);
}
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreatorId)))
{
if (_currentUser != null)
{
entityInfo.SetValue(_currentUser.Id);
}
}
//插入时需要租户id,先预留
if (entityInfo.PropertyName.Equals(nameof(IMultiTenant.TenantId)))
{
//if (this.CurrentTenant is not null)
//{
// entityInfo.SetValue(this.CurrentTenant.Id);
//}
}
break;
}
}
/// <summary>
/// 日志
/// </summary>
/// <param name="s"></param>
/// <param name="p"></param>
protected virtual void OnLogExecuting(string s, SugarParameter[] p)
{
StringBuilder sb = new StringBuilder();
sb.Append($"\r\n 完整SQL{UtilMethods.GetSqlString(DbType.MySql, s, p)}");
_logger?.LogDebug(sb.ToString());
}
}
}

View File

@@ -1,4 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Furion;
using Microsoft.Extensions.DependencyInjection;
using Yi.Framework.Infrastructure.Sqlsugar.Uow;
namespace Yi.Framework.Infrastructure.Sqlsugar
{
@@ -7,13 +9,42 @@ namespace Yi.Framework.Infrastructure.Sqlsugar
/// </summary>
public static class SqlsugarExtensions
{
//使用上下文对象
/// <summary>
/// 使用默认上下文
/// </summary>
/// <param name="services"></param>
public static void AddDbSqlsugarContextServer(this IServiceCollection services)
{
services.AddDbSqlsugarOption();
services.AddSingleton(x => x.GetRequiredService<SqlSugarDbContext>().SqlSugarClient);
services.AddSingleton<SqlSugarDbContext>();
}
/// <summary>
/// 自定义上下文
/// </summary>
/// <typeparam name="DbContext"></typeparam>
/// <param name="services"></param>
public static void AddDbSqlsugarContextServer<DbContext>(this IServiceCollection services) where DbContext : SqlSugarDbContext
{
services.AddDbSqlsugarOption();
services.AddSingleton(x => x.GetRequiredService<DbContext>().SqlSugarClient);
services.AddSingleton<DbContext>();
}
public static void AddDbSqlsugarOption(this IServiceCollection services)
{
services.Configure<DbConnOptions>(App.Configuration.GetSection("DbConnOptions"));
services.AddUnitOfWork<SqlsugarUnitOfWork>();
}
}
}

View File

@@ -21,13 +21,6 @@ public class Startup : AppStartup
public void ConfigureServices(IServiceCollection services)
{
services.AddCurrentUserServer();
services.Configure<DbConnOptions>(App.Configuration.GetSection("DbConnOptions"));
services.AddDbSqlsugarContextServer();
services.AddUnitOfWork<SqlsugarUnitOfWork>();
services.AddTransient<IDataFilter, SqlsugarDataFilter>();

View File

@@ -8,6 +8,6 @@ namespace Yi.Furion.Application.Rbac.Services
/// </summary>
public interface IDeptService : ICrudAppService<DeptGetOutputDto, DeptGetListOutputDto, long, DeptGetListInputVo, DeptCreateInputVo, DeptUpdateInputVo>
{
Task<List<long>> GetChiIds(long deptId);
Task<List<long>> GetChildListAsync(long deptId);
}
}

View File

@@ -13,7 +13,7 @@ namespace Yi.Furion.Application.Rbac.Services.Impl
IDeptService, ITransient, IDynamicApiController
{
[NonAction]
public async Task<List<long>> GetChiIds(long deptId)
public async Task<List<long>> GetChildListAsync(long deptId)
{
var entities= await _DbQueryable.ToChildListAsync(x=>x.ParentId,deptId);
return entities.Select(x => x.Id).ToList();

View File

@@ -1,9 +1,13 @@
using Furion.DatabaseAccessor;
using SqlSugar;
using Yi.Framework.Infrastructure.Ddd.Dtos;
using Yi.Framework.Infrastructure.Ddd.Repositories;
using Yi.Framework.Infrastructure.Ddd.Services;
using Yi.Framework.Infrastructure.Helper;
using Yi.Furion.Application.Rbac.Domain;
using Yi.Furion.Core.Rbac.Dtos.Role;
using Yi.Furion.Core.Rbac.Entities;
using Yi.Furion.Core.Rbac.Enums;
namespace Yi.Furion.Application.Rbac.Services.Impl
{
@@ -13,13 +17,34 @@ namespace Yi.Furion.Application.Rbac.Services.Impl
public class RoleService : CrudAppService<RoleEntity, RoleGetOutputDto, RoleGetListOutputDto, long, RoleGetListInputVo, RoleCreateInputVo, RoleUpdateInputVo>,
IRoleService, ITransient, IDynamicApiController
{
public RoleService(RoleManager roleManager) =>
_roleManager =
roleManager;
public RoleService(RoleManager roleManager, IRepository<RoleDeptEntity> roleDeptRepository) =>
(_roleManager, _roleDeptRepository) =
(roleManager, roleDeptRepository);
private RoleManager _roleManager { get; set; }
private IRepository<RoleDeptEntity> _roleDeptRepository;
public async Task<List<long>> GetDeptIdsAsync(long roleId)
{
var entities = await _roleDeptRepository.GetListAsync(x => x.RoleId == roleId);
return entities.Select(x => x.DeptId).ToList();
}
[UnitOfWork]
public async Task UpdateDataScpoceAsync(UpdateDataScpoceInput input)
{
//只有自定义的需要特殊处理
if (input.DataScope == DataScopeEnum.CUSTOM)
{
await _roleDeptRepository.DeleteAsync(x => x.RoleId == input.RoleId);
var insertEntities = input.DeptIds.Select(x => new RoleDeptEntity {Id=SnowflakeHelper.NextId, DeptId = x, RoleId = input.RoleId }).ToList();
await _roleDeptRepository.InsertRangeAsync(insertEntities);
}
await _repository._Db.Updateable(new RoleEntity() { Id = input.RoleId, DataScope = input.DataScope }).UpdateColumns(x => x.DataScope).ExecuteCommandAsync();
}
public override async Task<PagedResultDto<RoleGetListOutputDto>> GetListAsync(RoleGetListInputVo input)
{

View File

@@ -45,7 +45,7 @@ namespace Yi.Furion.Application.Rbac.Services.Impl
List<long> deptIds = null;
if (input.DeptId is not null)
{
deptIds= await _deptService.GetChiIds(input.DeptId ?? 0);
deptIds= await _deptService.GetChildListAsync(input.DeptId ?? 0);
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yi.Furion.Core.Rbac.Enums;
namespace Yi.Furion.Core.Rbac.Dtos.Role
{
public class UpdateDataScpoceInput
{
public long RoleId { get; set; }
public List<long>? DeptIds { get; set;}
public DataScopeEnum DataScope { get; set; }
}
}

View File

@@ -1,5 +1,6 @@
using Furion;
using Microsoft.Extensions.DependencyInjection;
using Yi.Framework.Infrastructure.Sqlsugar;
namespace Yi.Furion.Sqlsugar.Core;
@@ -7,10 +8,6 @@ public class Startup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
//services.AddDatabaseAccessor(options =>
//{
// options.AddDbPool<DefaultDbContext>();
//}, "Yi.Furion.Rbac.Database.Migrations");
System.Console.WriteLine();
services.AddDbSqlsugarContextServer<YiDbContext>();
}
}

View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using SqlSugar;
using Yi.Framework.Infrastructure.CurrentUsers;
using Yi.Framework.Infrastructure.Sqlsugar;
namespace Yi.Furion.Sqlsugar.Core
{
/// <summary>
/// 使用自定义上下文
/// </summary>
public class YiDbContext : SqlSugarDbContext
{
public YiDbContext(IOptions<DbConnOptions> options, ICurrentUser currentUser, ILogger<SqlSugarDbContext> logger) : base(options, currentUser, logger)
{
}
//进行Aop数据权限过滤
protected override void OnSqlSugarClientConfig(ISqlSugarClient sqlSugarClient)
{
//这里Aop进行数据权限过滤
var userId = _currentUser.Id;
if (userId == 0) return;
_logger.LogInformation($"用户【{userId}】访问Aop");
/*
* 这里数据权限,步骤:
* 1获取用户id
* 2通过用户id获取该用户的全部角色
* 3便利每一个角色获取全部的数据权限
* 4会涉及部门表的筛选所以还需要获取用户的所在部门如果没有部门那就是过滤到只看自己
* 5可直接使用DB进行查询部门即可
*/
}
}
}

View File

@@ -55,7 +55,7 @@ export function delDept(deptId) {
// 根据角色ID查询菜单下拉树结构
export function roleDeptTreeselect(roleId) {
return request({
url: '/dept/role-id/' + roleId,
url: '/role/dept-ids/' + roleId,
method: 'get'
})
}

View File

@@ -40,7 +40,7 @@ export function updateRole(data) {
// 角色数据权限
export function dataScope(data) {
return request({
url: '/role/UpdateDataScpoce',
url: '/role/data-scpoce',
method: 'put',
data: data
})

View File

@@ -426,7 +426,7 @@ function handleAdd() {
function getDeptTree(roleId) {
return listDept().then((response) => {
const selectList = [];
response.data.forEach((res) => {
response.data.items.forEach((res) => {
selectList.push({
id: res.id,
label: res.deptName,
@@ -439,7 +439,7 @@ function getDeptTree(roleId) {
let deptIds = [];
roleDeptTreeselect(roleId).then((response) => {
deptIds = response.data.map((x) => x.id);
deptIds = response.data;
// nextTick(() => {
if (deptRef.value) {
deptRef.value.setCheckedKeys(deptIds);
@@ -534,7 +534,13 @@ function handleDataScope(row) {
function submitDataScope() {
if (form.value.id != undefined) {
form.value.deptIds = getDeptAllCheckedKeys();
dataScope(form.value).then((response) => {
const data={
roleId:form.value.id,
deptIds:form.value.deptIds,
dataScope:form.value.dataScope
}
console.log(data)
dataScope(data).then((response) => {
proxy.$modal.msgSuccess("修改成功");
openDataScope.value = false;
getList();