All checks were successful
continuous-integration/drone/push Build is passing
202 lines
7.4 KiB
C#
202 lines
7.4 KiB
C#
using CampusErrand.Data;
|
||
using CampusErrand.Models;
|
||
using CampusErrand.Models.Dtos;
|
||
using CampusErrand.Services;
|
||
using CampusErrand.Helpers;
|
||
using Microsoft.EntityFrameworkCore;
|
||
|
||
namespace CampusErrand.Endpoints;
|
||
|
||
public static class AuthEndpoints
|
||
{
|
||
public static void MapAuthEndpoints(this WebApplication app)
|
||
{
|
||
// 微信手机号登录接口
|
||
app.MapPost("/api/auth/login", async (
|
||
WeChatLoginRequest request,
|
||
IWeChatService weChatService,
|
||
JwtService jwtService,
|
||
AppDbContext db) =>
|
||
{
|
||
// 1. 调用微信 code2Session 获取 session_key 和 openid
|
||
var sessionResult = await weChatService.Code2SessionAsync(request.Code);
|
||
if (!sessionResult.Success)
|
||
{
|
||
return Results.BadRequest(new { code = 400, message = sessionResult.ErrorMessage });
|
||
}
|
||
|
||
// 2. 使用 session_key 解密手机号
|
||
string phoneNumber;
|
||
try
|
||
{
|
||
phoneNumber = weChatService.DecryptPhoneNumber(
|
||
sessionResult.SessionKey!, request.EncryptedData, request.Iv);
|
||
}
|
||
catch (Exception)
|
||
{
|
||
return Results.BadRequest(new { code = 400, message = "手机号解密失败" });
|
||
}
|
||
|
||
// 3. 根据手机号查找或创建用户
|
||
var user = await db.Users.FirstOrDefaultAsync(u => u.Phone == phoneNumber);
|
||
if (user == null)
|
||
{
|
||
user = new User
|
||
{
|
||
Uid = await BusinessHelpers.GenerateUniqueUid(db),
|
||
OpenId = sessionResult.OpenId!,
|
||
Phone = phoneNumber,
|
||
Nickname = $"用户{phoneNumber[^4..]}",
|
||
CreatedAt = DateTime.UtcNow
|
||
};
|
||
db.Users.Add(user);
|
||
await db.SaveChangesAsync();
|
||
}
|
||
else if (string.IsNullOrEmpty(user.OpenId) && !string.IsNullOrEmpty(sessionResult.OpenId))
|
||
{
|
||
// 更新 OpenId(如果之前为空)
|
||
user.OpenId = sessionResult.OpenId;
|
||
await db.SaveChangesAsync();
|
||
}
|
||
|
||
// 4. 生成 JWT 返回
|
||
var token = jwtService.GenerateToken(user.Id, user.Role.ToString());
|
||
|
||
return Results.Ok(new LoginResponse
|
||
{
|
||
Token = token,
|
||
UserInfo = new UserInfo
|
||
{
|
||
Id = user.Id,
|
||
Uid = user.Uid,
|
||
Phone = user.Phone,
|
||
Nickname = user.Nickname,
|
||
AvatarUrl = user.AvatarUrl,
|
||
Role = user.Role.ToString()
|
||
}
|
||
});
|
||
});
|
||
|
||
// 微信快捷登录(仅需 code,通过 openid 注册/登录)
|
||
app.MapPost("/api/auth/wx-login", async (
|
||
WxLoginRequest request,
|
||
IWeChatService weChatService,
|
||
JwtService jwtService,
|
||
AppDbContext db) =>
|
||
{
|
||
// 1. 调用微信 code2Session 获取 openid
|
||
Console.WriteLine($"[wx-login] 收到 code: {request.Code}");
|
||
var sessionResult = await weChatService.Code2SessionAsync(request.Code);
|
||
if (!sessionResult.Success)
|
||
{
|
||
return Results.BadRequest(new { code = 400, message = sessionResult.ErrorMessage });
|
||
}
|
||
|
||
// 2. 根据 openid 查找或创建用户
|
||
var openId = sessionResult.OpenId!;
|
||
var user = await db.Users.FirstOrDefaultAsync(u => u.OpenId == openId);
|
||
if (user == null)
|
||
{
|
||
// 自动注册,手机号暂时留空
|
||
var randomSuffix = Random.Shared.Next(1000, 9999).ToString();
|
||
user = new User
|
||
{
|
||
Uid = await BusinessHelpers.GenerateUniqueUid(db),
|
||
OpenId = openId,
|
||
Phone = "",
|
||
Nickname = $"微信用户{randomSuffix}",
|
||
CreatedAt = DateTime.UtcNow
|
||
};
|
||
db.Users.Add(user);
|
||
await db.SaveChangesAsync();
|
||
}
|
||
|
||
// 3. 生成 JWT 返回
|
||
var token = jwtService.GenerateToken(user.Id, user.Role.ToString());
|
||
|
||
return Results.Ok(new LoginResponse
|
||
{
|
||
Token = token,
|
||
UserInfo = new UserInfo
|
||
{
|
||
Id = user.Id,
|
||
Uid = user.Uid,
|
||
Phone = user.Phone,
|
||
Nickname = user.Nickname,
|
||
AvatarUrl = user.AvatarUrl,
|
||
Role = user.Role.ToString()
|
||
}
|
||
});
|
||
});
|
||
|
||
// 受保护的测试端点(用于验证认证和授权)
|
||
app.MapGet("/api/protected", () => Results.Ok("ok"))
|
||
.RequireAuthorization();
|
||
|
||
// 更新用户信息(昵称、头像)
|
||
app.MapPut("/api/user/profile", async (UpdateProfileRequest request, HttpContext httpContext, AppDbContext db) =>
|
||
{
|
||
var userIdClaim = httpContext.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier);
|
||
if (userIdClaim == null) return Results.Unauthorized();
|
||
var userId = int.Parse(userIdClaim.Value);
|
||
|
||
var user = await db.Users.FindAsync(userId);
|
||
if (user == null) return Results.NotFound(new { code = 404, message = "用户不存在" });
|
||
|
||
if (!string.IsNullOrWhiteSpace(request.Nickname))
|
||
user.Nickname = request.Nickname.Trim();
|
||
if (!string.IsNullOrWhiteSpace(request.AvatarUrl))
|
||
user.AvatarUrl = request.AvatarUrl.Trim();
|
||
|
||
await db.SaveChangesAsync();
|
||
|
||
return Results.Ok(new UserInfo
|
||
{
|
||
Id = user.Id,
|
||
Uid = user.Uid,
|
||
Phone = user.Phone,
|
||
Nickname = user.Nickname,
|
||
AvatarUrl = user.AvatarUrl,
|
||
Role = user.Role.ToString()
|
||
});
|
||
}).RequireAuthorization();
|
||
|
||
// 管理员账号密码登录接口
|
||
app.MapPost("/api/admin/auth/login", async (
|
||
AdminLoginRequest request,
|
||
JwtService jwtService,
|
||
AppDbContext db,
|
||
IConfiguration configuration) =>
|
||
{
|
||
// 从配置读取管理员凭据
|
||
var adminUsername = configuration["Admin:Username"] ?? "admin";
|
||
var adminPassword = configuration["Admin:Password"] ?? "admin123";
|
||
|
||
if (request.Username != adminUsername || request.Password != adminPassword)
|
||
{
|
||
return Results.BadRequest(new { code = 400, message = "账号或密码错误" });
|
||
}
|
||
|
||
// 查找或创建管理员用户
|
||
var admin = await db.Users.FirstOrDefaultAsync(u => u.Role == UserRole.Admin);
|
||
if (admin == null)
|
||
{
|
||
admin = new User
|
||
{
|
||
OpenId = "admin",
|
||
Phone = "admin",
|
||
Nickname = "管理员",
|
||
Role = UserRole.Admin,
|
||
CreatedAt = DateTime.UtcNow
|
||
};
|
||
db.Users.Add(admin);
|
||
await db.SaveChangesAsync();
|
||
}
|
||
|
||
var token = jwtService.GenerateToken(admin.Id, admin.Role.ToString());
|
||
|
||
return Results.Ok(new { token });
|
||
});
|
||
}
|
||
}
|