chore: 同步当前开发内容

This commit is contained in:
2025-11-23 01:25:20 +08:00
parent ddf584f212
commit 1169e1f220
58 changed files with 1886 additions and 82 deletions

View File

@@ -0,0 +1,87 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using TakeoutSaaS.Application.Identity.Abstractions;
using TakeoutSaaS.Application.Identity.Contracts;
using TakeoutSaaS.Domain.Identity.Entities;
using TakeoutSaaS.Domain.Identity.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
namespace TakeoutSaaS.Application.Identity.Services;
/// <summary>
/// 管理后台认证服务实现。
/// </summary>
public sealed class AdminAuthService : IAdminAuthService
{
private readonly IIdentityUserRepository _userRepository;
private readonly IPasswordHasher<IdentityUser> _passwordHasher;
private readonly IJwtTokenService _jwtTokenService;
private readonly IRefreshTokenStore _refreshTokenStore;
public AdminAuthService(
IIdentityUserRepository userRepository,
IPasswordHasher<IdentityUser> passwordHasher,
IJwtTokenService jwtTokenService,
IRefreshTokenStore refreshTokenStore)
{
_userRepository = userRepository;
_passwordHasher = passwordHasher;
_jwtTokenService = jwtTokenService;
_refreshTokenStore = refreshTokenStore;
}
public async Task<TokenResponse> LoginAsync(AdminLoginRequest request, CancellationToken cancellationToken = default)
{
var user = await _userRepository.FindByAccountAsync(request.Account, cancellationToken)
?? throw new BusinessException(ErrorCodes.Unauthorized, "账号或密码错误");
var result = _passwordHasher.VerifyHashedPassword(user, user.PasswordHash, request.Password);
if (result == PasswordVerificationResult.Failed)
{
throw new BusinessException(ErrorCodes.Unauthorized, "账号或密码错误");
}
var profile = BuildProfile(user);
return await _jwtTokenService.CreateTokensAsync(profile, false, cancellationToken);
}
public async Task<TokenResponse> RefreshTokenAsync(RefreshTokenRequest request, CancellationToken cancellationToken = default)
{
var descriptor = await _refreshTokenStore.GetAsync(request.RefreshToken, cancellationToken);
if (descriptor == null || descriptor.ExpiresAt <= DateTime.UtcNow || descriptor.Revoked)
{
throw new BusinessException(ErrorCodes.Unauthorized, "RefreshToken 无效或已过期");
}
var user = await _userRepository.FindByIdAsync(descriptor.UserId, cancellationToken)
?? throw new BusinessException(ErrorCodes.Unauthorized, "用户不存在");
await _refreshTokenStore.RevokeAsync(descriptor.Token, cancellationToken);
var profile = BuildProfile(user);
return await _jwtTokenService.CreateTokensAsync(profile, false, cancellationToken);
}
public async Task<CurrentUserProfile> GetProfileAsync(Guid userId, CancellationToken cancellationToken = default)
{
var user = await _userRepository.FindByIdAsync(userId, cancellationToken)
?? throw new BusinessException(ErrorCodes.NotFound, "用户不存在");
return BuildProfile(user);
}
private static CurrentUserProfile BuildProfile(IdentityUser user)
=> new()
{
UserId = user.Id,
Account = user.Account,
DisplayName = user.DisplayName,
TenantId = user.TenantId,
MerchantId = user.MerchantId,
Roles = user.Roles,
Permissions = user.Permissions,
Avatar = user.Avatar
};
}