diff --git a/Yi.Abp.Net8/framework/Yi.Framework.Ddd.Application/YiCacheCrudAppService.cs b/Yi.Abp.Net8/framework/Yi.Framework.Ddd.Application/YiCacheCrudAppService.cs new file mode 100644 index 00000000..d10cdd82 --- /dev/null +++ b/Yi.Abp.Net8/framework/Yi.Framework.Ddd.Application/YiCacheCrudAppService.cs @@ -0,0 +1,119 @@ +using Volo.Abp.Application.Dtos; +using Volo.Abp.Caching; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.MultiTenancy; + +namespace Yi.Framework.Ddd.Application +{ + public abstract class YiCacheCrudAppService : YiCrudAppService + where TEntity : class, IEntity + where TEntityDto : IEntityDto + { + protected YiCacheCrudAppService(IRepository repository) : base(repository) + { + } + } + + public abstract class YiCacheCrudAppService + : YiCrudAppService + where TEntity : class, IEntity + where TEntityDto : IEntityDto + { + protected YiCacheCrudAppService(IRepository repository) : base(repository) + { + } + } + + + public abstract class YiCacheCrudAppService + : YiCrudAppService + where TEntity : class, IEntity + where TEntityDto : IEntityDto + { + protected YiCacheCrudAppService(IRepository repository) : base(repository) + { + } + } + + public abstract class YiCacheCrudAppService + : YiCrudAppService + where TEntity : class, IEntity + where TEntityDto : IEntityDto + { + protected YiCacheCrudAppService(IRepository repository) : base(repository) + { + } + } + + + public abstract class YiCacheCrudAppService + : YiCrudAppService + where TEntity : class, IEntity + where TGetOutputDto : IEntityDto + where TGetListOutputDto : IEntityDto + { + protected IDistributedCache Cache => LazyServiceProvider.LazyGetRequiredService>(); + + protected string GetCacheKey(TKey id) => typeof(TEntity).Name + ":" + CurrentTenant.Id ?? Guid.Empty + ":" + id.ToString(); + protected YiCacheCrudAppService(IRepository repository) : base(repository) + { + } + + public override async Task UpdateAsync(TKey id, TUpdateInput input) + { + var output = await base.UpdateAsync(id, input); + await Cache.RemoveAsync(GetCacheKey(id)); + return output; + } + + public override async Task> GetListAsync(TGetListInput input) + { + //两种方式: + //1:全表缓存,使用缓存直接查询 + //2:非全部缓存,查询到的数据直接添加到缓存 + + //判断是否该实体为全表缓存 + throw new NotImplementedException(); + + //IDistributedCache 有局限性,条件查询无法进行缓存了 + //if (true) + //{ + // return await GetListByCacheAsync(input); + //} + //else + //{ + // return await GetListByDbAsync(input); + //} + + } + + protected virtual async Task> GetListByDbAsync(TGetListInput input) + { + //如果不是全表缓存,可以走这个啦 + throw new NotImplementedException(); + } + protected virtual async Task> GetListByCacheAsync(TGetListInput input) + { + //如果是全表缓存,可以走这个啦 + throw new NotImplementedException(); + } + + + protected override async Task GetEntityByIdAsync(TKey id) + { + var output = await Cache.GetOrAddAsync(GetCacheKey(id), async () => await base.GetEntityByIdAsync(id)); + return output!; + } + + public override async Task DeleteAsync(IEnumerable id) + { + await base.DeleteAsync(id); + foreach (var itemId in id) + { + await Cache.RemoveAsync(GetCacheKey(itemId)); + } + + } + } +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/DictionaryTypeService.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/DictionaryTypeService.cs index ce3ca28f..441e1793 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/DictionaryTypeService.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/DictionaryTypeService.cs @@ -1,5 +1,7 @@ +using Microsoft.Extensions.DependencyInjection; using SqlSugar; using Volo.Abp.Application.Dtos; +using Volo.Abp.Caching; using Yi.Framework.Ddd.Application; using Yi.Framework.Rbac.Application.Contracts.Dtos.DictionaryType; using Yi.Framework.Rbac.Application.Contracts.IServices; @@ -36,6 +38,5 @@ namespace Yi.Framework.Rbac.Application.Services Items = await MapToGetListOutputDtosAsync(entities) }; } - } } diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/System/UserService.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/System/UserService.cs index ca822d31..79d2a473 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/System/UserService.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/System/UserService.cs @@ -3,6 +3,7 @@ using SqlSugar; using TencentCloud.Tcr.V20190924.Models; using Volo.Abp; using Volo.Abp.Application.Dtos; +using Volo.Abp.Caching; using Volo.Abp.EventBus.Local; using Volo.Abp.Users; using Yi.Framework.Ddd.Application; @@ -12,6 +13,7 @@ using Yi.Framework.Rbac.Domain.Authorization; using Yi.Framework.Rbac.Domain.Entities; using Yi.Framework.Rbac.Domain.Managers; using Yi.Framework.Rbac.Domain.Repositories; +using Yi.Framework.Rbac.Domain.Shared.Caches; using Yi.Framework.Rbac.Domain.Shared.Consts; using Yi.Framework.Rbac.Domain.Shared.Etos; using Yi.Framework.Rbac.Domain.Shared.OperLog; @@ -25,10 +27,11 @@ namespace Yi.Framework.Rbac.Application.Services.System public class UserService : YiCrudAppService,IUserService //IUserService { - public UserService(ISqlSugarRepository repository, UserManager userManager, IUserRepository userRepository, ICurrentUser currentUser, IDeptService deptService, ILocalEventBus localEventBus) : base(repository) + private IDistributedCache _userCache; + public UserService(ISqlSugarRepository repository, UserManager userManager, IUserRepository userRepository, ICurrentUser currentUser, IDeptService deptService, ILocalEventBus localEventBus, IDistributedCache userCache) : base(repository) => - (_userManager, _userRepository, _currentUser, _deptService, _repository, _localEventBus) = - (userManager, userRepository, currentUser, deptService, repository, localEventBus); + (_userManager, _userRepository, _currentUser, _deptService, _repository, _localEventBus, _userCache) = + (userManager, userRepository, currentUser, deptService, repository, localEventBus, userCache); private UserManager _userManager { get; set; } private ISqlSugarRepository _repository; private IUserRepository _userRepository { get; set; } @@ -77,6 +80,14 @@ namespace Yi.Framework.Rbac.Application.Services.System return result; } + + protected override UserEntity MapToEntity(UserCreateInputVo createInput) + { + var output= base.MapToEntity(createInput); + output.EncryPassword = new Domain.Entities.ValueObjects.EncryPasswordValueObject(createInput.Password); + return output; + } + /// /// 添加用户 /// @@ -99,13 +110,13 @@ namespace Yi.Framework.Rbac.Application.Services.System { throw new UserFriendlyException(UserConst.User_Exist); } - var entities = await MapToEntityAsync(input); - - entities.BuildPassword(); + var entitiy = await MapToEntityAsync(input); + + entitiy.BuildPassword(); //using (var uow = _unitOfWorkManager.CreateContext()) //{ - var returnEntity = await _repository.InsertReturnEntityAsync(entities); + var returnEntity = await _repository.InsertReturnEntityAsync(entitiy); await _userManager.GiveUserSetRoleAsync(new List { returnEntity.Id }, input.RoleIds); await _userManager.GiveUserSetPostAsync(new List { returnEntity.Id }, input.PostIds); //uow.Commit(); @@ -152,17 +163,17 @@ namespace Yi.Framework.Rbac.Application.Services.System //更新密码,特殊处理 if (input.Password is not null) { - entity.Password = input.Password; + entity.EncryPassword.Password = input.Password; entity.BuildPassword(); } await MapToEntityAsync(input, entity); - //using (var uow = _unitOfWorkManager.CreateContext()) - //{ + var res1 = await _repository.UpdateAsync(entity); await _userManager.GiveUserSetRoleAsync(new List { id }, input.RoleIds); await _userManager.GiveUserSetPostAsync(new List { id }, input.PostIds); - // uow.Commit(); - //} + + await _userCache.RefreshAsync(new UserInfoCacheKey(_currentUser.GetId())); + return await MapToGetOutputDtoAsync(entity); } @@ -179,6 +190,7 @@ namespace Yi.Framework.Rbac.Application.Services.System await _repository.UpdateAsync(entity); var dto = await MapToGetOutputDtoAsync(entity); + await _userCache.RefreshAsync(new UserInfoCacheKey(_currentUser.GetId())); return dto; } @@ -200,13 +212,16 @@ namespace Yi.Framework.Rbac.Application.Services.System } entity.State = state; await _repository.UpdateAsync(entity); + await _userCache.RefreshAsync(new UserInfoCacheKey(id)); return await MapToGetOutputDtoAsync(entity); } [OperLog("删除用户", OperEnum.Delete)] [Permission("system:user:delete")] public override async Task DeleteAsync(Guid id) { + await base.DeleteAsync(id); + await _userCache.RefreshAsync(new UserInfoCacheKey(id)); } [Permission("system:user:export")] diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/UserEntity.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/UserEntity.cs index 4925273f..12865286 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/UserEntity.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/UserEntity.cs @@ -4,6 +4,7 @@ using Volo.Abp.Auditing; using Volo.Abp.Domain.Entities; using Yi.Framework.Core.Data; using Yi.Framework.Core.Helper; +using Yi.Framework.Rbac.Domain.Entities.ValueObjects; using Yi.Framework.Rbac.Domain.Shared.Enums; namespace Yi.Framework.Rbac.Domain.Entities @@ -22,7 +23,7 @@ namespace Yi.Framework.Rbac.Domain.Entities public UserEntity(string userName, string password, long phone, string nick = "萌新") { UserName = userName; - Password = password; + EncryPassword.Password = password; Phone = phone; Nick = nick; BuildPassword(); @@ -55,14 +56,20 @@ namespace Yi.Framework.Rbac.Domain.Entities public string UserName { get; set; } = string.Empty; /// - /// 密码 + /// 加密密码 /// - public string Password { get; set; } = string.Empty; + [SugarColumn(IsOwnsOne = true)] + public EncryPasswordValueObject EncryPassword { get; set; } = new EncryPasswordValueObject(); - /// - /// 加密盐值 - /// - public string Salt { get; set; } = string.Empty; + ///// + ///// 密码 + ///// + //public string Password { get; set; } = string.Empty; + + ///// + ///// 加密盐值 + ///// + //public string Salt { get; set; } = string.Empty; /// /// 头像 @@ -175,14 +182,14 @@ namespace Yi.Framework.Rbac.Domain.Entities //如果不传值,那就把自己的password当作传进来的password if (password == null) { - if (Password == null) + if (EncryPassword?.Password == null) { - throw new ArgumentNullException(nameof(Password)); + throw new ArgumentNullException(nameof(EncryPassword.Password)); } - password = Password; + password = EncryPassword.Password; } - Salt = MD5Helper.GenerateSalt(); - Password = MD5Helper.SHA2Encode(password, Salt); + EncryPassword.Salt = MD5Helper.GenerateSalt(); + EncryPassword.Password = MD5Helper.SHA2Encode(password, EncryPassword.Salt); return this; } @@ -193,12 +200,12 @@ namespace Yi.Framework.Rbac.Domain.Entities /// public bool JudgePassword(string password) { - if (Salt is null) + if (EncryPassword.Salt is null) { - throw new ArgumentNullException(Salt); + throw new ArgumentNullException(EncryPassword.Salt); } - var p = MD5Helper.SHA2Encode(password, Salt); - if (Password == MD5Helper.SHA2Encode(password, Salt)) + var p = MD5Helper.SHA2Encode(password, EncryPassword.Salt); + if (EncryPassword.Password == MD5Helper.SHA2Encode(password, EncryPassword.Salt)) { return true; } diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/ValueObjects/EncryPasswordValueObject.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/ValueObjects/EncryPasswordValueObject.cs new file mode 100644 index 00000000..6b825434 --- /dev/null +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Entities/ValueObjects/EncryPasswordValueObject.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.Domain.Values; + +namespace Yi.Framework.Rbac.Domain.Entities.ValueObjects +{ + public class EncryPasswordValueObject : ValueObject + { + public EncryPasswordValueObject() { } + public EncryPasswordValueObject(string password) { this.Password = password; } + + /// + /// 密码 + /// + public string Password { get; set; } = string.Empty; + + /// + /// 加密盐值 + /// + public string Salt { get; set; } = string.Empty; + + protected override IEnumerable GetAtomicValues() + { + yield return Password; + yield return Salt; + } + } +} diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs index 8a460e31..b326282e 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs @@ -154,7 +154,7 @@ namespace Yi.Framework.Rbac.Domain.Managers { userAction.Invoke(user); } - if (user.Password == MD5Helper.SHA2Encode(password, user.Salt)) + if (user.EncryPassword.Password == MD5Helper.SHA2Encode(password, user.EncryPassword.Salt)) { return; } @@ -247,7 +247,7 @@ namespace Yi.Framework.Rbac.Domain.Managers { throw new UserFriendlyException("无效更新!原密码错误!"); } - user.Password = newPassword; + user.EncryPassword.Password = newPassword; user.BuildPassword(); await _repository.UpdateAsync(user); } @@ -262,7 +262,7 @@ namespace Yi.Framework.Rbac.Domain.Managers { var user = await _repository.GetByIdAsync(userId); // EntityHelper.TrySetId(user, () => GuidGenerator.Create(), true); - user.Password = password; + user.EncryPassword.Password = password; user.BuildPassword(); return await _repository.UpdateAsync(user); } diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/UserManager.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/UserManager.cs index 7c5edc0f..dcc906b6 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/UserManager.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/UserManager.cs @@ -95,42 +95,26 @@ namespace Yi.Framework.Rbac.Domain.Managers /// public async Task GetInfoAsync(Guid userId) { - var user = await _userRepository.GetUserAllInfoAsync(userId); - var output = await GetInfoByCacheAsync(user); + + var output = await GetInfoByCacheAsync(userId); return output; } - - /// - /// 批量查询用户信息 - /// - /// - /// - public async Task> GetInfoListAsync(List userIds) - { - List output = new List(); - var users = await _userRepository.GetListUserAllInfoAsync(userIds); - foreach (var user in users) - { - output.Add(await GetInfoByCacheAsync(user)); - } - return output; - } - - private async Task GetInfoByCacheAsync(UserEntity user) + private async Task GetInfoByCacheAsync(Guid userId) { //此处优先从缓存中获取 UserRoleMenuDto output = null; var tokenExpiresMinuteTime = LazyServiceProvider.GetRequiredService>().Value.ExpiresMinuteTime; - var cacheData = await _userCache.GetOrAddAsync(new UserInfoCacheKey(user.Id), + var cacheData = await _userCache.GetOrAddAsync(new UserInfoCacheKey(userId), async () => { + var user = await _userRepository.GetUserAllInfoAsync(userId); var data = EntityMapToDto(user); //系统用户数据被重置,老前端访问重新授权 if (data is null) { throw new AbpAuthorizationException(); } - data.Menus.Clear(); + //data.Menus.Clear(); output = data; return new UserInfoCacheItem(data); }, @@ -143,6 +127,24 @@ namespace Yi.Framework.Rbac.Domain.Managers return output!; } + + /// + /// 批量查询用户信息 + /// + /// + /// + public async Task> GetInfoListAsync(List userIds) + { + List output = new List(); + foreach (var userId in userIds) + { + output.Add(await GetInfoByCacheAsync(userId)); + } + return output; + } + + + private UserRoleMenuDto EntityMapToDto(UserEntity user) { @@ -152,8 +154,8 @@ namespace Yi.Framework.Rbac.Domain.Managers //{ // throw new UserFriendlyException($"数据错误,用户id:{nameof(userId)} 不存在,请重新登录"); //} - user.Password = string.Empty; - user.Salt = string.Empty; + user.EncryPassword.Password = string.Empty; + user.EncryPassword.Salt = string.Empty; //超级管理员特殊处理 if (UserConst.Admin.Equals(user.UserName)) diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.SqlSugarCore/DataSeeds/UserDataSeed.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.SqlSugarCore/DataSeeds/UserDataSeed.cs index 2183e868..963621b0 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.SqlSugarCore/DataSeeds/UserDataSeed.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.SqlSugarCore/DataSeeds/UserDataSeed.cs @@ -2,6 +2,7 @@ using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Yi.Framework.Rbac.Domain.Entities; +using Yi.Framework.Rbac.Domain.Entities.ValueObjects; using Yi.Framework.Rbac.Domain.Shared.Enums; using Yi.Framework.Rbac.Domain.Shared.Options; using Yi.Framework.SqlSugarCore.Abstractions; @@ -27,7 +28,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds Name = "大橙子", UserName = "cc", Nick = "橙子", - Password = _options.AdminPassword, + EncryPassword = new EncryPasswordValueObject(_options.AdminPassword), Email = "454313500@qq.com", Phone = 13800000000, Sex = SexEnum.Male, @@ -47,7 +48,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds Name = "大测试", UserName = "test", Nick = "测试", - Password = "123456", + EncryPassword=new EncryPasswordValueObject("123456"), Email = "454313500@qq.com", Phone = 15900000000, Sex = SexEnum.Woman, @@ -68,7 +69,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds Name = "游客", UserName = "guest", Nick = "测试", - Password = "123456", + EncryPassword = new EncryPasswordValueObject("123456"), Email = "454313500@qq.com", Phone = 15900000000, Sex = SexEnum.Woman, diff --git a/Yi.Abp.Net8/version.props b/Yi.Abp.Net8/version.props index 1cfda791..7a7a259e 100644 --- a/Yi.Abp.Net8/version.props +++ b/Yi.Abp.Net8/version.props @@ -1,6 +1,6 @@ 8.0.5 - 5.1.4.149 + 5.1.4.154-preview01 \ No newline at end of file