Search code examples
structuremaprhinoninject-2rhino-security

Rhino.Security and IEntityInformationExtractor


I've recently downloaded Rhino.Security and I am trying to implement permissions on a entity. Since I like Ninject (v2) I would like to put together a simple example to start with. In my NinjectModule I've bound the repository and the services:

Bind<ISessionFactory>()
    .ToProvider(new SessionFactoryProvider())
    .InSingletonScope();
Bind<ISession>().ToProvider(new SessionProvider())
    .InSingletonScope();
Bind<IAuthorizationRepository>()
     .To<AuthorizationRepository>()
     .InSingletonScope();
Bind<IPermissionsService>()
    .To<PermissionsService>()
    .InSingletonScope();
Bind<IAuthorizationService>()
    .To<AuthorizationService>()
    .InSingletonScope();
Bind<IPermissionsBuilderService>()
    .To<PermissionsBuilderService>()
    .InSingletonScope();

I am testing everything in a console app and everything works fine. I can run this test with no problem:

public void RunTest()
{
Model.User user1;
Rhino.Security.Model.UsersGroup grp1;

    using (session)
    {
        session.BeginTransaction();

        user1 = new Model.User { Name = "xxx xxx" };
        session.Save(user1);
        session.Flush();

        grp1 = authorizationRepository.CreateUsersGroup("Administrators");
        session.Flush();

        authorizationRepository.AssociateUserWith(user1, grp1);
        session.Flush();

        var OpAccountEdit = authorizationRepository.CreateOperation("/Account/Edit");
        session.Flush();

        permissionsBuilderService
        .Allow(OpAccountEdit)
        .For(grp1)
        .OnEverything()
        .Level(10)
        .Save();

        permissionsBuilderService
        .Deny(OpAccountEdit)
        .For(user1)
        .OnEverything()
        .Level(10)
        .Save();

        Console.WriteLine(authorizationService.IsAllowed(user1, "/Account/Edit"));

        session.Transaction.Rollback();

        Console.ReadLine();
       }
    }

Now, I would like to define a permission for an account; something like this:

account1 = new Model.Account() { Name = "My Account", SecurityKey = new Guid(), Id = 1 };
session.Save(account1);
session.Flush();

permissionsBuilderService
   .Allow("/Account/Delete")
   .For(user1)
   .On(account1)
   .Level(20)
   .Save();

I've defined my class, as Ayende did in the sample code found in the solution:

public class AccountInfromationExtractor : IEntityInformationExtractor<Model.Account>
{
...
}

and I've tried to bind (in my ninject module) the interface IEntityInformationExtractor to the class

 Bind<IEntityInformationExtractor<Model.Account>>()
   .To<AccountInfromationExtractor>();

but when I run my app I get an "Object reference not set to an instance of an object." in the Security class. The service locator cannot resolve the instance and it generates and exception right here:

var extractor = ServiceLocator.Current.GetInstance<IEntityInformationExtractor<TEntity>>();

Is there anyone who tried to use Ninject with Rhino.Security and would be able to help me?

Thanks


Solution

  • At the end I couldn't manage to make it work with Ninject so I switched to StructureMap.
    Rhino.Security works with MS ServiceLocator to resolve IEntityInformationExtractor. I've found a ServiceLocator adapter for StructureMap

    So I've referenced in my project the following assemblies:

    Microsoft.Practices.ServiceLocation
    StructureMap
    StructureMapAdapter

    changed my code to use StructureMap:

    public static class Bootstrapper
        {
            public static void Initialize()
            {
                ObjectFactory.Initialize(cfg =>
                {
                    cfg.AddRegistry<StructureMapRegistry>();
                });
                ServiceLocator.SetLocatorProvider(() => new StructureMapServiceLocator(ObjectFactory.Container));
            }
        }
    

    and my StructureMapRegistry class:

    public class StructureMapRegistry : Registry
    {
        public StructureMapRegistry()
        {
            string ConnDb = "Data Source=(local); Initial Catalog=RhinoSecurity_Test; Trusted_Connection=true;";
    
            For<ISessionFactory>()
                .Singleton()
                .TheDefault.Is.ConstructedBy(() => new NHSessionFactory(ConnDb, false).SessionFactory);
            For<ISession>()
                .Singleton()
                .TheDefault.Is.ConstructedBy(x => x.GetInstance<ISessionFactory>().OpenSession());
            For<IAuthorizationRepository>()
                 .Use<AuthorizationRepository>();
            For<IPermissionsService>()
                .Use<PermissionsService>();
            For<IAuthorizationService>()
                .Use<AuthorizationService>();
            For<IPermissionsBuilderService>()
                .Use<PermissionsBuilderService>();
            For<IEntityInformationExtractor<Model.Account>>()
                .Use(p =>
                    {
                    return (new AccountInfromationExtractor(p.GetInstance<ISession>()));
                    });
        }
    }
    

    I hope this might help someone.