Plugin Base WebViewPage #22 & Authorization #24

Plugins have a base WebViewPage to inherit, this offers integration with
various Disco services. Plugins can also add Authorization attributes to
their Web Handlers and Controller Methods.
This commit is contained in:
Gary Sharp
2013-10-14 20:13:00 +11:00
parent 4b822d3ae3
commit 9784c5d282
21 changed files with 496 additions and 112 deletions
@@ -8,7 +8,7 @@ using System.Web.Mvc;
namespace Disco.Services.Authorization
{
public class DiscoAuthorizeAllAttribute : AuthorizeAttribute
public class DiscoAuthorizeAllAttribute : DiscoAuthorizeBaseAttribute
{
string[] authorizedClaims;
@@ -20,22 +20,17 @@ namespace Disco.Services.Authorization
this.authorizedClaims = AuthorisedClaims;
}
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
public override bool IsAuthorized(System.Web.HttpContextBase httpContext)
{
if (httpContext == null)
throw new ArgumentNullException("httpContext");
var authToken = UserService.CurrentAuthorization;
if (authToken == null)
if (Token == null)
return false; // No Current User
return authToken.HasAll(authorizedClaims);
return Token.HasAll(authorizedClaims);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
public override string HandleUnauthorizedMessage()
{
filterContext.Result = new HttpUnauthorizedResult(AuthorizationToken.BuildRequireAllMessage(authorizedClaims));
return AuthorizationToken.BuildRequireAllMessage(authorizedClaims);
}
}
}
@@ -8,7 +8,7 @@ using System.Web.Mvc;
namespace Disco.Services.Authorization
{
public class DiscoAuthorizeAnyAttribute : AuthorizeAttribute
public class DiscoAuthorizeAnyAttribute : DiscoAuthorizeBaseAttribute
{
string[] authorizedClaims;
@@ -20,22 +20,17 @@ namespace Disco.Services.Authorization
this.authorizedClaims = AuthorisedClaims;
}
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
public override bool IsAuthorized(System.Web.HttpContextBase httpContext)
{
if (httpContext == null)
throw new ArgumentNullException("httpContext");
var authToken = UserService.CurrentAuthorization;
if (authToken == null)
if (Token == null)
return false; // No Current User
return authToken.HasAny(authorizedClaims);
return Token.HasAny(authorizedClaims);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
public override string HandleUnauthorizedMessage()
{
filterContext.Result = new HttpUnauthorizedResult(AuthorizationToken.BuildRequireAnyMessage(authorizedClaims));
return AuthorizationToken.BuildRequireAnyMessage(authorizedClaims);
}
}
}
@@ -8,7 +8,7 @@ using System.Web.Mvc;
namespace Disco.Services.Authorization
{
public class DiscoAuthorizeAttribute : AuthorizeAttribute
public class DiscoAuthorizeAttribute : DiscoAuthorizeBaseAttribute
{
string authorizedClaim;
@@ -19,23 +19,18 @@ namespace Disco.Services.Authorization
this.authorizedClaim = AuthorisedClaim;
}
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
public override bool IsAuthorized(System.Web.HttpContextBase httpContext)
{
if (httpContext == null)
throw new ArgumentNullException("httpContext");
var authToken = UserService.CurrentAuthorization;
if (authToken == null)
if (Token == null)
return false; // No Current User
if (authorizedClaim == null)
return authToken.RoleTokens.Count > 0; // Just Authenticate - no Authorization (but require at least 1 role)
return Token.RoleTokens.Count > 0; // Just Authenticate - no Authorization (but require at least 1 role)
else
return authToken.Has(authorizedClaim);
return Token.Has(authorizedClaim);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
public override string HandleUnauthorizedMessage()
{
string resultMessage;
@@ -47,7 +42,7 @@ namespace Disco.Services.Authorization
else
resultMessage = AuthorizationToken.BuildRequireMessage(authorizedClaim);
filterContext.Result = new HttpUnauthorizedResult(resultMessage);
return resultMessage;
}
}
}
@@ -0,0 +1,39 @@
using Disco.Services.Users;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace Disco.Services.Authorization
{
public abstract class DiscoAuthorizeBaseAttribute : AuthorizeAttribute
{
protected AuthorizationToken Token
{
get
{
return UserService.CurrentAuthorization;
}
}
public abstract bool IsAuthorized(System.Web.HttpContextBase httpContext);
public abstract string HandleUnauthorizedMessage();
protected sealed override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
{
if (httpContext == null)
throw new ArgumentNullException("httpContext");
return IsAuthorized(httpContext);
}
protected sealed override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
string resultMessage = HandleUnauthorizedMessage();
filterContext.Result = new HttpUnauthorizedResult(resultMessage);
}
}
}
+4 -1
View File
@@ -92,6 +92,7 @@
<Compile Include="Authorization\AccessDeniedException.cs" />
<Compile Include="Authorization\AuthorizationToken.cs" />
<Compile Include="Authorization\ClaimNavigatorItem.cs" />
<Compile Include="Authorization\DiscoAuthorizeBaseAttribute.cs" />
<Compile Include="Authorization\DiscoAuthorizeAllAttribute.cs" />
<Compile Include="Authorization\DiscoAuthorizeAnyAttribute.cs" />
<Compile Include="Authorization\DiscoAuthorizeAttribute.cs" />
@@ -174,6 +175,8 @@
<Compile Include="Plugins\PluginWebHandlerController.cs" />
<Compile Include="Plugins\UninstallPluginTask.cs" />
<Compile Include="Plugins\UnknownPluginException.cs" />
<Compile Include="Plugins\WebHelper.cs" />
<Compile Include="Plugins\PluginWebViewPage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Tasks\ScheduledTask.cs" />
<Compile Include="Tasks\ScheduledTasks.cs" />
@@ -220,7 +223,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
<UserProperties BuildVersion_UseGlobalSettings="False" BuildVersion_DetectChanges="False" BuildVersion_BuildAction="Both" BuildVersion_StartDate="2011/7/1" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
<UserProperties BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_StartDate="2011/7/1" BuildVersion_BuildAction="Both" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" />
</VisualStudio>
</ProjectExtensions>
<PropertyGroup>
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace Disco.Services.Plugins.Features.UIExtension.Results
{
@@ -18,7 +19,7 @@ namespace Disco.Services.Plugins.Features.UIExtension.Results
this.results = Results;
}
public override void ExecuteResult<T>(System.Web.Mvc.WebViewPage<T> page)
public override void ExecuteResult<T>(WebViewPage<T> page)
{
foreach (var result in this.results)
{
@@ -1,9 +1,12 @@
using System;
using Disco.Services.Web.Bundles;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace Disco.Services.Plugins.Features.UIExtension.Results
{
@@ -16,13 +19,13 @@ namespace Disco.Services.Plugins.Features.UIExtension.Results
: base(Source)
{
this._resource = Resource;
this._resourceUrl = HttpContext.Current.Request.RequestContext.DiscoPluginResourceUrl(Resource, false, Source.PluginManifest);
this._resourceUrl = new HtmlString(Source.PluginManifest.WebResourceUrl(Resource));
var deferredBundles = HttpContext.Current.Items["Bundles.UIExtensionCss"] as List<HtmlString>;
var deferredBundles = HttpContext.Current.Items[Bundle.UIExtensionCssKey] as List<HtmlString>;
if (deferredBundles == null)
{
deferredBundles = new List<HtmlString>();
HttpContext.Current.Items["Bundles.UIExtensionCss"] = deferredBundles;
HttpContext.Current.Items[Bundle.UIExtensionCssKey] = deferredBundles;
}
if (!deferredBundles.Contains(this._resourceUrl))
deferredBundles.Add(this._resourceUrl);
@@ -1,4 +1,5 @@
using System;
using Disco.Services.Web.Bundles;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -17,16 +18,16 @@ namespace Disco.Services.Plugins.Features.UIExtension.Results
: base(Source)
{
this._resource = Resource;
this._resourceUrl = HttpContext.Current.Request.RequestContext.DiscoPluginResourceUrl(Resource, false, Source.PluginManifest);
this._resourceUrl = new HtmlString(Source.PluginManifest.WebResourceUrl(Resource));
this._placeInPageHead = PlaceInPageHead;
if (this._placeInPageHead)
{
var deferredBundles = HttpContext.Current.Items["Bundles.UIExtensionScripts"] as List<HtmlString>;
var deferredBundles = HttpContext.Current.Items[Bundle.UIExtensionScriptsKey] as List<HtmlString>;
if (deferredBundles == null)
{
deferredBundles = new List<HtmlString>();
HttpContext.Current.Items["Bundles.UIExtensionScripts"] = deferredBundles;
HttpContext.Current.Items[Bundle.UIExtensionScriptsKey] = deferredBundles;
}
if (!deferredBundles.Contains(this._resourceUrl))
deferredBundles.Add(this._resourceUrl);
+34 -26
View File
@@ -10,6 +10,7 @@ using System.Web.Routing;
using System.Web;
using System.Web.Mvc.Html;
using System.Globalization;
using Disco.Services.Web.Bundles;
namespace Disco.Services.Plugins
{
@@ -93,34 +94,13 @@ namespace Disco.Services.Plugins
#endregion
#region Virtual Directories
//public static string WebHandlerResource(this PluginManifest pluginManifest, string resourcePath, RequestContext requestContext)
//{
// var rootPath = WebHandlerRootUrl(pluginManifest, requestContext);
// return string.Concat(rootPath, resourcePath);
//}
//public static string WebHandlerRootUrl(this PluginManifest pluginManifest, RequestContext requestContext)
//{
// var tempPath = pluginManifest.WebHandlerActionUrl(requestContext, "_");
// return tempPath.Substring(0, tempPath.LastIndexOf(@"/") + 1);
//}
//public static string WebHandlerActionUrl(this PluginManifest pluginManifest, RequestContext requestContext, string PluginAction)
//{
// var routeValues = new RouteValueDictionary(new { PluginId = pluginManifest.Id, PluginAction = PluginAction });
// return UrlHelper.GenerateUrl("Plugin", "PluginWebHandler", "Index", routeValues, RouteTable.Routes, requestContext, true);
//}
//public static string WebHandlerResourceUrl(this PluginManifest pluginManifest, RequestContext requestContext, string PluginAction)
//{
// var routeValues = new RouteValueDictionary(new { PluginId = pluginManifest.Id, PluginAction = PluginAction });
// return UrlHelper.GenerateUrl("Plugin", "PluginWebHandler", "Index", routeValues, RouteTable.Routes, requestContext, true);
//}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static HtmlString DiscoPluginResourceUrl<T>(this WebViewPage<T> ViewPage, string Resource)
{
return ViewPage.DiscoPluginResourceUrl(Resource, false);
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static HtmlString DiscoPluginResourceUrl<T>(this WebViewPage<T> ViewPage, string Resource, bool Download)
{
if (string.IsNullOrEmpty(Resource))
@@ -133,10 +113,12 @@ namespace Disco.Services.Plugins
return ViewPage.DiscoPluginResourceUrl(Resource, false, manifest);
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static HtmlString DiscoPluginResourceUrl<T>(this WebViewPage<T> ViewPage, string Resource, bool Download, PluginManifest manifest)
{
return ViewPage.ViewContext.RequestContext.DiscoPluginResourceUrl(Resource, Download, manifest);
}
[Obsolete]
public static HtmlString DiscoPluginResourceUrl(this RequestContext RequestContext, string Resource, bool Download, PluginManifest manifest)
{
var resourcePath = manifest.WebResourcePath(Resource);
@@ -151,6 +133,7 @@ namespace Disco.Services.Plugins
return new HtmlString(pluginActionUrl);
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static HtmlString DiscoPluginActionUrl<T>(this WebViewPage<T> ViewPage, string PluginAction)
{
if (string.IsNullOrEmpty(PluginAction))
@@ -163,16 +146,19 @@ namespace Disco.Services.Plugins
return ViewPage.DiscoPluginActionUrl(PluginAction, manifest);
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static HtmlString DiscoPluginActionUrl<T>(this WebViewPage<T> ViewPage, string PluginAction, PluginManifest manifest)
{
return ViewPage.ViewContext.RequestContext.DiscoPluginActionUrl(PluginAction, manifest);
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static HtmlString DiscoPluginActionUrl(this RequestContext RequestContext, string PluginAction, PluginManifest manifest)
{
var routeValues = new RouteValueDictionary(new { PluginId = manifest.Id, PluginAction = PluginAction });
string pluginActionUrl = UrlHelper.GenerateUrl("Plugin", null, null, routeValues, RouteTable.Routes, RequestContext, false);
return new HtmlString(pluginActionUrl);
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static HtmlString DiscoPluginConfigureUrl<T>(this WebViewPage<T> ViewPage)
{
// Find Plugin
@@ -182,16 +168,19 @@ namespace Disco.Services.Plugins
return ViewPage.DiscoPluginConfigureUrl(manifest);
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static HtmlString DiscoPluginConfigureUrl<T>(this WebViewPage<T> ViewPage, PluginManifest manifest)
{
return new HtmlString(ViewPage.ViewContext.RequestContext.DiscoPluginConfigureUrl(manifest));
}
[Obsolete]
public static string DiscoPluginConfigureUrl(this RequestContext RequestContext, PluginManifest manifest)
{
var routeValues = new RouteValueDictionary(new { PluginId = manifest.Id });
string pluginActionUrl = UrlHelper.GenerateUrl("Config_Plugins_Configure", null, null, routeValues, RouteTable.Routes, RequestContext, false);
return pluginActionUrl;
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static MvcForm DiscoPluginActionBeginForm<T>(this WebViewPage<T> ViewPage, string PluginAction, FormMethod method, IDictionary<string, object> htmlAttributes)
{
if (string.IsNullOrEmpty(PluginAction))
@@ -207,19 +196,29 @@ namespace Disco.Services.Plugins
return ViewPage.FormHelper(pluginActionUrl, method, htmlAttributes);
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static MvcForm DiscoPluginActionBeginForm<T>(this WebViewPage<T> ViewPage, string PluginAction, FormMethod method)
{
#pragma warning disable 618
return ViewPage.DiscoPluginActionBeginForm(PluginAction, method, null);
#pragma warning restore 618
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static MvcForm DiscoPluginActionBeginForm<T>(this WebViewPage<T> ViewPage, string PluginAction, IDictionary<string, object> htmlAttributes)
{
#pragma warning disable 618
return ViewPage.DiscoPluginActionBeginForm(PluginAction, FormMethod.Post, htmlAttributes);
#pragma warning restore 618
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static MvcForm DiscoPluginActionBeginForm<T>(this WebViewPage<T> ViewPage, string PluginAction)
{
#pragma warning disable 618
return ViewPage.DiscoPluginActionBeginForm(PluginAction, FormMethod.Post, null);
#pragma warning restore 618
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
private static MvcForm FormHelper<T>(this WebViewPage<T> ViewPage, string formAction, FormMethod method, IDictionary<string, object> htmlAttributes)
{
TagBuilder builder = new TagBuilder("form");
@@ -244,7 +243,7 @@ namespace Disco.Services.Plugins
return form;
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static void DiscoPluginRegisterStylesheet<T>(this WebViewPage<T> ViewPage, string Resource)
{
if (string.IsNullOrEmpty(Resource))
@@ -257,10 +256,12 @@ namespace Disco.Services.Plugins
ViewPage.DiscoPluginRegisterStylesheet(Resource, manifest);
}
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static void DiscoPluginRegisterStylesheet<T>(this WebViewPage<T> ViewPage, string Resource, PluginManifest manifest)
{
ViewPage.ViewContext.RequestContext.DiscoPluginRegisterStylesheet(Resource, manifest);
}
[Obsolete]
public static void DiscoPluginRegisterStylesheet(this RequestContext RequestContext, string Resource, PluginManifest manifest)
{
var resourcePath = manifest.WebResourcePath(Resource);
@@ -272,11 +273,11 @@ namespace Disco.Services.Plugins
HtmlString pluginResourceUrlHtml = new HtmlString(pluginResourceUrl);
var deferredBundles = RequestContext.HttpContext.Items["Bundles.UIExtensionCss"] as List<HtmlString>;
var deferredBundles = RequestContext.HttpContext.Items[Bundle.UIExtensionCssKey] as List<HtmlString>;
if (deferredBundles == null)
{
deferredBundles = new List<HtmlString>();
HttpContext.Current.Items["Bundles.UIExtensionCss"] = deferredBundles;
HttpContext.Current.Items[Bundle.UIExtensionCssKey] = deferredBundles;
}
if (!deferredBundles.Contains(pluginResourceUrlHtml))
deferredBundles.Add(pluginResourceUrlHtml);
@@ -285,6 +286,7 @@ namespace Disco.Services.Plugins
#endregion
#region Request Caching
[Obsolete]
public static void SetCacheability(this PluginWebHandler Handler, TimeSpan CacheDuration)
{
var cache = Handler.HostController.Response.Cache;
@@ -293,6 +295,7 @@ namespace Disco.Services.Plugins
cache.SetValidUntilExpires(true);
cache.SetCacheability(HttpCacheability.Private);
}
[Obsolete]
public static void SetCacheabilityOff(this PluginWebHandler Handler)
{
var cache = Handler.HostController.Response.Cache;
@@ -302,6 +305,7 @@ namespace Disco.Services.Plugins
#endregion
#region Render Partial Compiled
[Obsolete]
private static void RenderPartialCompiledInternal(this HtmlHelper htmlHelper, Type viewType, object model, TextWriter writer)
{
if (writer == null)
@@ -315,15 +319,19 @@ namespace Disco.Services.Plugins
HttpContextBase httpContext = htmlHelper.ViewContext.HttpContext;
page.ExecutePageHierarchy(new WebPageContext(httpContext, null, model), writer, null);
}
[Obsolete]
public static MvcHtmlString PartialCompiled(this HtmlHelper htmlHelper, Type viewType)
{
return PartialCompiled(htmlHelper, viewType, null);
}
[Obsolete]
public static MvcHtmlString PartialCompiled(this HtmlHelper htmlHelper, Type viewType, object model)
{
using (StringWriter writer = new StringWriter(CultureInfo.CurrentCulture))
{
#pragma warning disable 618
htmlHelper.RenderPartialCompiledInternal(viewType, model, writer);
#pragma warning restore 618
return MvcHtmlString.Create(writer.ToString());
}
}
+28
View File
@@ -12,6 +12,8 @@ using Disco.Data.Repository;
using Disco.Services.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Disco.Services.Authorization;
using System.Web.Routing;
namespace Disco.Services.Plugins
{
@@ -54,6 +56,8 @@ namespace Disco.Services.Plugins
private Type ConfigurationHandlerType { get; set; }
[JsonIgnore]
private Type WebHandlerType { get; set; }
[JsonIgnore]
private DiscoAuthorizeBaseAttribute[] WebHandlerAuthorizers { get; set; }
[JsonIgnore]
public string PluginLocation { get; private set; }
@@ -426,6 +430,18 @@ namespace Disco.Services.Plugins
if (!typeof(PluginWebHandler).IsAssignableFrom(this.WebHandlerType))
throw new ArgumentException("The Plugin WebHandlerType must inherit Disco.Services.Plugins.PluginWebHandler", "WebHandlerType");
// Determine WebHandler Authorize Attributes
if (this.WebHandlerAuthorizers == null)
{
this.WebHandlerAuthorizers = this.WebHandlerType.GetCustomAttributes<DiscoAuthorizeBaseAttribute>(true).ToArray();
}
if (this.WebHandlerAuthorizers.Length > 0)
{
var attributeDenied = this.WebHandlerAuthorizers.FirstOrDefault(a => !a.IsAuthorized(HostController.HttpContext));
if (attributeDenied != null)
throw new AccessDeniedException(attributeDenied.HandleUnauthorizedMessage());
}
var handler = (PluginWebHandler)Activator.CreateInstance(this.WebHandlerType);
handler.Manifest = this;
@@ -480,6 +496,18 @@ namespace Disco.Services.Plugins
return new Tuple<string, string>(resourcePath, resourceHash.Item1);
}
public string WebResourceUrl(string Resource)
{
var resourcePath = this.WebResourcePath(Resource);
var url = UrlHelper.GenerateUrl("Plugin_Resources", null, null,
new RouteValueDictionary(new Dictionary<string, object>() { { "PluginId", this.Id }, { "res", Resource } }),
RouteTable.Routes, HttpContext.Current.Request.RequestContext, false);
url += string.Format("?v={0}", resourcePath.Item2);
return url;
}
public void LogException(Exception PluginException)
{
+101 -9
View File
@@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Authorization;
using Disco.Services.Users;
using RazorGenerator.Mvc;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using RazorGenerator.Mvc;
namespace Disco.Services.Plugins
{
@@ -14,18 +16,103 @@ namespace Disco.Services.Plugins
{
public PluginManifest Manifest { get; set; }
public Controller HostController { get; set; }
protected DiscoDataContext Database;
public void OnActionExecuting()
{
this.Database = new DiscoDataContext();
this.Database.Configuration.LazyLoadingEnabled = false;
}
public abstract ActionResult ExecuteAction(string ActionName);
public virtual void Dispose()
{
// Nothing in Base Class
if (this.Database != null)
{
this.Database.Dispose();
this.Database = null;
}
}
public AuthorizationToken Authorization
{
get
{
return UserService.CurrentAuthorization;
}
}
public User CurrentUser
{
get
{
return UserService.CurrentUser;
}
}
#region Caching
public void SetCacheability(TimeSpan CacheDuration)
{
var cache = this.HostController.Response.Cache;
cache.SetOmitVaryStar(true);
cache.SetExpires(DateTime.Now.Add(CacheDuration));
cache.SetValidUntilExpires(true);
cache.SetCacheability(HttpCacheability.Private);
}
public void SetCacheabilityOff()
{
var cache = this.HostController.Response.Cache;
cache.SetExpires(DateTime.Now.AddDays(-1));
cache.SetCacheability(HttpCacheability.NoCache);
}
#endregion
#region Action Results
#region Compiled View
private static string[] _viewFileNames = new string[] { "cshtml" };
public ActionResult CompiledView<ViewType>(object Model, bool UseDiscoLayout) where ViewType : WebViewPage
{
string layoutPath = UseDiscoLayout ? "~/Views/Shared/_Layout.cshtml" : null;
IView v = new PrecompiledMvcView(this.HostController.Request.Path, layoutPath, typeof(ViewType), false, _viewFileNames);
if (Model != null)
this.HostController.ViewData.Model = Model;
return new ViewResult { View = v, ViewData = this.HostController.ViewData, TempData = this.HostController.TempData };
}
public ActionResult CompiledView<ViewType>(bool UseDiscoLayout) where ViewType : WebViewPage
{
return this.CompiledView<ViewType>(null, UseDiscoLayout);
}
public ActionResult CompiledView<ViewType>(object Model) where ViewType : WebViewPage
{
return this.CompiledView<ViewType>(Model, true);
}
public ActionResult CompiledView<ViewType>() where ViewType : WebViewPage
{
return this.CompiledView<ViewType>(false, true);
}
public ActionResult CompiledPartialView<ViewType>(object Model) where ViewType : WebViewPage
{
IView v = new PrecompiledMvcView(this.HostController.Request.Path, typeof(ViewType), false, _viewFileNames);
if (Model != null)
this.HostController.ViewData.Model = Model;
return new PartialViewResult { View = v, ViewData = this.HostController.ViewData, TempData = this.HostController.TempData };
}
public ActionResult CompiledPartialView<ViewType>() where ViewType : WebViewPage
{
return this.CompiledView<ViewType>();
}
[Obsolete("Use Generic Methods")]
public ActionResult CompiledView(Type CompiledViewType, object Model, bool UseDiscoLayout)
{
string layoutPath = UseDiscoLayout ? "~/Views/Shared/_Layout.cshtml" : null;
@@ -37,19 +124,23 @@ namespace Disco.Services.Plugins
return new ViewResult { View = v, ViewData = this.HostController.ViewData, TempData = this.HostController.TempData };
}
[Obsolete("Use Generic Methods")]
public ActionResult CompiledView(Type CompiledViewType, bool UseDiscoLayout)
{
return this.CompiledView(CompiledViewType, null, UseDiscoLayout);
}
[Obsolete("Use Generic Methods")]
public ActionResult CompiledView(Type CompiledViewType, object Model)
{
return this.CompiledView(CompiledViewType, Model, true);
}
public ActionResult CompiledView(Type CompiledViewType)
[Obsolete("Use Generic Methods")]
public ActionResult CompiledView(Type CompiledViewType)
{
return this.CompiledView(CompiledViewType, false, true);
}
public ActionResult CompiledPartialView(Type PartialCompiledViewType, object Model)
[Obsolete("Use Generic Methods")]
public ActionResult CompiledPartialView(Type PartialCompiledViewType, object Model)
{
IView v = new PrecompiledMvcView(this.HostController.Request.Path, PartialCompiledViewType, false, _viewFileNames);
@@ -58,7 +149,8 @@ namespace Disco.Services.Plugins
return new PartialViewResult { View = v, ViewData = this.HostController.ViewData, TempData = this.HostController.TempData };
}
public ActionResult CompiledPartialView(Type PartialCompiledViewType)
[Obsolete("Use Generic Methods")]
public ActionResult CompiledPartialView(Type PartialCompiledViewType)
{
return this.CompiledView(PartialCompiledViewType, null);
}
@@ -1,4 +1,5 @@
using System;
using Disco.Services.Authorization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@@ -19,6 +20,14 @@ namespace Disco.Services.Plugins
if (methodDescriptor == null)
return this.HttpNotFound("Unknown Plugin Method");
// Authorize Method
if (methodDescriptor.Authorizers.Length > 0)
{
var attributeDenied = methodDescriptor.Authorizers.FirstOrDefault(a => !a.IsAuthorized(HostController.HttpContext));
if (attributeDenied != null)
return new HttpUnauthorizedResult(attributeDenied.HandleUnauthorizedMessage());
}
var methodParams = BuildMethodParameters(handlerType, methodDescriptor.MethodInfo, ActionName, this.HostController);
return (ActionResult)methodDescriptor.MethodInfo.Invoke(this, methodParams);
@@ -63,24 +72,6 @@ namespace Disco.Services.Plugins
parameterValue = methodParam.DefaultValue;
result[i] = parameterValue;
//var paramInstance = Activator.CreateInstance(methodParam.ParameterType);
//IModelBinder binder = ModelBinders.Binders.GetBinder(methodParam.ParameterType);
//ModelBindingContext bindingContext = new ModelBindingContext
//{
// ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => paramInstance, methodParam.ParameterType),
// ModelName = methodParam.Name,
// ModelState = HostController.ModelState,
// PropertyFilter = (p) => true,
// ValueProvider = HostController.ValueProvider
//};
//binder.BindModel(HostController.ControllerContext, bindingContext);
//if (methodParam.HasDefaultValue && paramInstance == null)
// paramInstance = methodParam.DefaultValue;
//result[i] = paramInstance;
}
return result;
@@ -102,7 +93,8 @@ namespace Disco.Services.Plugins
var item = new WebHandlerCachedItem()
{
Method = method.Name,
MethodInfo = method
MethodInfo = method,
Authorizers = method.GetCustomAttributes<DiscoAuthorizeBaseAttribute>().ToArray()
};
result.Add(item.Method.ToLower(), item);
}
@@ -115,6 +107,7 @@ namespace Disco.Services.Plugins
{
public string Method { get; set; }
public MethodInfo MethodInfo { get; set; }
public DiscoAuthorizeBaseAttribute[] Authorizers { get; set; }
}
#endregion
}
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Plugins
{
public abstract class PluginWebViewPage<T> : Disco.Services.Web.WebViewPage<T>
{
public WebHelper<T> Plugin { get; private set; }
public PluginWebViewPage()
{
var self = this.GetType();
var manifest = Plugins.GetPlugin(self.Assembly);
this.Plugin = new WebHelper<T>(this, manifest);
}
}
}
+184
View File
@@ -0,0 +1,184 @@
using Disco.Services.Web.Bundles;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;
using System.Web.WebPages;
namespace Disco.Services.Plugins
{
public class WebHelper<T>
{
private WebViewPage<T> ViewPage { get; set; }
public PluginManifest Manifest { get; private set; }
public WebHelper(WebViewPage<T> ViewPage, PluginManifest manifest)
{
this.ViewPage = ViewPage;
this.Manifest = manifest;
}
#region Html Helpers
#region Form Helpers
public MvcForm BeginForm(string Action, FormMethod Method, bool MultipartEncoding, IDictionary<string, object> HtmlAttributes)
{
if (string.IsNullOrEmpty(Action))
throw new ArgumentNullException("PluginAction");
var url = ActionUrl(Action);
return BeginForm_Helper(url.ToString(), Method, MultipartEncoding, HtmlAttributes);
}
public MvcForm BeginForm(string Action, FormMethod Method, bool MultipartEncoding)
{
return BeginForm(Action, Method, MultipartEncoding, null);
}
public MvcForm BeginForm(string Action, FormMethod Method, IDictionary<string, object> HtmlAttributes)
{
return BeginForm(Action, Method, false, HtmlAttributes);
}
public MvcForm BeginForm(string Action, FormMethod Method)
{
return BeginForm(Action, Method, false, null);
}
public MvcForm BeginForm(string Action)
{
return BeginForm(Action, FormMethod.Get, false, null);
}
private MvcForm BeginForm_Helper(string FormAction, FormMethod Method, bool MultipartEncoding, IDictionary<string, object> HtmlAttributes)
{
TagBuilder builder = new TagBuilder("form");
builder.MergeAttributes(HtmlAttributes);
if (MultipartEncoding)
builder.MergeAttribute("enctype", "multipart/form-data");
builder.MergeAttribute("action", FormAction);
builder.MergeAttribute("method", HtmlHelper.GetFormMethodString(Method), true);
bool useClientValidation = ViewPage.ViewContext.ClientValidationEnabled && !ViewPage.ViewContext.UnobtrusiveJavaScriptEnabled;
if (useClientValidation)
{
object lastFormNumber = ViewPage.ViewContext.HttpContext.Items["DiscoPluginLastFormNum"];
int num = (lastFormNumber != null) ? (((int)lastFormNumber) + 1) : 1000;
ViewPage.ViewContext.HttpContext.Items["DiscoPluginLastFormNum"] = num;
builder.GenerateId(string.Format(CultureInfo.InvariantCulture, "form{0}", new object[] { num }));
}
ViewPage.ViewContext.Writer.Write(builder.ToString(TagRenderMode.StartTag));
MvcForm form = new MvcForm(ViewPage.ViewContext);
if (useClientValidation)
{
ViewPage.ViewContext.FormContext.FormId = builder.Attributes["id"];
}
return form;
}
#endregion
public void IncludeStyleSheet(string Resource)
{
var url = ResourceUrl(Resource);
var deferredBundles = ViewPage.Context.Items[Bundle.UIExtensionCssKey] as List<HtmlString>;
if (deferredBundles == null)
{
deferredBundles = new List<HtmlString>();
ViewPage.Context.Items[Bundle.UIExtensionCssKey] = deferredBundles;
}
if (!deferredBundles.Contains(url))
deferredBundles.Add(url);
}
public void IncludeJavaScript(string Resource)
{
var url = ResourceUrl(Resource);
var deferredBundles = ViewPage.Context.Items[Bundle.UIExtensionScriptsKey] as List<HtmlString>;
if (deferredBundles == null)
{
deferredBundles = new List<HtmlString>();
ViewPage.Context.Items[Bundle.UIExtensionScriptsKey] = deferredBundles;
}
if (!deferredBundles.Contains(url))
deferredBundles.Add(url);
}
public HtmlString PartialCompiled<ViewType>(object Model) where ViewType : WebViewPage
{
using (System.IO.StringWriter writer = new StringWriter(CultureInfo.CurrentCulture))
{
RenderPartialCompiled<ViewType>(writer, Model);
return new HtmlString(writer.ToString());
}
}
public HtmlString PartialCompiled<ViewType>() where ViewType : WebViewPage
{
return PartialCompiled<ViewType>(null);
}
private void RenderPartialCompiled<ViewType>(TextWriter Writer, object Model)
{
if (Writer == null)
throw new ArgumentNullException("Writer");
WebViewPage page = Activator.CreateInstance(typeof(ViewType)) as WebViewPage;
if (page == null)
throw new InvalidOperationException("Invalid View Type");
page.ViewContext = ViewPage.ViewContext;
page.ViewData = new ViewDataDictionary(Model);
page.InitHelpers();
HttpContextBase httpContext = ViewPage.ViewContext.HttpContext;
page.ExecutePageHierarchy(new WebPageContext(httpContext, null, Model), Writer, null);
}
#endregion
#region Urls
public HtmlString ConfigurationUrl()
{
var url = GenerateUrl("Config_Plugins_Configure", new Dictionary<string, object>() { { "PluginId", Manifest.Id } });
return new HtmlString(url);
}
public HtmlString ActionUrl(string Action)
{
var url = GenerateUrl("Plugin", new Dictionary<string, object>() { { "PluginId", Manifest.Id }, { "PluginAction", Action } });
return new HtmlString(url);
}
public HtmlString ResourceUrl(string Resource)
{
return ResourceUrl(Resource, false);
}
public HtmlString ResourceUrl(string Resource, bool Download)
{
var url = Manifest.WebResourceUrl(Resource);
if (Download)
url += "&Download=true";
return new HtmlString(url);
}
#endregion
#region Helpers
private string GenerateUrl(string RouteName, RouteValueDictionary RouteValues)
{
return UrlHelper.GenerateUrl(RouteName, null, null, RouteValues, RouteTable.Routes, ViewPage.Request.RequestContext, false);
}
private string GenerateUrl(string RouteName, IDictionary<string, object> RouteValues)
{
return GenerateUrl(RouteName, new RouteValueDictionary(RouteValues));
}
#endregion
}
}
+4
View File
@@ -11,6 +11,10 @@ namespace Disco.Services.Web.Bundles
{
public class Bundle
{
public const string DeferredKey = "Bundles.Deferred";
public const string UIExtensionScriptsKey = "Bundles.UIExtensionScripts";
public const string UIExtensionCssKey = "Bundles.UIExtensionCss";
private DateTime? _FileLastModified { get; set; }
private string _FileHash { get; set; }
private string _VersionUrl { get; set; }
@@ -16,21 +16,21 @@ namespace Disco.Services.Web
// Ensure 'App-Relative' Url:
BundleUrl = BundleUrl.StartsWith("~/") ? BundleUrl : (BundleUrl.StartsWith("/") ? string.Concat("~", BundleUrl) : string.Concat("~/", BundleUrl));
var deferredBundles = htmlHelper.ViewContext.HttpContext.Items["Bundles.Deferred"] as List<string>;
var deferredBundles = htmlHelper.ViewContext.HttpContext.Items[Bundle.DeferredKey] as List<string>;
if (deferredBundles == null)
{
deferredBundles = new List<string>();
htmlHelper.ViewContext.HttpContext.Items["Bundles.Deferred"] = deferredBundles;
htmlHelper.ViewContext.HttpContext.Items[Bundle.DeferredKey] = deferredBundles;
}
if (!deferredBundles.Contains(BundleUrl))
deferredBundles.Add(BundleUrl);
}
public static HtmlString BundleRenderDeferred(this HtmlHelper htmlHelper)
{
var deferredBundles = htmlHelper.ViewContext.HttpContext.Items["Bundles.Deferred"] as List<string>;
var deferredBundles = htmlHelper.ViewContext.HttpContext.Items[Bundle.DeferredKey] as List<string>;
var uiExtensionScripts = htmlHelper.ViewContext.HttpContext.Items["Bundles.UIExtensionScripts"] as List<HtmlString>;
var uiExtensionCss = htmlHelper.ViewContext.HttpContext.Items["Bundles.UIExtensionCss"] as List<HtmlString>;
var uiExtensionScripts = htmlHelper.ViewContext.HttpContext.Items[Bundle.UIExtensionScriptsKey] as List<HtmlString>;
var uiExtensionCss = htmlHelper.ViewContext.HttpContext.Items[Bundle.UIExtensionCssKey] as List<HtmlString>;
if (deferredBundles != null || uiExtensionScripts != null || uiExtensionCss != null)
{
@@ -34,16 +34,16 @@ namespace Disco.Web.Extensions
{
htmlHelper.RenderPartialCompiledInternal(viewType, model, htmlHelper.ViewContext.Writer);
}
public static MvcHtmlString PartialCompiled(this HtmlHelper htmlHelper, Type viewType)
public static HtmlString PartialCompiled(this HtmlHelper htmlHelper, Type viewType)
{
return PartialCompiled(htmlHelper, viewType, null);
}
public static MvcHtmlString PartialCompiled(this HtmlHelper htmlHelper, Type viewType, object model)
public static HtmlString PartialCompiled(this HtmlHelper htmlHelper, Type viewType, object model)
{
using (StringWriter writer = new StringWriter(CultureInfo.CurrentCulture))
{
htmlHelper.RenderPartialCompiledInternal(viewType, model, writer);
return MvcHtmlString.Create(writer.ToString());
return new HtmlString(writer.ToString());
}
}
#endregion
+6
View File
@@ -213,6 +213,12 @@
#UserDetailTab-Authorization .fancytree-container {
border: none;
}
#UserDetailTab-Authorization span.fancytree-ico-c > span.fancytree-icon {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACgklEQVQ4y5XSXUhTYRgH8OkItViSri676CIIupC6kIjIrQTNtLbhMEOLmjGsi1CiJoULZmEpW4l5RDehkR/owJNF+3DLliMd6GDWcrFNyNEceAarZZuc7d8xSNQzgx54Lt6v3/vxvBwAnI3Z0NDAJQiifWJiImgwGOIkScasVuuMWq2u3Dp3LTc15HJ5Zk9PzzhFURh79fpTr7avv4voHns/ORkJh8NQqVTX/wmIxWLZW5sNBNGt3tgvrareYzQavVqt9nt5eXnetkCTosk4OkrGWh485G7dqfXR4yvMlSCVSs9sC3z2frFOTU0vp7ur2TJe4XA4oNFoKrcFZl0us9lsodIBk44PpSaTCXa7vSwtoNPpAsxqOJ1OBAIBOhKJ0PF4nE6lUjQzTq+srKR8Ph/m5uaSS0tLLSygsbFx1ev1IhgMwuPxIBQKIRaLIZlM4m+4XC4olUp0dna+YwEKhSLh9/uxuLgIt9v9B4pGo6Bpeh1YOx1TSuj1+nEWcPfe/cSsy4fgtzB8vgX4F34wADbF/Pw81JoOGEgbG3jeVppY9jVD2XwbN+ol+BURwdBfC1ldPaL+ywi5ZTgvuYibshJQ5nNsQFxWmHCTRzHWvR88XjaeKrmgPnJw8AAPFcKdzANkQCrIQn4+H3fEWWyg4MixuOD4IdDTeWiTZyB3Nw+Wrkx4BjOxj5+LW1XZwDAHJw/vAjdnr5kNFBSsSipr0asqwcKbQlyqLkH91bOgZk6DaKlgfuAFzOpOwN5xCnw+37kOFBcX7ygqKrpWU1P7kylPqrXtGdqf6DAwMIjhkZcYGrHAZLbBYrGhT0/ixdBoSiQSfRUKhRKBQJDDSffr/id/A3fSz48XbZuBAAAAAElFTkSuQmCC') /*Images/Actions/locked.png*/;
}
#UserDetailTab-Authorization span.fancytree-ico-c.fancytree-selected > span.fancytree-icon {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACWUlEQVQ4y6XRXWiSURgHcJsXa4WNNuuyiy6CoAupixERoXXhmljuxaJiFrVA1i72cVFCOSMt8rNt2YfGO5g5Z1NstWW+c4ZBq4QpqMkEbZDSCObAMprjdf90sIjxsgUdODd/zvmd5zwPCwDrf/aGB7q6utgmk8ngdruzVqt10eVyTWu1Wuk/AXK5vMpoNPpjsRgGbU8/9fbdH/J4PAuRSARKpfLKhoBYLG595nTCaDSZVjPp6TPbHQ5H0mAwfBeJRHXrAp0dna9JcqCguX2H/Xd+S625aLFYQBDE8XWBd+8/TI6Njc+vzcfGX4nLX4FOp5OuC0wGAlS53NzaPPAm2Gi32+H3+5tYJEl+pigKoVAIPp+PnpqaosPhMF1uHB2Px2mv14vya6VgMKhhHGN3d/dSMplENptFIpHA3NwcCoUCSqUSKqvScZVKBbPZHGQEFApFMZ1OI5PJIBqNrkD5fB40Ta8AlcrUajVsNpufEbh+42YxHEkh+/UbUqlZpGd/lAH8WTMzMzDd64d7NMAMDOobi/OpHqh6rqK9jcCvBQncQzK0Xm5DPn0BJ4lz6GgVIkedYAaamxqK0dEDePl4FziczehTsZGLs7BnNwdiwRac4lejvp6La83VzABv/8FF/qG9oD/WQS/fhNptHEw8rEJiuAo7ubXACAtH9m0Fu2YHxQzweEuEVIYnaiFmvQ04f1aItksi5KaP4ZFGjDB5GG/7j4LL5YYYgZYW2c/yiJbv6h/A0EvC4RjGiOsFnK4J+KgABmyjsDufL0skki8CgYCoXOLz+TWrwG+kXMkgQ6yv+QAAAABJRU5ErkJggg==') /*Images/Actions/unlocked.png*/;
}
#UserDetailTab-Authorization span.fancytree-node.fancytree-selected {
font-style: normal;
}
+8
View File
@@ -182,6 +182,14 @@
border: none;
}
span.fancytree-ico-c > span.fancytree-icon {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACgklEQVQ4y5XSXUhTYRgH8OkItViSri676CIIupC6kIjIrQTNtLbhMEOLmjGsi1CiJoULZmEpW4l5RDehkR/owJNF+3DLliMd6GDWcrFNyNEceAarZZuc7d8xSNQzgx54Lt6v3/vxvBwAnI3Z0NDAJQiifWJiImgwGOIkScasVuuMWq2u3Dp3LTc15HJ5Zk9PzzhFURh79fpTr7avv4voHns/ORkJh8NQqVTX/wmIxWLZW5sNBNGt3tgvrareYzQavVqt9nt5eXnetkCTosk4OkrGWh485G7dqfXR4yvMlSCVSs9sC3z2frFOTU0vp7ur2TJe4XA4oNFoKrcFZl0us9lsodIBk44PpSaTCXa7vSwtoNPpAsxqOJ1OBAIBOhKJ0PF4nE6lUjQzTq+srKR8Ph/m5uaSS0tLLSygsbFx1ev1IhgMwuPxIBQKIRaLIZlM4m+4XC4olUp0dna+YwEKhSLh9/uxuLgIt9v9B4pGo6Bpeh1YOx1TSuj1+nEWcPfe/cSsy4fgtzB8vgX4F34wADbF/Pw81JoOGEgbG3jeVppY9jVD2XwbN+ol+BURwdBfC1ldPaL+ywi5ZTgvuYibshJQ5nNsQFxWmHCTRzHWvR88XjaeKrmgPnJw8AAPFcKdzANkQCrIQn4+H3fEWWyg4MixuOD4IdDTeWiTZyB3Nw+Wrkx4BjOxj5+LW1XZwDAHJw/vAjdnr5kNFBSsSipr0asqwcKbQlyqLkH91bOgZk6DaKlgfuAFzOpOwN5xCnw+37kOFBcX7ygqKrpWU1P7kylPqrXtGdqf6DAwMIjhkZcYGrHAZLbBYrGhT0/ixdBoSiQSfRUKhRKBQJDDSffr/id/A3fSz48XbZuBAAAAAElFTkSuQmCC') /*Images/Actions/locked.png*/;
}
span.fancytree-ico-c.fancytree-selected > span.fancytree-icon {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACWUlEQVQ4y6XRXWiSURgHcJsXa4WNNuuyiy6CoAupixERoXXhmljuxaJiFrVA1i72cVFCOSMt8rNt2YfGO5g5Z1NstWW+c4ZBq4QpqMkEbZDSCObAMprjdf90sIjxsgUdODd/zvmd5zwPCwDrf/aGB7q6utgmk8ngdruzVqt10eVyTWu1Wuk/AXK5vMpoNPpjsRgGbU8/9fbdH/J4PAuRSARKpfLKhoBYLG595nTCaDSZVjPp6TPbHQ5H0mAwfBeJRHXrAp0dna9JcqCguX2H/Xd+S625aLFYQBDE8XWBd+8/TI6Njc+vzcfGX4nLX4FOp5OuC0wGAlS53NzaPPAm2Gi32+H3+5tYJEl+pigKoVAIPp+PnpqaosPhMF1uHB2Px2mv14vya6VgMKhhHGN3d/dSMplENptFIpHA3NwcCoUCSqUSKqvScZVKBbPZHGQEFApFMZ1OI5PJIBqNrkD5fB40Ta8AlcrUajVsNpufEbh+42YxHEkh+/UbUqlZpGd/lAH8WTMzMzDd64d7NMAMDOobi/OpHqh6rqK9jcCvBQncQzK0Xm5DPn0BJ4lz6GgVIkedYAaamxqK0dEDePl4FziczehTsZGLs7BnNwdiwRac4lejvp6La83VzABv/8FF/qG9oD/WQS/fhNptHEw8rEJiuAo7ubXACAtH9m0Fu2YHxQzweEuEVIYnaiFmvQ04f1aItksi5KaP4ZFGjDB5GG/7j4LL5YYYgZYW2c/yiJbv6h/A0EvC4RjGiOsFnK4J+KgABmyjsDufL0skki8CgYCoXOLz+TWrwG+kXMkgQ6yv+QAAAABJRU5ErkJggg==') /*Images/Actions/unlocked.png*/;
}
span.fancytree-node.fancytree-selected {
font-style: normal;
}
File diff suppressed because one or more lines are too long
@@ -11,7 +11,6 @@ namespace Disco.Web.Controllers
{
public partial class PluginWebHandlerController : Controller
{
[DiscoAuthorize(Claims.DiscoAdminAccount)]
[OutputCache(Duration = 0, Location = System.Web.UI.OutputCacheLocation.None)]
public virtual ActionResult Index(string PluginId, string PluginAction)
{
@@ -19,11 +18,20 @@ namespace Disco.Web.Controllers
if (manifest.HasWebHandler)
{
using (var pluginWebHandler = manifest.CreateWebHandler(this))
try
{
return pluginWebHandler.ExecuteAction(PluginAction);
using (var pluginWebHandler = manifest.CreateWebHandler(this))
{
pluginWebHandler.OnActionExecuting();
return pluginWebHandler.ExecuteAction(PluginAction);
}
}
catch (AccessDeniedException accessDeniedException)
{
return new HttpUnauthorizedResult(accessDeniedException.Message);
}
}
return HttpNotFound("Plugin has no Web Handler");
}
@@ -42,7 +50,7 @@ namespace Disco.Web.Controllers
{
return HttpNotFound("Plugin Resource Not Found");
}
var pluginResourcePath = pluginResource.Item1;
var mimeType = Disco.BI.Interop.MimeTypes.ResolveMimeType(pluginResourcePath);