The Problem Domain
Say I have an entity that looks something like this ...
public class HierarchyObject
{
[Key]
public int Id { get; set; }
[ForeignKey("Parent")]
public int ParentId { get; set; }
public virtual HierarchyObject Parent { get; set; }
public virtual ICollection<HierarchyObject> Children { get; set; }
}
Ok now i'm using EF so I can simply do something like ...
var ctx = new MyContext();
var getAll = ctx.HierarchyObjects.AsQueryable();
Now lets say I add permissions to these objects so certain users can only do basic CRUD operations on a subset of these objects I might now do something like ...
getAll = getAll().Where(o => o.Permissions.Any(p => p.Read && UserId == currentUserId));
This returns only the items that the user can access.
Now I want to expose this behind a queryable endpoint, lets say OData.
OData will allow me to write a URL like this ...
~/Api/HierarchyObject?$Expand=Children
... having done that I just broke my security as the EF proxy does not know about my permission rule as the result would be "All objects I have access to and their children" and the real question should have been "all objects I can access expand in to all their children that I have access to".
So my question is
Is there a way to tell EF that when crawling that Children Property it should also apply a where clause ...
o.Children = o.Children.Where(o => o.Permissions.Any(p => p.Read && UserId == currentUserId));
... and apply that rule on all my Heirarchy objects any time it "proxies" one of them?
More details
I found this:
How can I dynamically customize a POCO proxy in EF 4?
All well and good, ssays what i'm trying to do is impossible in EF4 but i'm using EF6 so I figured that Microsoft / someone else perhaps may have foudn a way round this by now allowing a decent way to intercept / override the proxy creation process in some way perhaps using the type IDbSet as the driver for a rule hook that lets you define some proxying rules in some way for relational crawls but I haven't found anything yet!
So it turns out I went the wrong way about this. Instead of proxying the object to prevent relatinship crawling I found I can restrict returned entities by type using EF filters.
There's a bunch of packages for this on Nuget that extend the EF functionality essentially giving a context sensitive "cut of the db" before running any of the business logic code on top of it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.