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

Friday, May 27, 2011

On security system, part 5

After releasing DataObjects.Net 4.5 Beta 1 with Firebird & MySQL providers as well as with LINQPad provider, the team switched back to the security-related stuff.

In the previous part we discussed the roles and permissions in terms of restricting LINQ queries. This time let's focus on users, passwords and validation.

First of all, according to the requirements to the security system listed in the very first post concerning this topic, we announced that it would be good if we integrate somehow with the core .NET security interfaces, like IPrincipal & IIdentity. As a result, our core IPrincipal interface inherits System.Security.IPrincipal interface and adds 2 persistent fields and 1 method:

public interface IPrincipal : IEntity, System.Security.Principal.IPrincipal
  {
    [Field]
    string Name { get; }

    [Field]
    [Association(PairTo = "Principal", OnOwnerRemove = OnRemoveAction.Cascade)]
    PrincipalRoleSet PrincipalRoles { get; }

    bool IsInRole(Role role);
  }

Field 'Name' is used for storing identity information in storage. 'PrincipalRoles' is a set of roles that a principal owns. The PrincipalRole type is just a auxiliary type that help associate a Principal with its roles. A role itself is not persistent type, so we use its name as a reference.

  [HierarchyRoot]
  [KeyGenerator(KeyGeneratorKind.None)]
  public class PrincipalRole : Entity
  {
    [Field, Key(0)]
    public IPrincipal Principal { get; private set; }

    [Field(Length = 50), Key(1)]
    public string Name { get; private set; }

    public PrincipalRole (Session session, IPrincipal principal, string name)
      : base(session, principal, name) {}
  }

In order not to realize all functionality of IPrincipal interface by yourselves, there is 2 base implementations: Principal & GenericPrincipal. The first one is pure implementation of the IPrincipal interface with no additional stuff. Here it is:

public abstract class Principal : Entity, IPrincipal
  {
    [NotNullConstraint(Mode = ConstrainMode.OnValidate)]
    [Field(Length = 50, Indexed = true)]
    public string Name { get; set; }

    public virtual IIdentity Identity
    {
      get { return new GenericIdentity(Name); }
    }

    [Field]
    public PrincipalRoleSet PrincipalRoles { get; private set; }

    public bool IsInRole(string role)
    {
      return PrincipalRoles.Any(r => r.Name == role);
    }

    public bool IsInRole(Role role)
    {
      return PrincipalRoles.Contains(role);
    }
  }

The second persistent class called GenericPrincipal is designed for use in scenarios with username/password matching:

public abstract class GenericPrincipal : Principal
  {
    [Field(Length = 50)]
    public string Password { get; protected set; }

    public virtual void SetPassword(string password);
  }
Note that both classes neither define Key fields nor apply HierarchyRoot attribute because no prediction can be made about such properties in your domain models. However, this means that you should add your own persistent type called User or similar and inherit from Principal or GenericPrinipal types in order to use all features of the security system. No additional coding is required, just inherit one of them, define Key field(s) and apply HierarchyRoot on top and that's all.

As GenericPrincipal type is intended to be used in username/password scenarios, the next question is: who will be responsible for possible encryption of passwords and how users will be validated/authenticated?

The previous version of DataObjects.Net provided several password encryption algorithms you could choose from, however the possibility to implement your own one was absent. This time we are going to provide a generic interface for string encryption as well as several common implementations. Customers will have the ability to make their own implementations and plug them in. Here is the interface:

  public interface IEncryptionService : IDomainService
  {
    string Encrypt(string value);
  }

It is absolutely simple and straightforward. For now there are 2 realizations: PlainEncryptionService that actually doesn't make any encryption at all and could be used for testing purposes, and Md5EncryptionService. I'll show how to configure the services later.

The next part is user authentication. Keeping in mind that DataObjects.Net-based applications might operate with various types of principals, for example, Windows principal or generic one with username/password authorization scheme, we provide the following generic interface for this task:

  public interface IPrincipalValidationService : ISessionService
  {
    IPrincipal Validate(IIdentity identity, params object[] args);

    IPrincipal Validate(string name, params object[] args);
  }

The method that takes IIdentity as the first parameter is more generic, it might take WindowsIdentity as well as any other IIdentity descendants. The second argument is an array of values that are used for authentication, these could be passwords, tokens, tickets, you name it. The framework will provide base user validation service for username/password authentication scheme, and you'll have the ability to make your own ones.

It seems that there is nothing left to describe. In the next part we'll try making our first sample with integrated security. Stay tuned.

Tuesday, May 24, 2011

DataObjects.Net on Uganda .NET Usergroup

Hello All,

On Friday, 27th May 2011 Malisa Ncube will present DataObjects.Net on Uganda .NET Usergroup meeting and demonstrate how DataObjects.Net fits into Microsoft technology stack and how software engineers can accelerate project development using the application framework.

It is a completely free event. If you’d like to attend, please register here.

Wednesday, May 18, 2011

DataObjects.Net 4.5 Beta 1

Today the DataObjects.Net Team is releasing the first beta of the upcoming 4.5 version of DataObjects.Net.

In this release are included both new providers: for Firebird 2.x & for MySQL 5.x as well as the LINQPad provider.

Both stable versions are also updated to the latest revision. Issues resolved:

- Index attribute on abstract class not in hierarchy root
- No Foreign Key on field from Interface
- Bug of Inheritance with non open generic
- Unsufficient error message when domain build
- Structure field migration

The beta as well as stable versions are available in the download section of the official website.

Please, report any issues concerning new providers so we could fix them before the final version is released. Thanks.

Tuesday, May 03, 2011

DataObjects.Net is updated to build 7487

Hello All,

Today, May 3, both stable versions of DataObjects.Net (v.4.3 & v.4.4) were updated to the latest revision, 7487.

Bugs fixed:

- Field with type of object is not initialized in DTO on query execution. Here is the detailed scenario, although simplified:
public class MyEntity : Entity
{
  [Field, Key]
  public int Id { get; private set; }

  [Field]
  public string Text { get; set; }
}

public class DTO1
{
  public int Id { get; set; }

  public DTO1(MyEntity entity)
  {
    Id = entity.Id;
  }
}

public class DTO2
{
  public object DTO1 { get; set; }
}

using (var session = Domain.OpenSession()) {
  using (var t = session.OpenTransaction()) {

    var q = session.Query.All()
      .Select(c => new DTO2 {DTO1 = new DTO1(c)});
    Assert.IsNotNull(q.First().DTO1);
  }
}

Updates:

- Entity.IsMaterializing flag is added to help distinguishing the case when Entity is being materialized from the case when it is being created via ordinary constructor. Usage:

// Overriding Entity.OnInitialize method
protected override void OnInitialize()
{
  base.OnInitialize();

  if(!IsMaterializing)
    // Make some new entity initialization logic
}

The updated installers as well as binaries can be downloaded from the official website: dataobjects.net.

UPDATE:
The detailed scenario is added to the bug fixed.