The problem I see with this, is that
this will be application wide,
Then you need common service that handles it. Suprisingly, I would call it IAuthorisationService.
and I
am looking for best practices on how
to approach this. Should I be looking
at CustomControllers? Filters? or
what?
Whichever way you choose you should use common IAuthorisationService above.
From my experience I can tell that it is easier to inject the service into controller and use it on every action:
/* Interfaces */
public interface IAuthorisationService {
bool CanEdit(YourItem item);
}
public interface ICurrentUserProvider {
YourUserEntity GetCurrentUser();
}
/* Implementations */
public class HttpUserProvider : ICurrentUserProvider {
public YourUserEntity GetCurrentUser() {
return HttpContext.Current.User.Principal as YourUserEntity;
}
}
public calss RolesAuthorisationService : IAuthorisationService {
ICurrentUserProvider userProvider
public RolesAuthorisationService(ICurrentUserProvider userProvider) {
this.userProvider = userProvider;
}
public bool CanEdit(YourItem item) {
var u = userProvider.GetCurrentUser();
if (u == null)
return false;
return item.Owner == u && u.IsInRole("EditYourItem");
}
}
/* Controller */
public class MyController: Controller {
IAuthorisationService authorisation;
public MyController(IAuthorisationService authorisation) {
this.authorisation = authorisation;
}
public ActionResult Edit(int id) {
var item = GetTheItembyIdSomehow();
if (!authorisation.CanEdit(item))
return new HttpUnauthorizedResult();
// Can do this
}
}
Then you can use ControllerFactory to inject the required dependencies automatically into the controllers:
class DependencyInjectionContainer : WindsorContainer {
public DependencyInjectionContainer() {
RegisterDependencies();
}
private void RegisterDependencies() {
// Services
Register(
AllTypes.Of<IDiscoverableService>()
.FromAssembly(typeof(IDiscoverableService).Assembly)
.Configure(c => c.LifeStyle.Transient)
.WithService.FromInterface()
);
// Controllers
Register(
AllTypes.Of<IController>()
.FromAssembly(typeof(DependencyInjectionContainer).Assembly)
.Configure(c => c.LifeStyle.Transient)
);
}
}
class WindsorControllerFactory : DefaultControllerFactory, IDisposable {
private readonly IWindsorContainer container;
public WindsorControllerFactory() {
container = new DependencyInjectionContainer();
}
protected override IController GetControllerInstance(Type controllerType) {
if (controllerType == null)
return base.GetControllerInstance(controllerType);
return (IController) container.Resolve(controllerType);
}
public void Dispose() {
container.Dispose();
}
}