Seamus hace 3 meses
padre
commit
b1b0d231b5

+ 1 - 2
ERP.Core/Application.cs

@@ -49,8 +49,7 @@ namespace ERP.Core
             // Todo 添加MiniProfiler 性能分析
 
             // Swagger
-            builder.Services.AddSwaggerGen();
-            //builder.Services.AddSwagger();
+            builder.Services.AddSwagger();
 
             // 校验异常拦截
             // 全局异常拦截

+ 11 - 17
ERP.Core/Controller/AuthController.cs

@@ -1,12 +1,14 @@
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Configuration;
-using ERP.Core.Service;
-using ERP.Core.Dto;
-using ERP.Core.Emum;
+using ERP.Core.Dto;
+using ERP.Core.Interface;
 using ERP.Framework.Config;
 using ERP.Framework.Constants;
+using ERP.Framework.Emum;
+using ERP.Framework.Security;
 using ERP.Framework.WebApi;
-using ERP.Core.Interface;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Swashbuckle.AspNetCore.Annotations;
+
 //using Swashbuckle.AspNetCore.Annotations;
 
 namespace ERP.Core.Controller
@@ -24,28 +26,20 @@ namespace ERP.Core.Controller
         }
 
         [HttpPost("/login")]
-        //[SwaggerOperation(Description = "登录接口", Summary = "Login")]
+        [SwaggerOperation(Description = "登录接口", Summary = "Login")]
         public IActionResult LoginAsync([FromBody] LoginBody form)
         {
             var securityConfig = _configuration.GetSection(FrameworkConstant.SECURITY_CONFIG).Get<SecurityConfig>() ?? new SecurityConfig();
 
             var loginUser = _authService.GetLoginUser(securityConfig, form.LoginName, form.Password);
 
-            //var jwtToken = LoginHelper.LoginByDevice(loginUser, securityConfig, DeviceEnum.Web);
-
-            //var isFirst = loginUser.UserStatus == API.Core.Enum.UserStatusEnum.New;
-
-            //var isPasswordExpire = loginUser.PasswordExpirationTime >= DateTime.Now;
+            var result = LoginHelper.LoginByDevice(loginUser, securityConfig, DeviceEnum.Web);
 
             //Todo 记录登录日志
 
             return Success(new
             {
-                //token = jwtToken.Token,
-                //expire = jwtToken.Expire,
-                //userInfo = loginUser,
-                //isFirst,
-                //isPasswordExpire,
+                access_token = result,
             });
         }
     }

+ 36 - 15
ERP.Core/CoreDbContext.cs

@@ -19,23 +19,13 @@ namespace ERP.Core
 
         public override int SaveChanges()
         {
-            var entityEntries = ChangeTracker.Entries().ToList();
-            foreach (var entry in entityEntries)
-            {
-                if (entry.State == EntityState.Added)
-                {
-                    Entry(entry.Entity).Property(nameof(BaseEntity.CreateTime)).CurrentValue = DateTime.Now;
+            BeforeSaveChanges();
+         
+            var result = base.SaveChanges();
 
-                    //Entry(entry.Entity).Property(nameof(BaseEntity.CreateBy)).CurrentValue = DateTime.Now;
-                }
-
-                if (entry.State == EntityState.Modified)
-                {
-                    Entry(entry.Entity).Property(nameof(BaseEntity.UpdateTime)).CurrentValue = DateTime.Now;
-                }
-            }
+            AfterSaveChanges();
 
-            return base.SaveChanges();
+            return result;
         }
 
         protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
@@ -71,6 +61,37 @@ namespace ERP.Core
             }
         }
 
+        private void BeforeSaveChanges()
+        {
+            ChangeTracker.DetectChanges();
+            var entityEntries = ChangeTracker.Entries().ToList();
+            foreach (var entry in entityEntries)
+            {
+                // 新增时赋值CreatetIime CreateBy
+                if (entry.State == EntityState.Added)
+                {
+                    Entry(entry.Entity).Property(nameof(BaseEntity.CreateTime)).CurrentValue = DateTime.Now;
+
+                    //Entry(entry.Entity).Property(nameof(BaseEntity.CreateBy)).CurrentValue = DateTime.Now;
+                }
+
+                if (entry.State == EntityState.Deleted)
+                {
+                }
+
+                // 修改时赋值CreatetIime CreateBy
+                if (entry.State == EntityState.Modified)
+                {
+                    Entry(entry.Entity).Property(nameof(BaseEntity.UpdateTime)).CurrentValue = DateTime.Now;
+                }
+            }
+        }
+
+        private void AfterSaveChanges()
+        {
+
+        }
+
         private void UseLog(DbContextOptionsBuilder optionsBuilder)
         {
             optionsBuilder.UseLoggerFactory(LoggerFactory.Create(builder =>

+ 1 - 0
ERP.Core/Entity/SysMenu.cs

@@ -1,4 +1,5 @@
 using ERP.Core.Enum;
+using ERP.Framework.Enum;
 using ERP.Framework.WebApi;
 using System.ComponentModel.DataAnnotations.Schema;
 

+ 1 - 0
ERP.Core/Entity/SysRole.cs

@@ -1,4 +1,5 @@
 using ERP.Core.Enum;
+using ERP.Framework.Enum;
 using ERP.Framework.WebApi;
 using System.ComponentModel.DataAnnotations.Schema;
 

+ 1 - 0
ERP.Core/Entity/SysUser.cs

@@ -1,4 +1,5 @@
 using ERP.Core.Enum;
+using ERP.Framework.Enum;
 using ERP.Framework.WebApi;
 using System.ComponentModel.DataAnnotations.Schema;
 

+ 1 - 0
ERP.Core/Interface/IAuthService.cs

@@ -5,6 +5,7 @@
 
 using ERP.Core.Dto;
 using ERP.Framework.Config;
+using ERP.Framework.Security.Core;
 using System;
 using System.Collections.Generic;
 using System.Linq;

+ 13 - 4
ERP.Core/Service/AuthService.cs

@@ -1,12 +1,12 @@
-using ERP.Core.Dto;
-using ERP.Core.Entity;
-using ERP.Core.Enum;
+using ERP.Core.Entity;
 using ERP.Core.Interface;
 using ERP.Core.Repository;
 using ERP.Core.Resource;
 using ERP.Framework.Cache;
 using ERP.Framework.Config;
 using ERP.Framework.Constants;
+using ERP.Framework.Enum;
+using ERP.Framework.Security.Core;
 using ERP.Framework.Utils;
 using Microsoft.Extensions.Localization;
 
@@ -66,7 +66,16 @@ namespace ERP.Core.Service
                 permissions = _sysMenuRepository.SelectPermissionsByRoleIds(roleIds);
             }
 
-            return new LoginUser(user, roleKeyList, permissions);
+            return new LoginUser()
+            {
+                UserId = user.Id,
+                UserName = user.UserName,
+                Avatar = user.Avatar,
+                Email = user.Email,
+                UserStatus = user.UserStatus,
+                RoleKeys = roleKeyList,
+                Permission = permissions
+            };
         }
 
         private void CheckUserStatus(SysUser user)

+ 1 - 1
ERP.Framework/Config/SecurityConfig.cs

@@ -25,7 +25,7 @@ namespace ERP.Framework.Config
         /// <summary>
         /// JWT 密匙
         /// </summary>
-        public string JwtSecurityKey { get; set; } = "ipl234567890KLmnbvcxz";
+        public string JwtSecurityKey { get; set; } = "ma8v4HqAEMOFTWY6sF013isL6wYiczX1Na5mTQLdB3bKXpyRhRSn3iStepOUSvmI";
 
         /// <summary>
         /// Token 对应的 Redis 存储时间(单位:分钟 ,默认1天)

+ 2 - 7
ERP.Framework/ERP.Framework.csproj

@@ -6,14 +6,8 @@
     <Nullable>enable</Nullable>
   </PropertyGroup>
 
-
-  <ItemGroup>
-    <FrameworkReference Include="Microsoft.AspNetCore.App" />
-  </ItemGroup>
-  
   <ItemGroup>
-    <Folder Include="Office\" />
-    <Folder Include="Validator\" />
+	<FrameworkReference Include="Microsoft.AspNetCore.App" />
   </ItemGroup>
 
   <ItemGroup>
@@ -31,6 +25,7 @@
     <PackageReference Include="Serilog.Extensions.Logging" Version="7.0.0" />
     <PackageReference Include="StackExchange.Redis" Version="2.6.122" />
     <PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
+    <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.6.2" />
     <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.6.3" />
     <PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
   </ItemGroup>

+ 85 - 0
ERP.Framework/Extensions/SwaggerExtension.cs

@@ -0,0 +1,85 @@
+// <author></author>
+// <date></date>
+// <description></description>
+
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.Annotations;
+using Swashbuckle.AspNetCore.SwaggerGen;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ERP.Framework.Extensions
+{
+    public static class SwaggerExtension
+    {
+        public static void AddSwagger(this IServiceCollection services)
+        {
+            services.AddSwaggerGen(options =>
+            {
+                // 设置 Swagger UI 的标题和版本 (描述,联系人,许可证)
+                options.SwaggerDoc("v1", new OpenApiInfo { Title = "ERP", Version = "v1" });
+                // 安全方案
+                //options.AddSecurityDefinition()
+                // 自定义逻辑
+                options.OperationFilter<SwaggerDescriptionFilter>();
+                options.OperationFilter<SwaggerSummaryFilter>();
+            });
+        }
+
+        private class PrefixDocumentFilter : IDocumentFilter
+        {
+            private readonly string _prefix;
+
+            public PrefixDocumentFilter(string prefix)
+            {
+                _prefix = prefix;
+            }
+
+            public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
+            {
+                var paths = new OpenApiPaths();
+
+                foreach (var path in swaggerDoc.Paths)
+                {
+                    paths.Add(_prefix + path.Key, path.Value);
+                }
+
+                swaggerDoc.Paths = paths;
+            }
+        }
+
+        private class SwaggerDescriptionFilter : IOperationFilter
+        {
+            public void Apply(OpenApiOperation operation, OperationFilterContext context)
+            {
+                var attribute = context.MethodInfo
+             .GetCustomAttributes(typeof(SwaggerOperationAttribute), false)
+             .FirstOrDefault() as SwaggerOperationAttribute;
+
+                if (attribute != null && !string.IsNullOrEmpty(attribute.Description))
+                {
+                    operation.Description = attribute.Description;
+                }
+            }
+        }
+
+        public class SwaggerSummaryFilter : IOperationFilter
+        {
+            public void Apply(OpenApiOperation operation, OperationFilterContext context)
+            {
+                var attribute = context.MethodInfo
+                    .GetCustomAttributes(typeof(SwaggerOperationAttribute), false)
+                    .FirstOrDefault() as SwaggerOperationAttribute;
+
+                if (attribute != null && !string.IsNullOrEmpty(attribute.Summary))
+                {
+                    operation.Summary = attribute.Summary;
+                }
+            }
+        }
+    }
+}

+ 0 - 21
ERP.Framework/Security/Core/JwtToken.cs

@@ -1,21 +0,0 @@
-namespace ERP.Framework.Security.Core
-{
-    public class JwtToken
-    {
-        public JwtToken(string token, int expire)
-        {
-            Token = token;
-            Expire = expire;
-        }
-
-        /// <summary>
-        /// Token 字符串
-        /// </summary>
-        public string Token { get; set; }
-
-        /// <summary>
-        /// Tokne 所对应的Redis失效时间
-        /// </summary>
-        public int Expire { get; set; }
-    }
-}

+ 3 - 18
ERP.Framework/Security/Core/LoginUser.cs

@@ -1,4 +1,5 @@
-using Newtonsoft.Json;
+using ERP.Framework.Enum;
+using Newtonsoft.Json;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -49,25 +50,9 @@ namespace ERP.Framework.Security.Core
         /// </summary>
         public string? Avatar { get; set; }
 
-        /// <summary>
+        /// <summary>w
         /// 邮箱
         /// </summary>
         public string? Email { get; set; } 
-
-
-        public LoginUser()
-        {
-        }
-
-        //public LoginUser(SysUser user, List<string> roleKeys, List<string> permission)
-        //{
-        //    this.UserId = user.Id;
-        //    this.UserName=user.UserName;
-        //    this.RoleKeys = roleKeys;
-        //    this.Permission = permission;
-        //    this.Avatar = user.Avatar;
-        //    this.Email = user.Email;
-        //    this.UserStatus = user.UserStatus;
-        //}
     }
 }

+ 29 - 20
ERP.Framework/Security/LoginHelper.cs

@@ -28,11 +28,10 @@ namespace ERP.Framework.Security
         /// <param name="device"></param>
         /// <param name="deviceKey"></param>
         /// <returns></returns>
-        public static JwtToken LoginByDevice(
+        public static string LoginByDevice(
             LoginUser userInfo
             , SecurityConfig securityConfig
-            , DeviceEnum device
-            , string deviceKey)
+            , DeviceEnum device)
         {
             string tokenId;
 
@@ -61,28 +60,38 @@ namespace ERP.Framework.Security
 
             SetUserInfo(tokenId, userInfo, securityConfig.TimeOut);
 
-            var result = new JwtToken(FrameworkConstant.TOKEN_PREFIX + " " + token, securityConfig.TimeOut);
+            var result = $"{FrameworkConstant.TOKEN_PREFIX} {token}";
 
             return result;
         }
 
-        //public static LoginUser GetLoginUser()
-        //{
-        //    var httpContextAccessor = new HttpContextAccessor();
-        //    var httpContext = httpContextAccessor.HttpContext;
-        //    var loginUser = httpContext!.Items["LoginUser"] as LoginUser;
+        public static LoginUser GetLoginUser()
+        {
+            var httpContextAccessor = new HttpContextAccessor();
+            var httpContext = httpContextAccessor.HttpContext;
+            var loginUser = httpContext!.Items["LoginUser"] as LoginUser;
+
+            if (loginUser != null)
+            {
+                return loginUser;
+            }
+
+            var tokenId = httpContext!.Items["TokenId"] as string;
+            var redisData = RedisHelper.Get(AuthConstant.USER_INFO + tokenId);
+            var result = JsonConvert.DeserializeObject<LoginUser>(redisData);
 
-        //    if (loginUser != null)
-        //    {
-        //        return loginUser;
-        //    }
+            if (result != null)
+            {
+                httpContext.Items["LoginUser"] = result;
 
-        //    var tokenId = httpContext!.Items["TokenId"] as string;
-        //    var redisData = RedisHelper.Get(AuthConstant.UserInfo + tokenId);
-        //    var result = JsonConvert.DeserializeObject<LoginUser>(redisData);
-        //    httpContext.Items["LoginUser"] = result;
-        //    return result;
-        //}
+                return result;
+            }
+            else
+            {
+                // Todo 抛出异常处理
+                throw new Exception("");
+            }
+        }
 
         /// <summary>
         /// 获取TokenList缓存
@@ -96,7 +105,7 @@ namespace ERP.Framework.Security
             if (!tokenListData.IsNullOrEmpty())
             {
                 var data = JsonConvert.DeserializeObject<List<TokenSign>>(tokenListData);
-                return data;`
+                return data;
             }
 
             return new List<TokenSign>();

+ 40 - 7
ERP.Framework/WebApi/BaseRepository.cs

@@ -1,11 +1,6 @@
 using Microsoft.EntityFrameworkCore;
-using System;
-using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
-using System.Linq;
 using System.Linq.Expressions;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace ERP.Framework.WebApi
 {
@@ -23,13 +18,25 @@ namespace ERP.Framework.WebApi
             return Filter(exp).FirstOrDefault();
         }
 
+        public Task<T?> FirstOrDefaultAsync(Expression<Func<T, bool>>? exp = null)
+        {
+            return Filter(exp).FirstOrDefaultAsync();
+        }
+
         public void Add(T entity)
         {
             Context.Set<T>().Add(entity);
             Save();
+            // EF不再跟踪实体更改
             Context.Entry(entity).State = EntityState.Detached;
         }
 
+        public async Task<bool> AddAsync(T entity)
+        {
+            await Context.Set<T>().AddAsync(entity);
+            return await TaskSave();
+        }
+
         public void Save()
         {
             try
@@ -53,13 +60,39 @@ namespace ERP.Framework.WebApi
                 //Console.WriteLine($"{nameof(Save)} validation exception: {exc?.Message}");
                 //throw (exc.InnerException as Exception ?? exc);
             }
-            catch (Exception ex) //DbUpdateException 
+            catch (Exception ex) //DbUpdateException
             {
                 // Todo 抛出异常
                 //throw (ex.InnerException as Exception ?? ex);
             }
         }
 
+        public Task<bool> TaskSave()
+        {
+            try
+            {
+                var entities = Context.ChangeTracker.Entries()
+                    .Where(e => e.State == EntityState.Added
+                                || e.State == EntityState.Modified)
+                    .Select(e => e.Entity);
+
+                foreach (var entity in entities)
+                {
+                    var validationContext = new ValidationContext(entity);
+                    Validator.ValidateObject(entity, validationContext, validateAllProperties: true);
+                }
+
+                var result = Context.SaveChanges();
+
+                return Task.FromResult(result > 0);
+            }
+            catch (Exception ex)
+            {
+                // Todo 打印日志
+                return Task.FromResult(false); ;
+            }
+        }
+
         private IQueryable<T> Filter(Expression<Func<T, bool>>? exp)
         {
             var dbSet = Context.Set<T>().AsNoTracking().AsQueryable();
@@ -68,4 +101,4 @@ namespace ERP.Framework.WebApi
             return dbSet;
         }
     }
-}
+}