120 lines
4.6 KiB
C#
120 lines
4.6 KiB
C#
using FluentValidation;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using SimpleTodoApiWithPg.Data;
|
|
using SimpleTodoApiWithPg.Models;
|
|
using SimpleTodoApiWithPg.UserService;
|
|
using System.ComponentModel.DataAnnotations;
|
|
|
|
|
|
|
|
namespace SimpleTodoApiWithPg.Endpoints
|
|
{
|
|
public static class UserEndpoints
|
|
{
|
|
|
|
public static void MapUserEndpoints ( this WebApplication app)
|
|
{
|
|
|
|
var usersApi = app.MapGroup("/users")
|
|
.CacheOutput()
|
|
.RequireAuthorization()
|
|
.WithTags("Users");
|
|
|
|
|
|
usersApi.MapGet("/", async (UserServices userService) =>
|
|
{
|
|
return await userService.GetUsersAsync();
|
|
}).WithTags("获取所有用户");
|
|
|
|
usersApi.MapGet("/{id}", async (Guid id, UserServices userService) =>
|
|
{
|
|
return await userService.GetoneUserAsync(id);
|
|
}).WithTags("根据id获取对应的用户信息");
|
|
|
|
usersApi.MapPost("/", async (RegisterRequest request, UserServices userService) =>
|
|
{
|
|
var response = await userService.RegisterAsync(request);
|
|
if (!response.Success)
|
|
{
|
|
return Results.BadRequest(response);
|
|
}
|
|
return Results.Ok(response);
|
|
}).WithTags("用户注册接口")
|
|
.AllowAnonymous()
|
|
.AddEndpointFilter<ValidationFilter<RegisterRequest>>()
|
|
.ProducesValidationProblem();
|
|
|
|
usersApi.MapPatch("/{id}", async (int id, UpdateUserRequest updateUser, UserServices userService) =>
|
|
{
|
|
return await userService.UpdateUserAsync(id, updateUser);
|
|
}).WithTags("用户信息更新接口");
|
|
|
|
|
|
usersApi.MapDelete("/{id}", async (Guid id,UserServices userService) =>
|
|
{
|
|
return await userService.DeleteUserAsync(id);
|
|
}).WithTags("删除用户接口");
|
|
|
|
var loginauthApi = app.MapGroup("/api/auth")
|
|
.CacheOutput()
|
|
.WithTags("登录认证接口!");
|
|
|
|
loginauthApi.MapPost("/", async (UserServices userService, LoginRequest loginRequest) =>
|
|
{
|
|
var response = await userService.LoginAuthAsync(loginRequest);
|
|
// 如果登录失败,返回一个带有错误码和错误信息的 BadRequest
|
|
if (!response.Success)
|
|
{
|
|
return Results.BadRequest(response);
|
|
}
|
|
|
|
return Results.Ok(response);
|
|
}).WithTags("登录认证授权接口!");
|
|
|
|
// --- 新增刷新令牌端点 ---
|
|
loginauthApi.MapPost("/refresh-token", async (
|
|
/* 这里可以定义一个DTO来接收RefreshToken */
|
|
RefreshTokenRequest refreshToken,
|
|
AppDbContext dbContext,
|
|
UserServices userServices /* 注入UserServices来复用逻辑 */
|
|
) =>
|
|
{
|
|
// 通过传入的 refreshToken 查找数据库中对应的记录
|
|
var storedToken = await dbContext.RefreshTokens
|
|
.Include(rt => rt.User) // 同时加载关联的用户信息
|
|
.FirstOrDefaultAsync(rt => rt.Token == refreshToken.RefreshToken);
|
|
|
|
// 检查令牌是否存在、是否有效
|
|
if (storedToken == null || !storedToken.IsActive)
|
|
{
|
|
return Results.BadRequest("无效的刷新令牌。");
|
|
}
|
|
|
|
// (安全增强) 使旧的刷新令牌失效
|
|
storedToken.Revoked = DateTime.UtcNow;
|
|
|
|
// 生成新的访问令牌
|
|
var newAccessTokenExpiration = DateTime.UtcNow.AddMinutes(1);
|
|
var newAccessToken = userServices.GenerateJwtToken(storedToken.User, newAccessTokenExpiration); // 需要将 GenerateJwtToken 访问修饰符改为 public 或 internal
|
|
|
|
// 生成新的刷新令牌
|
|
var newRefreshToken = userServices.GenerateRefreshToken(); // GenerateRefreshToken 也需要 public/internal
|
|
newRefreshToken.UserId = storedToken.UserId;
|
|
await dbContext.RefreshTokens.AddAsync(newRefreshToken);
|
|
|
|
await dbContext.SaveChangesAsync();
|
|
|
|
return Results.Ok(new AuthResponse
|
|
{
|
|
AccessToken = newAccessToken,
|
|
RefreshToken = newRefreshToken.Token,
|
|
AccessTokenExpiration = newAccessTokenExpiration
|
|
});
|
|
})
|
|
.WithTags("刷新令牌接口");
|
|
}
|
|
|
|
|
|
}
|
|
}
|