using System; using System.Web.Http; using System.Web.Http.Controllers; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Web.Composing; namespace Umbraco.Web.Install { /// /// Ensures authorization occurs for the installer if it has already completed. /// If install has not yet occured then the authorization is successful. /// internal class HttpInstallAuthorizeAttribute : AuthorizeAttribute { // todo - cannot inject UmbracoContext nor RuntimeState in the attribute, read: // http://stackoverflow.com/questions/30096903/dependency-injection-inside-a-filterattribute-in-asp-net-mvc-6 // https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=98 - don't do it! // http://blog.ploeh.dk/2014/06/13/passive-attributes/ - passive attributes // http://xunitpatterns.com/Humble%20Object.html - humble objects // // so... either access them via Current service locator, OR use an action filter alongside this attribute (see articles). // the second solution is nicer BUT for the time being, let's use the first (simpler). private readonly UmbracoContext _umbracoContext; private readonly IRuntimeState _runtimeState; private IRuntimeState RuntimeState => _runtimeState ?? Current.RuntimeState; private UmbracoContext UmbracoContext => _umbracoContext ?? Current.UmbracoContext; /// /// THIS SHOULD BE ONLY USED FOR UNIT TESTS /// /// /// public HttpInstallAuthorizeAttribute(UmbracoContext umbracoContext, IRuntimeState runtimeState) { if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); _umbracoContext = umbracoContext; _runtimeState = runtimeState; } public HttpInstallAuthorizeAttribute() { } protected override bool IsAuthorized(HttpActionContext actionContext) { try { // if not configured (install or upgrade) then we can continue // otherwise we need to ensure that a user is logged in return RuntimeState.Level == RuntimeLevel.Install || RuntimeState.Level == RuntimeLevel.Upgrade || UmbracoContext.Security.ValidateCurrentUser(); } catch (Exception ex) { Current.Logger.Error(ex, "An error occurred determining authorization"); return false; } } } }