Skip to content

Commit

Permalink
feat(auth): 将数据权限重构为独立服务IDataAuthService dotnetcore#233
Browse files Browse the repository at this point in the history
  • Loading branch information
gmf520 committed Apr 17, 2021
1 parent ccf67de commit 89df1ff
Show file tree
Hide file tree
Showing 10 changed files with 480 additions and 200 deletions.
2 changes: 2 additions & 0 deletions src/OSharp.AspNetCore/Mvc/AreaApiControllerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
// <last-date>2018-06-09 20:32</last-date>
// -----------------------------------------------------------------------

using System;

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
Expand Down
82 changes: 0 additions & 82 deletions src/OSharp.AspNetCore/VerifyCodeHandler.cs

This file was deleted.

73 changes: 35 additions & 38 deletions src/OSharp.Authorization.Datas/DataAuthorizationManagerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
using System.Linq.Expressions;
using System.Threading.Tasks;

using Microsoft.Extensions.DependencyInjection;

using OSharp.Authorization.Dtos;
using OSharp.Authorization.Entities;
using OSharp.Authorization.EntityInfos;
Expand Down Expand Up @@ -48,37 +50,32 @@ public abstract class DataAuthorizationManagerBase<TEntityInfo, TEntityInfoInput
where TRole : RoleBase<TRoleKey>
where TRoleKey : IEquatable<TRoleKey>
{
private readonly IRepository<TEntityInfo, Guid> _entityInfoRepository;
private readonly IRepository<TEntityRole, Guid> _entityRoleRepository;
private readonly IEventBus _eventBus;
private readonly IRepository<TRole, TRoleKey> _roleRepository;
private readonly IServiceProvider _provider;

/// <summary>
/// 初始化一个 SecurityManager 类型的新实例
/// </summary>
/// <param name="eventBus">事件总线</param>
/// <param name="entityInfoRepository">实体仓储</param>
/// <param name="entityRoleRepository">实体角色仓储</param>
/// <param name="roleRepository">角色仓储</param>
protected DataAuthorizationManagerBase(
IEventBus eventBus,
IRepository<TEntityInfo, Guid> entityInfoRepository,
IRepository<TEntityRole, Guid> entityRoleRepository,
IRepository<TRole, TRoleKey> roleRepository
)
protected DataAuthorizationManagerBase(IServiceProvider provider)
{
_eventBus = eventBus;
_entityInfoRepository = entityInfoRepository;
_entityRoleRepository = entityRoleRepository;
_roleRepository = roleRepository;
_provider = provider;
}

protected IRepository<TEntityInfo, Guid> EntityInfoRepository => _provider.GetRequiredService<IRepository<TEntityInfo, Guid>>();

protected IRepository<TEntityRole, Guid> EntityRoleRepository => _provider.GetRequiredService<IRepository<TEntityRole, Guid>>();

protected IEventBus EventBus => _provider.GetRequiredService<IEventBus>();

protected IRepository<TRole, TRoleKey> RoleRepository => _provider.GetRequiredService<IRepository<TRole, TRoleKey>>();

protected IFilterService FilterService => _provider.GetRequiredService<IFilterService>();

#region Implementation of IEntityInfoStore<TEntityInfo,in TEntityInfoInputDto>

/// <summary>
/// 获取 实体信息查询数据集
/// </summary>
public IQueryable<TEntityInfo> EntityInfos => _entityInfoRepository.QueryAsNoTracking();
public IQueryable<TEntityInfo> EntityInfos => EntityInfoRepository.QueryAsNoTracking();

/// <summary>
/// 检查实体信息是否存在
Expand All @@ -88,7 +85,7 @@ IRepository<TRole, TRoleKey> roleRepository
/// <returns>实体信息是否存在</returns>
public virtual Task<bool> CheckEntityInfoExists(Expression<Func<TEntityInfo, bool>> predicate, Guid id = default(Guid))
{
return _entityInfoRepository.CheckExistsAsync(predicate, id);
return EntityInfoRepository.CheckExistsAsync(predicate, id);
}

/// <summary>
Expand All @@ -99,7 +96,7 @@ IRepository<TRole, TRoleKey> roleRepository
public virtual Task<OperationResult> UpdateEntityInfos(params TEntityInfoInputDto[] dtos)
{
Check.Validate<TEntityInfoInputDto, Guid>(dtos, nameof(dtos));
return _entityInfoRepository.UpdateAsync(dtos);
return EntityInfoRepository.UpdateAsync(dtos);
}

#endregion Implementation of IEntityInfoStore<TEntityInfo,in TEntityInfoInputDto>
Expand All @@ -109,7 +106,7 @@ public virtual Task<OperationResult> UpdateEntityInfos(params TEntityInfoInputDt
/// <summary>
/// 获取 实体角色信息查询数据集
/// </summary>
public virtual IQueryable<TEntityRole> EntityRoles => _entityRoleRepository.QueryAsNoTracking();
public virtual IQueryable<TEntityRole> EntityRoles => EntityRoleRepository.QueryAsNoTracking();

/// <summary>
/// 检查实体角色信息是否存在
Expand All @@ -119,7 +116,7 @@ public virtual Task<OperationResult> UpdateEntityInfos(params TEntityInfoInputDt
/// <returns>实体角色信息是否存在</returns>
public virtual Task<bool> CheckEntityRoleExists(Expression<Func<TEntityRole, bool>> predicate, Guid id = default(Guid))
{
return _entityRoleRepository.CheckExistsAsync(predicate, id);
return EntityRoleRepository.CheckExistsAsync(predicate, id);
}

/// <summary>
Expand All @@ -131,7 +128,7 @@ public virtual Task<OperationResult> UpdateEntityInfos(params TEntityInfoInputDt
/// <returns>过滤条件组</returns>
public virtual FilterGroup[] GetEntityRoleFilterGroups(TRoleKey roleId, Guid entityId, DataAuthOperation operation)
{
return _entityRoleRepository.QueryAsNoTracking(m => m.RoleId.Equals(roleId) && m.EntityId == entityId && m.Operation == operation)
return EntityRoleRepository.QueryAsNoTracking(m => m.RoleId.Equals(roleId) && m.EntityId == entityId && m.Operation == operation)
.Select(m => m.FilterGroupJson).ToArray().Select(m => m.FromJsonString<FilterGroup>()).ToArray();
}

Expand All @@ -145,16 +142,16 @@ public virtual async Task<OperationResult> CreateEntityRoles(params TEntityRoleI
Check.Validate<TEntityRoleInputDto, Guid>(dtos, nameof(dtos));

DataAuthCacheRefreshEventData eventData = new DataAuthCacheRefreshEventData();
OperationResult result = await _entityRoleRepository.InsertAsync(dtos,
OperationResult result = await EntityRoleRepository.InsertAsync(dtos,
async dto =>
{
TRole role = await _roleRepository.GetAsync(dto.RoleId);
TRole role = await RoleRepository.GetAsync(dto.RoleId);
if (role == null)
{
throw new OsharpException($"编号为“{dto.RoleId}”的角色信息不存在");
}

TEntityInfo entityInfo = await _entityInfoRepository.GetAsync(dto.EntityId);
TEntityInfo entityInfo = await EntityInfoRepository.GetAsync(dto.EntityId);
if (entityInfo == null)
{
throw new OsharpException($"编号为“{dto.EntityId}”的数据实体信息不存在");
Expand Down Expand Up @@ -184,7 +181,7 @@ public virtual async Task<OperationResult> CreateEntityRoles(params TEntityRoleI
});
if (result.Succeeded && eventData.HasData())
{
await _eventBus.PublishAsync(eventData);
await EventBus.PublishAsync(eventData);
}

return result;
Expand All @@ -200,16 +197,16 @@ public virtual async Task<OperationResult> UpdateEntityRoles(params TEntityRoleI
Check.Validate<TEntityRoleInputDto, Guid>(dtos, nameof(dtos));

DataAuthCacheRefreshEventData eventData = new DataAuthCacheRefreshEventData();
OperationResult result = await _entityRoleRepository.UpdateAsync(dtos,
OperationResult result = await EntityRoleRepository.UpdateAsync(dtos,
async (dto, entity) =>
{
TRole role = await _roleRepository.GetAsync(dto.RoleId);
TRole role = await RoleRepository.GetAsync(dto.RoleId);
if (role == null)
{
throw new OsharpException($"编号为“{dto.RoleId}”的角色信息不存在");
}

TEntityInfo entityInfo = await _entityInfoRepository.GetAsync(dto.EntityId);
TEntityInfo entityInfo = await EntityInfoRepository.GetAsync(dto.EntityId);
if (entityInfo == null)
{
throw new OsharpException($"编号为“{dto.EntityId}”的数据实体信息不存在");
Expand Down Expand Up @@ -246,7 +243,7 @@ public virtual async Task<OperationResult> UpdateEntityRoles(params TEntityRoleI

if (result.Succeeded && eventData.HasData())
{
await _eventBus.PublishAsync(eventData);
await EventBus.PublishAsync(eventData);
}

return result;
Expand All @@ -260,11 +257,11 @@ public virtual async Task<OperationResult> UpdateEntityRoles(params TEntityRoleI
public virtual async Task<OperationResult> DeleteEntityRoles(params Guid[] ids)
{
DataAuthCacheRefreshEventData eventData = new DataAuthCacheRefreshEventData();
OperationResult result = await _entityRoleRepository.DeleteAsync(ids,
OperationResult result = await EntityRoleRepository.DeleteAsync(ids,
async entity =>
{
TRole role = await _roleRepository.GetAsync(entity.RoleId);
TEntityInfo entityInfo = await _entityInfoRepository.GetAsync(entity.EntityId);
TRole role = await RoleRepository.GetAsync(entity.RoleId);
TEntityInfo entityInfo = await EntityInfoRepository.GetAsync(entity.EntityId);
if (role != null && entityInfo != null)
{
eventData.RemoveItems.Add(new DataAuthCacheItem()
Expand All @@ -274,13 +271,13 @@ public virtual async Task<OperationResult> DeleteEntityRoles(params Guid[] ids)
if (result.Succeeded && eventData.HasData())
{
//移除数据权限缓存
await _eventBus.PublishAsync(eventData);
await EventBus.PublishAsync(eventData);
}

return result;
}

private static OperationResult CheckFilterGroup(FilterGroup group, TEntityInfo entityInfo)
private OperationResult CheckFilterGroup(FilterGroup group, TEntityInfo entityInfo)
{
EntityProperty[] properties = entityInfo.Properties;

Expand Down Expand Up @@ -323,7 +320,7 @@ private static OperationResult CheckFilterGroup(FilterGroup group, TEntityInfo e
}

Type entityType = Type.GetType(entityInfo.TypeName);
result = FilterHelper.CheckFilterGroup(group, entityType);
result = FilterService.CheckFilterGroup(group, entityType);
if (!result.Succeeded)
{
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public override IServiceCollection AddServices(IServiceCollection services)
{
services.AddSingleton(typeof(IDataAuthCache), typeof(TDataAuthCache));

services.AddScoped<IDataAuthService, DataAuthService>();
services.AddScoped<TDataAuthorizationManager>();
services.AddScoped(typeof(IEntityInfoStore<TEntityInfo, TEntityInfoInputDto>), provider => provider.GetService<TDataAuthorizationManager>());
services.AddScoped(typeof(IEntityRoleStore<TEntityRole, TEntityRoleInputDto, TRoleKey>), provider => provider.GetService<TDataAuthorizationManager>());
Expand Down
44 changes: 8 additions & 36 deletions src/OSharp.EntityFrameworkCore/Repository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class Repository<TEntity, TKey> : IRepository<TEntity, TKey>
private readonly ILogger _logger;
private readonly ICancellationTokenProvider _cancellationTokenProvider;
private readonly IPrincipal _principal;
private readonly IDataAuthService _dataAuthService;

/// <summary>
/// 初始化一个<see cref="Repository{TEntity, TKey}"/>类型的新实例
Expand All @@ -61,37 +62,14 @@ public Repository(IServiceProvider serviceProvider)
_logger = serviceProvider.GetLogger<Repository<TEntity, TKey>>();
_cancellationTokenProvider = serviceProvider.GetService<ICancellationTokenProvider>();
_principal = serviceProvider.GetService<IPrincipal>();
_dataAuthService = serviceProvider.GetService<IDataAuthService>();
}

/// <summary>
/// 获取 数据上下文
/// </summary>
public IDbContext DbContext => _dbContext;

/// <summary>
/// 获取 <typeparamref name="TEntity"/>不跟踪数据更改(NoTracking)的查询数据源
/// </summary>
public virtual IQueryable<TEntity> Entities
{
get
{
Expression<Func<TEntity, bool>> dataFilterExp = GetDataFilter(DataAuthOperation.Read);
return _dbSet.AsQueryable().AsNoTracking().Where(dataFilterExp);
}
}

/// <summary>
/// 获取 <typeparamref name="TEntity"/>跟踪数据更改(Tracking)的查询数据源
/// </summary>
public virtual IQueryable<TEntity> TrackEntities
{
get
{
Expression<Func<TEntity, bool>> dataFilterExp = GetDataFilter(DataAuthOperation.Read);
return _dbSet.AsQueryable().Where(dataFilterExp);
}
}

#region 同步方法

/// <summary>
Expand Down Expand Up @@ -489,9 +467,9 @@ public virtual IQueryable<TEntity> Query(Expression<Func<TEntity, bool>> predica
public IQueryable<TEntity> Query(Expression<Func<TEntity, bool>> predicate, bool filterByDataAuth)
{
IQueryable<TEntity> query = _dbSet.AsQueryable();
if (filterByDataAuth)
if (filterByDataAuth && _dataAuthService != null)
{
Expression<Func<TEntity, bool>> dataAuthExp = GetDataFilter(DataAuthOperation.Read);
Expression<Func<TEntity, bool>> dataAuthExp = _dataAuthService.GetDataFilter<TEntity>(DataAuthOperation.Read);
query = query.Where(dataAuthExp);
}
if (predicate == null)
Expand Down Expand Up @@ -908,26 +886,20 @@ private static string GetNameValue(object value)
/// </summary>
/// <param name="operation">数据权限操作</param>
/// <param name="entities">要验证的实体对象</param>
private static void CheckDataAuth(DataAuthOperation operation, params TEntity[] entities)
private void CheckDataAuth(DataAuthOperation operation, params TEntity[] entities)
{
if (entities.Length == 0)
{
return;
}
Expression<Func<TEntity, bool>> exp = GetDataFilter(operation);
Func<TEntity, bool> func = exp.Compile();
bool flag = entities.All(func);

bool flag = _dataAuthService.CheckDataAuth<TEntity>(operation, entities);
if (!flag)
{
throw new OsharpException($"实体 {typeof(TEntity)} 的数据 {entities.ExpandAndToString(m => m.Id.ToString())} 进行 {operation.ToDescription()} 操作时权限不足");
}
}

private static Expression<Func<TEntity, bool>> GetDataFilter(DataAuthOperation operation)
{
return FilterHelper.GetDataFilterExpression<TEntity>(operation: operation);
}


private TEntity[] CheckInsert(params TEntity[] entities)
{
for (int i = 0; i < entities.Length; i++)
Expand Down
Loading

0 comments on commit 89df1ff

Please sign in to comment.