Files
2026-03-30 11:07:30 +08:00

146 lines
4.6 KiB
C#

using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;
using StopShopping.Services;
using StopShopping.Services.Extensions;
using StopShopping.Services.Models.Req;
using StopShopping.Services.Models.Resp;
namespace StopShopping.Api.Routes;
public static class User
{
public static RouteGroupBuilder MapUser(this RouteGroupBuilder routes)
{
routes.MapPost("/user/signup", SignUpAsync)
.AllowAnonymous().WithTags(OpenApiTags..ToString());
routes.MapPost("/user/signin", SignInAsync)
.AllowAnonymous().WithTags(OpenApiTags..ToString());
routes.MapPost("/user/changepassword", ChangePasswordAsync)
.WithTags(OpenApiTags..ToString());
routes.MapGet("/user/info", GetUserAsync)
.WithTags(OpenApiTags..ToString());
routes.MapPost("/user/edit", EditUserAsync)
.WithTags(OpenApiTags..ToString());
return routes;
}
public static RouteGroupBuilder MapUserAnonymous(this RouteGroupBuilder routes)
{
routes.MapPost("/user/refreshtoken", RefreshTokenAsync)
.Produces<ApiResponse<AccessToken>>()
.WithTags(OpenApiTags..ToString());
routes.MapPost("/user/signout", SignOutAsync)
.WithTags(OpenApiTags..ToString());
return routes;
}
private static async Task<ApiResponse> SignUpAsync(
SignUpParams model,
IUserService userService)
{
await userService.SignUpAsync(model);
return ApiResponse.Succed();
}
private static async Task<ApiResponse<SignInUser>> SignInAsync(
SignInParams model,
IUserService userService,
HttpContext httpContext,
IOptions<AppOptions> options,
IWebHostEnvironment env)
{
var result = await userService.SignInAsync(model);
var resp = new ApiResponse<SignInUser>
{
IsSucced = result.IsSucced,
Data = result.User,
Message = result.Message
};
if (result.IsSucced)
{
httpContext.Response.Cookies.AppendRefreshToken(
env,
options.Value,
TimeSpan.FromSeconds(result.RefreshToken!.ExpiresIn),
result.RefreshToken.Token!
);
}
return resp;
}
private static async Task<ApiResponse> ChangePasswordAsync(
ChangePasswordParams model,
IUserService userService,
HttpContext httpContext,
IAccessTokenService accessTokenService
)
{
var resp = await userService.ChangePasswordAsync(model);
if (resp.IsSucced)
await SignOutAsync(httpContext, accessTokenService);
return resp;
}
private static async Task<ApiResponse<Services.Models.Resp.User>> GetUserAsync(
IUserService userService
)
{
return await userService.GetUserInfoAsync();
}
private static async Task<ApiResponse> EditUserAsync(
EditUserParams model,
IUserService userService
)
{
return await userService.EditAsync(model);
}
private static async Task<IResult> RefreshTokenAsync(
HttpContext httpContext,
IAccessTokenService accessTokenService)
{
var refreshToken = httpContext.Request.Cookies[HttpExtensions.REFRESH_TOKEN_COOKIE_KEY];
if (string.IsNullOrWhiteSpace(refreshToken))
return Results.Unauthorized();
var accessToken = await accessTokenService.GenerateAccessTokenAsync(refreshToken);
if (null == accessToken)
return Results.Unauthorized();
return Results.Ok(new ApiResponse<AccessToken>(accessToken));
}
public static async Task<ApiResponse> SignOutAsync(
HttpContext httpContext,
IAccessTokenService accessTokenService)
{
var accessTokenHeader = httpContext.Request.Headers[HeaderNames.Authorization];
if (accessTokenHeader.Count != 0)
{
var accessToken = accessTokenHeader.First()!.Split(" ").Last();
if (!string.IsNullOrWhiteSpace(accessToken))
await accessTokenService.AddAccessTokenBlacklistAsync(accessToken);
}
var refreshToken = httpContext.Request.Cookies[HttpExtensions.REFRESH_TOKEN_COOKIE_KEY];
if (!string.IsNullOrWhiteSpace(refreshToken))
{
await accessTokenService.RevokeRefreshTokenAsync(refreshToken);
httpContext.Response.Cookies.Delete(HttpExtensions.REFRESH_TOKEN_COOKIE_KEY);
}
return ApiResponse.Succed();
}
}