Let’s create metadata based permission policies

XAF Team Blog
08 November 2012

XAF has a great security system which can be used to protect our data either at client or server side. There is also great support for modifying the Security behavior at runtime using a permission matrix. However we need to provide initial permissions before distributing our application. In this post we are going to discuss a way to connect methods that describe permission policies with our domain objects, of course using metadata (Attributes).

For supplying initial data XAF provides a well documented approach through ModuleUpdaters. We can use them and write methods that create initial permissions. There are also many extension methods that can help us write faster code,

image

Full permission policy

This policy can be applied to any role and give full permission for the related objects. To connect a domain object with a method we need to do the following:

  1. Define a FullPermissionAttribute as,

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]

    public class FullPermissionAttribute : Attribute {

    }

     

  2. Decorate all related objects

    [FullPermission]

    public class MovieArtist : VideoRentalBaseObject {

    [FullPermission]

    public class Artist : VideoPerson {

  3. With the use of XAF’s sub types info metadata API write an abstract algorithm that will enumerate all domain objects and assign full permission to them for a certain role

    public static void CreateFullPermissionAttributes(this SecuritySystemRole systemRole,  bool defaultAllowValues = true) {

        var persistentTypes = XafTypesInfo.Instance.PersistentTypes.Where(info => info.FindAttribute<FullPermissionAttribute>() != null);

        foreach (var typeInfo in persistentTypes) {

            systemRole.CreateTypePermission(typeInfo.Type,  defaultAllowValues);

        }

    }

    public static SecuritySystemTypePermissionObject CreateTypePermission(this SecuritySystemRole systemRole, Type targetType, bool defaultAllowValues = true) {

        var permission = systemRole.CreateTypePermission(targetType);

        permission.TargetType = targetType;

        permission.AllowDelete = defaultAllowValues;

        permission.AllowNavigate = defaultAllowValues;

        permission.AllowRead = defaultAllowValues;

        permission.AllowWrite = defaultAllowValues;

        permission.AllowCreate = defaultAllowValues;

        return permission;

    }

  4. Invoke the CreateFullPermissionAttributes form the roles you want to apply inside the ModuleUpdater’s

    public override void UpdateDatabaseAfterUpdateSchema() {

        base.UpdateDatabaseAfterUpdateSchema();

        var employersRole = ObjectSpace.GetRole<SecuritySystemRole>("Employers");

        employersRole.CreateFullPermissionAttributes();

Permission Behavior policy

A common policy for an application is a “settings” policy. Which really means that for certain roles like the employee role there should be limited access to objects that store “settings” data. To implement this we can follow the follow steps

  1. Define an attribute to decorate our objects as in previous step. This time we do not know the policy name (settings) so we design this as an Enum parameter in the ctor.

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]

    public class PermissionBehaviorAttribute : Attribute {

        readonly string _name;

     

        public PermissionBehaviorAttribute(object @enum) {

            if (!@enum.GetType().IsEnum)

                throw new NotImplementedException();

            _name = Enum.GetName(@enum.GetType(), @enum);

        }

     

        public PermissionBehaviorAttribute(string name) {

            _name = name;

        }

     

        public string Name {

            get { return _name; }

        }

    }

     

  2. Design an enumeration to hold all possible security policies

    public enum PermissionBehavior {

        Admin,

        Settings,

        ReadOnlyAccess

    }

     

  3. Decorate related objects

    [PermissionBehavior(PermissionBehavior.ReadOnlyAccess)]

    public class Language : VideoRentalBaseObject {

  4. Create a method to describe the ReadOnlyAccess permission policy inside ModuleUpdater.

    public class Updater : ModuleUpdater {

        void ReadOnlyAccesPermissionBehaviour(SecuritySystemRole securitySystemRole, ITypeInfo typeInfo) {

            securitySystemRole.SetTypePermissions(typeInfo.Type, SecurityOperations.ReadOnlyAccess, SecuritySystemModifier.Allow);

        }

  5. With the use of XAF’s sub types info API write an abstract algorithm that will enumerate all domain objects and invoke a delegate with same parameters as the method in step 4

    public static void CreatePermissionBehaviour(this SecuritySystemRole systemRole, Enum behaviourEnum, Action<SecuritySystemRole, ITypeInfo> action) {

        var typeInfos = XafTypesInfo.Instance.PersistentTypes.Where(info => {

            var permissionBehaviorAttribute = info.FindAttribute<PermissionBehaviorAttribute>();

            return permissionBehaviorAttribute != null && permissionBehaviorAttribute.Name.Equals(Enum.GetName(behaviourEnum.GetType(), behaviourEnum));

        });

        foreach (var typeInfo in typeInfos) {

            action.Invoke(systemRole, typeInfo);

        }

    }

     

  6. Invoke the CreatePermissionBehaviour inside the ModulerUpdater feeding it with the ReadOnlyAccesPermissionBehaviour method of step 4

    employersRole.CreatePermissionBehaviour(PermissionBehavior.ReadOnlyAccess, ReadOnlyAccesPermissionBehaviour);

In this post we created reusable algorithms from any XAF projects to help us speeding up the configuration of the initial permissions. When of course talking about code reusability we talk about money saving!

P.S. In a real world application the above coding will be converted to a permission matrix UI representation, making super easy further configurations!

 
image

We would appreciate your feedback on this post. Has it been useful to you? Feel free to contact us with any further questions

Next post will be about what else? its model time!

Happy XAFing as always.

Updated: The code and screen shots are taken from the XVideoRental application. This demo can be found along with the other XAF demos in v12.2 

3 comment(s)
Goldy Wang
Goldy Wang

Can XAF work on WPF now?

22 November, 2012
Dennis (DevExpress)
Dennis (DevExpress)

No, XAF supports only WinForms and ASP.NET at the moment. We do not have immediate plans for the WPF/SL clients for the reasons detailed in this blog: community.devexpress.com/.../resetting-the-direction-for-the-devexpress-business-frameworks.aspx

30 November, 2012
Geoff Davis
Geoff Davis

Does this mean that XAF has a limited future now that DXTreme has arrived?

21 December, 2012

Please login or register to post comments.