XAF 有条件的对象访问权限

Conditional Object Access Permission:http://www.devexpress.com/Support/Center/p/Q267964.aspx

Custom ObjectAccessPermission type is ignored by the Security system :http://www.devexpress.com/Support/Center/p/Q268440.aspx

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using DevExpress.Xpo;
using DevExpress.ExpressApp.Security;
using System.Security.Permissions;
using DevExpress.ExpressApp.Editors;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.Base.Security;
using DevExpress.ExpressApp.Filtering;
using DevExpress.Data.Filtering.Helpers;
using DevExpress.ExpressApp;

namespace ConditionPermission.Module
{
    [NonPersistent]
    
public class ConditionalObjectAccessPermission : ObjectAccessPermission
    {
        
public ConditionalObjectAccessPermission() { }
        
public ConditionalObjectAccessPermission(PermissionState permissionState)
            : 
base(permissionState) { }
        
public ConditionalObjectAccessPermission(Type objectType, ObjectAccess access)
            : 
base(objectType, access) { }
        
public ConditionalObjectAccessPermission(Type objectType, ObjectAccess access, SecurityContextList contexts)
            : 
base(objectType, access, contexts) { }
        
public ConditionalObjectAccessPermission(Type objectType, ObjectAccess objectAccess, ObjectAccessModifier modifier)
            : 
base(objectType, objectAccess, modifier) { }
        
public ConditionalObjectAccessPermission(Type objectType, ObjectAccess access, params DevExpress.ExpressApp.Security.SecurityContext[] securityContexts)
            : 
base(objectType, access, securityContexts) { }

        
const string conditionAttr = "condition";
        
public override SecurityElement ToXml()
        {
            SecurityElement result 
= base.ToXml();
            
if (result != null && condition != null)
                
foreach(SecurityElement particularAccessItemElement in result.Children) 
                    particularAccessItemElement.AddAttribute(conditionAttr, SecurityElement.Escape(condition));
            
return result;
        }
        
public override void FromXml(SecurityElement element)
        {
            
base.FromXml(element);
            condition 
= null;
            
if (element != null)
                
foreach(SecurityElement particularAccessItemElement in element.Children) 
                {
                    
string tempCondition = particularAccessItemElement.Attribute(conditionAttr);
                    
if (condition != null && condition != tempCondition)
                        
throw new ArgumentException("Stored particular access item conditions do not match!");
                    condition 
= tempCondition ?? condition;
                }
            var newAccessList 
= AccessItemList.Select(item => new ConditionalParticularAccessItem(item.ObjectType, item.Access, item.Modifier, condition)).ToList();
            AccessItemList.Clear();
            
foreach (ParticularAccessItem item in newAccessList)
                AccessItemList.Add(item);
        }

        
string condition = string.Empty;
        [CriteriaObjectTypeMember(
"ObjectType"), Size(-1), ImmediatePostData]
        
public string Condition
        {
            
get { return condition; }
            
set { condition = value; }
        }
        
public override string ToString()
        {
            
return string.IsNullOrEmpty(condition) ? base.ToString() : string.Format("{0} ({1})"base.ToString(), condition);
        }
        
public override IPermission Copy()
        {
            ConditionalObjectAccessPermission result 
= new ConditionalObjectAccessPermission { ObjectType = ObjectType };
            
foreach(ConditionalParticularAccessItem item in AccessItemList)
                result.AccessItemList.Add(item);
            
return result;
        }
        
public override IPermission Union(IPermission target)
        {
            
return Union<ConditionalObjectAccessPermission>(target);
        }
        
public virtual IPermission Union<TActualResultType>(IPermission target) where TActualResultType : ObjectAccessPermission
        {
            
if (!(target is ObjectAccessPermission))
                
throw new ArgumentException("Can't unite anything other than an ObjectAccessPermission or one of its descendants!");
            
if (!typeof(ObjectAccessPermission).IsAssignableFrom(typeof(TActualResultType)))
                
throw new ArgumentException("Resultant object Type must be an ObjectAccessPermission or one of its descendants!");
            List
<ParticularAccessItem> resultItems = new List<ParticularAccessItem>();
            IEnumerable
<ParticularAccessItem> allItems = AccessItemList.Union(((ObjectAccessPermission)target).AccessItemList);
            
if (target is ConditionalObjectAccessPermission)
                resultItems.AddRange(allItems.Distinct());
            
else
                
foreach (ParticularAccessItem item in allItems)
                {
                    
// only process items not already stored in the result set
                    if (!resultItems.Exists(i => i.ObjectType == item.ObjectType && i.Access == item.Access))
                    {
                        
// a conditional item (with an actual condition) has precedence over unconditional items...
                        
// NOTE: multiple non mutually-exclusive conditional items will be ignored!
                        ConditionalParticularAccessItem conditionalItem = item as ConditionalParticularAccessItem;
                        
if (conditionalItem == null || conditionalItem != null && string.IsNullOrEmpty(conditionalItem.Condition))
                        {
                            var duplicateItems 
= allItems.Where(i => i.ObjectType == item.ObjectType && i.Access == item.Access && !object.ReferenceEquals(i, item));
                            conditionalItem 
=
                                (ConditionalParticularAccessItem)duplicateItems.FirstOrDefault(i 
=> i is ConditionalParticularAccessItem && !string.IsNullOrEmpty(((ConditionalParticularAccessItem)i).Condition));
                        }
                        
if (conditionalItem != null)
                            resultItems.Add(
new ConditionalParticularAccessItem(conditionalItem.ObjectType, conditionalItem.Access, conditionalItem.Modifier, conditionalItem.Condition));
                        
else
                            resultItems.Add(
new ParticularAccessItem(item.ObjectType, item.Access, item.Modifier));
                    }
                }
            ObjectAccessPermission result 
= (ObjectAccessPermission)Activator.CreateInstance(typeof(TActualResultType));
            resultItems.ForEach(item 
=> result.AccessItemList.Add(item));
            
return result;
        }
        
public virtual ConditionalObjectAccessPermission FilterUnfitItems(object contextObject)
        {
            Type objectType 
= contextObject.GetType();
            ObjectSpace objectSpace 
= (ObjectSpace)ObjectSpace.FindObjectSpaceByObject(contextObject);
            EvaluatorContextDescriptor descriptor 
= objectSpace != null ? objectSpace.GetEvaluatorContextDescriptor(objectType) : new EvaluatorContextDescriptorDefault(objectType);
            ConditionalObjectAccessPermission result 
= new ConditionalObjectAccessPermission();
            
foreach (ConditionalParticularAccessItem item in AccessItemList)
            {
                
bool itemFits = string.IsNullOrEmpty(item.Condition);
                
if (!itemFits && item.ObjectType == objectType)
                {
                    LocalizedCriteriaWrapper wrapper 
= new LocalizedCriteriaWrapper(objectType, item.Condition);
                    wrapper.UpdateParametersValues(contextObject);
                    ExpressionEvaluator evaluator 
= new ExpressionEvaluator(descriptor, wrapper.CriteriaOperator);
                    itemFits 
= evaluator.Fit(contextObject);
                }
                
if (itemFits)
                    result.AccessItemList.Add(item);
            } 
            
return result;
        }
    }

    
public class ConditionalParticularAccessItem : ParticularAccessItem, IEquatable<ConditionalParticularAccessItem>
    {
        
public ConditionalParticularAccessItem(Type objectType, ObjectAccess particularAccess, ObjectAccessModifier modifier)
            : 
this(objectType, particularAccess, modifier, string.Empty) { }
        
public ConditionalParticularAccessItem(Type objectType, ObjectAccess particularAccess, ObjectAccessModifier modifier, string condition)
            : 
base(objectType, particularAccess, modifier) {
            Condition 
= condition ?? string.Empty;
        }
        
public string Condition { getprivate set; }
        
public override bool Equals(object obj)
        {
            ConditionalParticularAccessItem item 
= obj as ConditionalParticularAccessItem;
            
if (ReferenceEquals(item, null))
                
return false;
            
return Equals(item);
        }
        
public bool Equals(ConditionalParticularAccessItem item)
        {
            
if (ReferenceEquals(item, null))
                
return false;
            
return ObjectType == item.ObjectType && Access == item.Access && Modifier == item.Modifier && Condition == item.Condition;
        }
        
public static bool operator ==(ConditionalParticularAccessItem i1, ConditionalParticularAccessItem i2)
        {
            
if (ReferenceEquals(i1, null))
                
if (ReferenceEquals(i2, null))
                    
return true;
                
else
                    
return false;
            
return i1.Equals(i2);
        }
        
public static bool operator !=(ConditionalParticularAccessItem i1, ConditionalParticularAccessItem i2)
        {
            
return !(i1 == i2);
        }
        
public override int GetHashCode()
        {
            
return ObjectType.GetHashCode() ^ Access.GetHashCode() ^ Modifier.GetHashCode() ^ Condition.GetHashCode();
        }
    }

    
public class ConditionalObjectAccessComparer: ObjectAccessComparer
    {
        
public ConditionalObjectAccessComparer() { }
        
public ConditionalObjectAccessComparer(ObjectAccessCompareMode objectAccessCompareMode)
            : 
base(objectAccessCompareMode) { }

        
public override bool IsSubsetOf(ObjectAccessPermission sourcePermission, ObjectAccessPermission targetPermission)
        {
            ObjectAccessPermission mergedTargetPermission 
= MergeTargetWithConditionalPermission(targetPermission, sourcePermission.Contexts);
            
return base.IsSubsetOf(sourcePermission, mergedTargetPermission);
        }
        
static ObjectAccessPermission MergeTargetWithConditionalPermission(ObjectAccessPermission targetPermission, SecurityContextList contexts)
        {
            
if (contexts.TargetObjectContext != null && contexts.TargetObjectContext.TargetObject != null)
            {
                
object targetObject = contexts.TargetObjectContext.TargetObject;
                ConditionalObjectAccessPermission validatedConditionalPermission 
= ConditionalPermission.FilterUnfitItems(targetObject);
                
return (ObjectAccessPermission)validatedConditionalPermission.Union<ObjectAccessPermission>(targetPermission);
            }
            
return targetPermission;
        }
        
static ConditionalObjectAccessPermission ConditionalPermission
        {
            
get
            {
                IUser user 
= (IUser)SecuritySystem.Instance.User;
                
if (user != null)
                    
return user.GetUserPermission<ConditionalObjectAccessPermission>() ?? new ConditionalObjectAccessPermission();
                
return new ConditionalObjectAccessPermission();
            }
        }
    }

    
public static class IUserHelper
    {
        
static public TPermissionType GetUserPermission<TPermissionType>(this IUser user) where TPermissionType : class, IPermission
        {
            PermissionSet permissions 
= new PermissionSet(PermissionState.None);
            
foreach (IPermission currentPermission in user.Permissions)
                permissions.AddPermission(currentPermission);
            TPermissionType result 
= permissions.GetPermission(typeof(TPermissionType)) as TPermissionType;
            
return result;
        }
    }
}

///

using System;

using DevExpress.ExpressApp.Updating;
using DevExpress.Xpo;
using DevExpress.Data.Filtering;
using DevExpress.Persistent.BaseImpl;
using DevExpress.ExpressApp.Security;

namespace ConditionPermission.Module
{
    
public class Updater : ModuleUpdater
    {
        
public Updater(Session session, Version currentDBVersion) : base(session, currentDBVersion) { }

        Role CreateRole(
string roleName)
        {
            
// if the role does not exist, create it
            Role role =
                Session.FindObject
<Role>(new BinaryOperator("Name", roleName)) ??
                
new Role(Session) { Name = roleName, };
            
// remove all currently assigned permissions to the bundled roles
            while (role.PersistentPermissions.Count > 0)
                Session.Delete(role.PersistentPermissions[
0]);
            
// Allow full access to all objects (this should be added to all Roles by default)
            role.AddPermission(new ObjectAccessPermission(typeof(object), ObjectAccess.AllAccess));
            
return role;
        }

        User AddUserToRole(
string userName, string password, string personName, Role role)
        {
            User user 
= Session.FindObject<User>(new BinaryOperator("UserName", userName));
            
if (user == null)
            {
                user 
= new User(Session);
                user.UserName 
= userName;
                user.FirstName 
= personName;
                user.SetPassword(password);
            }
            user.Roles.Add(role);
            user.Save();
            
return user;
        }

        
public override void UpdateDatabaseAfterUpdateSchema()
        {
            
base.UpdateDatabaseAfterUpdateSchema();

            Role admins 
= CreateRole("Administrator");
            admins.AddPermission(
new ConditionalObjectAccessPermission(typeof(Employee), ObjectAccess.Delete, ObjectAccessModifier.Allow) { Condition = "[FullName] Like 'Felipe%'" });
            admins.AddPermission(
new ConditionalObjectAccessPermission(typeof(Employee), ObjectAccess.Delete, ObjectAccessModifier.Deny) { Condition = "[FullName] Like 'Vitor%'" });
            admins.AddPermission(
new ConditionalObjectAccessPermission(typeof(Employee), ObjectAccess.Delete, ObjectAccessModifier.Deny));
            admins.Save();
            AddUserToRole(
"Admin""admin""Administrator", admins);

            Role staff 
= CreateRole("Staff");
            staff.AddPermission(
new ConditionalObjectAccessPermission(typeof(Employee), ObjectAccess.Delete, ObjectAccessModifier.Allow) { Condition = "[FullName] Like 'Felipe%'" });
            staff.AddPermission(
new ConditionalObjectAccessPermission(typeof(Employee), ObjectAccess.Delete, ObjectAccessModifier.Deny) { Condition = "[FullName] Like 'Vitor%'" });
            
// the following OVERRIDES all previous conditional permissions because of code inside DeleteObjectViewController that tests if the delete action should be enabled 
            
// without passing the current object or testing the selected objects, effectivelly IMPOSING the more general permission over the object's specific permissions...
            
// to avoid this behavior, use the ConditionalObjectAccessPermission without a permission, because it only applies to individual objects (see the Admin conditions above!)
            staff.AddPermission(new ObjectAccessPermission(typeof(Employee), ObjectAccess.Delete, ObjectAccessModifier.Deny));
            staff.Save();
            AddUserToRole(
"User""user""StaffUser", staff);
        }
    }
}
原文地址:https://www.cnblogs.com/Tonyyang/p/1985083.html