feat: 完成微信小程序账户应用服务

This commit is contained in:
橙子
2024-10-19 16:17:26 +08:00
parent 736995c35b
commit 0f687a7e34
16 changed files with 363 additions and 73 deletions

View File

@@ -101,7 +101,7 @@ namespace Yi.Framework.Rbac.Application.Services
/// <param name="input"></param>
/// <returns></returns>
[AllowAnonymous]
public async Task<object> PostLoginAsync(LoginInputVo input)
public async Task<LoginOutputDto> PostLoginAsync(LoginInputVo input)
{
if (string.IsNullOrEmpty(input.Password) || string.IsNullOrEmpty(input.UserName))
{
@@ -115,10 +115,21 @@ namespace Yi.Framework.Rbac.Application.Services
//校验
await _accountManager.LoginValidationAsync(input.UserName, input.Password, x => user = x);
return await PostLoginAsync(user.Id);
}
/// <summary>
/// 提供其他服务使用根据用户id直接返回token
/// </summary>
/// <returns></returns>
[RemoteService(isEnabled: false)]
public async Task<LoginOutputDto> PostLoginAsync(Guid userId)
{
var userInfo = new UserRoleMenuDto();
//获取token
var accessToken = await _accountManager.GetTokenByUserIdAsync(user.Id, (info) => userInfo = info);
var refreshToken = _accountManager.CreateRefreshToken(user.Id);
var accessToken = await _accountManager.GetTokenByUserIdAsync(userId, (info) => userInfo = info);
var refreshToken = _accountManager.CreateRefreshToken(userId);
//这里抛出一个登录的事件,也可以在全部流程走完,在应用层组装
if (_httpContextAccessor.HttpContext is not null)
@@ -130,10 +141,9 @@ namespace Yi.Framework.Rbac.Application.Services
await LocalEventBus.PublishAsync(loginEto);
}
return new { Token = accessToken, RefreshToken = refreshToken };
return new LoginOutputDto { Token = accessToken, RefreshToken = refreshToken };
}
/// <summary>
/// 刷新token
/// </summary>
@@ -158,7 +168,7 @@ namespace Yi.Framework.Rbac.Application.Services
var uuid = _guidGenerator.Create();
var captcha = _captcha.Generate(uuid.ToString());
var enableCaptcha = _rbacOptions.EnableCaptcha;
return new CaptchaImageDto { Img = captcha.Bytes, Uuid = uuid,IsEnableCaptcha= enableCaptcha };
return new CaptchaImageDto { Img = captcha.Bytes, Uuid = uuid, IsEnableCaptcha = enableCaptcha };
}
/// <summary>
@@ -202,17 +212,19 @@ namespace Yi.Framework.Rbac.Application.Services
/// 手机验证码
/// </summary>
/// <returns></returns>
private async Task<object> PostCaptchaPhoneAsync(ValidationPhoneTypeEnum validationPhoneType,
public async Task<object> PostCaptchaPhoneAsync(ValidationPhoneTypeEnum validationPhoneType,
PhoneCaptchaImageDto input)
{
await ValidationPhone(input.Phone);
//注册的手机号验证,是不能已经注册过的
if (validationPhoneType == ValidationPhoneTypeEnum.Register&& await _userRepository.IsAnyAsync(x => x.Phone.ToString() == input.Phone))
{
throw new UserFriendlyException("该手机号已被注册!");
}
//这里为了统一,绑定流程,不在次校验,而是在注册时校验
// if (validationPhoneType == ValidationPhoneTypeEnum.Register &&
// await _userRepository.IsAnyAsync(x => x.Phone.ToString() == input.Phone))
// {
// throw new UserFriendlyException("该手机号已被注册!");
// }
var value = await _phoneCache.GetAsync(new CaptchaPhoneCacheKey(validationPhoneType, input.Phone));
//防止暴刷
@@ -264,7 +276,7 @@ namespace Yi.Framework.Rbac.Application.Services
{
//校验验证码,根据电话号码获取 value比对验证码已经uuid
await ValidationPhoneCaptchaAsync(ValidationPhoneTypeEnum.RetrievePassword, input.Phone, input.Code);
var entity = await _userRepository.GetFirstAsync(x => x.Phone == input.Phone);
if (entity is null)
{
@@ -272,7 +284,7 @@ namespace Yi.Framework.Rbac.Application.Services
}
await _accountManager.RestPasswordAsync(entity.Id, input.Password);
return entity.UserName;
}
@@ -322,6 +334,30 @@ namespace Yi.Framework.Rbac.Application.Services
return output;
}
[RemoteService(isEnabled: false)]
public async Task<UserRoleMenuDto?> GetAsync(string? userName, long? phone)
{
var user = await _userRepository._DbQueryable
.WhereIF(userName is not null, x => x.UserName == userName)
.WhereIF(phone is not null, x => x.Phone == phone)
.Where(x => x.State == true)
.FirstAsync();
//该用户不存在
if (user is null)
{
return null;
}
//注意用户名大小写数据库不敏感问题
if (userName is not null && user.UserName.Equals(userName))
{
throw new UserFriendlyException($"该用户名不存在或已禁用-{userName}");
}
var output = await _userManager.GetInfoAsync(user.Id);
return output;
}
/// <summary>
/// 获取当前登录用户的前端路由
@@ -430,7 +466,7 @@ namespace Yi.Framework.Rbac.Application.Services
/// <returns></returns>
public async Task<bool> UpdateIconAsync(UpdateIconDto input)
{
Guid userId=input.UserId == null?_currentUser.GetId():input.UserId.Value;
Guid userId = input.UserId == null ? _currentUser.GetId() : input.UserId.Value;
var entity = await _userRepository.GetByIdAsync(userId);

View File

@@ -7,8 +7,10 @@ using SqlSugar;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Users;
using Yi.Framework.Ddd.Application;
using Yi.Framework.Rbac.Application.Contracts.Dtos.Account;
using Yi.Framework.Rbac.Application.Contracts.IServices;
using Yi.Framework.Rbac.Domain.Authorization;
using Yi.Framework.Rbac.Domain.Managers;
using Yi.Framework.SqlSugarCore.Abstractions;
@@ -18,13 +20,17 @@ namespace Yi.Framework.Rbac.Application.Services.Authentication
/// <summary>
/// 第三方授权服务
/// </summary>
public class AuthService : YiCrudAppService<AuthAggregateRoot, AuthOutputDto, Guid, AuthGetListInput>
public class AuthService :
YiCrudAppService<AuthAggregateRoot, AuthOutputDto, Guid, AuthGetListInput, AuthCreateOrUpdateInputDto>,
IAuthService
{
private HttpContext HttpContext { get; set; }
private ILogger<AuthService> _logger;
private ISqlSugarRepository<AuthAggregateRoot, Guid> _repository;
private IAccountManager _accountManager;
public AuthService(IAccountManager accountManager, IHttpContextAccessor httpContextAccessor, ILogger<AuthService> logger, ISqlSugarRepository<AuthAggregateRoot, Guid> repository) : base(repository)
public AuthService(IAccountManager accountManager, IHttpContextAccessor httpContextAccessor,
ILogger<AuthService> logger, ISqlSugarRepository<AuthAggregateRoot, Guid> repository) : base(repository)
{
_logger = logger;
HttpContext = httpContextAccessor.HttpContext ?? throw new ApplicationException("未注册Http");
@@ -49,8 +55,9 @@ namespace Yi.Framework.Rbac.Application.Services.Authentication
{
throw new UserFriendlyException("第三方登录失败,请先注册后,在个人中心进行绑定该第三方后使用");
}
var accessToken = await _accountManager.GetTokenByUserIdAsync(authEntity.UserId);
return new { token= accessToken };
return new { token = accessToken };
}
/// <summary>
@@ -71,6 +78,7 @@ namespace Yi.Framework.Rbac.Application.Services.Authentication
{
throw new UserFriendlyException("绑定失败,该第三方账号已被注册");
}
var authAggregateRoot = new AuthAggregateRoot(scheme, userId ?? Guid.Empty, openId, name);
await _repository.InsertAsync(authAggregateRoot);
@@ -84,6 +92,7 @@ namespace Yi.Framework.Rbac.Application.Services.Authentication
{
throw new UserFriendlyException(authenticateResult.Failure.Message);
}
var openidClaim = authenticateResult.Principal.Claims.Where(x => x.Type == "urn:openid").FirstOrDefault();
var nameClaim = authenticateResult.Principal.Claims.Where(x => x.Type == "urn:name").FirstOrDefault();
return (openidClaim.Value, nameClaim.Value);
@@ -104,21 +113,31 @@ namespace Yi.Framework.Rbac.Application.Services.Authentication
return (await GetListAsync(input)).Items;
}
public async Task<AuthOutputDto?> TryGetByOpenIdAsync(string openId, string authType)
{
var entity = await _repository._DbQueryable.Where(x => x.OpenId == openId)
.Where(x => x.AuthType == authType)
.FirstAsync();
var output = await MapToGetOutputDtoAsync(entity);
return output;
}
public override async Task<PagedResultDto<AuthOutputDto>> GetListAsync(AuthGetListInput input)
{
RefAsync<int> total = 0;
var entities = await _repository._DbQueryable.WhereIF(input.UserId is not null, x => x.UserId == input.UserId)
.WhereIF(!string.IsNullOrEmpty(input.AuthType), x => x.AuthType == input.AuthType)
.WhereIF(!string.IsNullOrEmpty(input.OpenId), x => x.OpenId == input.OpenId)
.WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
var entities = await _repository._DbQueryable
.WhereIF(input.UserId is not null, x => x.UserId == input.UserId)
.WhereIF(!string.IsNullOrEmpty(input.AuthType), x => x.AuthType == input.AuthType)
.WhereIF(!string.IsNullOrEmpty(input.OpenId), x => x.OpenId == input.OpenId)
.WhereIF(input.StartTime is not null && input.EndTime is not null,
x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
return new PagedResultDto<AuthOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
}
[RemoteService(IsEnabled = false)]
public override Task<AuthOutputDto> UpdateAsync(Guid id, AuthOutputDto input)
public override Task<AuthOutputDto> UpdateAsync(Guid id, AuthCreateOrUpdateInputDto input)
{
throw new NotImplementedException();
}
@@ -135,9 +154,23 @@ namespace Yi.Framework.Rbac.Application.Services.Authentication
}
[RemoteService(IsEnabled = false)]
public override Task<AuthOutputDto> CreateAsync(AuthOutputDto input)
public override async Task<AuthOutputDto> CreateAsync(AuthCreateOrUpdateInputDto input)
{
throw new NotImplementedException();
var entity = await MapToEntityAsync(input);
await _repository.InsertAsync(entity);
return MapToGetOutputDto(entity);
}
protected override async Task CheckCreateInputDtoAsync(AuthCreateOrUpdateInputDto input)
{
//同一个类型,一个用户只能绑定一个第三方授权
var isAny = await _repository._DbQueryable.Where(x => x.AuthType == input.AuthType)
.Where(x => x.OpenId == input.OpenId || x.UserId == input.UserId).AnyAsync();
if (isAny)
{
throw new UserFriendlyException("该用户已有此应用授权");
}
}
}
}
}