Set value of property in IQueryable after join with another table based on some conditions

automapper entity-framework entity-framework-6 iqueryable linq

Question

I am implementing Authorization for WPF. I have bound permissions with screens. For example, there is a screen called floor. It has four permissions associated with it.

  1. View Floor
  2. Add Floor
  3. Edit Floor
  4. Delete Floor

Along with every permission we have four levels of permissions.

  1. All
  2. Self
  3. Role
  4. User

So, if users have {View Floor} permission with permission level {ALL}. They can view all floors created by any user.

If users have {Self} Permission Level. They can only view floors created by themselves.

If a user have a Permission Level of {Role}. They can view all floors assigned against specified roles.

Roles for Permission Level are assigned like this:

Roles: Supervisor,Technician

If a BranchManager have the above Permission Level. Then he can view floors created by himself and created by any users which are having role of supervisor or technician.

Permission Level {User} is same as {Role}.

Here is my IQueryable to fetch floors:

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();

After this I need to apply some custom filter to this query based on Permission Level

FloorsQueryable = CustomFilter(FloorsQueryable,CurrentUserId,filters);

CustomFilter Code

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;
}

Now for Permission Level {Role} I need to add CreatorRoleId in select clause of IQueryable to apply the required check in the following code.

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
            );
}

Is it possible to some how set the value of CreatorRoleId? Some thing like the following

select {q=>q.CreatorRoleId=r.Id return q;}

This is supposed to be generic and run for any IQueryable. I do not want to join Role and UserInRole table for all the queries in project because these joins are only needed when some user has this {Role} Permission Level.

1
5
1/15/2020 9:25:52 AM

Popular Answer

I think it's something like return query.Where(q => q.CreatorRoleId == r.Id); I guess.

0
2/7/2020 11:19:16 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow