From 60804ae95a95475a64a9588b6ced2be435a1d688 Mon Sep 17 00:00:00 2001 From: suhacan Date: Thu, 12 Nov 2009 21:52:01 +0000 Subject: [PATCH] - RolesBasedAuthorizationService. - Retrofit Media and CmsPages modules to call into the AuthorizationService.CheckAccess() when they need to verify user permissions. --HG-- extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4039974 --- .../Controllers/AdminControllerTests.cs | 15 ++++ .../Orchard.CmsPages/CmsPagesPermissions.cs | 18 ++--- .../Controllers/AdminController.cs | 72 +++++++++++++++++++ .../Controllers/AdminController.cs | 67 ++++++++++++++++- .../Orchard.Roles/Orchard.Roles.csproj | 1 + .../RolesBasedAuthorizationService.cs | 27 +++++++ .../Providers/OrchardMembershipProvider.cs | 4 -- .../Security/Providers/OrchardRoleProvider.cs | 3 - src/Orchard/Security/SecurityFilter.cs | 6 +- src/Orchard/Security/SecurityModule.cs | 5 -- 10 files changed, 191 insertions(+), 27 deletions(-) create mode 100644 src/Orchard.Web/Packages/Orchard.Roles/Services/RolesBasedAuthorizationService.cs diff --git a/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Controllers/AdminControllerTests.cs b/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Controllers/AdminControllerTests.cs index 6d470b635..6f0ad6c6d 100644 --- a/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Controllers/AdminControllerTests.cs +++ b/src/Orchard.Web/Packages/Orchard.CmsPages.Tests/Controllers/AdminControllerTests.cs @@ -11,6 +11,8 @@ using Orchard.CmsPages.Services; using Orchard.CmsPages.Services.Templates; using Orchard.CmsPages.ViewModels; using Orchard.Data; +using Orchard.Security; +using Orchard.Security.Permissions; using Orchard.Tests.Stubs; using Orchard.UI.Notify; using Orchard.Utility; @@ -21,6 +23,7 @@ namespace Orchard.CmsPages.Tests.Controllers { private AdminController _controller; private IPageManager _pageManager; private IPageScheduler _pageScheduler; + private IAuthorizationService _authorizationService; private ITemplateProvider _templateProvider; private int _slugPageId; private IRepository _pagesRepository; @@ -34,6 +37,7 @@ namespace Orchard.CmsPages.Tests.Controllers { _pageManager = _container.Resolve(); _pageScheduler = _container.Resolve(); _templateProvider = _container.Resolve(); + _authorizationService = _container.Resolve(); var page = _pageManager.CreatePage(new PageCreateViewModel { Slug = "slug", Templates = _templateProvider.List() }); _slugPageId = page.Id; @@ -47,6 +51,7 @@ namespace Orchard.CmsPages.Tests.Controllers { builder.Register().As(); builder.Register().As(); builder.Register(new StubTemplateProvider()).As(); + builder.Register(new StubAuthorizationService()).As(); } class StubTemplateProvider : ITemplateProvider { @@ -68,6 +73,16 @@ namespace Orchard.CmsPages.Tests.Controllers { } } + class StubAuthorizationService : IAuthorizationService { + #region Implementation of IAuthorizationService + + public bool CheckAccess(IUser user, Permission permission) { + return true; + } + + #endregion + } + [Test] public void CreateShouldReturnViewWithErrorIfSlugIsNull() { var input = new FormCollection { { ReflectOn.NameOf(m => m.Slug), null } }; diff --git a/src/Orchard.Web/Packages/Orchard.CmsPages/CmsPagesPermissions.cs b/src/Orchard.Web/Packages/Orchard.CmsPages/CmsPagesPermissions.cs index 0f4c72fd5..07ad71585 100644 --- a/src/Orchard.Web/Packages/Orchard.CmsPages/CmsPagesPermissions.cs +++ b/src/Orchard.Web/Packages/Orchard.CmsPages/CmsPagesPermissions.cs @@ -3,14 +3,15 @@ using Orchard.Security.Permissions; namespace Orchard.CmsPages { public class CmsPagesPermissionsProvider : IPermissionProvider { - public static readonly Permission ViewPagesPermission = new Permission { Description = "Viewing CMS Pages", Name = "ViewCmsPagesPermission" }; - public static readonly Permission CreatePagesPermission = new Permission { Description = "Creating CMS Pages", Name = "CreateCmsPagesPermission" }; - public static readonly Permission CreateDraftPagesPermission = new Permission { Description = "Creating CMS Page Drafts", Name = "CreateDraftCmsPagesPermission" }; - public static readonly Permission ModifyPagesPermission = new Permission { Description = "Modifying CMS Pages", Name = "ModifyCmsPagesPermission" }; - public static readonly Permission DeletePagesPermission = new Permission { Description = "Deleting CMS Pages", Name = "DeleteCmsPagesPermission" }; - public static readonly Permission PublishPagesPermission = new Permission { Description = "Publishing CMS Pages", Name = "PublishCmsPagesPermission" }; - public static readonly Permission UnpublishPagesPermission = new Permission { Description = "Unpublishing CMS Pages", Name = "UnpublishCmsPagesPermission" }; - public static readonly Permission SchedulePagesPermission = new Permission { Description = "Scheduling CMS Pages", Name = "ScheduleCmsPagesPermission" }; + public static readonly Permission ViewPagesPermission = new Permission { Description = "Viewing CMS Pages", Name = "ViewPagesPermission" }; + public static readonly Permission CreatePagesPermission = new Permission { Description = "Creating CMS Pages", Name = "CreatePagesPermission" }; + public static readonly Permission CreateDraftPagesPermission = new Permission { Description = "Creating CMS Page Drafts", Name = "CreateDraftPagesPermission" }; + public static readonly Permission DeleteDraftPagesPermission = new Permission { Description = "Deleting CMS Page Drafts", Name = "DeleteDraftPagesPermission" }; + public static readonly Permission ModifyPagesPermission = new Permission { Description = "Modifying CMS Pages", Name = "ModifyPagesPermission" }; + public static readonly Permission DeletePagesPermission = new Permission { Description = "Deleting CMS Pages", Name = "DeletePagesPermission" }; + public static readonly Permission PublishPagesPermission = new Permission { Description = "Publishing CMS Pages", Name = "PublishPagesPermission" }; + public static readonly Permission UnpublishPagesPermission = new Permission { Description = "Unpublishing CMS Pages", Name = "UnpublishPagesPermission" }; + public static readonly Permission SchedulePagesPermission = new Permission { Description = "Scheduling CMS Pages", Name = "SchedulePagesPermission" }; #region Implementation of IPermissionProvider @@ -25,6 +26,7 @@ namespace Orchard.CmsPages { ViewPagesPermission, CreatePagesPermission, CreateDraftPagesPermission, + DeleteDraftPagesPermission, ModifyPagesPermission, DeletePagesPermission, PublishPagesPermission, diff --git a/src/Orchard.Web/Packages/Orchard.CmsPages/Controllers/AdminController.cs b/src/Orchard.Web/Packages/Orchard.CmsPages/Controllers/AdminController.cs index f98579f26..d47cd5b23 100644 --- a/src/Orchard.Web/Packages/Orchard.CmsPages/Controllers/AdminController.cs +++ b/src/Orchard.Web/Packages/Orchard.CmsPages/Controllers/AdminController.cs @@ -11,6 +11,7 @@ using Orchard.CmsPages.ViewModels; using Orchard.Data; using Orchard.Logging; using Orchard.UI.Notify; +using Orchard.Security; namespace Orchard.CmsPages.Controllers { [ValidateInput(false)] @@ -19,21 +20,28 @@ namespace Orchard.CmsPages.Controllers { private readonly IPageScheduler _pageScheduler; private readonly IRepository _repository; private readonly ITemplateProvider _templateProvider; + private readonly IAuthorizationService _authorizationService; private readonly INotifier _notifier; public AdminController(IPageManager pageManager, IPageScheduler pageScheduler, IRepository repository, ITemplateProvider templateProvider, + IAuthorizationService authorizationService, INotifier notifier) { _pageManager = pageManager; _pageScheduler = pageScheduler; _repository = repository; _templateProvider = templateProvider; + _authorizationService = authorizationService; _notifier = notifier; Logger = NullLogger.Instance; } + // That's what it takes to get the CurrentUser for a module. + // See Orchard.Security.SecurityModule. + public IUser CurrentUser { get; set; } + public ILogger Logger { get; set; } protected override void OnActionExecuting(ActionExecutingContext filterContext) { @@ -87,6 +95,13 @@ namespace Orchard.CmsPages.Controllers { case PageIndexBulkAction.PublishNow: //TODO: Transaction + if (!_authorizationService.CheckAccess(CurrentUser, CmsPagesPermissionsProvider.PublishPagesPermission)) { + _notifier.Error("Couldn't publish page, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + CmsPagesPermissionsProvider.PublishPagesPermission.Name); + //return new HttpUnauthorizedResult(); + break; + } foreach (PageEntry entry in checkedEntries) { entry.Page = _repository.Get(entry.PageId); _pageScheduler.ClearTasks(entry.Page); @@ -96,6 +111,13 @@ namespace Orchard.CmsPages.Controllers { break; case PageIndexBulkAction.PublishLater: + if (!_authorizationService.CheckAccess(CurrentUser, CmsPagesPermissionsProvider.SchedulePagesPermission)) { + _notifier.Error("Couldn't publish page, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + CmsPagesPermissionsProvider.SchedulePagesPermission.Name); + //return new HttpUnauthorizedResult(); + break; + } if (viewModel.Options.BulkPublishLaterDate != null) { //TODO: Transaction foreach (PageEntry entry in checkedEntries) { @@ -111,6 +133,13 @@ namespace Orchard.CmsPages.Controllers { break; case PageIndexBulkAction.Unpublish: + if (!_authorizationService.CheckAccess(CurrentUser, CmsPagesPermissionsProvider.UnpublishPagesPermission)) { + _notifier.Error("Couldn't unpublish page, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + CmsPagesPermissionsProvider.UnpublishPagesPermission.Name); + //return new HttpUnauthorizedResult(); + break; + } foreach (PageEntry entry in checkedEntries) { var page = _repository.Get(entry.PageId); _pageManager.UnpublishPage(page); @@ -118,6 +147,13 @@ namespace Orchard.CmsPages.Controllers { break; case PageIndexBulkAction.Delete: + if (!_authorizationService.CheckAccess(CurrentUser, CmsPagesPermissionsProvider.DeletePagesPermission)) { + _notifier.Error("Couldn't delete page, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + CmsPagesPermissionsProvider.DeletePagesPermission.Name); + //return new HttpUnauthorizedResult(); + break; + } if (viewModel.Options.BulkDeleteConfirmed) { //TODO: Transaction foreach (PageEntry entry in checkedEntries) { @@ -176,6 +212,13 @@ namespace Orchard.CmsPages.Controllers { var viewModel = new PageCreateViewModel { Templates = _templateProvider.List() }; try { UpdateModel(viewModel, input.ToValueProvider()); + if (!_authorizationService.CheckAccess(CurrentUser, CmsPagesPermissionsProvider.CreatePagesPermission)) { + _notifier.Error("Couldn't create page, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + CmsPagesPermissionsProvider.CreatePagesPermission.Name); + //return new HttpUnauthorizedResult(); + return View(viewModel); + } Logger.Information("Creating CmsPage slug:{0} title{1}: template{2}", viewModel.Slug, viewModel.Title, viewModel.TemplateName); var revision = _pageManager.CreatePage(viewModel); @@ -225,11 +268,32 @@ namespace Orchard.CmsPages.Controllers { RemoveUnusedContentItems(model.Revision, model.Template); _pageScheduler.ClearTasks(model.Revision.Page); + if (!_authorizationService.CheckAccess(CurrentUser, CmsPagesPermissionsProvider.ModifyPagesPermission)) { + _notifier.Error("Couldn't edit page, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + CmsPagesPermissionsProvider.ModifyPagesPermission.Name); + //return new HttpUnauthorizedResult(); + return RedirectToAction("Index"); + } switch (model.Command) { case PageEditCommand.PublishNow: + if (!_authorizationService.CheckAccess(CurrentUser, CmsPagesPermissionsProvider.PublishPagesPermission)) { + _notifier.Error("Couldn't publish page, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + CmsPagesPermissionsProvider.PublishPagesPermission.Name); + //return new HttpUnauthorizedResult(); + break; + } _pageManager.Publish(model.Revision, new PublishOptions()); break; case PageEditCommand.PublishLater: + if (!_authorizationService.CheckAccess(CurrentUser, CmsPagesPermissionsProvider.SchedulePagesPermission)) { + _notifier.Error("Couldn't publish page, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + CmsPagesPermissionsProvider.SchedulePagesPermission.Name); + //return new HttpUnauthorizedResult(); + break; + } if (model.PublishLaterDate == null) throw new ArgumentNullException("No pub later value"); _pageScheduler.AddPublishTask(model.Revision, model.PublishLaterDate.Value); @@ -255,6 +319,14 @@ namespace Orchard.CmsPages.Controllers { [FormValueRequired("submit.DeleteDraft")] public ActionResult DeleteDraft(int id) { #warning UNIT TEST!!!! + if (!_authorizationService.CheckAccess(CurrentUser, CmsPagesPermissionsProvider.DeleteDraftPagesPermission)) { + _notifier.Error("Couldn't delete draft page, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + CmsPagesPermissionsProvider.DeleteDraftPagesPermission.Name); + //return new HttpUnauthorizedResult(); + return RedirectToAction("Edit", new { id }); + } + var lastRevision = _pageManager.GetLastRevision(id); if (!lastRevision.IsPublished()) lastRevision.Page.Revisions.Remove(lastRevision); diff --git a/src/Orchard.Web/Packages/Orchard.Media/Controllers/AdminController.cs b/src/Orchard.Web/Packages/Orchard.Media/Controllers/AdminController.cs index 6e97c459a..58c8f7568 100644 --- a/src/Orchard.Web/Packages/Orchard.Media/Controllers/AdminController.cs +++ b/src/Orchard.Web/Packages/Orchard.Media/Controllers/AdminController.cs @@ -5,19 +5,25 @@ using System.Web.Mvc; using Orchard.Media.Models; using Orchard.Media.Services; using Orchard.Media.ViewModels; +using Orchard.Security; using Orchard.UI.Notify; namespace Orchard.Media.Controllers { [ValidateInput(false)] public class AdminController : Controller { private readonly IMediaService _mediaService; + private readonly IAuthorizationService _authorizationService; private readonly INotifier _notifier; - public AdminController(IMediaService mediaService, INotifier notifier) { + public AdminController(IMediaService mediaService, IAuthorizationService authorizationService, INotifier notifier) { _mediaService = mediaService; + _authorizationService = authorizationService; _notifier = notifier; } + // That's what it takes to get the CurrentUser for a module. + // See Orchard.Security.SecurityModule. + public IUser CurrentUser { get; set; } public ActionResult Index() { // Root media folders @@ -52,7 +58,13 @@ namespace Orchard.Media.Controllers { var viewModel = new MediaFolderCreateViewModel(); try { UpdateModel(viewModel, input.ToValueProvider()); - + if (!_authorizationService.CheckAccess(CurrentUser, MediaPermissionsProvider.CreateMediaFolderPermission)) { + _notifier.Error("Couldn't create media folder, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + MediaPermissionsProvider.CreateMediaFolderPermission.Name); + //return new HttpUnauthorizedResult(); + return View(viewModel); + } _mediaService.CreateFolder(viewModel.MediaPath, viewModel.Name); return RedirectToAction("Index"); } @@ -76,11 +88,25 @@ namespace Orchard.Media.Controllers { if (key.StartsWith("Checkbox.File.") && input[key] == "true") { string fileName = key.Substring("Checkbox.File.".Length); string folderName = input[fileName]; + if (!_authorizationService.CheckAccess(CurrentUser, MediaPermissionsProvider.DeleteMediaPermission)) { + _notifier.Error("Couldn't delete media file, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + MediaPermissionsProvider.DeleteMediaPermission.Name); + //return new HttpUnauthorizedResult(); + return RedirectToAction("Index"); + } _mediaService.DeleteFile(fileName, folderName); } else if (key.StartsWith("Checkbox.Folder.") && input[key] == "true") { string folderName = key.Substring("Checkbox.Folder.".Length); string folderPath = input[folderName]; + if (!_authorizationService.CheckAccess(CurrentUser, MediaPermissionsProvider.DeleteMediaFolderPermission)) { + _notifier.Error("Couldn't delete media folder, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + MediaPermissionsProvider.DeleteMediaFolderPermission.Name); + //return new HttpUnauthorizedResult(); + return RedirectToAction("Index"); + } _mediaService.DeleteFolder(folderPath); } } @@ -105,10 +131,24 @@ namespace Orchard.Media.Controllers { //TODO: There may be better ways to do this. // Delete if (!String.IsNullOrEmpty(HttpContext.Request.Form["submit.Delete"])) { + if (!_authorizationService.CheckAccess(CurrentUser, MediaPermissionsProvider.DeleteMediaFolderPermission)) { + _notifier.Error("Couldn't delete media folder, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + MediaPermissionsProvider.DeleteMediaFolderPermission.Name); + //return new HttpUnauthorizedResult(); + return View(viewModel); + } _mediaService.DeleteFolder(viewModel.MediaPath); } // Save else { + if (!_authorizationService.CheckAccess(CurrentUser, MediaPermissionsProvider.RenameMediaFolderPermission)) { + _notifier.Error("Couldn't rename media folder, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + MediaPermissionsProvider.RenameMediaFolderPermission.Name); + //return new HttpUnauthorizedResult(); + return View(viewModel); + } _mediaService.RenameFolder(viewModel.MediaPath, viewModel.Name); } @@ -130,6 +170,15 @@ namespace Orchard.Media.Controllers { var viewModel = new MediaItemAddViewModel(); try { UpdateModel(viewModel, input.ToValueProvider()); + + if (!_authorizationService.CheckAccess(CurrentUser, MediaPermissionsProvider.UploadMediaPermission)) { + _notifier.Error("Couldn't upload media file, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + MediaPermissionsProvider.UploadMediaPermission.Name); + //return new HttpUnauthorizedResult(); + return View(viewModel); + } + foreach (string fileName in Request.Files) { HttpPostedFileBase file = Request.Files[fileName]; _mediaService.UploadMediaFile(viewModel.MediaPath, file); @@ -159,9 +208,23 @@ namespace Orchard.Media.Controllers { var viewModel = new MediaItemEditViewModel(); try { UpdateModel(viewModel, input.ToValueProvider()); + if (!_authorizationService.CheckAccess(CurrentUser, MediaPermissionsProvider.ModifyMediaPermission)) { + _notifier.Error("Couldn't modify media file, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + MediaPermissionsProvider.ModifyMediaPermission.Name); + //return new HttpUnauthorizedResult(); + return View(viewModel); + } //TODO: There may be better ways to do this. // Delete if (!String.IsNullOrEmpty(HttpContext.Request.Form["submit.Delete"])) { + if (!_authorizationService.CheckAccess(CurrentUser, MediaPermissionsProvider.DeleteMediaPermission)) { + _notifier.Error("Couldn't delete media file, user " + + (CurrentUser != null ? CurrentUser.UserName : String.Empty) + " doesn't have " + + MediaPermissionsProvider.DeleteMediaPermission.Name); + //return new HttpUnauthorizedResult(); + return View(viewModel); + } _mediaService.DeleteFile(viewModel.Name, viewModel.MediaPath); return RedirectToAction("Edit", new { name = viewModel.FolderName, mediaPath = viewModel.MediaPath }); } diff --git a/src/Orchard.Web/Packages/Orchard.Roles/Orchard.Roles.csproj b/src/Orchard.Web/Packages/Orchard.Roles/Orchard.Roles.csproj index 50b561e29..50db3e7fe 100644 --- a/src/Orchard.Web/Packages/Orchard.Roles/Orchard.Roles.csproj +++ b/src/Orchard.Web/Packages/Orchard.Roles/Orchard.Roles.csproj @@ -67,6 +67,7 @@ + diff --git a/src/Orchard.Web/Packages/Orchard.Roles/Services/RolesBasedAuthorizationService.cs b/src/Orchard.Web/Packages/Orchard.Roles/Services/RolesBasedAuthorizationService.cs new file mode 100644 index 000000000..dd37ccfc3 --- /dev/null +++ b/src/Orchard.Web/Packages/Orchard.Roles/Services/RolesBasedAuthorizationService.cs @@ -0,0 +1,27 @@ +using Orchard.Logging; +using Orchard.Security; +using Orchard.Security.Permissions; + +namespace Orchard.Roles.Services { + public class RolesBasedAuthorizationService : IAuthorizationService { + private readonly IRoleService _roleService; + + public RolesBasedAuthorizationService(IRoleService roleService) { + _roleService = roleService; + Logger = NullLogger.Instance; + } + + public ILogger Logger { get; set; } + + #region Implementation of IAuthorizationService + + public bool CheckAccess(IUser user, Permission permission) { + //TODO: Get roles for user + //TODO: Get permissions for Roles of the IUser from the role service + //TODO: Return false if current user doesn't have the permission + return true; + } + + #endregion + } +} diff --git a/src/Orchard/Security/Providers/OrchardMembershipProvider.cs b/src/Orchard/Security/Providers/OrchardMembershipProvider.cs index df62b219a..70479036e 100644 --- a/src/Orchard/Security/Providers/OrchardMembershipProvider.cs +++ b/src/Orchard/Security/Providers/OrchardMembershipProvider.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Web; using System.Web.Security; using Orchard.Environment; diff --git a/src/Orchard/Security/Providers/OrchardRoleProvider.cs b/src/Orchard/Security/Providers/OrchardRoleProvider.cs index f20d7fdec..7ffbfb8e2 100644 --- a/src/Orchard/Security/Providers/OrchardRoleProvider.cs +++ b/src/Orchard/Security/Providers/OrchardRoleProvider.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Web.Security; namespace Orchard.Security.Providers { diff --git a/src/Orchard/Security/SecurityFilter.cs b/src/Orchard/Security/SecurityFilter.cs index 60229ecab..c935950f0 100644 --- a/src/Orchard/Security/SecurityFilter.cs +++ b/src/Orchard/Security/SecurityFilter.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Web.Mvc; +using System.Web.Mvc; using Orchard.Mvc.Filters; using Orchard.Mvc.ViewModels; diff --git a/src/Orchard/Security/SecurityModule.cs b/src/Orchard/Security/SecurityModule.cs index 5cfb4c869..fa04a0c6f 100644 --- a/src/Orchard/Security/SecurityModule.cs +++ b/src/Orchard/Security/SecurityModule.cs @@ -1,10 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Reflection; -using System.Text; -using System.Web; -using System.Web.Mvc; using Module=Autofac.Builder.Module; namespace Orchard.Security {