285 lines
9.3 KiB
C#
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();
|
|
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();
|
|
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();
|
|
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();
|
|
|
|
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();
|
|
|
|
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();
|
|
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
|
|
}
|