private static RequestDelegate CreateRouteHandler( string path, CarterModule module, IEnumerable <IStatusCodeHandler> statusCodeHandlers, ILogger logger) { return(async ctx => { if (!module.Routes.TryGetValue((ctx.Request.Method, path), out var routeHandler)) { // if the path was registered but a handler matching the // current method was not found, return MethodNotFound ctx.Response.StatusCode = StatusCodes.Status405MethodNotAllowed; return; } // begin handling the request if (HttpMethods.IsHead(ctx.Request.Method)) { //Cannot read the default stream once WriteAsync has been called on it ctx.Response.Body = new MemoryStream(); } // run the module handlers bool shouldContinue = true; if (module.Before != null) { shouldContinue = await module.Before(ctx); } if (shouldContinue) { // run the route handler logger.LogDebug("Executing module route handler for {Method} /{Path}", ctx.Request.Method, path); await routeHandler(ctx); // run after handler if (module.After != null) { await module.After(ctx); } } // run status code handler var scHandler = statusCodeHandlers.FirstOrDefault(x => x.CanHandle(ctx.Response.StatusCode)); if (scHandler != null) { await scHandler.Handle(ctx); } if (HttpMethods.IsHead(ctx.Request.Method)) { var length = ctx.Response.Body.Length; ctx.Response.Body.SetLength(0); ctx.Response.ContentLength = length; } }); }
/// <summary> /// A way to require authentication for your <see cref="CarterModule"/> /// </summary> /// <param name="module">Current <see cref="CarterModule"/></param> public static void RequiresAuthentication(this CarterModule module) { module.Before += context => { var authenticated = context.User?.Identity != null && context.User.Identity.IsAuthenticated; if (!authenticated) { context.Response.StatusCode = 401; } return(Task.FromResult(authenticated)); }; }
/// <summary> /// A way to require claims for your <see cref="CarterModule"/> /// </summary> /// <param name="module">Current <see cref="CarterModule"/></param> /// <param name="claims">The claims required for the routes in your <see cref="CarterModule"/></param> public static void RequiresClaims(this CarterModule module, params Predicate <Claim>[] claims) { module.RequiresAuthentication(); module.Before += context => { var validClaims = context.User != null && claims.All(context.User.HasClaim); if (!validClaims) { context.Response.StatusCode = 401; } return(Task.FromResult(validClaims)); }; }
/// <summary> /// A way to require policies for your <see cref="CarterModule"/> /// </summary> /// <param name="module">Current <see cref="CarterModule"/></param> /// <param name="policyNames">The policies required for the routes in your <see cref="CarterModule"/></param> public static void RequiresPolicy(this CarterModule module, params string[] policyNames) { module.RequiresAuthentication(); module.Before += async context => { var authorizationService = context.RequestServices.GetRequiredService <IAuthorizationService>(); foreach (var policy in policyNames) { var result = await authorizationService.AuthorizeAsync(context.User, policy); if (!result.Succeeded) { context.Response.StatusCode = 401; return(false); } } return(true); }; }
/// <summary> /// A way to require policies for your <see cref="CarterModule"/> /// </summary> /// <param name="module">Current <see cref="CarterModule"/></param> /// <param name="policyNames">The policies required for the routes in your <see cref="CarterModule"/></param> public static void RequiresPolicy(this CarterModule module, params string[] policyNames) { module.AuthPolicies = module.AuthPolicies.Concat(policyNames).ToArray(); }
/// <summary> /// A way to require authentication for your <see cref="CarterModule"/> /// </summary> /// <param name="module">Current <see cref="CarterModule"/></param> public static void RequiresAuthorization(this CarterModule module) { module.RequiresAuth = true; }