This is what I did:
- Added a DefaultBuildingId to the user profile.
Then I created a CustomRoleProvider and overrided GetRolesForUser method like this
public override string[] GetRolesForUser(string userName) { if (HttpContext.Current.Session != null) { var user = _userRepository.GetByName(userName); if (!user.IsActive) { throw new ApplicationException(string.Format("some message {0}", userName)); } if (HttpContext.Current.Session["BuildingId"] == null) { var building = _buildingRepository.Get(user.DefaultBuildingId); if (building == null) { throw new ApplicationException("error message"); } HttpContext.Current.Session["BuildingId"] = building.BuildingId; } int buildingId = Convert.ToInt32(HttpContext.Current.Session["BuildingId"]); return _userRepository.GetRolesForUserInBuilding(user.UserId, buildingId).ToArray(); } throw new ApplicationException("error message."); }
Added a custom AuthorizeAttribute
protected override bool AuthorizeCore(HttpContextBase httpContext) { var authorized = base.AuthorizeCore(httpContext); if (!authorized) { return false; } var repo = UnityManager.Resolve<IUserRepository>(); var buildingId = (int)httpContext.Session["BuildingId"]; var userName = httpContext.User.Identity.Name; var user = repo.GetByName(userName); var userRolesInBuilding = repo.GetRolesForUserInBuilding(user.UserId, buildingId); foreach (var role in Roles.Split(',')) { if (userRolesInBuilding.Contains(role.Trim())) { return true; } } return false;
}
And finally this is how to use it at controller or action level.
[BuildingAthorize(Roles = "Administrators")]
I also added a ddl to the layout to let the user change the building and set the new BuildingId overriding the value at the session/db. This way a user can work in different Hotels during the same session and only access areas and functionality he has for that particular hotel.