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:  }

Komentarze

dotnetomaniak.pl

25 lipca 2011 08:49

Maciej Aniserowicz | Ukrywanie linków dla nieautoryzowanych użytkowników

Dziękujemy za publikację - Trackback z dotnetomaniak.pl

Gutek

25 lipca 2011 10:50

to ja jeszcze dam linka do tego:
www.vivienchevallier.com/.../create-an-authorized-action-link-extension-for-aspnet-mvc-3

AuthorizedActionLink extension do HtmlHelper z mozliwoscia wypisania ciagu znakow jak osoba nie ma dostepu.

TeeeX

30 lipca 2011 13:28

Link do poprzedniego postu nie działa.

procent

31 lipca 2011 19:25

TeeeX,
Dzięki, poprawione.

Komentarze zamknięte