feat/Update_Controllers_to_Allow_for_Premium_Membership
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
using System.Security.Claims;
|
||||
using System.Text.Json;
|
||||
using JobTrackerApi.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization.Policy;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace JobTrackerApi.Services;
|
||||
|
||||
public static class ProEntitlement
|
||||
{
|
||||
public const string Policy = "Pro";
|
||||
public const string RequiredCode = "pro_required";
|
||||
public const string DisabledCode = "ai_disabled";
|
||||
}
|
||||
|
||||
public sealed class ProEntitlementRequirement : IAuthorizationRequirement;
|
||||
|
||||
public sealed class ProEntitlementHandler(UserManager<ApplicationUser> users)
|
||||
: AuthorizationHandler<ProEntitlementRequirement>
|
||||
{
|
||||
protected override async Task HandleRequirementAsync(
|
||||
AuthorizationHandlerContext context,
|
||||
ProEntitlementRequirement requirement)
|
||||
{
|
||||
var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier)
|
||||
?? context.User.FindFirstValue("sub");
|
||||
var user = string.IsNullOrWhiteSpace(userId) ? null : await users.FindByIdAsync(userId);
|
||||
if (user is null || !AccountPlans.ForRoles(await users.GetRolesAsync(user)).Ai)
|
||||
{
|
||||
context.Fail(new AuthorizationFailureReason(this, ProEntitlement.RequiredCode));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!user.AiEnabled)
|
||||
{
|
||||
context.Fail(new AuthorizationFailureReason(this, ProEntitlement.DisabledCode));
|
||||
return;
|
||||
}
|
||||
|
||||
context.Succeed(requirement);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ProEntitlementAuthorizationResultHandler : IAuthorizationMiddlewareResultHandler
|
||||
{
|
||||
private readonly AuthorizationMiddlewareResultHandler _fallback = new();
|
||||
|
||||
public async Task HandleAsync(
|
||||
RequestDelegate next,
|
||||
HttpContext context,
|
||||
AuthorizationPolicy policy,
|
||||
PolicyAuthorizationResult authorizeResult)
|
||||
{
|
||||
if (authorizeResult.Forbidden
|
||||
&& policy.Requirements.OfType<ProEntitlementRequirement>().Any())
|
||||
{
|
||||
var aiDisabled = authorizeResult.AuthorizationFailure?.FailureReasons
|
||||
.Any(reason => reason.Message == ProEntitlement.DisabledCode) == true;
|
||||
context.Response.StatusCode = StatusCodes.Status403Forbidden;
|
||||
context.Response.ContentType = "application/json";
|
||||
await JsonSerializer.SerializeAsync(context.Response.Body, new
|
||||
{
|
||||
code = aiDisabled ? ProEntitlement.DisabledCode : ProEntitlement.RequiredCode,
|
||||
message = aiDisabled
|
||||
? "AI is disabled in your privacy settings."
|
||||
: "This AI feature requires Pro.",
|
||||
}, cancellationToken: context.RequestAborted);
|
||||
return;
|
||||
}
|
||||
|
||||
await _fallback.HandleAsync(next, context, policy, authorizeResult);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user