Initial project import

This commit is contained in:
2026-07-24 23:11:20 +08:00
commit 6396eabb87
372 changed files with 49682 additions and 0 deletions
@@ -0,0 +1,58 @@
using System.Security.Claims;
using MiaoJiZhang.Api.Contracts;
using MiaoJiZhang.Infrastructure.Persistence;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.EntityFrameworkCore;
namespace MiaoJiZhang.Api.Services;
public static class FeaturePermissionKeys
{
public const string Ai = "ai";
}
public sealed class AiPermissionService(AppDbContext db)
{
public async Task<bool> IsEnabledAsync(long userId, CancellationToken ct = default)
{
var value = await db.UserFeaturePermissions
.AsNoTracking()
.Where(x => x.UserId == userId && x.PermissionKey == FeaturePermissionKeys.Ai)
.Select(x => (bool?)x.IsEnabled)
.FirstOrDefaultAsync(ct);
// Existing installations remain compatible if a migration has not backfilled yet.
return value ?? true;
}
}
public sealed class RequireAiPermissionAttribute : TypeFilterAttribute
{
public RequireAiPermissionAttribute() : base(typeof(AiPermissionFilter))
{
}
}
public sealed class AiPermissionFilter(AiPermissionService permissions) : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
var value = context.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier)
?? context.HttpContext.User.FindFirstValue("sub");
if (!long.TryParse(value, out var userId) ||
!await permissions.IsEnabledAsync(userId, context.HttpContext.RequestAborted))
{
context.Result = new ObjectResult(new ApiError(
"AI_PERMISSION_DENIED",
"当前账号暂无 AI 功能权限"))
{
StatusCode = StatusCodes.Status403Forbidden,
};
return;
}
await next();
}
}