Ostatnio pokazałem jak dobrać się do typu kontrolera dla dowolnego żądania. Było mi to potrzebne do wykonania zadania, które okazało się dużo bardziej skomplikowane niż początkowo zakładałem.
Chciałem mianowicie być w stanie zrobić takie coś:
1: <% if (MVC.Administration.Users.DisableUser().IsUserAuthorized(this.ViewContext.RequestContext)) { %>
2: <a href="#" data-role="disable-user">Disable user</a>
3: <% } %>
Czyli: w dowolnym miejscu (w tym przypadku - w widoku) sprawdzić, czy aktualny użytkownik ma uprawnienia do wykonania akcji pod danym URLem (ta fajna, silnie typowana notacja dzięki T4MVC). Bo po co go wyświetlać skoro i tak nie może go użyć? (można to oczywiście zamknąć w jakimś helperze)
Kod metody IsUserAuthorized przedstawia się następująco:
1: public static class ActionResultExtensions
2: {
3: public static bool IsUserAuthorized(this ActionResult @this, RequestContext requestContext)
4: {
5: string controllerName = (string)@this.GetRouteValueDictionary()["Controller"];
6: string actionName = (string)@this.GetRouteValueDictionary()["Action"];
7:
8: Type controllerType = ControllerTypeLocator.FindControllerType(
9: requestContext, controllerName
10: );
11:
12: var controllerDescriptor = new ReflectedControllerDescriptor(controllerType);
13:
14: var controllerLevelAuthorization = controllerDescriptor
15: .GetCustomAttributes(true).OfType<AuthorizeAttribute>();
16:
17: var actionsDescriptors = controllerDescriptor.GetCanonicalActions
18: ().Where(x => x.ActionName == actionName);
19:
20: var actionLevelAuthorization = actionsDescriptors
21: .SelectMany(x => x.GetCustomAttributes(true).OfType<AuthorizeAttribute>());
22:
23: bool isAuthorized = controllerLevelAuthorization.Concat(actionLevelAuthorization)
24: .Select(x => new OpenAuthorizeAttribute(x))
25: .All(x => x.Authorized(requestContext));
26:
27: return isAuthorized;
28: }
29: }
Wykorzystany wyżej OpenAuthorizeAttribute pochodzi z projektu MvcContrib. A ControllerTypeLocator przedstawiłem poprzednim poście.
No i na koniec wspomniany helper generujący linki dla autoryzowanych użytkowników:
1: public static MvcHtmlString ActionLinkIfAuthorized(this HtmlHelper @this, string linkText, ActionResult actionResult, string format, object linkAttributes)
2: {
3: if (actionResult.IsUserAuthorized(@this.ViewContext.RequestContext) == false)
4: {
5: return MvcHtmlString.Empty;
6: }
7:
8: var a = @this.ActionLink(linkText, actionResult, linkAttributes);
9:
10: if (format.HasNoText())
11: {
12: return a;
13: }
14:
15: return MvcHtmlString.Create(format.FormatWith(a.ToString()));
16: }