From 76efbd96f92fafec89c623dcf49150e766cc6702 Mon Sep 17 00:00:00 2001
From: lq1405 <2769838458@qq.com>
Date: Fri, 27 Jun 2025 11:16:03 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E6=96=87?=
=?UTF-8?q?=E4=BB=B6=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/.config/dotnet-tools.json | 13 +
src/.dockerignore | 30 ++
src/Common/Enums/ResponseCode.cs | 40 ++
.../Extensions/ClaimsPrincipalExtensions.cs | 16 +
src/Common/Extensions/EndpointExtensions.cs | 62 +++
.../Extensions/HttpContextExtensions.cs | 59 +++
...teHandlerBuilderAuthorizationExtensions.cs | 20 +
...RouteHandlerBuilderValidationExtensions.cs | 65 +++
.../Extensions/ValidationRulesExtension.cs | 24 ++
.../Filters/EnsureEntityExistsFilter.cs | 30 ++
.../Filters/EnsureUserOwnsEntityFilter.cs | 41 ++
src/Common/Filters/RequestLoggingFilter.cs | 11 +
src/Common/Filters/RequestValidationFilter.cs | 29 ++
.../Filters/SplitMJAuthorizationFilter.cs | 69 ++++
src/Common/Helper/ConfigHelper.cs | 39 ++
src/Common/Helper/JSONHelper.cs | 38 ++
src/Common/Helper/LogHelper.cs | 46 +++
src/Common/Results/APIResponseModel.cs | 164 ++++++++
src/Common/Results/ErrorResult.cs | 4 +
src/Common/Results/IOperationResult.cs | 6 +
src/Common/Results/MessageResult.cs | 4 +
src/Common/Results/NotFoundProblem.cs | 36 ++
.../Results/TransferAuthorizationResult.cs | 4 +
src/Common/Results/TransferResult.cs | 10 +
src/Common/Types/IEntity.cs | 12 +
src/Configuration/ApplicationDbContext.cs | 17 +
src/Configuration/MyDbcontextDesignFactory.cs | 26 ++
src/Configuration/SerilogConfig.cs | 31 ++
src/Configuration/SwaggerConfig.cs | 34 ++
src/Configuration/config/serilog.json | 23 ++
src/Configuration/config/transfer.json | 6 +
src/ConfigureApp.cs | 40 ++
src/ConfigureServices.cs | 138 +++++++
src/Dockerfile | 30 ++
.../MJTransferEndpoint/MJGetFetchIdService.cs | 375 ++++++++++++++++++
.../MJGetImageSeedService.cs | 51 +++
.../MJTransferEndpoint/MJPostActionService.cs | 50 +++
.../MJTransferEndpoint/MJPostBlendService.cs | 49 +++
.../MJPostDescribeService.cs | 50 +++
.../MJPostFetchListByConditionService.cs | 149 +++++++
.../MJPostFetchListByIdsService.cs | 56 +++
.../MJPostImagineService.cs | 58 +++
.../MJTransferEndpoint/MJPostModalService.cs | 48 +++
.../MJPostShortenService.cs | 49 +++
.../MJPostSwapFaceService.cs | 48 +++
.../MJPostUploadDiscordImages.cs | 44 ++
.../UserEndpoint/UserRegisterService.cs | 90 +++++
src/EndpointServices/WeatherForecast.cs | 44 ++
src/Endpoints/IEndpoint.cs | 7 +
src/Endpoints/MJEndpoint.cs | 52 +++
src/Endpoints/MainEndpoints.cs | 23 ++
src/Endpoints/UserEndpoint.cs | 18 +
src/Endpoints/WeatherForecastEndpoint.cs | 18 +
src/Model/Entity/Role.cs | 17 +
src/Model/Entity/User.cs | 40 ++
src/Model/Entity/UserRoles.cs | 11 +
src/Program.cs | 26 ++
src/Properties/launchSettings.json | 46 +++
src/Tool/Attributes/DescriptionAttribute.cs | 13 +
src/Tool/Attributes/NotEmptyAttribute.cs | 17 +
src/Tool/Attributes/ResultAttribute.cs | 13 +
src/Tool/Extensions/BeijingTimeExtension.cs | 52 +++
src/Tool/Extensions/ConvertExtension.cs | 61 +++
src/Tool/Extensions/EnumExtensions.cs | 73 ++++
src/Tool/Extensions/JsonConfigReader.cs | 107 +++++
src/appsettings.Development.json | 8 +
src/appsettings.json | 9 +
src/docker_release.sh | 14 +
src/lai_transfer.csproj | 39 ++
src/lai_transfer.http | 6 +
src/lai_transfer.sln | 25 ++
71 files changed, 3073 insertions(+)
create mode 100644 src/.config/dotnet-tools.json
create mode 100644 src/.dockerignore
create mode 100644 src/Common/Enums/ResponseCode.cs
create mode 100644 src/Common/Extensions/ClaimsPrincipalExtensions.cs
create mode 100644 src/Common/Extensions/EndpointExtensions.cs
create mode 100644 src/Common/Extensions/HttpContextExtensions.cs
create mode 100644 src/Common/Extensions/RouteHandlerBuilderAuthorizationExtensions.cs
create mode 100644 src/Common/Extensions/RouteHandlerBuilderValidationExtensions.cs
create mode 100644 src/Common/Extensions/ValidationRulesExtension.cs
create mode 100644 src/Common/Filters/EnsureEntityExistsFilter.cs
create mode 100644 src/Common/Filters/EnsureUserOwnsEntityFilter.cs
create mode 100644 src/Common/Filters/RequestLoggingFilter.cs
create mode 100644 src/Common/Filters/RequestValidationFilter.cs
create mode 100644 src/Common/Filters/SplitMJAuthorizationFilter.cs
create mode 100644 src/Common/Helper/ConfigHelper.cs
create mode 100644 src/Common/Helper/JSONHelper.cs
create mode 100644 src/Common/Helper/LogHelper.cs
create mode 100644 src/Common/Results/APIResponseModel.cs
create mode 100644 src/Common/Results/ErrorResult.cs
create mode 100644 src/Common/Results/IOperationResult.cs
create mode 100644 src/Common/Results/MessageResult.cs
create mode 100644 src/Common/Results/NotFoundProblem.cs
create mode 100644 src/Common/Results/TransferAuthorizationResult.cs
create mode 100644 src/Common/Results/TransferResult.cs
create mode 100644 src/Common/Types/IEntity.cs
create mode 100644 src/Configuration/ApplicationDbContext.cs
create mode 100644 src/Configuration/MyDbcontextDesignFactory.cs
create mode 100644 src/Configuration/SerilogConfig.cs
create mode 100644 src/Configuration/SwaggerConfig.cs
create mode 100644 src/Configuration/config/serilog.json
create mode 100644 src/Configuration/config/transfer.json
create mode 100644 src/ConfigureApp.cs
create mode 100644 src/ConfigureServices.cs
create mode 100644 src/Dockerfile
create mode 100644 src/EndpointServices/MJTransferEndpoint/MJGetFetchIdService.cs
create mode 100644 src/EndpointServices/MJTransferEndpoint/MJGetImageSeedService.cs
create mode 100644 src/EndpointServices/MJTransferEndpoint/MJPostActionService.cs
create mode 100644 src/EndpointServices/MJTransferEndpoint/MJPostBlendService.cs
create mode 100644 src/EndpointServices/MJTransferEndpoint/MJPostDescribeService.cs
create mode 100644 src/EndpointServices/MJTransferEndpoint/MJPostFetchListByConditionService.cs
create mode 100644 src/EndpointServices/MJTransferEndpoint/MJPostFetchListByIdsService.cs
create mode 100644 src/EndpointServices/MJTransferEndpoint/MJPostImagineService.cs
create mode 100644 src/EndpointServices/MJTransferEndpoint/MJPostModalService.cs
create mode 100644 src/EndpointServices/MJTransferEndpoint/MJPostShortenService.cs
create mode 100644 src/EndpointServices/MJTransferEndpoint/MJPostSwapFaceService.cs
create mode 100644 src/EndpointServices/MJTransferEndpoint/MJPostUploadDiscordImages.cs
create mode 100644 src/EndpointServices/UserEndpoint/UserRegisterService.cs
create mode 100644 src/EndpointServices/WeatherForecast.cs
create mode 100644 src/Endpoints/IEndpoint.cs
create mode 100644 src/Endpoints/MJEndpoint.cs
create mode 100644 src/Endpoints/MainEndpoints.cs
create mode 100644 src/Endpoints/UserEndpoint.cs
create mode 100644 src/Endpoints/WeatherForecastEndpoint.cs
create mode 100644 src/Model/Entity/Role.cs
create mode 100644 src/Model/Entity/User.cs
create mode 100644 src/Model/Entity/UserRoles.cs
create mode 100644 src/Program.cs
create mode 100644 src/Properties/launchSettings.json
create mode 100644 src/Tool/Attributes/DescriptionAttribute.cs
create mode 100644 src/Tool/Attributes/NotEmptyAttribute.cs
create mode 100644 src/Tool/Attributes/ResultAttribute.cs
create mode 100644 src/Tool/Extensions/BeijingTimeExtension.cs
create mode 100644 src/Tool/Extensions/ConvertExtension.cs
create mode 100644 src/Tool/Extensions/EnumExtensions.cs
create mode 100644 src/Tool/Extensions/JsonConfigReader.cs
create mode 100644 src/appsettings.Development.json
create mode 100644 src/appsettings.json
create mode 100644 src/docker_release.sh
create mode 100644 src/lai_transfer.csproj
create mode 100644 src/lai_transfer.http
create mode 100644 src/lai_transfer.sln
diff --git a/src/.config/dotnet-tools.json b/src/.config/dotnet-tools.json
new file mode 100644
index 0000000..05b4dd6
--- /dev/null
+++ b/src/.config/dotnet-tools.json
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "isRoot": true,
+ "tools": {
+ "dotnet-ef": {
+ "version": "9.0.6",
+ "commands": [
+ "dotnet-ef"
+ ],
+ "rollForward": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/.dockerignore b/src/.dockerignore
new file mode 100644
index 0000000..fe1152b
--- /dev/null
+++ b/src/.dockerignore
@@ -0,0 +1,30 @@
+**/.classpath
+**/.dockerignore
+**/.env
+**/.git
+**/.gitignore
+**/.project
+**/.settings
+**/.toolstarget
+**/.vs
+**/.vscode
+**/*.*proj.user
+**/*.dbmdl
+**/*.jfm
+**/azds.yaml
+**/bin
+**/charts
+**/docker-compose*
+**/Dockerfile*
+**/node_modules
+**/npm-debug.log
+**/obj
+**/secrets.dev.yaml
+**/values.dev.yaml
+LICENSE
+README.md
+!**/.gitignore
+!.git/HEAD
+!.git/config
+!.git/packed-refs
+!.git/refs/heads/**
\ No newline at end of file
diff --git a/src/Common/Enums/ResponseCode.cs b/src/Common/Enums/ResponseCode.cs
new file mode 100644
index 0000000..22f428a
--- /dev/null
+++ b/src/Common/Enums/ResponseCode.cs
@@ -0,0 +1,40 @@
+using lai_transfer.Tool.Attributes;
+
+namespace lai_transfer.Common.Enums;
+
+public enum ResponseCode
+{
+
+ #region 成功
+
+ [Result("请求成功")]
+ [Description("请求成功")]
+ Success = 1,
+
+ #endregion
+
+
+ #region 系统报错
+
+ [Result("系统错误")]
+ [Description("系统错误")]
+ SystemError = 5000,
+
+ [Result("参数错误")]
+ [Description("参数错误")]
+ ParameterError = 5001,
+
+ [Result("无效的操作")]
+ [Description("无效的操作")]
+ InvalidOptions = 5002,
+
+ [Result("数据不存在")]
+ [Description("数据不存在")]
+ IdDateNotFound = 5003,
+
+ [Result("操作错误")]
+ [Description("操作错误")]
+ OptionsError = 5004,
+ #endregion
+
+}
\ No newline at end of file
diff --git a/src/Common/Extensions/ClaimsPrincipalExtensions.cs b/src/Common/Extensions/ClaimsPrincipalExtensions.cs
new file mode 100644
index 0000000..5c5ed70
--- /dev/null
+++ b/src/Common/Extensions/ClaimsPrincipalExtensions.cs
@@ -0,0 +1,16 @@
+using System.Security.Claims;
+
+namespace lai_transfer.Common.Extensions;
+
+public static class ClaimsPrincipalExtensions
+{
+ public static long GetUserId(this ClaimsPrincipal claimsPrincipal)
+ {
+ if (!int.TryParse(claimsPrincipal.FindFirstValue(ClaimTypes.NameIdentifier), out var id))
+ {
+ throw new InvalidOperationException("Invalid UserId");
+ }
+
+ return id;
+ }
+}
diff --git a/src/Common/Extensions/EndpointExtensions.cs b/src/Common/Extensions/EndpointExtensions.cs
new file mode 100644
index 0000000..de883f8
--- /dev/null
+++ b/src/Common/Extensions/EndpointExtensions.cs
@@ -0,0 +1,62 @@
+using lai_transfer.Endpoints;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.OpenApi.Models;
+
+namespace lai_transfer.Common.Extensions
+{
+ public static class EndpointExtensions
+ {
+ private static readonly OpenApiSecurityScheme SecurityScheme = new()
+ {
+ Type = SecuritySchemeType.Http,
+ Name = JwtBearerDefaults.AuthenticationScheme,
+ Scheme = JwtBearerDefaults.AuthenticationScheme,
+ Reference = new()
+ {
+ Type = ReferenceType.SecurityScheme,
+ Id = JwtBearerDefaults.AuthenticationScheme
+ }
+ };
+
+ ///
+ /// 无需授权的分组
+ ///
+ ///
+ ///
+ ///
+ public static RouteGroupBuilder MapPublicGroup(this IEndpointRouteBuilder app, string? prefix = null)
+ {
+ return app.MapGroup(prefix ?? string.Empty)
+ .AllowAnonymous();
+ }
+
+ ///
+ /// 需要权限校验的分组
+ ///
+ ///
+ ///
+ ///
+ public static RouteGroupBuilder MapAuthorizedGroup(this IEndpointRouteBuilder app, string? prefix = null)
+ {
+ return app.MapGroup(prefix ?? string.Empty)
+ .RequireAuthorization()
+ .WithOpenApi(x => new(x)
+ {
+ Security = [new() { [SecurityScheme] = [] }],
+ });
+ }
+
+ ///
+ /// 绑定一个 IEndpoint 实现到路由中
+ ///
+ ///
+ ///
+ ///
+ public static IEndpointRouteBuilder MapEndpoint(this IEndpointRouteBuilder app)
+ where TEndpoint : IEndpoint
+ {
+ TEndpoint.Map(app);
+ return app;
+ }
+ }
+}
diff --git a/src/Common/Extensions/HttpContextExtensions.cs b/src/Common/Extensions/HttpContextExtensions.cs
new file mode 100644
index 0000000..d22f83f
--- /dev/null
+++ b/src/Common/Extensions/HttpContextExtensions.cs
@@ -0,0 +1,59 @@
+using lai_transfer.Common.Results;
+
+namespace lai_transfer.Common.Extensions
+{
+
+ public static class HttpContextExtensions
+ {
+ ///
+ /// 从HttpContext中获取存储的值
+ ///
+ /// Http上下文
+ /// 要获取的键名(如"AuthToken"或"BaseUrl")
+ /// 存储的值,如果不存在则返回null
+ public static string? GetContextItem(this HttpContext httpContext, string key)
+ {
+ return httpContext.Items.TryGetValue(key, out var value) ? value?.ToString() : null;
+ }
+
+
+ ///
+ /// 获取 转发接口中的 httpContext 中的 Authorization 相关的 Token 和 BaseUrl数据
+ ///
+ ///
+ ///
+ ///
+ public static TransferAuthorizationResult GetAuthorizationItemsAndValidation(this HttpContext httpContext)
+ {
+ string? token = httpContext.GetContextItem("AuthToken");
+ string? baseUrl = httpContext.GetContextItem("BaseUrl");
+ if (string.IsNullOrWhiteSpace(token) || string.IsNullOrWhiteSpace(baseUrl))
+ {
+ throw new InvalidOperationException("Authentication token or base URL is not set in the context.");
+ }
+ return new TransferAuthorizationResult(token, baseUrl);
+ }
+
+ ///
+ /// 获取当前请求的完整路径(不包括主机和端口)
+ ///
+ /// Http上下文
+ /// 是否包含查询字符串
+ /// 完整的请求路径
+ public static string GetFullRequestPath(this HttpContext httpContext, bool includeQueryString = true)
+ {
+ string pathBase = httpContext.Request.PathBase.Value ?? string.Empty;
+ string path = httpContext.Request.Path.Value ?? string.Empty;
+ string fullPath = $"{pathBase}{path}";
+
+ if (includeQueryString)
+ {
+ string queryString = httpContext.Request.QueryString.Value ?? string.Empty;
+ fullPath += queryString;
+ }
+
+ return fullPath;
+ }
+
+ }
+}
diff --git a/src/Common/Extensions/RouteHandlerBuilderAuthorizationExtensions.cs b/src/Common/Extensions/RouteHandlerBuilderAuthorizationExtensions.cs
new file mode 100644
index 0000000..465bcfd
--- /dev/null
+++ b/src/Common/Extensions/RouteHandlerBuilderAuthorizationExtensions.cs
@@ -0,0 +1,20 @@
+using lai_transfer.Common.Filters;
+using lai_transfer.Configuration;
+using Microsoft.AspNetCore.Mvc.Filters;
+
+namespace lai_transfer.Common.Extensions
+{
+
+ public static class RouteHandlerBuilderAuthorizationExtensions
+ {
+ ///
+ /// 添加授权头处理过滤器
+ ///
+ public static RouteHandlerBuilder WithMJAuthorizationHeader(this RouteHandlerBuilder builder)
+ {
+ return builder
+ .AddEndpointFilter()
+ .Produces(StatusCodes.Status401Unauthorized);
+ }
+ }
+}
diff --git a/src/Common/Extensions/RouteHandlerBuilderValidationExtensions.cs b/src/Common/Extensions/RouteHandlerBuilderValidationExtensions.cs
new file mode 100644
index 0000000..ed1c9a5
--- /dev/null
+++ b/src/Common/Extensions/RouteHandlerBuilderValidationExtensions.cs
@@ -0,0 +1,65 @@
+using lai_transfer.Common.Filters;
+using lai_transfer.Common.Types;
+using lai_transfer.Configuration;
+using System;
+using System.Security.Principal;
+
+namespace lai_transfer.Common.Extensions
+{
+ public static class RouteHandlerBuilderValidationExtensions
+ {
+ ///
+ /// Adds a request validation filter to the route handler.
+ ///
+ ///
+ ///
+ /// A that can be used to futher customize the endpoint.
+ public static RouteHandlerBuilder WithRequestValidation(this RouteHandlerBuilder builder)
+ {
+ return builder
+ .AddEndpointFilter>()
+ .ProducesValidationProblem();
+ }
+
+ ///
+ /// Adds a request validation filter to the route handler to ensure a exists with the id returned by .
+ ///
+ ///
+ ///
+ ///
+ /// A function which selects the Id property from the
+ /// A that can be used to futher customize the endpoint.
+ public static RouteHandlerBuilder WithEnsureEntityExists(this RouteHandlerBuilder builder, Func idSelector) where TEntity : class, IEntity
+ {
+ return builder
+ .AddEndpointFilterFactory((endpointFilterFactoryContext, next) => async context =>
+ {
+ var db = context.HttpContext.RequestServices.GetRequiredService();
+ var filter = new EnsureEntityExistsFilter(db, idSelector);
+ return await filter.InvokeAsync(context, next);
+ })
+ .ProducesProblem(StatusCodes.Status404NotFound);
+ }
+
+ ///
+ /// Adds a request validation filter to the route handler to ensure the current owns the with the id returned by .
+ ///
+ ///
+ ///
+ ///
+ /// A function which selects the Id property from the
+ /// A that can be used to futher customize the endpoint.
+ public static RouteHandlerBuilder WithEnsureUserOwnsEntity(this RouteHandlerBuilder builder, Func idSelector) where TEntity : class, IEntity, IOwnedEntity
+ {
+ return builder
+ .AddEndpointFilterFactory((endpointFilterFactoryContext, next) => async context =>
+ {
+ var db = context.HttpContext.RequestServices.GetRequiredService();
+ var filter = new EnsureUserOwnsEntityFilter(db, idSelector);
+ return await filter.InvokeAsync(context, next);
+ })
+ .ProducesProblem(StatusCodes.Status404NotFound)
+ .Produces(StatusCodes.Status403Forbidden);
+ }
+ }
+}
diff --git a/src/Common/Extensions/ValidationRulesExtension.cs b/src/Common/Extensions/ValidationRulesExtension.cs
new file mode 100644
index 0000000..9f128ec
--- /dev/null
+++ b/src/Common/Extensions/ValidationRulesExtension.cs
@@ -0,0 +1,24 @@
+using FluentValidation;
+
+namespace lai_transfer.Common.Extensions;
+
+public static class ValidationRulesExtension
+{
+ public static IRuleBuilderOptions AuthUsernameRule(
+ this IRuleBuilderInitial rule)
+ {
+ return rule.NotEmpty().WithMessage("用户名不能为空");
+ }
+
+ public static IRuleBuilderOptions AuthPasswordRule(
+ this IRuleBuilderInitial rule)
+ {
+ return rule.NotEmpty().MinimumLength(8);
+ }
+
+ public static IRuleBuilderOptions AuthNameRule(
+ this IRuleBuilderInitial rule)
+ {
+ return rule.NotEmpty().MaximumLength(50);
+ }
+}
diff --git a/src/Common/Filters/EnsureEntityExistsFilter.cs b/src/Common/Filters/EnsureEntityExistsFilter.cs
new file mode 100644
index 0000000..bce0bce
--- /dev/null
+++ b/src/Common/Filters/EnsureEntityExistsFilter.cs
@@ -0,0 +1,30 @@
+using lai_transfer.Common.Results;
+using lai_transfer.Common.Types;
+using lai_transfer.Configuration;
+using Microsoft.EntityFrameworkCore;
+
+namespace lai_transfer.Common.Filters;
+
+public class EnsureEntityExistsFilter(ApplicationDbContext database, Func idSelector) : IEndpointFilter
+ where TEntity : class, IEntity
+{
+ public async ValueTask