Reputation: 702
In my project I have some Post like as News
, Article
, Announcement
and ...
each post have Permission , for example News post by Id 1
just admin users can that and ...
I should show post by user roles if Login .
to do this I trye some way :
way 1: I Add a Extension Method to filter News,Article , ... Like this
public static class EfExtensionMethods
{
public IEnumerable<News> Filter( IDbSet<News> dbset)
{
return (dbset.Where(...));
}
}
way 2: I add a Method to Service Layer for Filter rows , Like this:
public void FilterNews(IEnumerable<News> newsList)
{
var roles = _currentUserService.GetCurrentUserRoles();
if (roles.Count == 0)
{
newsList = newsList.Where(...).ToList();
}
else
{
newsList = newsList.Where(...).ToList();
}
}
and everywhere I need just Pass List of NewsList to this Method to filter . witch one is beset ?
Is any best way ? I want a way that reuseable and dont copy for each class
Upvotes: 2
Views: 1659
Reputation: 14498
You should make a static class with static Expressions
, those you can use in your query and then it filters on the database (now you are fetching all rows from database and throwing away the ones you don't need which is a waste):
partial class News
{
public static class Q
{
public static Expression<Func<News,bool>> HasPermission(int permissionID)
{
return expr => expr.PermissionID == permissionID
}
}
}
Then you can do a query like this for example:
db.News.Where(News.Q.HasPermission(1)).ToList();
And you will fetch only the rows from the News
table where the permission equals '1'. I don't really know how exactly your permissions are stored, but I think you get the idea :)
Edit: with generics, I think the simplest is to make your models inherit from Permissionbase class or something:
public abstract class PermissionBase
{
public int PermissionID {get; set;}
}
public static class QueryExtensions
{
public static Expression<Func<T,bool>> HasPermission<T>(int permissionID) where T: PermissionBase
{
return expr => expr.PermissionID == permissionID
}
}
Without baseclass it should be possible too by building your Expression
on the run:
public static Expression<Func<T, bool>> HasPermission<T>(int PermissionID) where T : class
{
ParameterExpression pe = Expression.Parameter(typeof(T), "p");
System.Reflection.PropertyInfo pi = typeof(T).GetProperty("PermissionID");
MemberExpression me = Expression.MakeMemberAccess(pe, pi);
ConstantExpression ce = Expression.Constant(PermissionID);
BinaryExpression be = Expression.Equal(me, ce);
return Expression.Lambda<Func<T, bool>>(be, pe);
}
Just make sure the propertyname is correct in all your models then obviously, or you can pass the propertyname to the method with a string.
Upvotes: 3
Reputation: 58
As I assume you're talking about row-level security. It's quite a complex task. There are several approaches to do it.
For MSSQL try to have a look at MSDN Security Blog about RLS
Upvotes: 1