Установить значение свойства в IQueryable <T>после объединения с другой таблицей на основе некоторых условий - PullRequest
5 голосов
/ 15 января 2020

Я выполняю авторизацию для WPF. Я связал разрешения с экранами. Например, есть экран с названием floor. С ним связаны четыре разрешения.

  1. Просмотр этажа
  2. Добавить этаж
  3. Редактировать этаж
  4. Удалить этаж

Наряду с каждым разрешением у нас есть четыре уровня разрешений.

  1. Все
  2. Сам
  3. Роль
  4. Пользователь

Итак, если у пользователей есть разрешение {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}.

1 Ответ

0 голосов
/ 24 января 2020

Я думаю, что-то вроде return query.Where(q => q.CreatorRoleId == r.Id); Я думаю.

...