News, examples, tips, ideas and plans.
Thoughts around ORM, .NET and SQL databases.

Saturday, June 04, 2011

On security system, part 6

It seems that in the end of the previous post I was a bit wrong. One more topic left for detailed discussion. And its name is "Query conflicts resolving".

Let me explain it a bit. Say, there is a consulting firm that is managed by 2 managers. First of them, Dan, is responsible for negotiations with automobile companies, while the second one, John, works with aircraft enterprises. According to the approach that is described in the previous set of posts the security domain model would contains of two roles: AutomobileManagerRole and AircraftManagerRole, each of them would include a correspondent restrictive query.

public class AutomobileManagerRole : Role
  {
    private static IQueryable<Customer> GetCustomers(ImpersonationContext context, QueryEndpoint query)
    {
      return query.All<Customer>()
        .Where(c => c.IsAutomobileIndustry);
    }

    public AutomobileManagerRole()
    {
      RegisterPermission(new CustomerPermission(true, GetCustomers));
    }
  }

  public class AircraftManagerRole : Role
  {
    private static IQueryable<Customer> GetCustomers(ImpersonationContext context, QueryEndpoint query)
    {
      return query.All<Customer>()
        .Where(c => c.IsAircraftIndustry);
    }

    public AircraftManagerRole()
    {
      RegisterPermission(new CustomerPermission(true, GetCustomers));
    }
  }

Dan would be associated with AutomobileManagerRole and John - with AircraftManagerRole. The roles effectively avoid both of them to see customers that belong to industry other than a manager is responsible for.

But imagine a situation when one of the managers, let it be Dan, left on a vacation. To continue automobile customers management process John should get access to customers of Dan for the vacation period. To achieve this, a system security administrator goes to a security administration console and temporarily adds AutomobileManagerRole to John's account. As a result, John's account starts containing 2 roles, both of them with restrictive query for customers.

So, what should happen when John will execute a query for customers? How the conflict between 2 restrictive queries should be resolved?

The answer is that if the first role grants access to X set of entities and the second role grants it to Y set of entities then the result of combination of these roles should be a union of X and Y, not intersect or except.

Applying this approach to the situation with the managers, John will get access to the result of the following query:

query.All<Customer>()
  .Where(c => c.IsAutomobileIndustry)
  .Union(query.All<Customer>()
        .Where(c => c.IsAircraftIndustry));

This approach will be used always when impersonation context is active and user account contains more then one role with a restrictive query for a querying persistent type.

5 comments:

  1. As i understand well such 'union' handling will be done automatically by DO.NET right?

    ReplyDelete
  2. This looks beautiful Dmitri. My application of these roles will be composable using MEF/IoC, more like:

    [Export(typeof(Role)]
    public class AircraftManagerRole : Role
    {
    //implementation
    }

    :)

    ReplyDelete
  3. I'm looking forward to seeing first applications that use the security system. =)

    ReplyDelete