private bool CheckLocalReBuildRequired(IClearanceSource clearanceSource) { if (!ReferenceEquals(_LastClearanceSource, clearanceSource)) { _LocalFilterExpression = null; _LastClearanceSource = clearanceSource; } var ccDate = _LastClearanceSource.LastClearanceChangeDateUtc; if (ccDate > _ClearanceVersionWithinFilterExpression) { _LocalFilterExpression = null; _ClearanceVersionWithinFilterExpression = ccDate; } if (_LocalFilterExpression != null) { foreach (Type relatedType in _UpNavigations.Values) { if (EntityAccessControl.GetBuilderForEntity(relatedType).CheckLocalReBuildRequired(clearanceSource)) { _LocalFilterExpression = null; return(true); } } } return(_LocalFilterExpression == null); }
public static EntityAccessControl GetBuilderForEntity(Type entityType) { lock (_BuilderInstances) { if (_BuilderInstances.ContainsKey(entityType)) { return(_BuilderInstances[entityType]); } var newInstance = new EntityAccessControl(entityType); _BuilderInstances[entityType] = newInstance; return(newInstance); } }
/// <summary> /// returns null when nothing to validate /// </summary> public Expression BuildUntypedFilterExpressionIncludingPrincipals(IClearanceSource clearanceSource, Expression entitySourceExpression = null) { if (entitySourceExpression == null) { //in default we can use the lamba-entry parameter (which is our entity) entitySourceExpression = _EntityParameter; //we get external expressions, when we are called to build expression for just a part of the graph //in this case a member-expression which navigates from ou child up to us is passed via this arg... } Expression result = this.BuildUntypedLocalFilterExpression(clearanceSource, entitySourceExpression); foreach (var nav in _UpNavigations) { String navPropName = nav.Key.Name; Type parentEntityType = nav.Value; MemberExpression targetEntityNavigationExpression = MemberExpression.Property(entitySourceExpression, navPropName); var builderForParentEntityType = EntityAccessControl.GetBuilderForEntity(parentEntityType); Expression targetFilterExpression = builderForParentEntityType.BuildUntypedFilterExpressionIncludingPrincipals(clearanceSource, targetEntityNavigationExpression); //only when the nav has any filtering... if (targetFilterExpression != null) { if (result == null) { result = targetFilterExpression; } else { result = Expression.AndAlso(result, targetFilterExpression); } } } //can be null! return(result); }
public static IQueryable <TEntity> AccessScopeFiltered <TEntity>(this IQueryable <TEntity> extendee) { var filterExpression = EntityAccessControl.BuildExpressionIncludingPrincipals <TEntity>(AccessControlContext.Current); return(extendee.Where(filterExpression)); }
public void FilteringExtensionMethodShouldWork() { var rootEntities = new List <MockRootEntity>(); var subEntities = new List <MockSubEntity>(); var root1 = new MockRootEntity { RootName = "Root1", Scope = "A" }; var root2 = new MockRootEntity { RootName = "Root2", Scope = "B" }; var root3 = new MockRootEntity { RootName = "Root3", Scope = "A" }; var child1 = new MockSubEntity { SubName = "Child1" }; var child2 = new MockSubEntity { SubName = "Child2" }; var child3 = new MockSubEntity { SubName = "Child3" }; rootEntities.Add(root1); rootEntities.Add(root2); rootEntities.Add(root3); subEntities.Add(child1); subEntities.Add(child2); subEntities.Add(child3); root1.Childs.Add(child1); root2.Childs.Add(child2); root3.Childs.Add(child3); child1.Parent = root1; child2.Parent = root2; child3.Parent = root3; EntityAccessControl.RegisterPropertyAsAccessControlClassification( (MockRootEntity e) => e.Scope, "AccessControlDimension1" ); MockRootEntity[] filteredRootResult; MockSubEntity[] filteredResult; filteredResult = subEntities.AsQueryable().AccessScopeFiltered().ToArray(); Assert.AreEqual(0, filteredResult.Length); filteredRootResult = rootEntities.AsQueryable().AccessScopeFiltered().ToArray(); Assert.AreEqual(0, filteredRootResult.Length); AccessControlContext.Current.AddClearance("AccessControlDimension1", "A"); filteredResult = subEntities.AsQueryable().AccessScopeFiltered().ToArray(); Assert.AreEqual(2, filteredResult.Length); filteredRootResult = rootEntities.AsQueryable().AccessScopeFiltered().ToArray(); Assert.AreEqual(2, filteredRootResult.Length); AccessControlContext.Current.AddClearance("AccessControlDimension1", "B"); filteredResult = subEntities.AsQueryable().AccessScopeFiltered().ToArray(); Assert.AreEqual(3, filteredResult.Length); filteredRootResult = rootEntities.AsQueryable().AccessScopeFiltered().ToArray(); Assert.AreEqual(3, filteredRootResult.Length); }