Merge branch 'abp' of https://gitee.com/ccnetcore/Yi into abp
This commit is contained in:
@@ -24,5 +24,12 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
||||
/// 封面
|
||||
/// </summary>
|
||||
public string? Cover { get; set; }
|
||||
|
||||
public int OrderNum { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 是否禁止评论创建功能
|
||||
/// </summary>
|
||||
public bool IsDisableCreateComment { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
||||
{
|
||||
public class DiscussGetListOutputDto : EntityDto<Guid>
|
||||
{
|
||||
/// <summary>
|
||||
/// <20>Ƿ<EFBFBD><C7B7><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD>۴<EFBFBD><DBB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public bool IsDisableCreateComment { get; set; }
|
||||
/// <summary>
|
||||
/// <20>Ƿ<EFBFBD><C7B7>ѵ<EFBFBD><D1B5>ޣ<EFBFBD>Ĭ<EFBFBD><C4AC>δ<EFBFBD><CEB4>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
|
||||
@@ -6,6 +6,10 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
||||
{
|
||||
public class DiscussGetOutputDto : EntityDto<Guid>
|
||||
{
|
||||
/// <summary>
|
||||
/// <20>Ƿ<EFBFBD><C7B7><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD>۴<EFBFBD><DBB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public bool IsDisableCreateComment { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string? Types { get; set; }
|
||||
public string? Introduction { get; set; }
|
||||
|
||||
@@ -20,5 +20,12 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
||||
/// <20><><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public string? Cover { get; set; }
|
||||
|
||||
public int OrderNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <20>Ƿ<EFBFBD><C7B7><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD>۴<EFBFBD><DBB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
public bool IsDisableCreateComment { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,5 +10,9 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Plate
|
||||
public string? Introduction { get; set; }
|
||||
|
||||
public string Code { get; set; }
|
||||
|
||||
public int OrderNum { get; set; }
|
||||
|
||||
public bool IsDisableCreateDiscuss { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,5 +12,8 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Plate
|
||||
public string Code { get; set; }
|
||||
|
||||
public DateTime CreationTime { get; set; }
|
||||
|
||||
public int OrderNum { get; set; }
|
||||
public bool IsDisableCreateDiscuss { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,5 +10,8 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Plate
|
||||
public string Code { get; set; }
|
||||
|
||||
public DateTime CreationTime { get; set; }
|
||||
|
||||
public int OrderNum { get; set; }
|
||||
public bool IsDisableCreateDiscuss { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,5 +7,10 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Plate
|
||||
public string? Introduction { get; set; }
|
||||
|
||||
public string? Code { get; set; }
|
||||
|
||||
public int OrderNum { get; set; }
|
||||
|
||||
|
||||
public bool IsDisableCreateDiscuss { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ using Yi.Framework.Bbs.Application.Contracts.Dtos.Article;
|
||||
using Yi.Framework.Bbs.Application.Contracts.Dtos.Plate;
|
||||
using Yi.Framework.Bbs.Application.Contracts.IServices;
|
||||
using Yi.Framework.Bbs.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Extensions;
|
||||
using Yi.Framework.Bbs.Domain.Repositories;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Consts;
|
||||
using Yi.Framework.Core.Extensions;
|
||||
@@ -47,7 +48,7 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
RefAsync<int> total = 0;
|
||||
|
||||
var entities = await _articleRepository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.Name), x => x.Name.Contains(input.Name!))
|
||||
//.WhereIF(!string.IsNullOrEmpty(input.Code), x => x.Name.Contains(input.Code!))
|
||||
//.WhereIF(!string.IsNullOrEmpty(input.Code), x => x.Name.Contains(input.Code!))
|
||||
.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<ArticleGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
||||
@@ -98,34 +99,60 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
/// <exception cref="UserFriendlyException"></exception>
|
||||
public async override Task<ArticleGetOutputDto> CreateAsync(ArticleCreateInputVo input)
|
||||
{
|
||||
var discuss = await _discussRepository.GetFirstAsync(x => x.Id == input.DiscussId);
|
||||
if (discuss is null)
|
||||
{
|
||||
throw new UserFriendlyException(DiscussConst.No_Exist);
|
||||
}
|
||||
if (input.ParentId != Guid.Empty && !await _articleRepository.IsAnyAsync(x => x.Id == input.ParentId))
|
||||
{
|
||||
throw new UserFriendlyException(ArticleConst.No_Exist);
|
||||
}
|
||||
await VerifyDiscussCreateIdAsync(discuss.CreatorId);
|
||||
await VerifyDiscussCreateIdAsync(input.DiscussId);
|
||||
return await base.CreateAsync(input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新文章
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ArticleGetOutputDto> UpdateAsync(Guid id, ArticleUpdateInputVo input)
|
||||
{
|
||||
var entity = await _articleRepository.GetByIdAsync(id);
|
||||
await VerifyDiscussCreateIdAsync(entity.DiscussId);
|
||||
return await base.UpdateAsync(id, input);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 效验创建权限
|
||||
/// 删除文章
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public async Task VerifyDiscussCreateIdAsync(Guid? userId)
|
||||
public override async Task DeleteAsync(Guid id)
|
||||
{
|
||||
var entity = await _articleRepository.GetByIdAsync(id);
|
||||
await VerifyDiscussCreateIdAsync(entity.DiscussId);
|
||||
await base.DeleteAsync(id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 效验创建权限,userId为主题创建者
|
||||
/// </summary>
|
||||
/// <param name="disucssId"></param>
|
||||
/// <returns></returns>
|
||||
private async Task VerifyDiscussCreateIdAsync(Guid disucssId)
|
||||
{
|
||||
var discuss = await _discussRepository.GetFirstAsync(x => x.Id == disucssId);
|
||||
if (discuss is null)
|
||||
{
|
||||
throw new UserFriendlyException(DiscussConst.No_Exist);
|
||||
}
|
||||
//只有文章是特殊的,不能在其他主题下创建
|
||||
//主题的创建者不是当前用户,同时,没有权限或者超级管理
|
||||
//false & true & false ,三个条件任意满意一个,即可成功使用||,最后取反,一个都不满足
|
||||
//
|
||||
if (userId != CurrentUser.Id && !UserConst.Admin.Equals(this.CurrentUser.UserName) && this.LazyServiceProvider.GetRequiredService<IHttpContextAccessor>().HttpContext.GetUserPermissions(TokenTypeConst.Permission).Contains("bbs:discuss:add"))
|
||||
|
||||
|
||||
//一个条件都不满足,即可拦截
|
||||
if (discuss.CreatorId != CurrentUser.Id && !UserConst.Admin.Equals(this.CurrentUser.UserName) && !CurrentUser.GetPermissions().Contains("bbs:discuss:add"))
|
||||
{
|
||||
throw new UserFriendlyException("无权限在其他用户主题中创建子文章");
|
||||
throw new UserFriendlyException("权限不足,请联系主题作者或管理员申请开通");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,10 +102,17 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
/// <exception cref="UserFriendlyException"></exception>
|
||||
public override async Task<CommentGetOutputDto> CreateAsync(CommentCreateInputVo input)
|
||||
{
|
||||
if (!await _discussRepository.IsAnyAsync(x => x.Id == input.DiscussId))
|
||||
var discuess = await _discussRepository.GetFirstAsync(x => x.Id == input.DiscussId);
|
||||
if (discuess is null)
|
||||
{
|
||||
throw new UserFriendlyException(DiscussConst.No_Exist);
|
||||
}
|
||||
|
||||
if (discuess.IsDisableCreateComment == true)
|
||||
{
|
||||
throw new UserFriendlyException("该主题已禁止评论功能");
|
||||
|
||||
}
|
||||
var entity = await _forumManager.CreateCommentAsync(input.DiscussId, input.ParentId, input.RootId, input.Content);
|
||||
return await MapToGetOutputDtoAsync(entity);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using Volo.Abp.Users;
|
||||
using Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss;
|
||||
using Yi.Framework.Bbs.Application.Contracts.IServices;
|
||||
using Yi.Framework.Bbs.Domain.Entities;
|
||||
using Yi.Framework.Bbs.Domain.Extensions;
|
||||
using Yi.Framework.Bbs.Domain.Managers;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Consts;
|
||||
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||
@@ -16,6 +17,7 @@ using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||
using Yi.Framework.Ddd.Application;
|
||||
using Yi.Framework.Rbac.Application.Contracts.Dtos.User;
|
||||
using Yi.Framework.Rbac.Domain.Entities;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.Bbs.Application.Services
|
||||
@@ -26,11 +28,13 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
public class DiscussService : YiCrudAppService<DiscussEntity, DiscussGetOutputDto, DiscussGetListOutputDto, Guid, DiscussGetListInputVo, DiscussCreateInputVo, DiscussUpdateInputVo>,
|
||||
IDiscussService
|
||||
{
|
||||
public DiscussService(ForumManager forumManager, ISqlSugarRepository<PlateEntity> plateEntityRepository, ILocalEventBus localEventBus) : base(forumManager._discussRepository)
|
||||
private ISqlSugarRepository<DiscussTopEntity> _discussTopEntityRepository;
|
||||
public DiscussService(ForumManager forumManager, ISqlSugarRepository<DiscussTopEntity> discussTopEntityRepository, ISqlSugarRepository<PlateEntity> plateEntityRepository, ILocalEventBus localEventBus) : base(forumManager._discussRepository)
|
||||
{
|
||||
_forumManager = forumManager;
|
||||
_plateEntityRepository = plateEntityRepository;
|
||||
_localEventBus = localEventBus;
|
||||
_discussTopEntityRepository = discussTopEntityRepository;
|
||||
}
|
||||
private readonly ILocalEventBus _localEventBus;
|
||||
private ForumManager _forumManager { get; set; }
|
||||
@@ -78,12 +82,17 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
var items = await _forumManager._discussRepository._DbQueryable
|
||||
.WhereIF(!string.IsNullOrEmpty(input.Title), x => x.Title.Contains(input.Title))
|
||||
.WhereIF(input.PlateId is not null, x => x.PlateId == input.PlateId)
|
||||
.WhereIF(input.IsTop==true, x => x.IsTop == input.IsTop)
|
||||
|
||||
|
||||
.WhereIF(input.IsTop == true, x => x.IsTop == input.IsTop)
|
||||
|
||||
.LeftJoin<UserEntity>((discuss, user) => discuss.CreatorId == user.Id)
|
||||
|
||||
.OrderByDescending(discuss => discuss.OrderNum)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.New, discuss => discuss.CreationTime, OrderByType.Desc)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.Host, discuss => discuss.SeeNum, OrderByType.Desc)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.Suggest, discuss => discuss.AgreeNum, OrderByType.Desc)
|
||||
|
||||
.Select((discuss, user) => new DiscussGetListOutputDto
|
||||
{
|
||||
Id = discuss.Id,
|
||||
@@ -99,6 +108,18 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
return new PagedResultDto<DiscussGetListOutputDto>(total, items);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取首页的置顶主题
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<DiscussGetListOutputDto>> GetListTopAsync()
|
||||
{
|
||||
var entities = await _discussTopEntityRepository._DbQueryable.Includes(x => x.Discuss).OrderByDescending(x => x.OrderNum).ToListAsync();
|
||||
|
||||
var output = await MapToGetListOutputDtosAsync(entities.Select(x => x.Discuss).ToList());
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建主题
|
||||
/// </summary>
|
||||
@@ -106,17 +127,28 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
/// <returns></returns>
|
||||
public override async Task<DiscussGetOutputDto> CreateAsync(DiscussCreateInputVo input)
|
||||
{
|
||||
if (!await _plateEntityRepository.IsAnyAsync(x => x.Id == input.PlateId))
|
||||
var plate = await _plateEntityRepository.FindAsync(x => x.Id == input.PlateId);
|
||||
if (plate is null)
|
||||
{
|
||||
throw new UserFriendlyException(PlateConst.No_Exist);
|
||||
}
|
||||
|
||||
//如果开启了禁用创建主题
|
||||
if (plate.IsDisableCreateDiscuss == true)
|
||||
{
|
||||
|
||||
if (!CurrentUser.GetPermissions().Contains("") && CurrentUser.UserName != UserConst.Admin)
|
||||
{
|
||||
throw new UserFriendlyException("该板块已禁止创建主题,请在其他板块中发布");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var entity = await _forumManager.CreateDiscussAsync(await MapToEntityAsync(input));
|
||||
return await MapToGetOutputDtoAsync(entity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 效验主题查询权限
|
||||
/// </summary>
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace Yi.Framework.Bbs.Application.Services
|
||||
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.Name), x => x.Name.Contains(input.Name!))
|
||||
.WhereIF(!string.IsNullOrEmpty(input.Code), x => x.Name.Contains(input.Code!))
|
||||
.WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
|
||||
.OrderByDescending(x=>x.OrderNum)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
return new PagedResultDto<PlateGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ namespace Yi.Framework.Bbs.Domain.Entities
|
||||
//是否置顶,默认false
|
||||
public bool IsTop { get; set; }
|
||||
|
||||
public int OrderNum { get; set; } = 0;
|
||||
|
||||
|
||||
public DiscussPermissionTypeEnum PermissionType { get; set; }
|
||||
|
||||
@@ -57,5 +59,10 @@ namespace Yi.Framework.Bbs.Domain.Entities
|
||||
/// </summary>
|
||||
[SugarColumn(IsJson = true)]//使用json处理
|
||||
public List<Guid>? PermissionUserIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否禁止评论创建功能
|
||||
/// </summary>
|
||||
public bool IsDisableCreateComment { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Auditing;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// 首页置顶主题
|
||||
/// </summary>
|
||||
[SugarTable("DiscussTop")]
|
||||
public class DiscussTopEntity : Entity<Guid>, IHasModificationTime
|
||||
{
|
||||
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true)]
|
||||
public override Guid Id { get; protected set; }
|
||||
|
||||
public int OrderNum { get; set; }
|
||||
|
||||
public Guid DiscussId { get; set; }
|
||||
|
||||
[Navigate(NavigateType.OneToOne, nameof(DiscussId))]
|
||||
public DiscussEntity Discuss { get; set; }
|
||||
|
||||
public DateTime? LastModificationTime { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using Volo.Abp.Auditing;
|
||||
namespace Yi.Framework.Bbs.Domain.Entities
|
||||
{
|
||||
[SugarTable("Plate")]
|
||||
public class PlateEntity : Entity<Guid>, ISoftDelete,IAuditedObject
|
||||
public class PlateEntity : Entity<Guid>, ISoftDelete, IAuditedObject
|
||||
{
|
||||
|
||||
[SugarColumn(ColumnName = "Id", IsPrimaryKey = true)]
|
||||
@@ -27,5 +27,12 @@ namespace Yi.Framework.Bbs.Domain.Entities
|
||||
public Guid? LastModifierId { get; set; }
|
||||
|
||||
public DateTime? LastModificationTime { get; set; }
|
||||
|
||||
public int OrderNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否禁用创建主题,禁用后,只有管理员或者权限者能够发送
|
||||
/// </summary>
|
||||
public bool IsDisableCreateDiscuss { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||
|
||||
namespace Yi.Framework.Bbs.Domain.Extensions
|
||||
{
|
||||
public static class CurrestUserExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取用户权限codes
|
||||
/// </summary>
|
||||
/// <param name="currentUser"></param>
|
||||
/// <returns></returns>
|
||||
public static List<string> GetPermissions(this ICurrentUser currentUser)
|
||||
{
|
||||
return currentUser.FindClaims(TokenTypeConst.Permission).Select(x => x.Value).ToList();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,8 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
private IDistributedCache<CaptchaPhoneCacheItem, CaptchaPhoneCacheKey> _phoneCache;
|
||||
private readonly ICaptcha _captcha;
|
||||
private readonly IGuidGenerator _guidGenerator;
|
||||
private readonly RbacOptions _rbacOptions;
|
||||
private readonly IAliyunManger _aliyunManger;
|
||||
public AccountService(IUserRepository userRepository,
|
||||
ICurrentUser currentUser,
|
||||
AccountManager accountManager,
|
||||
@@ -50,7 +52,11 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
IOptions<JwtOptions> jwtOptions,
|
||||
IDistributedCache<CaptchaPhoneCacheItem, CaptchaPhoneCacheKey> phoneCache,
|
||||
ICaptcha captcha,
|
||||
IGuidGenerator guidGenerator)
|
||||
IGuidGenerator guidGenerator,
|
||||
IOptions<RbacOptions> options,
|
||||
IAliyunManger aliyunManger,
|
||||
ISqlSugarRepository<RoleEntity> roleRepository,
|
||||
UserManager userManager)
|
||||
{
|
||||
_userRepository = userRepository;
|
||||
_currentUser = currentUser;
|
||||
@@ -62,6 +68,10 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
_phoneCache = phoneCache;
|
||||
_captcha = captcha;
|
||||
_guidGenerator = guidGenerator;
|
||||
_rbacOptions = options.Value;
|
||||
_aliyunManger = aliyunManger;
|
||||
_roleRepository = roleRepository;
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
|
||||
@@ -79,27 +89,17 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
/// </summary>
|
||||
private void ValidationImageCaptcha(LoginInputVo input)
|
||||
{
|
||||
//登录不想要验证码 ,可不效验
|
||||
if (!_captcha.Validate(input.Uuid, input.Code))
|
||||
if (_rbacOptions.EnableCaptcha)
|
||||
{
|
||||
throw new UserFriendlyException("验证码错误");
|
||||
//登录不想要验证码 ,可不效验
|
||||
if (!_captcha.Validate(input.Uuid, input.Code))
|
||||
{
|
||||
throw new UserFriendlyException("验证码错误");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 效验电话验证码,需要与电话号码绑定
|
||||
/// </summary>
|
||||
private void ValidationPhoneCaptcha(RegisterDto input)
|
||||
{
|
||||
//var value = _memoryCache.Get<string>($"Yi:Phone:{input.Phone}");
|
||||
//if (value is not null && value.Equals($"{input.Code}"))
|
||||
//{
|
||||
// //成功,需要清空
|
||||
// _memoryCache.Remove($"Yi:Phone:{input.Phone}");
|
||||
// return;
|
||||
//}
|
||||
//throw new UserFriendlyException("验证码错误");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 登录
|
||||
@@ -114,7 +114,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
}
|
||||
|
||||
//效验验证码
|
||||
// ValidationImageCaptcha(input);
|
||||
ValidationImageCaptcha(input);
|
||||
|
||||
UserEntity user = new();
|
||||
//登录成功
|
||||
@@ -123,6 +123,12 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
//获取用户信息
|
||||
var userInfo = await _userRepository.GetUserAllInfoAsync(user.Id);
|
||||
|
||||
//判断用户状态
|
||||
if (userInfo.User.State == false)
|
||||
{
|
||||
throw new UserFriendlyException(UserConst.State_Is_State);
|
||||
}
|
||||
|
||||
if (userInfo.RoleCodes.Count == 0)
|
||||
{
|
||||
throw new UserFriendlyException(UserConst.No_Role);
|
||||
@@ -216,19 +222,9 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
//生成一个4位数的验证码
|
||||
//发送短信,同时生成uuid
|
||||
////key: 电话号码 value:验证码+uuid
|
||||
//var code = _securityCode.GetRandomEnDigitalText(4);
|
||||
var code = Guid.NewGuid().ToString().Substring(0, 4);
|
||||
var uuid = Guid.NewGuid();
|
||||
|
||||
//未开启短信验证,默认8888
|
||||
//if (_smsAliyunManagerOptions.Value.EnableFeature)
|
||||
//{
|
||||
// await _smsAliyunManager.Send(input.Phone, code);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
var code = "8888";
|
||||
//}
|
||||
//_memoryCache.Set($"Yi:Phone:{input.Phone}", $"{code}", new TimeSpan(0, 10, 0));
|
||||
await _aliyunManger.SendSmsAsync(input.Phone, code);
|
||||
|
||||
await _phoneCache.SetAsync(new CaptchaPhoneCacheKey(input.Phone), new CaptchaPhoneCacheItem(code), new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(10) });
|
||||
return new
|
||||
@@ -237,6 +233,22 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 效验电话验证码,需要与电话号码绑定
|
||||
/// </summary>
|
||||
private async Task ValidationPhoneCaptchaAsync(RegisterDto input)
|
||||
{
|
||||
var item = await _phoneCache.GetAsync(new CaptchaPhoneCacheKey(input.Phone.ToString()));
|
||||
if (item is not null && item.Code.Equals($"{input.Code}"))
|
||||
{
|
||||
//成功,需要清空
|
||||
await _phoneCache.RemoveAsync(new CaptchaPhoneCacheKey(input.Phone.ToString()));
|
||||
return;
|
||||
}
|
||||
throw new UserFriendlyException("验证码错误");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 注册,需要验证码通过
|
||||
/// </summary>
|
||||
@@ -246,6 +258,11 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
[UnitOfWork]
|
||||
public async Task<object> PostRegisterAsync(RegisterDto input)
|
||||
{
|
||||
if (_rbacOptions.EnableRegister == false)
|
||||
{
|
||||
throw new UserFriendlyException("该系统暂未开放注册功能");
|
||||
}
|
||||
|
||||
if (input.UserName == UserConst.Admin)
|
||||
{
|
||||
throw new UserFriendlyException("用户名无效注册!");
|
||||
@@ -260,15 +277,13 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
throw new UserFriendlyException("密码需大于等于6位!");
|
||||
}
|
||||
//效验验证码,根据电话号码获取 value,比对验证码已经uuid
|
||||
ValidationPhoneCaptcha(input);
|
||||
await ValidationPhoneCaptchaAsync(input);
|
||||
|
||||
|
||||
|
||||
//输入的用户名与电话号码都不能在数据库中存在
|
||||
UserEntity user = new();
|
||||
var isExist = await _userRepository.IsAnyAsync(x =>
|
||||
x.UserName == input.UserName
|
||||
|| x.Phone == input.Phone);
|
||||
var isExist = await _userRepository.IsAnyAsync(x =>x.UserName == input.UserName|| x.Phone == input.Phone);
|
||||
if (isExist)
|
||||
{
|
||||
throw new UserFriendlyException("用户已存在,注册失败");
|
||||
@@ -278,8 +293,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
|
||||
var entity = await _userRepository.InsertReturnEntityAsync(newUser);
|
||||
//赋上一个初始角色
|
||||
var roleRepository = _roleRepository;
|
||||
var role = await roleRepository.GetFirstAsync(x => x.RoleCode == UserConst.GuestRoleCode);
|
||||
var role = await _roleRepository.GetFirstAsync(x => x.RoleCode == UserConst.GuestRoleCode);
|
||||
if (role is not null)
|
||||
{
|
||||
await _userManager.GiveUserSetRoleAsync(new List<Guid> { entity.Id }, new List<Guid> { role.Id });
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
||||
<PackageReference Include="Lazy.Captcha.Core" Version="2.0.7" />
|
||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.6" />
|
||||
<PackageReference Include="Volo.Abp.BackgroundWorkers.Quartz" Version="8.0.0-rc.3" />
|
||||
<PackageReference Include="Volo.Abp.BackgroundWorkers.Quartz" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Yi.Framework.Rbac.Domain.Shared.Consts
|
||||
public const string Login_User_No_Exist = "登录失败!用户名不存在!";
|
||||
public const string Login_Passworld_Error = "密码为空,添加失败!";
|
||||
public const string User_Exist = "用户已经存在,添加失败!";
|
||||
public const string State_Is_State = "该用户已被禁用,请联系管理员进行恢复";
|
||||
public const string No_Permission = "登录禁用!该用户分配无任何权限,无意义登录!";
|
||||
public const string No_Role = "登录禁用!该用户分配无任何角色,无意义登录!";
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yi.Framework.Rbac.Domain.Shared.Options
|
||||
{
|
||||
public class AliyunOptions
|
||||
{
|
||||
|
||||
public string AccessKeyId { get; set; }
|
||||
public string AccessKeySecret { get; set; }
|
||||
public AliyunSms Sms { get; set; }
|
||||
}
|
||||
|
||||
public class AliyunSms
|
||||
{
|
||||
public string SignName { get; set; }
|
||||
public string TemplateCode { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -12,5 +12,15 @@ namespace Yi.Framework.Rbac.Domain.Shared.Options
|
||||
/// 超级管理员默认密码
|
||||
/// </summary>
|
||||
public string AdminPassword { get; set; } = "123456";
|
||||
|
||||
/// <summary>
|
||||
/// 是否开启登录验证码
|
||||
/// </summary>
|
||||
public bool EnableCaptcha { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否开启用户注册功能
|
||||
/// </summary>
|
||||
public bool EnableRegister { get; set; } = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="8.0.0-rc.3" />
|
||||
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
using AlibabaCloud.SDK.Dysmsapi20170525;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Volo.Abp.Domain.Services;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Options;
|
||||
|
||||
namespace Yi.Framework.Rbac.Domain.Managers
|
||||
{
|
||||
public class AliyunManger : DomainService, IAliyunManger
|
||||
{
|
||||
private ILogger<AliyunManger> _logger;
|
||||
private AliyunOptions Options { get; set; }
|
||||
public AliyunManger(ILogger<AliyunManger> logger, IOptions<AliyunOptions> options)
|
||||
{
|
||||
Options = options.Value;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
private Client CreateClient()
|
||||
{
|
||||
AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config
|
||||
{
|
||||
// 必填,您的 AccessKey ID
|
||||
AccessKeyId = Options.AccessKeyId,
|
||||
// 必填,您的 AccessKey Secret
|
||||
AccessKeySecret = Options.AccessKeySecret,
|
||||
};
|
||||
// 访问的域名
|
||||
config.Endpoint = "dysmsapi.aliyuncs.com";
|
||||
return new Client(config);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 发送短信
|
||||
/// </summary>
|
||||
/// <param name="phoneNumbers"></param>
|
||||
/// <param name="code"></param>
|
||||
/// <returns></returns>
|
||||
public async Task SendSmsAsync(string phoneNumbers, string code)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
var _aliyunClient = CreateClient();
|
||||
AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest sendSmsRequest = new AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest
|
||||
{
|
||||
PhoneNumbers = phoneNumbers,
|
||||
SignName = Options.Sms.SignName,
|
||||
TemplateCode = Options.Sms.TemplateCode,
|
||||
TemplateParam = System.Text.Json.JsonSerializer.Serialize(new { code })
|
||||
};
|
||||
|
||||
var response = await _aliyunClient.SendSmsAsync(sendSmsRequest);
|
||||
}
|
||||
|
||||
catch (Exception _error)
|
||||
{
|
||||
_logger.LogError(_error, "阿里云短信发送错误:" + _error.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IAliyunManger
|
||||
{
|
||||
Task SendSmsAsync(string phoneNumbers, string code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,13 @@ namespace Yi.Framework.Rbac.Domain.SignalRHubs
|
||||
{
|
||||
[HubRoute("/hub/main")]
|
||||
[Authorize]
|
||||
public class OnlineUserHub : AbpHub
|
||||
public class OnlineUserHub : AbpHub
|
||||
{
|
||||
public static readonly List<OnlineUserModel> clientUsers = new();
|
||||
|
||||
|
||||
private HttpContext? _httpContext;
|
||||
private ILogger<OnlineUserHub> _logger=> LoggerFactory.CreateLogger<OnlineUserHub>();
|
||||
private ILogger<OnlineUserHub> _logger => LoggerFactory.CreateLogger<OnlineUserHub>();
|
||||
public OnlineUserHub(IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_httpContext = httpContextAccessor?.HttpContext;
|
||||
@@ -68,10 +68,15 @@ namespace Yi.Framework.Rbac.Domain.SignalRHubs
|
||||
//判断用户是否存在,否则添加集合
|
||||
if (user != null)
|
||||
{
|
||||
clientUsers.Remove(user);
|
||||
Clients.All.SendAsync("onlineNum", clientUsers.Count);
|
||||
//Clients.All.SendAsync(HubsConstant.OnlineUser, clientUsers);
|
||||
_logger.LogInformation($"用户{user?.UserName}离开了,当前已连接{clientUsers.Count}个");
|
||||
var clientUser = clientUsers.FirstOrDefault(x => x.ConnnectionId == user.ConnnectionId);
|
||||
if (clientUser is not null)
|
||||
{
|
||||
clientUsers.Remove(clientUser);
|
||||
Clients.All.SendAsync("onlineNum", clientUsers.Count);
|
||||
//Clients.All.SendAsync(HubsConstant.OnlineUser, clientUsers);
|
||||
_logger.LogInformation($"用户{user?.UserName}离开了,当前已连接{clientUsers.Count}个");
|
||||
}
|
||||
|
||||
}
|
||||
return base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\common.props" />
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<PackageReference Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="2.0.24" />
|
||||
|
||||
<PackageReference Include="IPTools.China" Version="1.6.0" />
|
||||
|
||||
<PackageReference Include="TencentCloudSDK" Version="3.0.917" />
|
||||
|
||||
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||
|
||||
<PackageReference Include="Volo.Abp.AspNetCore.SignalR" Version="8.0.0-rc.3" />
|
||||
<PackageReference Include="Volo.Abp.AspNetCore.SignalR" Version="8.0.0" />
|
||||
|
||||
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="8.0.0-rc.3" />
|
||||
<PackageReference Include="Volo.Abp.Caching" Version="8.0.0-rc.3" />
|
||||
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="8.0.0" />
|
||||
<PackageReference Include="Volo.Abp.Caching" Version="8.0.0" />
|
||||
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
@@ -7,6 +7,7 @@ using Yi.Framework.Mapster;
|
||||
using Yi.Framework.Rbac.Domain.Authorization;
|
||||
using Yi.Framework.Rbac.Domain.Operlog;
|
||||
using Yi.Framework.Rbac.Domain.Shared;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Options;
|
||||
|
||||
namespace Yi.Framework.Rbac.Domain
|
||||
{
|
||||
@@ -22,11 +23,15 @@ namespace Yi.Framework.Rbac.Domain
|
||||
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||
{
|
||||
var service = context.Services;
|
||||
var configuration = context.Services.GetConfiguration();
|
||||
service.AddControllers(options =>
|
||||
{
|
||||
options.Filters.Add<PermissionGlobalAttribute>();
|
||||
options.Filters.Add<OperLogGlobalAttribute>();
|
||||
});
|
||||
|
||||
//配置阿里云短信
|
||||
Configure<AliyunOptions>(configuration.GetSection(nameof(AliyunOptions)));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user