How do you alternate Ninject bindings based on user?
You should use a provider instead of putting the logic in your module. First you can create something like a SecurityInformation class that can tell you whether the user is authenticated and their role. Currently your implementation I think only uses the authorization information of the first user to start the app. However you want to check the current user's permissions every time an instance of this module is requested.
public class CommandModuleProvider : IProvider
{
public Type Type { get { return typeof(ICommandModule); } }
public object Create(IContext context)
{
var securityInfo = context.Kernel.Get<SecurityInformation>();
if (securityInfo.IsAuthenticated)
if (securityInfo.IsCurrentUserAdministrator)
//load administrator command module
return context.Kernel.Get<AdministratorCommandModule>();
else if (securityInfo.IsCurrentUserModerator)
//Load moderator command module
return context.Kernel.Get<ModeratorCommandModule>();
else
//Load user command module
return context.Kernel.Get<UserCommandModule>();
else
//Load visitor command module
return context.Kernel.Get<VisitorCommandModule>();
}
}
The binding would then be specified like
Kernel.Bind<ICommandModule>().ToProvider<CommandModuleProvider>();
There should be a (very) limited number of Kernels running in your application: preferably just one in most cases. Instead of trying to create a new kernel for each user, make your binding produce a different implementation for each user. This can be done using IProvider
s as Vadim points out. Following is a variation on the same idea:
public override void Load()
{
Bind<ICommandModule>().ToMethod(
c =>
{
var sessionManager = c.Kernel<ISessionManager>();
if (!sessionManager.IsAuthenticated)
return c.Kernel.Get<VisitorCommandModule>();
var currentUser = sessionManager.CurrentUser;
if (currentUser.IsAdministrator)
return c.Kernel.Get<AdministratorCommandModule>();
if (currentUser.IsModerator)
return c.Kernel.Get<ModeratorCommandModule>();
return c.Kernel.Get<UserCommandModule>();
}).InRequestScope();
}
In this implementation, I would expect ISessionManager
to be implemented with a class that checks the current HttpContext
to determine who is logged in, and provide basic information about this person.
InRequestScope()
now resides in the Ninject.Web.Common
library, and will help to avoid re-performing all this logic more than once per request.