diff --git a/IRaCIS.Core.Application/Service/Management/DTO/UserLogViewModel.cs b/IRaCIS.Core.Application/Service/Management/DTO/UserLogViewModel.cs new file mode 100644 index 000000000..40d69d0c6 --- /dev/null +++ b/IRaCIS.Core.Application/Service/Management/DTO/UserLogViewModel.cs @@ -0,0 +1,55 @@ +//-------------------------------------------------------------------- +// 此代码由T4模板自动生成 byzhouhang 20210918 +// 生成时间 2023-07-04 16:10:46 +// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 +//-------------------------------------------------------------------- +using System; +using IRaCIS.Core.Domain.Share; +using System.Collections.Generic; +namespace IRaCIS.Core.Application.ViewModel +{ + /// UserLogView 列表视图模型 + public class UserLogView: UserLogAddOrEdit + { + + + public string UserRealName { get; set; } + public string UserName { get; set; } + + public UserType UserTypeEnum { get; set; } + + public bool IsSuccess { get; set; } + + } + + ///UserLogQuery 列表查询参数模型 + public class UserLogQuery : PageInput + { + public UserOptType? OptType { get; set; } + + public string? IP { get; set; } + + public string? LoginName { get; set; } + + public DateTime? BeginDate { get; set; } + + public DateTime? EndDate { get; set; } + + + } + + /// UserLogAddOrEdit 列表查询参数模型 + public class UserLogAddOrEdit + { + public Guid? Id { get; set; } + public string IP { get; set; } + + public string LoginName { get; set; } + public int OptType { get; set; } + public string LoginPassword { get; set; } + } + + +} + + diff --git a/IRaCIS.Core.Application/Service/Management/Interface/IUserLogService.cs b/IRaCIS.Core.Application/Service/Management/Interface/IUserLogService.cs new file mode 100644 index 000000000..521f71870 --- /dev/null +++ b/IRaCIS.Core.Application/Service/Management/Interface/IUserLogService.cs @@ -0,0 +1,24 @@ +//-------------------------------------------------------------------- +// 此代码由T4模板自动生成 byzhouhang 20210918 +// 生成时间 2023-07-04 16:10:34 +// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 +//-------------------------------------------------------------------- + +using IRaCIS.Core.Application.ViewModel; +namespace IRaCIS.Core.Application.Interfaces +{ + /// + /// IUserLogService + /// + public interface IUserLogService + { + + Task> GetUserLogList(UserLogQuery inQuery); + + //Task AddOrUpdateUserLog(UserLogAddOrEdit addOrEditUserLog); + + //Task DeleteUserLog(Guid userLogId); + + + } +} diff --git a/IRaCIS.Core.Application/Service/Management/UserLogService.cs b/IRaCIS.Core.Application/Service/Management/UserLogService.cs new file mode 100644 index 000000000..1aaf7aa27 --- /dev/null +++ b/IRaCIS.Core.Application/Service/Management/UserLogService.cs @@ -0,0 +1,67 @@ +//-------------------------------------------------------------------- +// 此代码由T4模板自动生成 byzhouhang 20210918 +// 生成时间 2023-07-04 16:10:37 +// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 +//-------------------------------------------------------------------- + +using IRaCIS.Core.Domain.Models; +using Microsoft.AspNetCore.Mvc; +using IRaCIS.Core.Application.Interfaces; +using IRaCIS.Core.Application.ViewModel; +namespace IRaCIS.Core.Application.Service +{ + /// + /// UserLogService + /// + [ApiExplorerSettings(GroupName = "Test")] + public class UserLogService : BaseService, IUserLogService + { + + private readonly IRepository _userLogRepository; + + public UserLogService(IRepository userLogRepository) + { + _userLogRepository = userLogRepository; + } + + public async Task> GetUserLogList(UserLogQuery inQuery) + { + + var userLogQueryable = + + _userLogRepository + .WhereIf(inQuery.OptType!=null ,t=>t.OptType==inQuery.OptType) + .WhereIf(inQuery.BeginDate != null, t => t.CreateTime >= inQuery.BeginDate) + .WhereIf(inQuery.EndDate != null, t => t.CreateTime <= inQuery.EndDate) + .WhereIf(!string.IsNullOrEmpty(inQuery.LoginName) , t => t.LoginName.Contains(inQuery.LoginName) ) + .WhereIf(!string.IsNullOrEmpty(inQuery.IP), t => t.IP.Contains(inQuery.IP)) + .WhereIf(!string.IsNullOrEmpty(inQuery.LoginName), t => t.LoginName.Contains(inQuery.LoginName)) + .ProjectTo(_mapper.ConfigurationProvider); + + var pageList = await userLogQueryable.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? "Id" : inQuery.SortField,inQuery.Asc); + + return pageList; + } + + + //public async Task AddOrUpdateUserLog(UserLogAddOrEdit addOrEditUserLog) + //{ + // // 在此处拷贝automapper 映射 + + // var entity = await _userLogRepository.InsertOrUpdateAsync(addOrEditUserLog, true); + + // return ResponseOutput.Ok(entity.Id.ToString()); + + //} + + + //[HttpDelete("{userLogId:guid}")] + //public async Task DeleteUserLog(Guid userLogId) + //{ + // var success = await _userLogRepository.DeleteFromQueryAsync(t => t.Id == userLogId, true); + // return ResponseOutput.Ok(); + //} + + + } +} diff --git a/IRaCIS.Core.Application/Service/Management/UserService.cs b/IRaCIS.Core.Application/Service/Management/UserService.cs index 2de18aeea..9305f852c 100644 --- a/IRaCIS.Core.Application/Service/Management/UserService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserService.cs @@ -27,6 +27,7 @@ namespace IRaCIS.Application.Services private readonly IOptionsMonitor _verifyConfig; + private readonly IRepository _userLogRepository; public UserService(IRepository userRepository, @@ -36,7 +37,8 @@ namespace IRaCIS.Application.Services IMemoryCache cache, IRepository userTrialRepository, IOptionsMonitor verifyConfig - +, + IRepository userLogRepository ) { _verifyConfig = verifyConfig; @@ -46,6 +48,7 @@ namespace IRaCIS.Application.Services _verificationCodeRepository = verificationCodeRepository; _doctorRepository = doctorRepository; _userTrialRepository = userTrialRepository; + _userLogRepository = userLogRepository; } @@ -639,6 +642,8 @@ namespace IRaCIS.Application.Services if (failCount >= maxFailures) { + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = Guid.Empty, LoginName = userName, IsSuccess = false, OptType = UserOptType.AccountLocked }, true); + throw new BusinessValidationFailedException($"密码连续错误{maxFailures}次,当前账号已被限制登录,请等待 {lockoutMinutes} 分钟后再试。"); } @@ -672,6 +677,8 @@ namespace IRaCIS.Application.Services failCount++; _cache.Set(cacheKey, failCount, TimeSpan.FromMinutes(lockoutMinutes)); + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = Guid.Empty, LoginName = userName, IsSuccess = false, OptType = UserOptType.PasswordError }, true); + return ResponseOutput.NotOk(_localizer["User_CheckNameOrPw"], new LoginReturnDTO()); @@ -688,7 +695,7 @@ namespace IRaCIS.Application.Services //登录成功 清除缓存 _cache.Set(cacheKey, 0, TimeSpan.FromMinutes(lockoutMinutes)); - + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = loginUser.Id, LoginName = userName, IsSuccess = true, OptType = UserOptType.Login }, true); userLoginReturnModel.BasicInfo = loginUser; @@ -701,32 +708,12 @@ namespace IRaCIS.Application.Services - //private bool loginIsLocked(string userName) - //{ + public async Task LoginOut(Guid userId,string loginName) + { + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = userId, LoginName = loginName, IsSuccess = true, OptType = UserOptType.LoginOut },true); - // //if (failCount == null) - // //{ - // // failCount = 0; - // //} - // //else - // //{ - // // failCount++; - // //} - - // //// 更新缓存中的登录失败次数 - // //_cache.Set(cacheKey, failCount, TimeSpan.FromMinutes(lockoutMinutes)); - - // //if (failCount >= maxFailures) - // //{ - // // // 如果登录失败次数达到了 3 次,则锁定用户 - // // _cache.Set(cacheKey + ":locked", true, TimeSpan.FromMinutes(lockoutMinutes)); - // //} - - - - - // //return isLocked; - //} + return ResponseOutput.Ok(); + } } } diff --git a/IRaCIS.Core.Application/Service/Management/_MapConfig.cs b/IRaCIS.Core.Application/Service/Management/_MapConfig.cs index fa77bf4c8..842de95ca 100644 --- a/IRaCIS.Core.Application/Service/Management/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Management/_MapConfig.cs @@ -119,7 +119,8 @@ namespace IRaCIS.Core.Application.Service .ForMember(d => d.UserTypeId, c => c.MapFrom(t => t)); - + CreateMap(); + CreateMap().ReverseMap(); } } diff --git a/IRaCIS.Core.Domain/Management/UserLog.cs b/IRaCIS.Core.Domain/Management/UserLog.cs new file mode 100644 index 000000000..923eb84f2 --- /dev/null +++ b/IRaCIS.Core.Domain/Management/UserLog.cs @@ -0,0 +1,70 @@ + +//-------------------------------------------------------------------- +// 此代码由T4模板自动生成 byzhouhang 20210918 +// 生成时间 2023-07-04 16:10:43 +// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 +using System; +using IRaCIS.Core.Domain.Share; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +namespace IRaCIS.Core.Domain.Models +{ + /// + ///UserLog + /// + [Table("UserLog")] + public class UserLog : Entity, IAuditAdd + { + + + + + public string IP { get; set; } + + + public DateTime CreateTime { get; set; } + + + public Guid CreateUserId { get; set; } + + + public string LoginName { get; set; } + + + public UserOptType OptType { get; set; } + + + public string LoginPassword { get; set; } + + public bool IsSuccess { get; set; } + + } + + /// + /// 登录或者登出 锁定类型 + /// + public enum UserOptType + { + + /// + /// 用户登录 + /// + Login = 1, + + /// + /// 用户登出 + /// + LoginOut = 2, + + /// + /// 密码错误 + /// + PasswordError = 3, + + /// + /// 账号锁定 + /// + AccountLocked = 4 + } + +} diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index 3d8ac8b8d..344cd1c73 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs @@ -508,6 +508,8 @@ namespace IRaCIS.Core.Infra.EFCore public virtual DbSet ReadingTableQuestionAnswer { get; set; } public virtual DbSet PublishLog { get; set; } + public virtual DbSet UserLog { get; set; } +