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 { get; private 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.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 { get; private 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);
}
}
}
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);
}
}
}