Friday, May 24, 2013

Security in On-line shop? Easily!

I can think many reason why Security is necessary when developing even the simplest online shop backend. I will not elaborate them but I will concentrate on how to empower the application prototype we created for our DXSK8 e-shop with a flexible Security System. Note that after this we really close to first paycheck Winking smile

I remind you that in previous post we applied a XAF layer(rich application) over an EF model located in an external lib (DSK8.Service). Now we will extend the same EF model to support XAF’s Security System.

1) Design Entity Framework Model for the Security System objects.

XAF’s Security system uses Users, Roles and Permissions to configure both the data access and the UI generation for both platforms! This is done with the help of a few system interfaces such as :
User: ISecurityUser, IAuthenticationStandardUser, IOperationPermissionProvider
Role:, IOperationPermissionProvider.

Our EF model from the DXSK8.Service project already contains an Employee entity which is perfect to take the role of XAF’s system user. Therefore, first we need to add all public properties of the user depended interfaces to our Employee entity. Do not worry XAF interfaces are well designed and its just 3 properties as you see below. The UserName in the black frame already existed in our Login entity that's why is not in the Employee entity with the rest of the new fields. However XAF has no problem to understand it as is!

image

Next step is to design the Roles and Permissions objects. I will go only for a Type Permission system although XAF supports member level and criteria based as well. So I only need the bellow Roles, TypePermissionObject entities.

image

The database migration should be done as suggested from EF and I will not elaborate but I followed a standard technic as the one described in Code First Migrations. 

Note: We also need to use partial classes to implement the consumed interfaces however their implementation is rather easy and reusable for example let’s see how easy it is to implement the Employee interfaces. For Role, TypePermissionObject implementation please check post’s sample (See also How to: Implement Custom Security Objects (Users, Roles, Operation Permissions))).

[ImageName("BO_User"), DefaultProperty("UserName")]

public partial class Employee : ISecurityUserIAuthenticationStandardUser,

                                IOperationPermissionProvider {

 

    #region IOperationPermissionProvider

    IEnumerable<IOperationPermissionProvider> IOperationPermissionProvider.GetChildren() {

        if (!Roles.IsLoaded) {

            Roles.Load();

        }

        return new EnumerableConverter<IOperationPermissionProvider, Role>(Roles);

    }

 

    IEnumerable<IOperationPermission> IOperationPermissionProvider.GetPermissions() {

        return new IOperationPermission[0];

    }

    #endregion

    #region ISecurityUser

    Boolean ISecurityUser.IsActive {

        get { return IsActive.HasValue && IsActive.Value; }

    }

 

    String ISecurityUser.UserName {

        get { return UserName; }

    }

    #endregion

 

    #region IAuthenticationStandardUser

    Boolean IAuthenticationStandardUser.ComparePassword(String password) {

        var passwordCryptographer = new PasswordCryptographer();

        return passwordCryptographer.AreEqual(StoredPassword, password);

    }

 

    public void SetPassword(String password) {

        var passwordCryptographer = new PasswordCryptographer();

        StoredPassword = passwordCryptographer.GenerateSaltedPassword(password);

    }

 

    Boolean IAuthenticationStandardUser.ChangePasswordOnFirstLogon {

        get { return ChangePasswordOnFirstLogon.HasValue && ChangePasswordOnFirstLogon.Value; }

        set { ChangePasswordOnFirstLogon = value; }

    }

 

    String IAuthenticationStandardUser.UserName {

        get { return UserName; }

    }

    #endregion

 

}

2)  Install XAF Security System

Although XAF has strong design time support I will go through this step using one line of code in both Program.cs and Global.asax.cs just before application.Setup() call.

application.Security = new SecurityStrategyComplex(typeof(DXSK8.Service.Employee), typeof(DXSK8.Service.Role), new AuthenticationStandard());

application.Setup();

The above snippet will apply a security strategy using the Entity Framework entities located in the external DXSk8.Service lib . For this type of security strategy XAF spares our time as usual and will automatically display a customizable credentials window for both platforms,

 

image

image

 

In addition XAF will detect the custom Security EF Entities we designed in step 1 and will auto populate the navigation menu.

 

Win
image
Web
image
   

 

3) Supply initial data

Always when installing a security system make sure that some one knows the password Smile. We forgot to add at least a user with admin privileges. For this job an appropriate event to use is XafApplication’s CustomCheckCompatibility event inside our platform agnostic module.

 

public override void Setup(XafApplication application) {

    base.Setup(application);

    application.CustomCheckCompatibility+=ApplicationOnCustomCheckCompatibility;

    application.CreateCustomObjectSpaceProvider += ApplicationOnCreateCustomObjectSpaceProvider;

}

 

void ApplicationOnCustomCheckCompatibility(object sender, CustomCheckCompatibilityEventArgs e) {

    var objectSpace = e.ObjectSpaceProvider.CreateUpdatingObjectSpace(true);

    var updater = new Updater(objectSpace, Version.Parse("1.0.0.0"));

    updater.UpdateDatabaseAfterUpdateSchema();

}

and the UpdateDatabaseAfterUpdateSchema where we created:
a) A Content Manager role with CRUD on Product but ReadOnly on Orders/Employees

b) A Sales Manager role wirh CRUD on Order but ReadOnly on Product/Employees

public override void UpdateDatabaseAfterUpdateSchema() {

    base.UpdateDatabaseAfterUpdateSchema();

    if (ObjectSpace.FindObject<Employee>(CriteriaOperator.Parse("UserName=?","Admin")) == null) {

        var roleAndUser = CreateRoleAndUser("Admin");

        roleAndUser.IsAdministrative = true;

        CreateRole("Content Manager", new[]{

            CRUDPermission(typeof(Product)),

            ReadOnlyPermission(typeof(Order)),

            ReadOnlyPermission(typeof(Employee))

        });

 

        CreateRole("Sales Manager", new[]{

            CRUDPermission(typeof(Order)),

            ReadOnlyPermission(typeof(Product)),

            ReadOnlyPermission(typeof(Employee))

        });

 

        var employees = ObjectSpace.GetObjects<Employee>();

        foreach (var employee in employees) {

            employee.IsActive = true;

            employee.ChangePasswordOnFirstLogon = true;

        }

 

        ObjectSpace.CommitChanges();

    }

}

In post’s sample you can explore the implementation of the rest of the methods which is really simple.

 

The rest of the job needs a business user to simply associate Employees with Roles using XAF’ well thought UI. For example in the next two shots we see how to assign a Content Manager Role to a list of users.

 

image

image

Conclusion

Trying to focus in solving business problems with the help of technology is hard. Therefore tools like XAF that bridge those two worlds are like god gifts. We saw how easy was to integrate a complex and sensitive feature like security while working with EF as datalayer. Thanks to the flexible and well designed XAF our product now can be market easier since it features a complete security system.

This time I will close with a phrase I hear constantly from our customers lately:

XAF really works!

Download sample from here and attach the mdf file found in DXSK8.Service/App_Data folder to your SQL instance. Also make sure you already visit How to: Get Started with the Entity Framework Model First in XAF to be sure you know the basics.

.

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Thursday, May 2, 2013

UI Annotation using Business Rules

XAF already provides strong and flexible validation for any object that fits specified Rules with build-in the Validation Module. In this post you can find a sample XAF application which extends the Validation to provide support for Warning/Information messages.

The implementation uses any Validation Business Rule that exists in XAF’s Application Model. Below we see the default ones but its applicable to custom business rules as well.

image

The sample code extends the Application Model of IModelRuleBase and by using one more property like RuleType marks the rule as warning or information as shown:

image

When the Validation occurs this implementation will not raise exceptions for Warning and Information Rules and will change their notification icon accordingly.

Windows

image

Web

image

By default, it is also possible to create business rules that evaluated when an object is changed  by using the ObjectSpaceObjectChanged custom context (see also Contextual Validation Concepts).

To use this RuleType functionality discussed today in your XAF Applications you need to download the sample from RuleType.zip. The functionality is described by just one controller in RuleTypeController.cs which is spanned across the platform agnostic and platform depended projects.

Note: I “borrow” the code for RuleType support from our community project expandframework and for one more time we clearly see how flexible is XAF and how powerful to provide reusable solutions!

P.S.: The original eXpand implementation has code support using a RuleTypeAttribute as well as ListView support and can be found in Xpand.ExpressApp.Validation, Xpand.ExpressApp.Validation.Win and Xpand.ExpressApp.Validation.Web assemblies (See also this discussion in eXpand’s forums).

Subscribe to XAF feed
Subscribe to community feed

DiggIt!