diff --git a/src/AgileConfig.Server.Apisite/ConfigureJwtBearerOptions.cs b/src/AgileConfig.Server.Apisite/ConfigureJwtBearerOptions.cs index d28859b9..ad25cf0e 100644 --- a/src/AgileConfig.Server.Apisite/ConfigureJwtBearerOptions.cs +++ b/src/AgileConfig.Server.Apisite/ConfigureJwtBearerOptions.cs @@ -8,11 +8,11 @@ namespace AgileConfig.Server.Apisite; public class ConfigureJwtBearerOptions( IJwtService jwtService, - ISettingService settingService) : IConfigureNamedOptions + ISystemInitializationService systemInitializationService) : IConfigureNamedOptions { public void Configure(JwtBearerOptions options) { - settingService.TryInitJwtSecret(); + systemInitializationService.TryInitJwtSecret(); options.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = jwtService.Issuer, diff --git a/src/AgileConfig.Server.Apisite/Controllers/UserController.cs b/src/AgileConfig.Server.Apisite/Controllers/UserController.cs index 39a5129a..1d02d908 100644 --- a/src/AgileConfig.Server.Apisite/Controllers/UserController.cs +++ b/src/AgileConfig.Server.Apisite/Controllers/UserController.cs @@ -38,7 +38,7 @@ public async Task Search(string userName, string team, int curren } var users = await _userService.GetAll(); - users = users.Where(x => x.Status == UserStatus.Normal && x.Id != SettingService.SuperAdminId).ToList(); + users = users.Where(x => x.Status == UserStatus.Normal && x.Id != SystemSettings.SuperAdminId).ToList(); if (!string.IsNullOrEmpty(userName)) { users = users.Where(x => x.UserName != null && x.UserName.Contains(userName)).ToList(); @@ -264,7 +264,7 @@ public async Task adminUsers() public async Task AllUsers() { var users = await _userService.GetAll(); - users = users.Where(x => x.Status == UserStatus.Normal && x.Id != SettingService.SuperAdminId).ToList(); + users = users.Where(x => x.Status == UserStatus.Normal && x.Id != SystemSettings.SuperAdminId).ToList(); return Json(new { diff --git a/src/AgileConfig.Server.Common/SystemSettings.cs b/src/AgileConfig.Server.Common/SystemSettings.cs new file mode 100644 index 00000000..06e957c3 --- /dev/null +++ b/src/AgileConfig.Server.Common/SystemSettings.cs @@ -0,0 +1,11 @@ +namespace AgileConfig.Server.Common; + +public static class SystemSettings +{ + public const string SuperAdminId = "super_admin"; + public const string SuperAdminUserName = "admin"; + + public const string DefaultEnvironment = "DEV,TEST,STAGING,PROD"; + public const string DefaultEnvironmentKey = "environment"; + public const string DefaultJwtSecretKey = "jwtsecret"; +} \ No newline at end of file diff --git a/src/AgileConfig.Server.Data.Abstraction/ISysInitRepository.cs b/src/AgileConfig.Server.Data.Abstraction/ISysInitRepository.cs new file mode 100644 index 00000000..063e2b27 --- /dev/null +++ b/src/AgileConfig.Server.Data.Abstraction/ISysInitRepository.cs @@ -0,0 +1,18 @@ +using AgileConfig.Server.Data.Entity; + +namespace AgileConfig.Server.Data.Abstraction; + +public interface ISysInitRepository +{ + /// + /// get jwt token secret from db + /// + /// + string? GetJwtTokenSecret(); + + /// + /// save initialization setting + /// + /// + void SaveInitSetting(Setting setting); +} \ No newline at end of file diff --git a/src/AgileConfig.Server.Data.Mongodb/MongodbRepository.cs b/src/AgileConfig.Server.Data.Mongodb/MongodbRepository.cs index 39a796a3..6dea867a 100644 --- a/src/AgileConfig.Server.Data.Mongodb/MongodbRepository.cs +++ b/src/AgileConfig.Server.Data.Mongodb/MongodbRepository.cs @@ -36,11 +36,11 @@ public async Task> AllAsync() private Expression> GetIdPropertyFilter(TId id) { - var expression = _access.MongoQueryable.Where(x => Equals(x.Id, id)).Expression; - return Expression.Lambda>(expression); + Expression> expression = x => Equals(x.Id, id); + return expression; } - public async Task GetAsync(TId id) + public async Task GetAsync(TId id) { var filter = GetIdPropertyFilter(id); return await (await _access.Collection.FindAsync(filter)).SingleOrDefaultAsync(); diff --git a/src/AgileConfig.Server.Data.Repository.Freesql/ServiceCollectionExt.cs b/src/AgileConfig.Server.Data.Repository.Freesql/ServiceCollectionExt.cs index fa82ccd9..281ddbbe 100644 --- a/src/AgileConfig.Server.Data.Repository.Freesql/ServiceCollectionExt.cs +++ b/src/AgileConfig.Server.Data.Repository.Freesql/ServiceCollectionExt.cs @@ -23,6 +23,8 @@ public static void AddFreeSqlRepository(this IServiceCollection sc) sc.AddScoped(); sc.AddScoped(); sc.AddScoped(); + + sc.AddSingleton(); } } } diff --git a/src/AgileConfig.Server.Data.Repository.Freesql/SysInitRepository.cs b/src/AgileConfig.Server.Data.Repository.Freesql/SysInitRepository.cs new file mode 100644 index 00000000..3f8996f0 --- /dev/null +++ b/src/AgileConfig.Server.Data.Repository.Freesql/SysInitRepository.cs @@ -0,0 +1,21 @@ +using AgileConfig.Server.Common; +using AgileConfig.Server.Data.Abstraction; +using AgileConfig.Server.Data.Entity; +using AgileConfig.Server.Data.Freesql; + +namespace AgileConfig.Server.Data.Repository.Freesql; + +public class SysInitRepository : ISysInitRepository +{ + public string? GetJwtTokenSecret() + { + var setting = FreeSQL.Instance.Select().Where(x => x.Id == SystemSettings.DefaultJwtSecretKey) + .ToOne(); + return setting?.Value; + } + + public void SaveInitSetting(Setting setting) + { + FreeSQL.Instance.Insert(setting); + } +} \ No newline at end of file diff --git a/src/AgileConfig.Server.Data.Repository.Mongodb/MongodbRepositoryExt.cs b/src/AgileConfig.Server.Data.Repository.Mongodb/MongodbRepositoryExt.cs index 9bf89958..e9f341d7 100644 --- a/src/AgileConfig.Server.Data.Repository.Mongodb/MongodbRepositoryExt.cs +++ b/src/AgileConfig.Server.Data.Repository.Mongodb/MongodbRepositoryExt.cs @@ -17,5 +17,7 @@ public static void AddMongodbRepository(this IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); + + services.AddSingleton(); } } \ No newline at end of file diff --git a/src/AgileConfig.Server.Data.Repository.Mongodb/SysInitRepository.cs b/src/AgileConfig.Server.Data.Repository.Mongodb/SysInitRepository.cs new file mode 100644 index 00000000..05f676f2 --- /dev/null +++ b/src/AgileConfig.Server.Data.Repository.Mongodb/SysInitRepository.cs @@ -0,0 +1,19 @@ +using AgileConfig.Server.Common; + +namespace AgileConfig.Server.Data.Repository.Mongodb; + +public class SysInitRepository : ISysInitRepository +{ + private readonly MongodbAccess _access = new(Global.Config["db:conn"]); + + public string? GetJwtTokenSecret() + { + var setting = _access.MongoQueryable.FirstOrDefault(x => x.Id == SystemSettings.DefaultJwtSecretKey); + return setting?.Value; + } + + public void SaveInitSetting(Setting setting) + { + _access.Collection.InsertOne(setting); + } +} \ No newline at end of file diff --git a/src/AgileConfig.Server.IService/ISettingService.cs b/src/AgileConfig.Server.IService/ISettingService.cs index c81bc7e3..a0ed09b6 100644 --- a/src/AgileConfig.Server.IService/ISettingService.cs +++ b/src/AgileConfig.Server.IService/ISettingService.cs @@ -46,17 +46,5 @@ public interface ISettingService: IDisposable /// /// Task GetEnvironmentList(); - - /// - /// 如果环境变量没有 JwtSetting:SecurityKey 则尝试生成一个key到数据库 - /// - /// - bool TryInitJwtSecret(); - - /// - /// 从配置表获取 jwt secret key - /// - /// - string GetJwtTokenSecret(); } } diff --git a/src/AgileConfig.Server.IService/ISystemInitializationService.cs b/src/AgileConfig.Server.IService/ISystemInitializationService.cs new file mode 100644 index 00000000..c76b240a --- /dev/null +++ b/src/AgileConfig.Server.IService/ISystemInitializationService.cs @@ -0,0 +1,6 @@ +namespace AgileConfig.Server.IService; + +public interface ISystemInitializationService +{ + bool TryInitJwtSecret(); +} \ No newline at end of file diff --git a/src/AgileConfig.Server.Service/JwtService.cs b/src/AgileConfig.Server.Service/JwtService.cs index a1252529..f903356e 100644 --- a/src/AgileConfig.Server.Service/JwtService.cs +++ b/src/AgileConfig.Server.Service/JwtService.cs @@ -3,6 +3,7 @@ using System.Security.Claims; using System.Text; using AgileConfig.Server.Common; +using AgileConfig.Server.Data.Abstraction; using AgileConfig.Server.IService; using Microsoft.IdentityModel.Tokens; @@ -11,9 +12,8 @@ namespace AgileConfig.Server.Service; /// /// jwt 相关业务 /// -public class JwtService : IJwtService +public class JwtService(ISysInitRepository sysInitRepository) : IJwtService { - private readonly ISettingService _settingService; // static JwtService() // { // // 则尝试生成一个key到数据库 @@ -21,11 +21,6 @@ public class JwtService : IJwtService // settingService.TryInitJwtSecret(); // } - public JwtService(ISettingService settingService) - { - _settingService = settingService; - } - public string Issuer => Global.Config["JwtSetting:Issuer"]; public string Audience => Global.Config["JwtSetting:Audience"]; public int ExpireSeconds => int.Parse(Global.Config["JwtSetting:ExpireSeconds"]); @@ -45,7 +40,7 @@ public string GetSecurityKey() } //using var settingService = new SettingService(new FreeSqlContext(FreeSQL.Instance)); - _secretKey = _settingService.GetJwtTokenSecret(); + _secretKey = sysInitRepository.GetJwtTokenSecret(); if (string.IsNullOrEmpty(_secretKey)) { diff --git a/src/AgileConfig.Server.Service/ServiceCollectionExt.cs b/src/AgileConfig.Server.Service/ServiceCollectionExt.cs index e3e5ee95..258497b0 100644 --- a/src/AgileConfig.Server.Service/ServiceCollectionExt.cs +++ b/src/AgileConfig.Server.Service/ServiceCollectionExt.cs @@ -14,6 +14,7 @@ public static class ServiceCollectionExt { public static void AddBusinessServices(this IServiceCollection sc) { + sc.AddSingleton(); sc.AddSingleton(); sc.AddScoped(); @@ -46,11 +47,11 @@ public static void AddBusinessServices(this IServiceCollection sc) }; }); - sc.AddTransient,EventRegisterTransient>(); - sc.AddTransient,EventRegisterTransient>(); - sc.AddTransient,EventRegisterTransient>(); - sc.AddTransient,EventRegisterTransient>(); - sc.AddTransient,EventRegisterTransient>(); + sc.AddTransient>(x => x.GetService); + sc.AddTransient>(x => x.GetService); + sc.AddTransient>(x => x.GetService); + sc.AddTransient>(x => x.GetService); + sc.AddTransient>(x => x.GetService); } } } diff --git a/src/AgileConfig.Server.Service/SettingService.cs b/src/AgileConfig.Server.Service/SettingService.cs index e0bb9fe0..f616aae2 100644 --- a/src/AgileConfig.Server.Service/SettingService.cs +++ b/src/AgileConfig.Server.Service/SettingService.cs @@ -14,13 +14,6 @@ public class SettingService : ISettingService private readonly IUserRepository _userRepository; private readonly IUserRoleRepository _userRoleRepository; - public const string SuperAdminId = "super_admin"; - public const string SuperAdminUserName = "admin"; - - public const string DefaultEnvironment = "DEV,TEST,STAGING,PROD"; - public const string DefaultEnvironmentKey = "environment"; - public const string DefaultJwtSecretKey = "jwtsecret"; - public SettingService( ISettingRepository settingRepository, IUserRepository userRepository, @@ -84,13 +77,13 @@ public async Task SetSuperAdminPassword(string password) password = Encrypt.Md5((password + newSalt)); var su = new User(); - su.Id = SuperAdminId; + su.Id = SystemSettings.SuperAdminId; su.Password = password; su.Salt = newSalt; su.Status = UserStatus.Normal; su.Team = ""; su.CreateTime = DateTime.Now; - su.UserName = SuperAdminUserName; + su.UserName = SystemSettings.SuperAdminUserName; await _userRepository.InsertAsync(su); var userRoles = new List(); @@ -98,14 +91,14 @@ public async Task SetSuperAdminPassword(string password) { Id = Guid.NewGuid().ToString("N"), Role = Role.SuperAdmin, - UserId = SuperAdminId + UserId = SystemSettings.SuperAdminId }; userRoles.Add(ursa); var ura = new UserRole() { Id = Guid.NewGuid().ToString("N"), Role = Role.Admin, - UserId = SuperAdminId + UserId = SystemSettings.SuperAdminId }; userRoles.Add(ura); @@ -116,20 +109,20 @@ public async Task SetSuperAdminPassword(string password) public async Task HasSuperAdmin() { - var admin = await _userRepository.GetAsync(SuperAdminId); + var admin = await _userRepository.GetAsync(SystemSettings.SuperAdminId); return admin != null; } public async Task InitDefaultEnvironment() { - var env = await _settingRepository.GetAsync(DefaultEnvironmentKey); + var env = await _settingRepository.GetAsync(SystemSettings.DefaultEnvironmentKey); if (env == null) { var setting = new Setting { - Id = DefaultEnvironmentKey, - Value = DefaultEnvironment, + Id = SystemSettings.DefaultEnvironmentKey, + Value = SystemSettings.DefaultEnvironment, CreateTime = DateTime.Now }; await _settingRepository.InsertAsync(setting); @@ -149,63 +142,9 @@ public void Dispose() public async Task GetEnvironmentList() { - var env = await _settingRepository.GetAsync(DefaultEnvironmentKey); + var env = await _settingRepository.GetAsync(SystemSettings.DefaultEnvironmentKey); return env?.Value?.ToUpper().Split(',') ?? []; } - - /// - /// 如果 配置文件或者环境变量没配置 JwtSetting:SecurityKey 则生成一个存库 - /// - /// - public bool TryInitJwtSecret() - { - var jwtSecretFromConfig = Global.Config["JwtSetting:SecurityKey"]; - if (string.IsNullOrEmpty(jwtSecretFromConfig)) - { - var jwtSecretSetting = _settingRepository.GetAsync(DefaultEnvironmentKey).Result; - if (jwtSecretSetting == null) - { - var setting = new Setting - { - Id = DefaultJwtSecretKey, - Value = GenreateJwtSecretKey(), - CreateTime = DateTime.Now - }; - - try - { - _ = _settingRepository.InsertAsync(setting).Result; - return true; - } - catch (Exception e) - { - //处理异常,防止多个实例第一次启动的时候,并发生成key值,发生异常,导致服务起不来 - Console.WriteLine(e); - } - - return false; - } - } - return true; - } - - public string GetJwtTokenSecret() - { - var jwtSecretSetting = _settingRepository.GetAsync(DefaultEnvironmentKey).Result; - return jwtSecretSetting?.Value; - } - - /// - /// 生成一个 jwt 加密的 key ,38位 - /// - /// - private string GenreateJwtSecretKey() - { - var guid1 = Guid.NewGuid().ToString("n"); - var guid2 = Guid.NewGuid().ToString("n"); - - return guid1.Substring(0, 19) + guid2.Substring(0, 19); - } } } diff --git a/src/AgileConfig.Server.Service/SystemInitializationService.cs b/src/AgileConfig.Server.Service/SystemInitializationService.cs new file mode 100644 index 00000000..78c8646a --- /dev/null +++ b/src/AgileConfig.Server.Service/SystemInitializationService.cs @@ -0,0 +1,59 @@ +using System; +using AgileConfig.Server.Common; +using AgileConfig.Server.Data.Abstraction; +using AgileConfig.Server.Data.Entity; +using AgileConfig.Server.IService; + +namespace AgileConfig.Server.Service; + +public class SystemInitializationService(ISysInitRepository sysInitRepository):ISystemInitializationService +{ + /// + /// 如果 配置文件或者环境变量没配置 JwtSetting:SecurityKey 则生成一个存库 + /// + /// + public bool TryInitJwtSecret() + { + var jwtSecretFromConfig = Global.Config["JwtSetting:SecurityKey"]; + if (string.IsNullOrEmpty(jwtSecretFromConfig)) + { + var jwtSecretSetting = sysInitRepository.GetJwtTokenSecret(); + if (jwtSecretSetting == null) + { + var setting = new Setting + { + Id = SystemSettings.DefaultJwtSecretKey, + Value = GenerateJwtSecretKey(), + CreateTime = DateTime.Now + }; + + try + { + sysInitRepository.SaveInitSetting(setting); + return true; + } + catch (Exception e) + { + //处理异常,防止多个实例第一次启动的时候,并发生成key值,发生异常,导致服务起不来 + Console.WriteLine(e); + } + + return false; + } + } + + return true; + } + + /// + /// 生成一个 jwt 加密的 key ,38位 + /// + /// + private static string GenerateJwtSecretKey() + { + var guid1 = Guid.NewGuid().ToString("n"); + var guid2 = Guid.NewGuid().ToString("n"); + + return guid1[..19] + guid2[..19]; + } +} \ No newline at end of file diff --git a/test/AgileConfig.Server.ServiceTests/mysql/SettingServiceTests.cs b/test/AgileConfig.Server.ServiceTests/mysql/SettingServiceTests.cs index 1886f35f..a73453f9 100644 --- a/test/AgileConfig.Server.ServiceTests/mysql/SettingServiceTests.cs +++ b/test/AgileConfig.Server.ServiceTests/mysql/SettingServiceTests.cs @@ -8,6 +8,7 @@ using AgileConfig.Server.Data.Entity; using System.Threading.Tasks; using System.Linq; +using AgileConfig.Server.Common; using AgileConfig.Server.IService; using Microsoft.Extensions.DependencyInjection; @@ -193,9 +194,9 @@ public async Task SetAdminPasswordTest() Assert.IsNotNull(list); Assert.AreEqual(2, list.Count); - var pass = list.FirstOrDefault(s => s.Id == SettingService.SuperAdminUserName); + var pass = list.FirstOrDefault(s => s.Id == SystemSettings.SuperAdminUserName); Assert.IsNotNull(pass); - var salt = list.FirstOrDefault(s => s.Id == SettingService.SuperAdminId); + var salt = list.FirstOrDefault(s => s.Id == SystemSettings.SuperAdminId); Assert.IsNotNull(salt); }