public void AssertContentPermissionsEqual(ContentPermission expected, ContentPermission actual) { Assert.Equal(expected.id, actual.id); Assert.Equal(expected.userId, actual.userId); Assert.Equal(expected.create, actual.create); Assert.Equal(expected.update, actual.update); Assert.Equal(expected.delete, actual.delete); Assert.Equal(expected.read, actual.read); }
/// <summary> /// Adds a route to the <see cref="IRouteBuilder"/> configured for data fetching, with the specified name, template, default values, and /// data tokens. /// </summary> /// <param name="routeBuilder">The <see cref="IRouteBuilder"/> to add the route to.</param> /// <param name="name">The name of the route.</param> /// <param name="template">The URL pattern of the route.</param> /// <param name="defaults"> /// An object that contains default values for route parameters. The object's properties represent the names /// and values of the default values. /// </param> /// <param name="constraints"> /// An object that contains constraints for the route. The object's properties represent the names and values /// of the constraints. /// </param> /// <param name="dataTokens"> /// An object that contains data tokens for the route. The object's properties represent the names and values /// of the data tokens. /// </param> /// <param name="writePermission"> /// A permission object which specifies who can create or edit the content item via this route /// </param> /// <param name="divertOverride"> /// A function which checks whether to switch out the default inner router with one which diverts the user /// to an editor controller /// </param> /// <returns>A reference to this instance after the operation has completed.</returns> public static IRouteBuilder MapDataRoute <T>( this IRouteBuilder routeBuilder, string name, string template, object defaults = null, object constraints = null, object dataTokens = null, ContentPermission writePermission = null, DiversionStrategy divertOverride = null) where T : class, new() { if (routeBuilder.DefaultHandler == null) { throw new InvalidOperationException("Default handler must be set"); } var inlineConstraintResolver = (IInlineConstraintResolver)routeBuilder .ServiceProvider .GetService(typeof(IInlineConstraintResolver)); // Interpose a DataFetchingRouter between the classic Route and the DefaultHandler, which // tries to fetch the data for the route var dataFetchingRouter = new DataFetchingRouter <T>(routeBuilder.DefaultHandler, false, writePermission, divertOverride); var dataRoute = new DataRoute( dataFetchingRouter, name, template, new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(dataTokens), inlineConstraintResolver); routeBuilder.Routes.Add(dataRoute); // Record the data route on Lynicon's internal RouteCollection used for reverse url generation if (ContentMap.Instance.RouteCollection == null) { ContentMap.Instance.RouteCollection = new RouteCollection(); } ContentMap.Instance.RouteCollection.Add(dataRoute); Type registerType = typeof(T); if (registerType.IsGenericType() && registerType.GetGenericTypeDefinition() == typeof(List <>)) { registerType = registerType.GetGenericArguments()[0]; } ContentTypeHierarchy.RegisterType(registerType); return(routeBuilder); }
public static void AddTestDataRoute <T>(this RouteCollection routes, string name, string template, object defaults, ContentPermission writePermission = null, DiversionStrategy divertOverride = null) where T : class, new() { IOptions <RouteOptions> routeOpts = Options.Create <RouteOptions>(new RouteOptions()); var constraintResolver = new DefaultInlineConstraintResolver(routeOpts); var dataFetchingRouter = new DataFetchingRouter <T>(new MockRouter(), false, writePermission, divertOverride); var dataRoute = new DataRoute( dataFetchingRouter, name, template, new RouteValueDictionary(defaults), new RouteValueDictionary(null), new RouteValueDictionary(null), constraintResolver); routes.Add(dataRoute); }
/// <summary> /// Work out whether and how a request should be diverted to an editor /// </summary> /// <param name="innerRouter">next inner router, probably MVC handler or something containing one</param> /// <param name="context">the route context</param> /// <param name="data">the fetched data (or null)</param> /// <param name="writePermission">whether the user can write</param> /// <returns>pair of router to use for diversion, and whether the calling router should drop through (true) or fail</returns> public abstract (IRouter, bool) GetDiversion(IRouter innerRouter, RouteContext context, object data, ContentPermission writePermission);
/// <summary> /// Routes as follows: /// POST + can't write => Unauthorized /// API req + no data => Not Found /// API req + data => Return content data (JSON) /// HTML req + can't write => Drop through (to SPA route to show page) /// Non editing => Drop through (to SPA route to show page) /// => Editor, but drop through if no data and can't create new /// </summary> /// <param name="innerRouter"></param> /// <param name="context"></param> /// <param name="data"></param> /// <param name="writePermission"></param> /// <returns>(router to use, drop through if can't use router)</returns> public override (IRouter, bool) GetDiversion(IRouter innerRouter, RouteContext context, object data, ContentPermission writePermission) { bool acceptsHtml = AcceptsHtml(context.HttpContext.Request); bool isPost = (context.HttpContext.Request.Method == "POST"); var actualWritePermission = writePermission ?? this.writePermission; bool canWrite = actualWritePermission.Permitted(data); if (isPost && !canWrite) { return(new DivertRouter(innerRouter, "Lynicon", "Api", "ErrorUnauthorized"), false); } if (acceptsHtml) { return(GetDiversionHtml(innerRouter, context, data, canWrite)); } else { return(GetDiversionApi(innerRouter, context, data, canWrite)); } }
public SpaDiversionStrategy(string editorArea, string editorController, ContentPermission writePermission = null) { this.editorController = editorController; this.editorArea = editorArea; this.writePermission = writePermission ?? new ContentPermission(User.EditorRole); }
public override (IRouter, bool) GetDiversion(IRouter innerRouter, RouteContext context, object data, ContentPermission writePermission) { bool acceptsHtml = AcceptsHtml(context.HttpContext.Request); bool isPost = (context.HttpContext.Request.Method == "POST"); var actualWritePermission = writePermission ?? this.writePermission; bool canWrite = actualWritePermission.Permitted(data); if (isPost && !canWrite) { return(new DivertRouter(innerRouter, "Api", "Unauthorized"), false); } if (!acceptsHtml && data == null) { return(new DivertRouter(innerRouter, "Api", "NotFound"), false); } if (!acceptsHtml) { return(new DivertRouter(innerRouter, ApiControllerArea, ApiController, "Index"), false); } if (acceptsHtml && !canWrite) { return(null, true); // drop through as SPA catch all should handle this request: a non-editor wants to read html } string action = ActionByModeFlag(context, data, canWrite) ?? "Index"; if (action == "") { return(null, true); } return(new DivertRouter(innerRouter, editorArea, editorController, action), false); }
public override (IRouter, bool) GetDiversion(IRouter innerRouter, RouteContext context, object data, ContentPermission writePermission) { bool acceptsHtml = AcceptsHtml(context.HttpContext.Request); bool isPost = (context.HttpContext.Request.Method == "POST"); var actualWritePermission = writePermission ?? this.writePermission; bool canWrite = actualWritePermission.Permitted(data); if (isPost && !canWrite) { return(new DivertRouter(innerRouter, "Lynicon", "Api", "ErrorUnauthorized"), false); } if (!acceptsHtml) { return(new DivertRouter(innerRouter, "Lynicon", "Api", "Index"), false); } string action = ActionByModeFlag(context, data, canWrite) ?? "Index"; if (action == "") { return(null, false); } return(new DivertRouter(innerRouter, editorArea, editorController, action), true); }
public override (IRouter, bool) GetDiversion(IRouter innerRouter, RouteContext context, object data, ContentPermission writePermission) { return(null, false); }