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 namespace Disco.Services.Authorization
{ {
public class DiscoAuthorizeAllAttribute : AuthorizeAttribute public class DiscoAuthorizeAllAttribute : DiscoAuthorizeBaseAttribute
{ {
string[] authorizedClaims; string[] authorizedClaims;
@@ -20,22 +20,17 @@ namespace Disco.Services.Authorization
this.authorizedClaims = AuthorisedClaims; this.authorizedClaims = AuthorisedClaims;
} }
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext) public override bool IsAuthorized(System.Web.HttpContextBase httpContext)
{ {
if (httpContext == null) if (Token == null)
throw new ArgumentNullException("httpContext");
var authToken = UserService.CurrentAuthorization;
if (authToken == null)
return false; // No Current User 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 namespace Disco.Services.Authorization
{ {
public class DiscoAuthorizeAnyAttribute : AuthorizeAttribute public class DiscoAuthorizeAnyAttribute : DiscoAuthorizeBaseAttribute
{ {
string[] authorizedClaims; string[] authorizedClaims;
@@ -20,22 +20,17 @@ namespace Disco.Services.Authorization
this.authorizedClaims = AuthorisedClaims; this.authorizedClaims = AuthorisedClaims;
} }
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext) public override bool IsAuthorized(System.Web.HttpContextBase httpContext)
{ {
if (httpContext == null) if (Token == null)
throw new ArgumentNullException("httpContext");
var authToken = UserService.CurrentAuthorization;
if (authToken == null)
return false; // No Current User 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 namespace Disco.Services.Authorization
{ {
public class DiscoAuthorizeAttribute : AuthorizeAttribute public class DiscoAuthorizeAttribute : DiscoAuthorizeBaseAttribute
{ {
string authorizedClaim; string authorizedClaim;
@@ -19,23 +19,18 @@ namespace Disco.Services.Authorization
this.authorizedClaim = AuthorisedClaim; this.authorizedClaim = AuthorisedClaim;
} }
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext) public override bool IsAuthorized(System.Web.HttpContextBase httpContext)
{ {
if (httpContext == null) if (Token == null)
throw new ArgumentNullException("httpContext");
var authToken = UserService.CurrentAuthorization;
if (authToken == null)
return false; // No Current User return false; // No Current User
if (authorizedClaim == null) 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 else
return authToken.Has(authorizedClaim); return Token.Has(authorizedClaim);
} }
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) public override string HandleUnauthorizedMessage()
{ {
string resultMessage; string resultMessage;
@@ -47,7 +42,7 @@ namespace Disco.Services.Authorization
else else
resultMessage = AuthorizationToken.BuildRequireMessage(authorizedClaim); 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\AccessDeniedException.cs" />
<Compile Include="Authorization\AuthorizationToken.cs" /> <Compile Include="Authorization\AuthorizationToken.cs" />
<Compile Include="Authorization\ClaimNavigatorItem.cs" /> <Compile Include="Authorization\ClaimNavigatorItem.cs" />
<Compile Include="Authorization\DiscoAuthorizeBaseAttribute.cs" />
<Compile Include="Authorization\DiscoAuthorizeAllAttribute.cs" /> <Compile Include="Authorization\DiscoAuthorizeAllAttribute.cs" />
<Compile Include="Authorization\DiscoAuthorizeAnyAttribute.cs" /> <Compile Include="Authorization\DiscoAuthorizeAnyAttribute.cs" />
<Compile Include="Authorization\DiscoAuthorizeAttribute.cs" /> <Compile Include="Authorization\DiscoAuthorizeAttribute.cs" />
@@ -174,6 +175,8 @@
<Compile Include="Plugins\PluginWebHandlerController.cs" /> <Compile Include="Plugins\PluginWebHandlerController.cs" />
<Compile Include="Plugins\UninstallPluginTask.cs" /> <Compile Include="Plugins\UninstallPluginTask.cs" />
<Compile Include="Plugins\UnknownPluginException.cs" /> <Compile Include="Plugins\UnknownPluginException.cs" />
<Compile Include="Plugins\WebHelper.cs" />
<Compile Include="Plugins\PluginWebViewPage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Tasks\ScheduledTask.cs" /> <Compile Include="Tasks\ScheduledTask.cs" />
<Compile Include="Tasks\ScheduledTasks.cs" /> <Compile Include="Tasks\ScheduledTasks.cs" />
@@ -220,7 +223,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions> <ProjectExtensions>
<VisualStudio> <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> </VisualStudio>
</ProjectExtensions> </ProjectExtensions>
<PropertyGroup> <PropertyGroup>
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web.Mvc;
namespace Disco.Services.Plugins.Features.UIExtension.Results namespace Disco.Services.Plugins.Features.UIExtension.Results
{ {
@@ -18,7 +19,7 @@ namespace Disco.Services.Plugins.Features.UIExtension.Results
this.results = 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) 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.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace Disco.Services.Plugins.Features.UIExtension.Results namespace Disco.Services.Plugins.Features.UIExtension.Results
{ {
@@ -16,13 +19,13 @@ namespace Disco.Services.Plugins.Features.UIExtension.Results
: base(Source) : base(Source)
{ {
this._resource = Resource; 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) if (deferredBundles == null)
{ {
deferredBundles = new List<HtmlString>(); deferredBundles = new List<HtmlString>();
HttpContext.Current.Items["Bundles.UIExtensionCss"] = deferredBundles; HttpContext.Current.Items[Bundle.UIExtensionCssKey] = deferredBundles;
} }
if (!deferredBundles.Contains(this._resourceUrl)) if (!deferredBundles.Contains(this._resourceUrl))
deferredBundles.Add(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.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -17,16 +18,16 @@ namespace Disco.Services.Plugins.Features.UIExtension.Results
: base(Source) : base(Source)
{ {
this._resource = Resource; 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; this._placeInPageHead = PlaceInPageHead;
if (this._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) if (deferredBundles == null)
{ {
deferredBundles = new List<HtmlString>(); deferredBundles = new List<HtmlString>();
HttpContext.Current.Items["Bundles.UIExtensionScripts"] = deferredBundles; HttpContext.Current.Items[Bundle.UIExtensionScriptsKey] = deferredBundles;
} }
if (!deferredBundles.Contains(this._resourceUrl)) if (!deferredBundles.Contains(this._resourceUrl))
deferredBundles.Add(this._resourceUrl); deferredBundles.Add(this._resourceUrl);
+34 -26
View File
@@ -10,6 +10,7 @@ using System.Web.Routing;
using System.Web; using System.Web;
using System.Web.Mvc.Html; using System.Web.Mvc.Html;
using System.Globalization; using System.Globalization;
using Disco.Services.Web.Bundles;
namespace Disco.Services.Plugins namespace Disco.Services.Plugins
{ {
@@ -93,34 +94,13 @@ namespace Disco.Services.Plugins
#endregion #endregion
#region Virtual Directories #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) public static HtmlString DiscoPluginResourceUrl<T>(this WebViewPage<T> ViewPage, string Resource)
{ {
return ViewPage.DiscoPluginResourceUrl(Resource, false); 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) public static HtmlString DiscoPluginResourceUrl<T>(this WebViewPage<T> ViewPage, string Resource, bool Download)
{ {
if (string.IsNullOrEmpty(Resource)) if (string.IsNullOrEmpty(Resource))
@@ -133,10 +113,12 @@ namespace Disco.Services.Plugins
return ViewPage.DiscoPluginResourceUrl(Resource, false, manifest); 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) public static HtmlString DiscoPluginResourceUrl<T>(this WebViewPage<T> ViewPage, string Resource, bool Download, PluginManifest manifest)
{ {
return ViewPage.ViewContext.RequestContext.DiscoPluginResourceUrl(Resource, Download, manifest); return ViewPage.ViewContext.RequestContext.DiscoPluginResourceUrl(Resource, Download, manifest);
} }
[Obsolete]
public static HtmlString DiscoPluginResourceUrl(this RequestContext RequestContext, string Resource, bool Download, PluginManifest manifest) public static HtmlString DiscoPluginResourceUrl(this RequestContext RequestContext, string Resource, bool Download, PluginManifest manifest)
{ {
var resourcePath = manifest.WebResourcePath(Resource); var resourcePath = manifest.WebResourcePath(Resource);
@@ -151,6 +133,7 @@ namespace Disco.Services.Plugins
return new HtmlString(pluginActionUrl); return new HtmlString(pluginActionUrl);
} }
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static HtmlString DiscoPluginActionUrl<T>(this WebViewPage<T> ViewPage, string PluginAction) public static HtmlString DiscoPluginActionUrl<T>(this WebViewPage<T> ViewPage, string PluginAction)
{ {
if (string.IsNullOrEmpty(PluginAction)) if (string.IsNullOrEmpty(PluginAction))
@@ -163,16 +146,19 @@ namespace Disco.Services.Plugins
return ViewPage.DiscoPluginActionUrl(PluginAction, manifest); 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) public static HtmlString DiscoPluginActionUrl<T>(this WebViewPage<T> ViewPage, string PluginAction, PluginManifest manifest)
{ {
return ViewPage.ViewContext.RequestContext.DiscoPluginActionUrl(PluginAction, 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) public static HtmlString DiscoPluginActionUrl(this RequestContext RequestContext, string PluginAction, PluginManifest manifest)
{ {
var routeValues = new RouteValueDictionary(new { PluginId = manifest.Id, PluginAction = PluginAction }); var routeValues = new RouteValueDictionary(new { PluginId = manifest.Id, PluginAction = PluginAction });
string pluginActionUrl = UrlHelper.GenerateUrl("Plugin", null, null, routeValues, RouteTable.Routes, RequestContext, false); string pluginActionUrl = UrlHelper.GenerateUrl("Plugin", null, null, routeValues, RouteTable.Routes, RequestContext, false);
return new HtmlString(pluginActionUrl); return new HtmlString(pluginActionUrl);
} }
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static HtmlString DiscoPluginConfigureUrl<T>(this WebViewPage<T> ViewPage) public static HtmlString DiscoPluginConfigureUrl<T>(this WebViewPage<T> ViewPage)
{ {
// Find Plugin // Find Plugin
@@ -182,16 +168,19 @@ namespace Disco.Services.Plugins
return ViewPage.DiscoPluginConfigureUrl(manifest); return ViewPage.DiscoPluginConfigureUrl(manifest);
} }
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static HtmlString DiscoPluginConfigureUrl<T>(this WebViewPage<T> ViewPage, PluginManifest manifest) public static HtmlString DiscoPluginConfigureUrl<T>(this WebViewPage<T> ViewPage, PluginManifest manifest)
{ {
return new HtmlString(ViewPage.ViewContext.RequestContext.DiscoPluginConfigureUrl(manifest)); return new HtmlString(ViewPage.ViewContext.RequestContext.DiscoPluginConfigureUrl(manifest));
} }
[Obsolete]
public static string DiscoPluginConfigureUrl(this RequestContext RequestContext, PluginManifest manifest) public static string DiscoPluginConfigureUrl(this RequestContext RequestContext, PluginManifest manifest)
{ {
var routeValues = new RouteValueDictionary(new { PluginId = manifest.Id }); var routeValues = new RouteValueDictionary(new { PluginId = manifest.Id });
string pluginActionUrl = UrlHelper.GenerateUrl("Config_Plugins_Configure", null, null, routeValues, RouteTable.Routes, RequestContext, false); string pluginActionUrl = UrlHelper.GenerateUrl("Config_Plugins_Configure", null, null, routeValues, RouteTable.Routes, RequestContext, false);
return pluginActionUrl; 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) public static MvcForm DiscoPluginActionBeginForm<T>(this WebViewPage<T> ViewPage, string PluginAction, FormMethod method, IDictionary<string, object> htmlAttributes)
{ {
if (string.IsNullOrEmpty(PluginAction)) if (string.IsNullOrEmpty(PluginAction))
@@ -207,19 +196,29 @@ namespace Disco.Services.Plugins
return ViewPage.FormHelper(pluginActionUrl, method, htmlAttributes); 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) public static MvcForm DiscoPluginActionBeginForm<T>(this WebViewPage<T> ViewPage, string PluginAction, FormMethod method)
{ {
#pragma warning disable 618
return ViewPage.DiscoPluginActionBeginForm(PluginAction, method, null); 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) 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); 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) public static MvcForm DiscoPluginActionBeginForm<T>(this WebViewPage<T> ViewPage, string PluginAction)
{ {
#pragma warning disable 618
return ViewPage.DiscoPluginActionBeginForm(PluginAction, FormMethod.Post, null); 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) private static MvcForm FormHelper<T>(this WebViewPage<T> ViewPage, string formAction, FormMethod method, IDictionary<string, object> htmlAttributes)
{ {
TagBuilder builder = new TagBuilder("form"); TagBuilder builder = new TagBuilder("form");
@@ -244,7 +243,7 @@ namespace Disco.Services.Plugins
return form; return form;
} }
[Obsolete("Inherit ViewPages from 'Disco.Services.Plugins.WebViewPage' instead.")]
public static void DiscoPluginRegisterStylesheet<T>(this WebViewPage<T> ViewPage, string Resource) public static void DiscoPluginRegisterStylesheet<T>(this WebViewPage<T> ViewPage, string Resource)
{ {
if (string.IsNullOrEmpty(Resource)) if (string.IsNullOrEmpty(Resource))
@@ -257,10 +256,12 @@ namespace Disco.Services.Plugins
ViewPage.DiscoPluginRegisterStylesheet(Resource, manifest); 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) public static void DiscoPluginRegisterStylesheet<T>(this WebViewPage<T> ViewPage, string Resource, PluginManifest manifest)
{ {
ViewPage.ViewContext.RequestContext.DiscoPluginRegisterStylesheet(Resource, manifest); ViewPage.ViewContext.RequestContext.DiscoPluginRegisterStylesheet(Resource, manifest);
} }
[Obsolete]
public static void DiscoPluginRegisterStylesheet(this RequestContext RequestContext, string Resource, PluginManifest manifest) public static void DiscoPluginRegisterStylesheet(this RequestContext RequestContext, string Resource, PluginManifest manifest)
{ {
var resourcePath = manifest.WebResourcePath(Resource); var resourcePath = manifest.WebResourcePath(Resource);
@@ -272,11 +273,11 @@ namespace Disco.Services.Plugins
HtmlString pluginResourceUrlHtml = new HtmlString(pluginResourceUrl); 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) if (deferredBundles == null)
{ {
deferredBundles = new List<HtmlString>(); deferredBundles = new List<HtmlString>();
HttpContext.Current.Items["Bundles.UIExtensionCss"] = deferredBundles; HttpContext.Current.Items[Bundle.UIExtensionCssKey] = deferredBundles;
} }
if (!deferredBundles.Contains(pluginResourceUrlHtml)) if (!deferredBundles.Contains(pluginResourceUrlHtml))
deferredBundles.Add(pluginResourceUrlHtml); deferredBundles.Add(pluginResourceUrlHtml);
@@ -285,6 +286,7 @@ namespace Disco.Services.Plugins
#endregion #endregion
#region Request Caching #region Request Caching
[Obsolete]
public static void SetCacheability(this PluginWebHandler Handler, TimeSpan CacheDuration) public static void SetCacheability(this PluginWebHandler Handler, TimeSpan CacheDuration)
{ {
var cache = Handler.HostController.Response.Cache; var cache = Handler.HostController.Response.Cache;
@@ -293,6 +295,7 @@ namespace Disco.Services.Plugins
cache.SetValidUntilExpires(true); cache.SetValidUntilExpires(true);
cache.SetCacheability(HttpCacheability.Private); cache.SetCacheability(HttpCacheability.Private);
} }
[Obsolete]
public static void SetCacheabilityOff(this PluginWebHandler Handler) public static void SetCacheabilityOff(this PluginWebHandler Handler)
{ {
var cache = Handler.HostController.Response.Cache; var cache = Handler.HostController.Response.Cache;
@@ -302,6 +305,7 @@ namespace Disco.Services.Plugins
#endregion #endregion
#region Render Partial Compiled #region Render Partial Compiled
[Obsolete]
private static void RenderPartialCompiledInternal(this HtmlHelper htmlHelper, Type viewType, object model, TextWriter writer) private static void RenderPartialCompiledInternal(this HtmlHelper htmlHelper, Type viewType, object model, TextWriter writer)
{ {
if (writer == null) if (writer == null)
@@ -315,15 +319,19 @@ namespace Disco.Services.Plugins
HttpContextBase httpContext = htmlHelper.ViewContext.HttpContext; HttpContextBase httpContext = htmlHelper.ViewContext.HttpContext;
page.ExecutePageHierarchy(new WebPageContext(httpContext, null, model), writer, null); page.ExecutePageHierarchy(new WebPageContext(httpContext, null, model), writer, null);
} }
[Obsolete]
public static MvcHtmlString PartialCompiled(this HtmlHelper htmlHelper, Type viewType) public static MvcHtmlString PartialCompiled(this HtmlHelper htmlHelper, Type viewType)
{ {
return PartialCompiled(htmlHelper, viewType, null); return PartialCompiled(htmlHelper, viewType, null);
} }
[Obsolete]
public static MvcHtmlString PartialCompiled(this HtmlHelper htmlHelper, Type viewType, object model) public static MvcHtmlString PartialCompiled(this HtmlHelper htmlHelper, Type viewType, object model)
{ {
using (StringWriter writer = new StringWriter(CultureInfo.CurrentCulture)) using (StringWriter writer = new StringWriter(CultureInfo.CurrentCulture))
{ {
#pragma warning disable 618
htmlHelper.RenderPartialCompiledInternal(viewType, model, writer); htmlHelper.RenderPartialCompiledInternal(viewType, model, writer);
#pragma warning restore 618
return MvcHtmlString.Create(writer.ToString()); return MvcHtmlString.Create(writer.ToString());
} }
} }
+28
View File
@@ -12,6 +12,8 @@ using Disco.Data.Repository;
using Disco.Services.Tasks; using Disco.Services.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using Disco.Services.Authorization;
using System.Web.Routing;
namespace Disco.Services.Plugins namespace Disco.Services.Plugins
{ {
@@ -54,6 +56,8 @@ namespace Disco.Services.Plugins
private Type ConfigurationHandlerType { get; set; } private Type ConfigurationHandlerType { get; set; }
[JsonIgnore] [JsonIgnore]
private Type WebHandlerType { get; set; } private Type WebHandlerType { get; set; }
[JsonIgnore]
private DiscoAuthorizeBaseAttribute[] WebHandlerAuthorizers { get; set; }
[JsonIgnore] [JsonIgnore]
public string PluginLocation { get; private set; } public string PluginLocation { get; private set; }
@@ -426,6 +430,18 @@ namespace Disco.Services.Plugins
if (!typeof(PluginWebHandler).IsAssignableFrom(this.WebHandlerType)) if (!typeof(PluginWebHandler).IsAssignableFrom(this.WebHandlerType))
throw new ArgumentException("The Plugin WebHandlerType must inherit Disco.Services.Plugins.PluginWebHandler", "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); var handler = (PluginWebHandler)Activator.CreateInstance(this.WebHandlerType);
handler.Manifest = this; handler.Manifest = this;
@@ -480,6 +496,18 @@ namespace Disco.Services.Plugins
return new Tuple<string, string>(resourcePath, resourceHash.Item1); 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) public void LogException(Exception PluginException)
{ {
+101 -9
View File
@@ -1,12 +1,14 @@
using System; using Disco.Data.Repository;
using System.Collections.Generic; using Disco.Models.Repository;
using Disco.Services.Authorization;
using Disco.Services.Users;
using RazorGenerator.Mvc;
using System;
using System.IO; using System.IO;
using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using System.Web.Routing; using System.Web.Routing;
using RazorGenerator.Mvc;
namespace Disco.Services.Plugins namespace Disco.Services.Plugins
{ {
@@ -14,18 +16,103 @@ namespace Disco.Services.Plugins
{ {
public PluginManifest Manifest { get; set; } public PluginManifest Manifest { get; set; }
public Controller HostController { 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 abstract ActionResult ExecuteAction(string ActionName);
public virtual void Dispose() 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 Action Results
#region Compiled View #region Compiled View
private static string[] _viewFileNames = new string[] { "cshtml" }; 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) public ActionResult CompiledView(Type CompiledViewType, object Model, bool UseDiscoLayout)
{ {
string layoutPath = UseDiscoLayout ? "~/Views/Shared/_Layout.cshtml" : null; 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 }; return new ViewResult { View = v, ViewData = this.HostController.ViewData, TempData = this.HostController.TempData };
} }
[Obsolete("Use Generic Methods")]
public ActionResult CompiledView(Type CompiledViewType, bool UseDiscoLayout) public ActionResult CompiledView(Type CompiledViewType, bool UseDiscoLayout)
{ {
return this.CompiledView(CompiledViewType, null, UseDiscoLayout); return this.CompiledView(CompiledViewType, null, UseDiscoLayout);
} }
[Obsolete("Use Generic Methods")]
public ActionResult CompiledView(Type CompiledViewType, object Model) public ActionResult CompiledView(Type CompiledViewType, object Model)
{ {
return this.CompiledView(CompiledViewType, Model, true); 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); 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); 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 }; 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); return this.CompiledView(PartialCompiledViewType, null);
} }
@@ -1,4 +1,5 @@
using System; using Disco.Services.Authorization;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
@@ -19,6 +20,14 @@ namespace Disco.Services.Plugins
if (methodDescriptor == null) if (methodDescriptor == null)
return this.HttpNotFound("Unknown Plugin Method"); 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); var methodParams = BuildMethodParameters(handlerType, methodDescriptor.MethodInfo, ActionName, this.HostController);
return (ActionResult)methodDescriptor.MethodInfo.Invoke(this, methodParams); return (ActionResult)methodDescriptor.MethodInfo.Invoke(this, methodParams);
@@ -63,24 +72,6 @@ namespace Disco.Services.Plugins
parameterValue = methodParam.DefaultValue; parameterValue = methodParam.DefaultValue;
result[i] = parameterValue; 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; return result;
@@ -102,7 +93,8 @@ namespace Disco.Services.Plugins
var item = new WebHandlerCachedItem() var item = new WebHandlerCachedItem()
{ {
Method = method.Name, Method = method.Name,
MethodInfo = method MethodInfo = method,
Authorizers = method.GetCustomAttributes<DiscoAuthorizeBaseAttribute>().ToArray()
}; };
result.Add(item.Method.ToLower(), item); result.Add(item.Method.ToLower(), item);
} }
@@ -115,6 +107,7 @@ namespace Disco.Services.Plugins
{ {
public string Method { get; set; } public string Method { get; set; }
public MethodInfo MethodInfo { get; set; } public MethodInfo MethodInfo { get; set; }
public DiscoAuthorizeBaseAttribute[] Authorizers { get; set; }
} }
#endregion #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 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 DateTime? _FileLastModified { get; set; }
private string _FileHash { get; set; } private string _FileHash { get; set; }
private string _VersionUrl { get; set; } private string _VersionUrl { get; set; }
@@ -16,21 +16,21 @@ namespace Disco.Services.Web
// Ensure 'App-Relative' Url: // Ensure 'App-Relative' Url:
BundleUrl = BundleUrl.StartsWith("~/") ? BundleUrl : (BundleUrl.StartsWith("/") ? string.Concat("~", BundleUrl) : string.Concat("~/", BundleUrl)); 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) if (deferredBundles == null)
{ {
deferredBundles = new List<string>(); deferredBundles = new List<string>();
htmlHelper.ViewContext.HttpContext.Items["Bundles.Deferred"] = deferredBundles; htmlHelper.ViewContext.HttpContext.Items[Bundle.DeferredKey] = deferredBundles;
} }
if (!deferredBundles.Contains(BundleUrl)) if (!deferredBundles.Contains(BundleUrl))
deferredBundles.Add(BundleUrl); deferredBundles.Add(BundleUrl);
} }
public static HtmlString BundleRenderDeferred(this HtmlHelper htmlHelper) 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 uiExtensionScripts = htmlHelper.ViewContext.HttpContext.Items[Bundle.UIExtensionScriptsKey] as List<HtmlString>;
var uiExtensionCss = htmlHelper.ViewContext.HttpContext.Items["Bundles.UIExtensionCss"] as List<HtmlString>; var uiExtensionCss = htmlHelper.ViewContext.HttpContext.Items[Bundle.UIExtensionCssKey] as List<HtmlString>;
if (deferredBundles != null || uiExtensionScripts != null || uiExtensionCss != null) if (deferredBundles != null || uiExtensionScripts != null || uiExtensionCss != null)
{ {
@@ -34,16 +34,16 @@ namespace Disco.Web.Extensions
{ {
htmlHelper.RenderPartialCompiledInternal(viewType, model, htmlHelper.ViewContext.Writer); 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); 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)) using (StringWriter writer = new StringWriter(CultureInfo.CurrentCulture))
{ {
htmlHelper.RenderPartialCompiledInternal(viewType, model, writer); htmlHelper.RenderPartialCompiledInternal(viewType, model, writer);
return MvcHtmlString.Create(writer.ToString()); return new HtmlString(writer.ToString());
} }
} }
#endregion #endregion
+6
View File
@@ -213,6 +213,12 @@
#UserDetailTab-Authorization .fancytree-container { #UserDetailTab-Authorization .fancytree-container {
border: none; 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 { #UserDetailTab-Authorization span.fancytree-node.fancytree-selected {
font-style: normal; font-style: normal;
} }
+8
View File
@@ -182,6 +182,14 @@
border: none; 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 { span.fancytree-node.fancytree-selected {
font-style: normal; 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 public partial class PluginWebHandlerController : Controller
{ {
[DiscoAuthorize(Claims.DiscoAdminAccount)]
[OutputCache(Duration = 0, Location = System.Web.UI.OutputCacheLocation.None)] [OutputCache(Duration = 0, Location = System.Web.UI.OutputCacheLocation.None)]
public virtual ActionResult Index(string PluginId, string PluginAction) public virtual ActionResult Index(string PluginId, string PluginAction)
{ {
@@ -19,11 +18,20 @@ namespace Disco.Web.Controllers
if (manifest.HasWebHandler) 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"); return HttpNotFound("Plugin has no Web Handler");
} }
@@ -42,7 +50,7 @@ namespace Disco.Web.Controllers
{ {
return HttpNotFound("Plugin Resource Not Found"); return HttpNotFound("Plugin Resource Not Found");
} }
var pluginResourcePath = pluginResource.Item1; var pluginResourcePath = pluginResource.Item1;
var mimeType = Disco.BI.Interop.MimeTypes.ResolveMimeType(pluginResourcePath); var mimeType = Disco.BI.Interop.MimeTypes.ResolveMimeType(pluginResourcePath);