Files
StopShopping/StopShopping.Services/Implementions/UserService.cs
2026-03-30 11:07:30 +08:00

285 lines
9.3 KiB
C#

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using StopShopping.EF;
using StopShopping.Services.Extensions;
using StopShopping.Services.Models;
using StopShopping.Services.Models.Req;
using StopShopping.Services.Models.Resp;
namespace StopShopping.Services.Implementions;
public class UserService : IUserService
{
public UserService(
ILogger<UserService> logger,
StopShoppingContext dbContext,
ICipherService cipherService,
IAccessTokenService accessTokenService,
IClaimsService claimsService,
IFileService fileService,
ISerialNoGenerator serialNoGenerator)
{
_logger = logger;
_dbContext = dbContext;
_cipherService = cipherService;
_accessTokenService = accessTokenService;
_claimsService = claimsService;
_fileService = fileService;
_serialNoGenerator = serialNoGenerator;
}
private readonly ILogger<UserService> _logger;
private readonly StopShoppingContext _dbContext;
private readonly ICipherService _cipherService;
private readonly IAccessTokenService _accessTokenService;
private readonly IClaimsService _claimsService;
private readonly IFileService _fileService;
private readonly ISerialNoGenerator _serialNoGenerator;
public async Task<ApiResponse> SignUpAsync(SignUpParams model)
{
var user = await _dbContext.Users.FirstOrDefaultAsync(u => u.Account == model.Account);
if (null != user)
return ApiResponse.Failed("帐户名已存在");
user = new EF.Models.User
{
Account = model.Account!,
Addresses = [],
Avatar = Consts.DEFAULT_AVATAR,
CurrentRole = model.DefaultRole.GetValue(),
NickName = model.NickName!,
Password = _cipherService.EncryptUserPassword(model.Password!)
};
await _dbContext.AddAsync(user);
if (await _dbContext.SaveChangesAsync() > 0)
return ApiResponse.Succed();
return ApiResponse.Failed("数据库操作失败");
}
public async Task<SignInResult<SignInUser>> SignInAsync(SignInParams model)
{
SignInResult<SignInUser> result = new();
var user = await _dbContext.Users
.FirstOrDefaultAsync(u => u.Account == model.Account);
if (null == user || user.Password != _cipherService.EncryptUserPassword(model.Password!))
{
result.IsSucced = false;
result.Message = "账号或密码错误";
return result;
}
user.LastLoginTime = DateTime.Now;
await _dbContext.SaveChangesAsync();
var claimsIdentity = _claimsService.BuildIdentity(user);
result.RefreshToken = await _accessTokenService.SetRefreshTokenAsync(user.Id, SystemRoles.User);
result.User = new SignInUser
{
AvatarUrl = string.IsNullOrWhiteSpace(user.Avatar)
? null
: _fileService.GetFileUrl(UploadScences.Avatar, user.Avatar),
NickName = user.NickName,
DefaultRole = user.CurrentRole.ToUserRoles(),
AccessToken = _accessTokenService.GenerateAccessToken(claimsIdentity)
};
return result;
}
public async Task<SignInResult<SignInAdmin>> SignInAdminAsync(SignInParams model)
{
SignInResult<SignInAdmin> result = new();
var admin = await _dbContext.Administrators
.FirstOrDefaultAsync(u => u.Account == model.Account);
if (null == admin || admin.Password != _cipherService.EncryptUserPassword(model.Password!))
{
result.IsSucced = false;
result.Message = "账号或密码错误";
return result;
}
admin.LastLoginTime = DateTime.Now;
await _dbContext.SaveChangesAsync();
var claimsIdentity = _claimsService.BuildAdminIdentity(admin);
result.RefreshToken = await _accessTokenService.SetRefreshTokenAsync(admin.Id, SystemRoles.Admin);
result.User = new SignInAdmin
{
NickName = admin.NickName,
AccessToken = _accessTokenService.GenerateAccessToken(claimsIdentity)
};
return result;
}
public async Task GenerateDefaultAdminAsync()
{
var defaultAdmin = await _dbContext.Administrators
.Where(a => a.Account == Consts.DEFAULT_ADMIN_ACCOUNT)
.FirstOrDefaultAsync();
if (null != defaultAdmin)
{
_logger.LogInformation("默认管理员已存在,已跳过");
return;
}
var pwd = _serialNoGenerator.GenerateRandomPassword();
defaultAdmin = new()
{
Account = Consts.DEFAULT_ADMIN_ACCOUNT,
NickName = "超级管理员",
Password = _cipherService.EncryptUserPassword(pwd)
};
await _dbContext.Administrators.AddAsync(defaultAdmin);
await _dbContext.SaveChangesAsync();
_logger.LogInformation(
"默认管理员({Account})已生成,请立马修改密码:{Password}",
Consts.DEFAULT_ADMIN_ACCOUNT,
pwd);
}
public async Task<ApiResponse> ChangePasswordAsync(ChangePasswordParams model)
{
int userId = _claimsService.GetCurrentUserId()!.Value;
var user = await _dbContext.Users
.FirstAsync(u => u.Id == userId);
if (_cipherService.EncryptUserPassword(model.OldPassword!) != user.Password)
return ApiResponse.Failed("原密码错误");
user.Password = _cipherService.EncryptUserPassword(model.NewPassword!);
await _dbContext.SaveChangesAsync();
return ApiResponse.Succed();
}
public async Task<ApiResponse<User>> GetUserInfoAsync()
{
var userId = _claimsService.GetCurrentUserId()!.Value;
var model = await _dbContext.Users
.FirstAsync(u => u.Id == userId);
User user = new()
{
Account = model.Account,
AvatarUrl = string.IsNullOrWhiteSpace(model.Avatar)
? null
: _fileService.GetFileUrl(UploadScences.Avatar, model.Avatar),
DefaultRole = model.CurrentRole.ToUserRoles(),
LastLoginTime = model.LastLoginTime?.ToFormatted(),
NickName = model.NickName,
Telephone = model.Telephone
};
return new ApiResponse<User>(user);
}
public async Task<ApiResponse> EditAsync(EditUserParams model)
{
int userId = _claimsService.GetCurrentUserId()!.Value;
var user = await _dbContext.Users.FirstAsync(u => u.Id == userId);
if (!string.IsNullOrWhiteSpace(model.AvatarFileName))
user.Avatar = model.AvatarFileName;
user.CurrentRole = model.DefaultRole.GetValue();
if (!string.IsNullOrWhiteSpace(model.NickName))
user.NickName = model.NickName;
if (!string.IsNullOrWhiteSpace(model.Telephone))
user.Telephone = model.Telephone;
await _dbContext.SaveChangesAsync();
return ApiResponse.Succed();
}
public ApiResponse<List<Address>> GetAddresses()
{
var userId = _claimsService.GetCurrentUserId()!.Value;
var addresses = _dbContext.Addresses
.Where(a => a.UserId == userId)
.OrderByDescending(a => a.Default)
.AsNoTracking()
.Select(Cast)
.ToList();
return new ApiResponse<List<Address>>(addresses);
}
public async Task<ApiResponse> EditAddressAsync(EditAddressParams model)
{
EF.Models.Address? address = null;
var userId = _claimsService.GetCurrentUserId()!.Value;
if (model.Id.HasValue && model.Id > 0)
{
address = await _dbContext.Addresses
.FirstOrDefaultAsync(a => a.Id == model.Id && a.UserId == userId);
if (null == address)
return ApiResponse.Failed("地址已不存在");
}
else
{
address = new();
await _dbContext.Addresses.AddAsync(address);
}
address.Default = model.Default;
address.Detail = model.Detail;
address.DistrictLevel1Id = model.DistrictLevel1Id;
address.DistrictLevel2Id = model.DistrictLevel2Id;
address.DistrictLevel3Id = model.DistrictLevel3Id;
address.DistrictLevel4Id = model.DistrictLevel4Id;
address.Name = model.Name;
address.Tag = model.Tag;
address.Telephone = model.Telephone;
await _dbContext.SaveChangesAsync();
return ApiResponse.Succed();
}
public async Task<ApiResponse> DeleteAddressAsync(int id)
{
var userId = _claimsService.GetCurrentUserId()!.Value;
await _dbContext.Addresses
.Where(a => a.Id == id && a.UserId == userId)
.ExecuteDeleteAsync();
return ApiResponse.Succed();
}
#region private methods
private Address Cast(EF.Models.Address a)
{
return new Address
{
Default = a.Default,
Detail = a.Detail,
DistrictLevel1Id = a.DistrictLevel1Id,
DistrictLevel2Id = a.DistrictLevel2Id,
DistrictLevel3Id = a.DistrictLevel3Id,
DistrictLevel4Id = a.DistrictLevel4Id,
Id = a.Id,
Name = a.Name,
Tag = a.Tag,
Telephone = a.Telephone
};
}
#endregion
}