Я выполняю авторизацию для WPF. Я связал разрешения с экранами. Например, есть экран с названием floor. С ним связаны четыре разрешения.
- Просмотр этажа
- Добавить этаж
- Редактировать этаж
- Удалить этаж
Наряду с каждым разрешением у нас есть четыре уровня разрешений.
- Все
- Сам
- Роль
- Пользователь
Итак, если у пользователей есть разрешение {View Floor} с уровнем разрешения {ALL}. Они могут просматривать все этажи, созданные любым пользователем.
Если пользователи имеют уровень доступа {Self}. Они могут только просматривать полы, созданные ими самими.
Если пользователь имеет уровень доступа {Role}. Они могут просматривать все этажи, назначенные для указанных ролей.
Роли для уровня разрешений назначаются следующим образом:
Roles: Supervisor,Technician
Если BranchManager имеет вышеуказанный уровень разрешений. Затем он может просматривать этажи, созданные им самим и созданные любыми пользователями, которые играют роль руководителя или технического специалиста.
Уровень разрешений {Пользователь} такой же, как {Роль}.
Вот мой IQueryable чтобы получить этажи:
IQueryable<FloorModel> FloorsQueryable = (from f in Floors
join b in Branches on f.BranchId equals b.Id
where (string.IsNullOrEmpty(filters.Name) || f.Name.ToLower().Contains(filters.Name.ToLower()))
&& (string.IsNullOrEmpty(filters.BranchName) || b.Name.ToLower().Contains(filters.BranchName.ToLower()))
&& (f.IsDeleted == null || f.IsDeleted == false)
&& f.BranchId == CurrentBranchId
&& f.ApplicationId == CurrentApplicationId
select new FloorModel
{
Id = f.Id,
Name = f.Name,
Code = f.Code,
Branch = new BranchBriefModel()
{
Id = f.BranchId,
Name = b.Name,
},
IsActive = f.IsActive ?? false,
Description = f.Description,
CreatedBy = f.CreatedBy ?? 0,
ApplicationId = CurrentApplicationId,
}).AsQueryable();
После этого мне нужно применить к этому запросу какой-либо пользовательский фильтр на основе уровня разрешений
FloorsQueryable = CustomFilter(FloorsQueryable,CurrentUserId,filters);
Код CustomFilter
public IQueryable<T> CustomFilter<T>(IQueryable<T> query, int CurrentUserId, BaseSearchModel search) where T : BaseModel, new()
{
var distinctClaims = search.ScreenPermission.Select(x => x.Claim.PermissionLevel).Distinct().ToList();
var viewPermission = search.ScreenPermission.Where(x => x.Name.Contains("View")).FirstOrDefault();
if (viewPermission != null && viewPermission.Claim.PermissionLevel != PermissionLevelCatalog.All)
{
if (distinctClaims.Any(x => x == PermissionLevelCatalog.Role))
{
query = (from q in query
join ur in UsersInRoles on q.CreatedBy equals ur.UserId
join r in Roles on ur.RoleId equals r.Id
select q);
}
string propertyName = "CreatedBy";
//if (string.IsNullOrEmpty(propertyName))
// return query;
// we have parameter "generic"
var selectorParameter = Expression.Parameter(typeof(T), "generic");
// constant "CurrentUserId"
var searchTermExpression = Expression.Constant(CurrentUserId);
// "generic.CreatedBy"
var selector = Expression.PropertyOrField(selectorParameter, propertyName);
// "generic.CreatedBy == "CurrentUserId"
var equal = Expression.Equal(selector, searchTermExpression);
// generic => generic.Name == "CurrentUserId"
var genericWhere = Expression.Lambda<Func<T, bool>>(equal, selectorParameter);
query = query.Where(genericWhere);
}
return query;
}
Теперь для уровня разрешения {Role} мне нужно добавить CreatorRoleId в предложении select IQueryable, чтобы применить требуемую проверку в следующем коде.
if (distinctClaims.Any(x => x == PermissionLevelCatalog.Role))
{
query = (from q in query
join ur in UsersInRoles on q.CreatedBy equals ur.UserId
join r in Roles on ur.RoleId equals r.Id
select q
);
}
Возможно ли для некоторых установить значение CreatorRoleId? Что-то вроде следующего
select {q=>q.CreatorRoleId=r.Id return q;}
Предполагается, что это будет generic c и работает для любого IQueryable. Я не хочу объединять таблицы Role и UserInRole для всех запросов в проекте, потому что эти объединения необходимы только тогда, когда какой-либо пользователь имеет этот уровень полномочий {Role}.