diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDataSeeder.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDataSeeder.cs new file mode 100644 index 000000000..a94e9bc6d --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDataSeeder.cs @@ -0,0 +1,59 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; + +namespace LINGYUN.Abp.MicroService.AdminService; +public class AdminServiceDataSeeder : ITransientDependency +{ + protected ILogger Logger { get; } + protected ICurrentTenant CurrentTenant { get; } + protected IPermissionDefinitionManager PermissionDefinitionManager { get; } + protected IPermissionDataSeeder PermissionDataSeeder { get; } + + public AdminServiceDataSeeder( + IPermissionDefinitionManager permissionDefinitionManager, + IPermissionDataSeeder permissionDataSeeder, + ICurrentTenant currentTenant) + { + PermissionDefinitionManager = permissionDefinitionManager; + PermissionDataSeeder = permissionDataSeeder; + CurrentTenant = currentTenant; + + Logger = NullLogger.Instance; + } + + public virtual async Task SeedAsync(DataSeedContext context) + { + using (CurrentTenant.Change(context.TenantId)) + { + await SeedAdminRolePermissionsAsync(context); + } + } + + private async Task SeedAdminRolePermissionsAsync(DataSeedContext context) + { + Logger.LogInformation("Seeding the default role permissions..."); + + var multiTenancySide = CurrentTenant.GetMultiTenancySide(); + var permissionNames = (await PermissionDefinitionManager.GetPermissionsAsync()) + .Where(p => p.MultiTenancySide.HasFlag(multiTenancySide)) + .Where(p => !p.Providers.Any() || p.Providers.Contains(RolePermissionValueProvider.ProviderName)) + .Select(p => p.Name) + .ToArray(); + + await PermissionDataSeeder.SeedAsync( + RolePermissionValueProvider.ProviderName, + "admin", + permissionNames, + context?.TenantId + ); + + Logger.LogInformation("Seed default role permissions completed."); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationEventHandler.cs index 21dde6a90..b69f18362 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationEventHandler.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationEventHandler.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.Logging; -using System; using System.Threading.Tasks; using Volo.Abp.Data; using Volo.Abp.DistributedLocking; @@ -11,7 +10,7 @@ using Volo.Abp.Uow; namespace LINGYUN.Abp.MicroService.AdminService; public class AdminServiceDbMigrationEventHandler : EfCoreDatabaseMigrationEventHandlerBase { - protected IDataSeeder DataSeeder { get; } + protected AdminServiceDataSeeder DataSeeder { get; } public AdminServiceDbMigrationEventHandler( ICurrentTenant currentTenant, @@ -20,7 +19,7 @@ public class AdminServiceDbMigrationEventHandler : EfCoreDatabaseMigrationEventH IAbpDistributedLock abpDistributedLock, IDistributedEventBus distributedEventBus, ILoggerFactory loggerFactory, - IDataSeeder dataSeeder) + AdminServiceDataSeeder dataSeeder) : base( ConnectionStringNameAttribute.GetConnStringName(), currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory) @@ -28,8 +27,18 @@ public class AdminServiceDbMigrationEventHandler : EfCoreDatabaseMigrationEventH DataSeeder = dataSeeder; } - protected async override Task SeedAsync(Guid? tenantId) + protected async override Task AfterTenantCreated(TenantCreatedEto eventData, bool schemaMigrated) { - await DataSeeder.SeedAsync(tenantId); + // 新租户数据种子 + var context = new DataSeedContext(eventData.Id); + if (eventData.Properties != null) + { + foreach (var property in eventData.Properties) + { + context.WithProperty(property.Key, property.Value); + } + } + + await DataSeeder.SeedAsync(context); } } diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationService.cs index 57aef9200..d8d39b780 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationService.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDbMigrationService.cs @@ -1,6 +1,7 @@ using LINGYUN.Abp.Data.DbMigrator; using Microsoft.Extensions.Logging; using System; +using System.Threading.Tasks; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.DistributedLocking; @@ -11,16 +12,25 @@ using Volo.Abp.Uow; namespace LINGYUN.Abp.MicroService.AdminService; public class AdminServiceDbMigrationService : EfCoreRuntimeDbMigratorBase, ITransientDependency { + protected AdminServiceDataSeeder DataSeeder { get; } public AdminServiceDbMigrationService( ICurrentTenant currentTenant, IUnitOfWorkManager unitOfWorkManager, IServiceProvider serviceProvider, IAbpDistributedLock abpDistributedLock, IDistributedEventBus distributedEventBus, - ILoggerFactory loggerFactory) + ILoggerFactory loggerFactory, + AdminServiceDataSeeder dataSeeder) : base( ConnectionStringNameAttribute.GetConnStringName(), unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory) { + DataSeeder = dataSeeder; + } + + protected async override Task SeedAsync() + { + // DbMigrator迁移数据种子 + await DataSeeder.SeedAsync(new DataSeedContext()); } } diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/AdminServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/AdminServiceModule.cs index aeb3b50fb..1a615061e 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/AdminServiceModule.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/AdminServiceModule.cs @@ -36,13 +36,11 @@ using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy; using Volo.Abp.AspNetCore.Serilog; using Volo.Abp.Autofac; using Volo.Abp.Caching.StackExchangeRedis; -using Volo.Abp.Data; using Volo.Abp.Http.Client; using Volo.Abp.Modularity; using Volo.Abp.PermissionManagement.Identity; using Volo.Abp.PermissionManagement.OpenIddict; using Volo.Abp.Swashbuckle; -using Volo.Abp.Threading; namespace LINGYUN.Abp.MicroService.AdminService; @@ -143,15 +141,4 @@ public partial class AdminServiceModule : AbpModule ConfigureDistributedLocking(context.Services, configuration); ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); } - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - AsyncHelper.RunSync(() => OnApplicationInitializationAsync(context)); - } - - public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context) - { - await context.ServiceProvider - .GetRequiredService() - .SeedAsync(); - } } diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/appsettings.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/appsettings.json index 38212c579..6a90cf896 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/appsettings.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.DbMigrator/appsettings.json @@ -1,5 +1,34 @@ { "ConnectionStrings": { "Default": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" + }, + "OpenIddict": { + "Applications": { + "VueAdmin": { + "ClientId": "vue-admin-client", + "ClientSecret": "1q2w3e*", + "RootUrls": [ "http://localhost:5666" ] + }, + "InternalService": { + "ClientId": "InternalServiceClient", + "ClientSecret": "1q2w3e*" + }, + "VueOAuthClient": { + "ClientId": "vue-oauth-client", + "RootUrls": [ + "http://localhost:5666", + "http://localhost:30000", + "http://localhost:30010", + "http://localhost:30015", + "http://localhost:30020", + "http://localhost:30025", + "http://localhost:30030", + "http://localhost:30040", + "http://localhost:30045", + "http://localhost:30050", + "http://localhost:30060" + ] + } + } } } diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDataSeeder.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDataSeeder.cs new file mode 100644 index 000000000..af93b66f7 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDataSeeder.cs @@ -0,0 +1,35 @@ +using LINGYUN.Abp.MicroService.AuthServer.DataSeeds; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.AuthServer; +public class AuthServerDataSeeder : ITransientDependency +{ + protected ICurrentTenant CurrentTenant { get; } + protected OpenIddictDataSeeder OpenIddictDataSeeder { get; } + protected IdentityClaimTypeDataSeeder IdentityClaimTypeDataSeeder { get; } + protected IdentityUserRoleDataSeeder IdentityUserRoleDataSeeder { get; } + public AuthServerDataSeeder( + ICurrentTenant currentTenant, + OpenIddictDataSeeder openIddictDataSeeder, + IdentityClaimTypeDataSeeder identityClaimTypeDataSeeder, + IdentityUserRoleDataSeeder identityUserRoleDataSeeder) + { + CurrentTenant = currentTenant; + OpenIddictDataSeeder = openIddictDataSeeder; + IdentityClaimTypeDataSeeder = identityClaimTypeDataSeeder; + IdentityUserRoleDataSeeder = identityUserRoleDataSeeder; + } + + public virtual async Task SeedAsync(DataSeedContext context) + { + using (CurrentTenant.Change(context.TenantId)) + { + await OpenIddictDataSeeder.SeedAsync(context); + await IdentityClaimTypeDataSeeder.SeedAsync(context); + await IdentityUserRoleDataSeeder.SeedAsync(context); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationEventHandler.cs index 249ddefb4..23be757a1 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationEventHandler.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationEventHandler.cs @@ -1,28 +1,17 @@ -using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; +using Microsoft.Extensions.Logging; using System.Threading.Tasks; -using Volo.Abp.Authorization.Permissions; using Volo.Abp.Data; using Volo.Abp.DistributedLocking; using Volo.Abp.EntityFrameworkCore.Migrations; using Volo.Abp.EventBus.Distributed; -using Volo.Abp.Guids; -using Volo.Abp.Identity; using Volo.Abp.MultiTenancy; -using Volo.Abp.PermissionManagement; using Volo.Abp.Uow; -using IdentityPermissions = Volo.Abp.Identity.IdentityPermissions; namespace LINGYUN.Abp.MicroService.AuthServer; public class AuthServerDbMigrationEventHandler : EfCoreDatabaseMigrationEventHandlerBase { - protected IGuidGenerator GuidGenerator { get; } - protected IdentityUserManager IdentityUserManager { get; } - protected IdentityRoleManager IdentityRoleManager { get; } - protected IPermissionDataSeeder PermissionDataSeeder { get; } + protected AuthServerDataSeeder DataSeeder { get; } public AuthServerDbMigrationEventHandler( ICurrentTenant currentTenant, @@ -31,102 +20,26 @@ public class AuthServerDbMigrationEventHandler : EfCoreDatabaseMigrationEventHan IAbpDistributedLock abpDistributedLock, IDistributedEventBus distributedEventBus, ILoggerFactory loggerFactory, - IGuidGenerator guidGenerator, - IdentityUserManager identityUserManager, - IdentityRoleManager identityRoleManager, - IPermissionDataSeeder permissionDataSeeder) + AuthServerDataSeeder dataSeeder) : base( ConnectionStringNameAttribute.GetConnStringName(), currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory) { - GuidGenerator = guidGenerator; - IdentityUserManager = identityUserManager; - IdentityRoleManager = identityRoleManager; - PermissionDataSeeder = permissionDataSeeder; + DataSeeder = dataSeeder; } protected async override Task AfterTenantCreated(TenantCreatedEto eventData, bool schemaMigrated) { - if (!schemaMigrated) + // 新租户数据种子 + var context = new DataSeedContext(eventData.Id); + if (eventData.Properties != null) { - return; - } - - using (CurrentTenant.Change(eventData.Id)) - { - await SeedTenantDefaultRoleAsync(eventData); - await SeedTenantAdminAsync(eventData); - } - } - - protected async virtual Task SeedTenantDefaultRoleAsync(TenantCreatedEto eventData) - { - // 默认用户 - var roleId = GuidGenerator.Create(); - var defaultRole = new IdentityRole(roleId, "Users", eventData.Id) - { - IsStatic = true, - IsPublic = true, - IsDefault = true, - }; - (await IdentityRoleManager.CreateAsync(defaultRole)).CheckErrors(); - - // 所有用户都应该具有查询用户权限, 用于IM场景 - await PermissionDataSeeder.SeedAsync( - RolePermissionValueProvider.ProviderName, - defaultRole.Name, - new string[] + foreach (var property in eventData.Properties ) { - IdentityPermissions.UserLookup.Default, - IdentityPermissions.Users.Default - }, - tenantId: eventData.Id); - } - - protected async virtual Task SeedTenantAdminAsync(TenantCreatedEto eventData) - { - const string tenantAdminUserName = "admin"; - const string tenantAdminRoleName = "admin"; - Guid tenantAdminRoleId; - if (!await IdentityRoleManager.RoleExistsAsync(tenantAdminRoleName)) - { - tenantAdminRoleId = GuidGenerator.Create(); - var tenantAdminRole = new IdentityRole(tenantAdminRoleId, tenantAdminRoleName, eventData.Id) - { - IsStatic = true, - IsPublic = true - }; - (await IdentityRoleManager.CreateAsync(tenantAdminRole)).CheckErrors(); - } - else - { - var tenantAdminRole = await IdentityRoleManager.FindByNameAsync(tenantAdminRoleName); - tenantAdminRoleId = tenantAdminRole.Id; + context.WithProperty(property.Key, property.Value); + } } - var adminUserId = GuidGenerator.Create(); - if (eventData.Properties.TryGetValue("AdminUserId", out var userIdString) && - Guid.TryParse(userIdString, out var adminUserGuid)) - { - adminUserId = adminUserGuid; - } - var adminEmailAddress = eventData.Properties.GetOrDefault("AdminEmail") ?? "admin@abp.io"; - var adminPassword = eventData.Properties.GetOrDefault("AdminPassword") ?? "1q2w3E*"; - - var tenantAdminUser = await IdentityUserManager.FindByNameAsync(adminEmailAddress); - if (tenantAdminUser == null) - { - tenantAdminUser = new IdentityUser( - adminUserId, - tenantAdminUserName, - adminEmailAddress, - eventData.Id); - - tenantAdminUser.AddRole(tenantAdminRoleId); - - // 创建租户管理用户 - (await IdentityUserManager.CreateAsync(tenantAdminUser)).CheckErrors(); - (await IdentityUserManager.AddPasswordAsync(tenantAdminUser, adminPassword)).CheckErrors(); - } + await DataSeeder.SeedAsync(context); } } diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationService.cs index f7ff2434d..ee1b6fd92 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationService.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/AuthServerDbMigrationService.cs @@ -2,6 +2,7 @@ using LINGYUN.Abp.Saas.Tenants; using Microsoft.Extensions.Logging; using System; +using System.Threading.Tasks; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.DistributedLocking; @@ -13,8 +14,8 @@ namespace LINGYUN.Abp.MicroService.AuthServer; public class AuthServerDbMigrationService : EfCoreRuntimeDbMigratorBase, ITransientDependency { + protected AuthServerDataSeeder DataSeeder { get; } public AuthServerDbMigrationService( - IDataSeeder dataSeeder, IDbSchemaMigrator dbSchemaMigrator, ITenantRepository tenantRepository, ICurrentTenant currentTenant, @@ -22,10 +23,18 @@ public class AuthServerDbMigrationService : EfCoreRuntimeDbMigratorBase(), unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory) { + DataSeeder = dataSeeder; + } + + protected async override Task SeedAsync() + { + // DbMigrator迁移数据种子 + await DataSeeder.SeedAsync(new DataSeedContext()); } } \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/IdentityClaimTypeDataSeeder.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/IdentityClaimTypeDataSeeder.cs new file mode 100644 index 000000000..a28332885 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/IdentityClaimTypeDataSeeder.cs @@ -0,0 +1,89 @@ +using JetBrains.Annotations; +using Microsoft.Extensions.Logging; +using OpenIddict.Abstractions; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using Volo.Abp.Identity; + +namespace LINGYUN.Abp.MicroService.AuthServer.DataSeeds; +public class IdentityClaimTypeDataSeeder : ITransientDependency +{ + public ILogger Logger { protected get; set; } + + protected IGuidGenerator GuidGenerator { get; } + protected IdentityClaimTypeManager IdentityClaimTypeManager { get; } + protected IIdentityClaimTypeRepository IdentityClaimTypeRepository { get; } + public IdentityClaimTypeDataSeeder( + IGuidGenerator guidGenerator, + IdentityClaimTypeManager identityClaimTypeManager, + IIdentityClaimTypeRepository identityClaimTypeRepository) + { + GuidGenerator = guidGenerator; + IdentityClaimTypeManager = identityClaimTypeManager; + IdentityClaimTypeRepository = identityClaimTypeRepository; + } + + public async virtual Task SeedAsync(DataSeedContext context) + { + if (context.TenantId.HasValue) + { + return; + } + + Logger.LogInformation("Seeding the default identity claim types..."); + + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Address); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Birthdate, valueType: IdentityClaimValueType.DateTime); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Country); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Email); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.EmailVerified, valueType: IdentityClaimValueType.Boolean); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.FamilyName); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Gender); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.GivenName); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Locale); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Locality); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.MiddleName); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Name); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Nickname); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.PhoneNumber); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.PhoneNumberVerified, valueType: IdentityClaimValueType.Boolean); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Picture); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.PostalCode); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.PreferredUsername); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Profile); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Region); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Role); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.StreetAddress); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Username); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Website); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Zoneinfo); + + Logger.LogInformation("Seeding default identity claim types completed."); + } + + private async Task CreateIdentityClaimTypeAsync( + [NotNull] string name, + bool required = false, + bool isStatic = false, + [CanBeNull] string regex = null, + [CanBeNull] string regexDescription = null, + [CanBeNull] string description = null, + IdentityClaimValueType valueType = IdentityClaimValueType.String) + { + if (!await IdentityClaimTypeRepository.AnyAsync(name)) + { + await IdentityClaimTypeManager.CreateAsync( + new IdentityClaimType( + GuidGenerator.Create(), + name, + required, + isStatic, + regex, + regexDescription, + description, + valueType)); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/IdentityUserRoleDataSeeder.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/IdentityUserRoleDataSeeder.cs new file mode 100644 index 000000000..02f716a52 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/IdentityUserRoleDataSeeder.cs @@ -0,0 +1,124 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; +using System; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using Volo.Abp.Identity; + +namespace LINGYUN.Abp.MicroService.AuthServer.DataSeeds; +public class IdentityUserRoleDataSeeder : ITransientDependency +{ + public const string AdminUserIdPropertyName = "AdminUserId"; + public const string AdminEmailPropertyName = "AdminEmail"; + public const string AdminEmailDefaultValue = "admin@abp.io"; + public const string AdminUserNamePropertyName = "AdminUserName"; + public const string AdminUserNameDefaultValue = "admin"; + public const string AdminPasswordPropertyName = "AdminPassword"; + public const string AdminPasswordDefaultValue = "1q2w3E*"; + + protected IGuidGenerator GuidGenerator { get; } + protected IIdentityRoleRepository RoleRepository { get; } + protected IIdentityUserRepository UserRepository { get; } + protected ILookupNormalizer LookupNormalizer { get; } + protected IdentityUserManager UserManager { get; } + protected IdentityRoleManager RoleManager { get; } + protected IOptions IdentityOptions { get; } + + public IdentityUserRoleDataSeeder( + IGuidGenerator guidGenerator, + IIdentityRoleRepository roleRepository, + IIdentityUserRepository userRepository, + ILookupNormalizer lookupNormalizer, + IdentityUserManager userManager, + IdentityRoleManager roleManager, + IOptions identityOptions) + { + GuidGenerator = guidGenerator; + RoleRepository = roleRepository; + UserRepository = userRepository; + LookupNormalizer = lookupNormalizer; + UserManager = userManager; + RoleManager = roleManager; + IdentityOptions = identityOptions; + } + + public virtual async Task SeedAsync(DataSeedContext context) + { + await SeedAdminUserAsync(context); + await SeedDefaultRoleAsync(context); + } + + private async Task SeedAdminUserAsync(DataSeedContext context) + { + await IdentityOptions.SetAsync(); + + const string adminRoleName = "admin"; + var adminUserName = context?[AdminUserNamePropertyName] as string ?? AdminUserNameDefaultValue; + + Guid adminRoleId; + if (!await RoleManager.RoleExistsAsync(adminRoleName)) + { + adminRoleId = GuidGenerator.Create(); + var adminRole = new IdentityRole( + adminRoleId, + adminRoleName, + context.TenantId) + { + IsStatic = true, + IsPublic = true + }; + (await RoleManager.CreateAsync(adminRole)).CheckErrors(); + } + else + { + var adminRole = await RoleManager.FindByNameAsync(adminRoleName); + adminRoleId = adminRole.Id; + } + + var adminUserId = GuidGenerator.Create(); + if (context.Properties.TryGetValue(AdminUserIdPropertyName, out var userIdString) && + Guid.TryParse(userIdString?.ToString(), out var adminUserGuid)) + { + adminUserId = adminUserGuid; + } + var adminEmailAddress = context?[AdminEmailPropertyName] as string ?? AdminEmailDefaultValue; + var adminPassword = context?[AdminPasswordPropertyName] as string ?? AdminPasswordDefaultValue; + + var adminUser = await UserManager.FindByNameAsync(adminUserName); + if (adminUser == null) + { + adminUser = new IdentityUser( + adminUserId, + adminUserName, + adminEmailAddress, + context.TenantId); + + adminUser.AddRole(adminRoleId); + + // 创建租户管理用户 + (await UserManager.CreateAsync(adminUser)).CheckErrors(); + (await UserManager.AddPasswordAsync(adminUser, adminPassword)).CheckErrors(); + } + } + + private async Task SeedDefaultRoleAsync(DataSeedContext context) + { + const string defaultRoleName = "Users"; + if (await RoleManager.FindByNameAsync(defaultRoleName) != null) + { + var roleId = GuidGenerator.Create(); + var defaultRole = new IdentityRole( + roleId, + defaultRoleName, + context.TenantId) + { + IsStatic = true, + IsPublic = true, + IsDefault = true, + }; + (await RoleManager.CreateAsync(defaultRole)).CheckErrors(); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/DataSeeder/OpenIddictDataSeederContributor.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/OpenIddictDataSeeder.cs similarity index 58% rename from aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/DataSeeder/OpenIddictDataSeederContributor.cs rename to aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/OpenIddictDataSeeder.cs index 73efc634f..b3722a46d 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/DataSeeder/OpenIddictDataSeederContributor.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/OpenIddictDataSeeder.cs @@ -14,13 +14,12 @@ using Volo.Abp.OpenIddict.Applications; using Volo.Abp.OpenIddict.Scopes; using Volo.Abp.PermissionManagement; -namespace LINGYUN.Abp.MicroService.AuthServer.DataSeeder; - -public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase, IDataSeedContributor, ITransientDependency +namespace LINGYUN.Abp.MicroService.AuthServer.DataSeeds; +public class OpenIddictDataSeeder : OpenIddictDataSeedContributorBase, ITransientDependency { - public ILogger Logger { protected get; set; } + public ILogger Logger { protected get; set; } protected IPermissionDataSeeder PermissionDataSeeder { get; } - public OpenIddictDataSeederContributor( + public OpenIddictDataSeeder( IConfiguration configuration, IOpenIddictApplicationRepository openIddictApplicationRepository, IAbpApplicationManager applicationManager, @@ -31,7 +30,7 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase { PermissionDataSeeder = permissionDataSeeder; - Logger = NullLogger.Instance; + Logger = NullLogger.Instance; } public async virtual Task SeedAsync(DataSeedContext context) @@ -54,17 +53,17 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase private async Task CreateDefaultScopeAsync() { - // OpenID Connect核心scope - 用于标识这是一个OIDC请求 + // OpenId Connect await CreateScopesAsync(new OpenIddictScopeDescriptor { Name = OpenIddictConstants.Scopes.OpenId, - DisplayName = "OpenID Connect", // 友好的显示名称 + DisplayName = "OpenId Connect", DisplayNames = { [CultureInfo.GetCultureInfo("zh-Hans")] = "身份认证", - [CultureInfo.GetCultureInfo("en")] = "OpenID Connect" + [CultureInfo.GetCultureInfo("en")] = "OpenId Connect" }, - Description = "使用OpenID Connect协议进行身份验证", + Description = "OpenId Connect协议进行身份验证", Descriptions = { [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序使用您的身份信息进行登录", @@ -72,7 +71,7 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase } }); - // Profile scope - 用户基本信息 + // Profile await CreateScopesAsync(new OpenIddictScopeDescriptor { Name = OpenIddictConstants.Scopes.Profile, @@ -90,7 +89,7 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase } }); - // Email scope + // Email await CreateScopesAsync(new OpenIddictScopeDescriptor { Name = OpenIddictConstants.Scopes.Email, @@ -108,7 +107,7 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase } }); - // Phone scope + // Phone await CreateScopesAsync(new OpenIddictScopeDescriptor { Name = OpenIddictConstants.Scopes.Phone, @@ -126,7 +125,7 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase } }); - // Address scope + // Address await CreateScopesAsync(new OpenIddictScopeDescriptor { Name = OpenIddictConstants.Scopes.Address, @@ -144,7 +143,7 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase } }); - // Roles scope + // Roles await CreateScopesAsync(new OpenIddictScopeDescriptor { Name = OpenIddictConstants.Scopes.Roles, @@ -162,7 +161,7 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase } }); - // Offline Access scope - 用于获取刷新令牌 + // OfflineAccess await CreateScopesAsync(new OpenIddictScopeDescriptor { Name = OpenIddictConstants.Scopes.OfflineAccess, @@ -183,6 +182,7 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase private async Task CreateApiScopeAsync(string scope) { + // 前端汇总授权范围 await CreateScopesAsync(new OpenIddictScopeDescriptor { Name = scope, @@ -213,6 +213,216 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase "workflow-service", } }); + // ApiGateway Swagger + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = "api-gateway", + DisplayName = "Api Gateway", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "应用程序接口网关", + [CultureInfo.GetCultureInfo("en")] = "Api Gateway" + }, + Description = "适用于应用程序接口网关Swagger授权", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "适用于应用程序接口网关Swagger授权", + [CultureInfo.GetCultureInfo("en")] = "Applicable to application Programming interface gateway Swagger authorization" + }, + Resources = + { + "api-gateway", + } + }); + // Admin Service + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = "admin-service", + DisplayName = "Admin Service", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "后台管理服务", + [CultureInfo.GetCultureInfo("en")] = "Admin Service" + }, + Description = "适用于后台管理服务Swagger授权", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "适用于后台管理服务Swagger授权", + [CultureInfo.GetCultureInfo("en")] = "Applicable to the back-end management service Swagger authorization" + }, + Resources = + { + "admin-service", + } + }); + // Identity Service + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = "identity-service", + DisplayName = "Identity Service", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "身份认证服务", + [CultureInfo.GetCultureInfo("en")] = "Identity Service" + }, + Description = "适用于身份认证服务Swagger授权", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "适用于身份认证服务Swagger授权", + [CultureInfo.GetCultureInfo("en")] = "Applicable to the identity service Swagger authorization" + }, + Resources = + { + "identity-service", + } + }); + // Localization Service + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = "localization-service", + DisplayName = "Localization Service", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "本地化管理服务", + [CultureInfo.GetCultureInfo("en")] = "Localization Service" + }, + Description = "适用于本地化管理服务Swagger授权", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "适用于本地化管理服务Swagger授权", + [CultureInfo.GetCultureInfo("en")] = "Applicable to the Localization service Swagger authorization" + }, + Resources = + { + "localization-service", + } + }); + // Message Service + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = "message-service", + DisplayName = "Message Service", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "消息管理服务", + [CultureInfo.GetCultureInfo("en")] = "Message Service" + }, + Description = "适用于消息管理服务Swagger授权", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "适用于消息管理服务Swagger授权", + [CultureInfo.GetCultureInfo("en")] = "Applicable to the Message service Swagger authorization" + }, + Resources = + { + "message-service", + } + }); + // Platform Service + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = "platform-service", + DisplayName = "Platform Service", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "平台管理服务", + [CultureInfo.GetCultureInfo("en")] = "Platform Service" + }, + Description = "适用于平台管理服务Swagger授权", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "适用于平台管理服务Swagger授权", + [CultureInfo.GetCultureInfo("en")] = "Applicable to the Platform service Swagger authorization" + }, + Resources = + { + "platform-service", + } + }); + // Task Service + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = "task-service", + DisplayName = "Task Service", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "任务管理服务", + [CultureInfo.GetCultureInfo("en")] = "Task Service" + }, + Description = "适用于任务管理服务Swagger授权", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "适用于任务管理服务Swagger授权", + [CultureInfo.GetCultureInfo("en")] = "Applicable to the Task service Swagger authorization" + }, + Resources = + { + "task-service", + } + }); + // Webhook Service + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = "webhook-service", + DisplayName = "Webhook Service", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "Webhook管理服务", + [CultureInfo.GetCultureInfo("en")] = "Webhook Service" + }, + Description = "适用于Webhook管理服务Swagger授权", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "适用于Webhook管理服务Swagger授权", + [CultureInfo.GetCultureInfo("en")] = "Applicable to the Webhook service Swagger authorization" + }, + Resources = + { + "webhook-service", + } + }); + // Wechat Service + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = "wechat-service", + DisplayName = "Wechat Service", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "微信管理服务", + [CultureInfo.GetCultureInfo("en")] = "Wechat Service" + }, + Description = "适用于微信管理服务Swagger授权", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "适用于微信管理服务Swagger授权", + [CultureInfo.GetCultureInfo("en")] = "Applicable to the Wechat service Swagger authorization" + }, + Resources = + { + "wechat-service", + } + }); + // Workflow Service + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = "workflow-service", + DisplayName = "Workflow Service", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "工作流管理服务", + [CultureInfo.GetCultureInfo("en")] = "Workflow Service" + }, + Description = "适用于工作流管理服务Swagger授权", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "适用于工作流管理服务Swagger授权", + [CultureInfo.GetCultureInfo("en")] = "Applicable to the Workflow service Swagger authorization" + }, + Resources = + { + "workflow-service", + } + }); } private async Task CreateApplicationAsync(string scope) @@ -316,7 +526,18 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase OpenIddictConstants.Scopes.Phone, OpenIddictConstants.Scopes.Profile, OpenIddictConstants.Scopes.OfflineAccess, - scope], + scope, + "api-gateway", + "auth-server", + "admin-service", + "identity-service", + "localization-service", + "message-service", + "platform-service", + "task-service", + "webhook-service", + "wechat-service", + "workflow-service"], oauthClientRedirectUrls, oauthClientPostLogoutRedirectUrls); diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/AuthServerModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/AuthServerModule.cs index 88ae4db6e..28a107f20 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/AuthServerModule.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/AuthServerModule.cs @@ -25,19 +25,15 @@ using LINGYUN.Abp.OpenIddict.WeChat.Work; using LINGYUN.Abp.Serilog.Enrichers.Application; using LINGYUN.Abp.Serilog.Enrichers.UniqueId; using LINGYUN.Abp.Sms.Platform; -using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite; using Volo.Abp.AspNetCore.Serilog; using Volo.Abp.Autofac; using Volo.Abp.Caching.StackExchangeRedis; -using Volo.Abp.Data; using Volo.Abp.Modularity; using Volo.Abp.PermissionManagement.Identity; -using Volo.Abp.Threading; namespace LINGYUN.Abp.MicroService.AuthServer; @@ -119,16 +115,4 @@ public partial class AuthServerModule : AbpModule ConfigureDistributedLocking(context.Services, configuration); ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); } - - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - AsyncHelper.RunSync(() => OnApplicationInitializationAsync(context)); - } - - public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context) - { - await context.ServiceProvider - .GetRequiredService() - .SeedAsync(); - } } diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/LINGYUN.Abp.MicroService.AuthServer.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/LINGYUN.Abp.MicroService.AuthServer.csproj index b1779d699..f7e001506 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/LINGYUN.Abp.MicroService.AuthServer.csproj +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/LINGYUN.Abp.MicroService.AuthServer.csproj @@ -78,10 +78,6 @@ - - - - @@ -89,10 +85,7 @@ $(MSBuildProjectDirectory)\package.json - + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.Development.json index 9548aa720..6a2741cf8 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.Development.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.Development.json @@ -93,35 +93,6 @@ "MapInboundClaims": false, "RequireHttpsMetadata": false }, - "OpenIddict": { - "Applications": { - "VueAdmin": { - "ClientId": "vue-admin-client", - "ClientSecret": "1q2w3e*", - "RootUrls": ["http://localhost:5666"] - }, - "InternalService": { - "ClientId": "InternalServiceClient", - "ClientSecret": "1q2w3e*" - }, - "VueOAuthClient": { - "ClientId": "vue-oauth-client", - "RootUrls": [ - "http://localhost:5666", - "http://localhost:30000", - "http://localhost:30010", - "http://localhost:30015", - "http://localhost:30020", - "http://localhost:30025", - "http://localhost:30030", - "http://localhost:30040", - "http://localhost:30045", - "http://localhost:30050", - "http://localhost:30060" - ] - } - } - }, "Identity": { "Password": { "RequiredLength": 6, diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/IdentityServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/IdentityServiceModule.cs index ad71ae28b..2494c33f3 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/IdentityServiceModule.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/IdentityServiceModule.cs @@ -128,10 +128,4 @@ public partial class IdentityServiceModule : AbpModule ConfigureDistributedLocking(context.Services, configuration); ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); } - - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var app = context.GetApplicationBuilder(); - - } } diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore.csproj index 565c85497..9650d9af3 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore.csproj +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore.csproj @@ -25,6 +25,7 @@ + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDataSeeder.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDataSeeder.cs new file mode 100644 index 000000000..8b2fab9c2 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDataSeeder.cs @@ -0,0 +1,47 @@ +using LINGYUN.Abp.UI.Navigation; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.PlatformService; +public class PlatformServiceDataSeeder : ITransientDependency +{ + protected IEnumerable NavigationSeedContributors { get; } + protected INavigationProvider NavigationProvider { get; } + protected ICurrentTenant CurrentTenant { get; } + public PlatformServiceDataSeeder( + IEnumerable navigationSeedContributors, + INavigationProvider navigationProvider, + ICurrentTenant currentTenant) + { + NavigationSeedContributors = navigationSeedContributors; + NavigationProvider = navigationProvider; + CurrentTenant = currentTenant; + } + + public async virtual Task SeedAsync(DataSeedContext context) + { + using (CurrentTenant.Change(context.TenantId)) + { + await SeedNavigationAsync(); + } + } + + private async Task SeedNavigationAsync() + { + var menus = await NavigationProvider.GetAllAsync(); + + var multiTenancySides = CurrentTenant.IsAvailable + ? MultiTenancySides.Tenant + : MultiTenancySides.Host; + + var seedContext = new NavigationSeedContext(menus, multiTenancySides); + + foreach (var contributor in NavigationSeedContributors) + { + await contributor.SeedAsync(seedContext); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationEventHandler.cs index b987094fe..ce598345a 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationEventHandler.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationEventHandler.cs @@ -1,10 +1,8 @@ using LINGYUN.Abp.Saas.Tenants; -using LINGYUN.Abp.UI.Navigation; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System; -using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Threading.Tasks; @@ -12,7 +10,6 @@ using Volo.Abp.Data; using Volo.Abp.DistributedLocking; using Volo.Abp.EntityFrameworkCore.Migrations; using Volo.Abp.EventBus.Distributed; -using Volo.Abp.Features; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; @@ -21,9 +18,7 @@ public class PlatformServiceDbMigrationEventHandler : EfCoreDatabaseMigrationEventHandlerBase, IDistributedEventHandler { - protected IEnumerable NavigationSeedContributors { get; } - protected INavigationProvider NavigationProvider { get; } - protected IFeatureChecker FeatureChecker { get; } + protected PlatformServiceDataSeeder DataSeeder { get; } protected IConfiguration Configuration { get; } public PlatformServiceDbMigrationEventHandler( ICurrentTenant currentTenant, @@ -32,37 +27,29 @@ public class PlatformServiceDbMigrationEventHandler : IAbpDistributedLock abpDistributedLock, IDistributedEventBus distributedEventBus, ILoggerFactory loggerFactory, - IFeatureChecker featureChecker, IConfiguration configuration, - INavigationProvider navigationProvider, - IEnumerable navigationSeedContributors) + PlatformServiceDataSeeder dataSeeder) : base( ConnectionStringNameAttribute.GetConnStringName(), currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory) { - FeatureChecker = featureChecker; Configuration = configuration; - NavigationProvider = navigationProvider; - NavigationSeedContributors = navigationSeedContributors; + DataSeeder = dataSeeder; } - protected async override Task SeedAsync(Guid? tenantId) + protected async override Task AfterTenantCreated(TenantCreatedEto eventData, bool schemaMigrated) { - using (CurrentTenant.Change(tenantId)) + // 新租户数据种子 + var context = new DataSeedContext(eventData.Id); + if (eventData.Properties != null) { - var menus = await NavigationProvider.GetAllAsync(); - - var multiTenancySides = CurrentTenant.IsAvailable - ? MultiTenancySides.Tenant - : MultiTenancySides.Host; - - var seedContext = new NavigationSeedContext(menus, multiTenancySides); - - foreach (var contributor in NavigationSeedContributors) + foreach (var property in eventData.Properties) { - await contributor.SeedAsync(seedContext); + context.WithProperty(property.Key, property.Value); } } + + await DataSeeder.SeedAsync(context); } public async virtual Task HandleEventAsync(TenantDeletedEto eventData) diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationService.cs index e8f51a089..81c9a8879 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationService.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceDbMigrationService.cs @@ -1,6 +1,7 @@ using LINGYUN.Abp.Data.DbMigrator; using Microsoft.Extensions.Logging; using System; +using System.Threading.Tasks; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.DistributedLocking; @@ -11,16 +12,25 @@ using Volo.Abp.Uow; namespace LINGYUN.Abp.MicroService.PlatformService; public class PlatformServiceDbMigrationService : EfCoreRuntimeDbMigratorBase, ITransientDependency { + protected PlatformServiceDataSeeder DataSeeder { get; } public PlatformServiceDbMigrationService( ICurrentTenant currentTenant, IUnitOfWorkManager unitOfWorkManager, IServiceProvider serviceProvider, IAbpDistributedLock abpDistributedLock, IDistributedEventBus distributedEventBus, - ILoggerFactory loggerFactory) + ILoggerFactory loggerFactory, + PlatformServiceDataSeeder dataSeeder) : base( ConnectionStringNameAttribute.GetConnStringName(), unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory) { + DataSeeder = dataSeeder; + } + + protected async override Task SeedAsync() + { + // DbMigrator迁移数据种子 + await DataSeeder.SeedAsync(new DataSeedContext()); } } diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceMigrationsEntityFrameworkCoreModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceMigrationsEntityFrameworkCoreModule.cs index f361163fd..507975d64 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceMigrationsEntityFrameworkCoreModule.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService.EntityFrameworkCore/PlatformServiceMigrationsEntityFrameworkCoreModule.cs @@ -1,6 +1,6 @@ using LINGYUN.Abp.Data.DbMigrator; using LINGYUN.Abp.Saas.EntityFrameworkCore; -using LINGYUN.Abp.UI.Navigation; +using LINGYUN.Abp.UI.Navigation.VueVbenAdmin5; using LINGYUN.Platform.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using System; @@ -14,7 +14,7 @@ using Volo.Abp.SettingManagement.EntityFrameworkCore; namespace LINGYUN.Abp.MicroService.PlatformService; [DependsOn( - typeof(AbpUINavigationModule), + typeof(AbpUINavigationVueVbenAdmin5Module), typeof(AbpSaasEntityFrameworkCoreModule), typeof(PlatformEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule), diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/LINGYUN.Abp.MicroService.PlatformService.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/LINGYUN.Abp.MicroService.PlatformService.csproj index 8e2bacb1f..4269d0f4f 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/LINGYUN.Abp.MicroService.PlatformService.csproj +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/LINGYUN.Abp.MicroService.PlatformService.csproj @@ -72,11 +72,9 @@ - - diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.cs index 2d4cc5590..0a5a0370f 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.cs @@ -25,11 +25,9 @@ using LINGYUN.Abp.Saas.EntityFrameworkCore; using LINGYUN.Abp.Serilog.Enrichers.Application; using LINGYUN.Abp.Serilog.Enrichers.UniqueId; using LINGYUN.Abp.Sms.Aliyun; -using LINGYUN.Abp.UI.Navigation.VueVbenAdmin5; using LINGYUN.Platform; using LINGYUN.Platform.EntityFrameworkCore; using LINGYUN.Platform.HttpApi; -using LINGYUN.Platform.Theme.VueVbenAdmin; using Microsoft.Extensions.Options; using Volo.Abp; using Volo.Abp.AspNetCore.Authentication.JwtBearer; @@ -38,7 +36,6 @@ using Volo.Abp.AspNetCore.Serilog; using Volo.Abp.Autofac; using Volo.Abp.BackgroundWorkers; using Volo.Abp.Caching.StackExchangeRedis; -using Volo.Abp.Data; using Volo.Abp.FeatureManagement.EntityFrameworkCore; using Volo.Abp.Http.Client; using Volo.Abp.Http.Client.IdentityModel.Web; @@ -60,8 +57,6 @@ namespace LINGYUN.Abp.MicroService.PlatformService; typeof(AbpAuditLoggingElasticsearchModule), typeof(AbpAspNetCoreMultiTenancyModule), typeof(AbpAspNetCoreMvcLocalizationModule), - typeof(AbpUINavigationVueVbenAdmin5Module), - typeof(PlatformThemeVueVbenAdminModule), typeof(AbpOssManagementAliyunModule), // 阿里云存储提供者模块 typeof(AbpOssManagementTencentModule), // 腾讯云存储提供者模块 typeof(AbpOssManagementNexusModule), // Nexus存储提供者模块 @@ -151,10 +146,6 @@ public partial class PlatformServiceModule : AbpModule public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context) { - await context.ServiceProvider - .GetRequiredService() - .SeedAsync(); - var options = context.ServiceProvider.GetRequiredService>().Value; if (options.IsCleanupEnabled) { diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceDataSeeder.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceDataSeeder.cs new file mode 100644 index 000000000..85af7f482 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceDataSeeder.cs @@ -0,0 +1,139 @@ +using LINGYUN.Abp.BackgroundTasks; +using LINGYUN.Abp.BackgroundTasks.Internal; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.TaskService; +public class TaskServiceDataSeeder : ITransientDependency +{ + protected AbpBackgroundTasksOptions Options { get; } + protected IJobStore JobStore { get; } + protected IJobScheduler JobScheduler { get; } + protected ICurrentTenant CurrentTenant { get; } + + public TaskServiceDataSeeder( + IOptions options, + IJobStore jobStore, + IJobScheduler jobScheduler, + ICurrentTenant currentTenant) + { + Options = options.Value; + JobStore = jobStore; + JobScheduler = jobScheduler; + CurrentTenant = currentTenant; + } + + public async virtual Task SeedAsync(DataSeedContext context) + { + if (context.TenantId.HasValue) + { + using (CurrentTenant.Change(context.TenantId)) + { + await QueueBackgroundJobAsync(context.TenantId.Value); + } + } + } + + public async virtual Task RemoveSeedAsync(Guid tenantId) + { + using (CurrentTenant.Change(tenantId)) + { + var pollingJob = BuildPollingJobInfo(tenantId); + await JobScheduler.RemoveAsync(pollingJob); + await JobStore.RemoveAsync(pollingJob.Id); + + var cleaningJob = BuildCleaningJobInfo(tenantId); + await JobScheduler.RemoveAsync(cleaningJob); + await JobStore.RemoveAsync(cleaningJob.Id); + + var checkingJob = BuildCheckingJobInfo(tenantId); + await JobScheduler.RemoveAsync(checkingJob); + await JobStore.RemoveAsync(checkingJob.Id); + } + } + + protected async virtual Task QueueBackgroundJobAsync(Guid tenantId) + { + var pollingJob = BuildPollingJobInfo(tenantId); + await JobStore.StoreAsync(pollingJob); + await JobScheduler.QueueAsync(pollingJob); + + var cleaningJob = BuildCleaningJobInfo(tenantId); + await JobStore.StoreAsync(cleaningJob); + await JobScheduler.QueueAsync(cleaningJob); + + var checkingJob = BuildCheckingJobInfo(tenantId); + await JobStore.StoreAsync(checkingJob); + await JobScheduler.QueueAsync(checkingJob); + } + + protected virtual JobInfo BuildPollingJobInfo(Guid tenantId) + { + return new JobInfo + { + Id = tenantId.ToString() + "_Polling", + Name = nameof(BackgroundPollingJob), + Group = "Polling", + Description = "Polling tasks to be executed", + Args = new Dictionary() { { nameof(JobInfo.TenantId), tenantId } }, + Status = JobStatus.Running, + BeginTime = DateTime.Now, + CreationTime = DateTime.Now, + Cron = Options.JobFetchCronExpression, + JobType = JobType.Period, + Priority = JobPriority.High, + Source = JobSource.System, + LockTimeOut = Options.JobFetchLockTimeOut, + TenantId = tenantId, + Type = typeof(BackgroundPollingJob).AssemblyQualifiedName, + }; + } + + protected virtual JobInfo BuildCleaningJobInfo(Guid tenantId) + { + return new JobInfo + { + Id = tenantId.ToString() + "_Cleaning", + Name = nameof(BackgroundCleaningJob), + Group = "Cleaning", + Description = "Cleaning tasks to be executed", + Args = new Dictionary() { { nameof(JobInfo.TenantId), tenantId } }, + Status = JobStatus.Running, + BeginTime = DateTime.Now, + CreationTime = DateTime.Now, + Cron = Options.JobCleanCronExpression, + JobType = JobType.Period, + Priority = JobPriority.High, + Source = JobSource.System, + TenantId = tenantId, + Type = typeof(BackgroundCleaningJob).AssemblyQualifiedName, + }; + } + + protected virtual JobInfo BuildCheckingJobInfo(Guid tenantId) + { + return new JobInfo + { + Id = tenantId.ToString() + "_Checking", + Name = nameof(BackgroundCheckingJob), + Group = "Checking", + Description = "Checking tasks to be executed", + Args = new Dictionary() { { nameof(JobInfo.TenantId), tenantId } }, + Status = JobStatus.Running, + BeginTime = DateTime.Now, + CreationTime = DateTime.Now, + Cron = Options.JobCheckCronExpression, + LockTimeOut = Options.JobCheckLockTimeOut, + JobType = JobType.Period, + Priority = JobPriority.High, + Source = JobSource.System, + TenantId = tenantId, + Type = typeof(BackgroundCheckingJob).AssemblyQualifiedName, + }; + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceDbMigrationEventHandler.cs index 57c56163c..079b1b838 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceDbMigrationEventHandler.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService.EntityFrameworkCore/TaskServiceDbMigrationEventHandler.cs @@ -1,10 +1,5 @@ -using LINGYUN.Abp.BackgroundTasks; -using LINGYUN.Abp.BackgroundTasks.Internal; -using LINGYUN.Abp.Saas.Tenants; +using LINGYUN.Abp.Saas.Tenants; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; using System.Threading.Tasks; using Volo.Abp.Data; using Volo.Abp.DistributedLocking; @@ -19,9 +14,7 @@ public class TaskServiceDbMigrationEventHandler : EfCoreDatabaseMigrationEventHandlerBase, IDistributedEventHandler> { - protected AbpBackgroundTasksOptions Options { get; } - protected IJobStore JobStore { get; } - protected IJobScheduler JobScheduler { get; } + protected TaskServiceDataSeeder DataSeeder { get; } public TaskServiceDbMigrationEventHandler( ICurrentTenant currentTenant, @@ -30,122 +23,33 @@ public class TaskServiceDbMigrationEventHandler : IAbpDistributedLock abpDistributedLock, IDistributedEventBus distributedEventBus, ILoggerFactory loggerFactory, - IJobStore jobStore, - IJobScheduler jobScheduler, - IOptions options) + TaskServiceDataSeeder dataSeeder) : base( ConnectionStringNameAttribute.GetConnStringName(), currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory) { - JobStore = jobStore; - JobScheduler = jobScheduler; - Options = options.Value; + DataSeeder = dataSeeder; } public async Task HandleEventAsync(EntityDeletedEto eventData) { // 租户删除时移除轮询作业 - var pollingJob = BuildPollingJobInfo(eventData.Entity.Id, eventData.Entity.Name); - await JobScheduler.RemoveAsync(pollingJob); - await JobStore.RemoveAsync(pollingJob.Id); - - var cleaningJob = BuildCleaningJobInfo(eventData.Entity.Id, eventData.Entity.Name); - await JobScheduler.RemoveAsync(cleaningJob); - await JobStore.RemoveAsync(cleaningJob.Id); - - var checkingJob = BuildCheckingJobInfo(eventData.Entity.Id, eventData.Entity.Name); - await JobScheduler.RemoveAsync(checkingJob); - await JobStore.RemoveAsync(checkingJob.Id); + await DataSeeder.RemoveSeedAsync(eventData.Entity.Id); } protected async override Task AfterTenantCreated(TenantCreatedEto eventData, bool schemaMigrated) { - if (!schemaMigrated) + // 新租户数据种子 + var context = new DataSeedContext(eventData.Id); + if (eventData.Properties != null) { - return; + foreach (var property in eventData.Properties) + { + context.WithProperty(property.Key, property.Value); + } } - await QueueBackgroundJobAsync(eventData); - } - - protected async virtual Task QueueBackgroundJobAsync(TenantCreatedEto eventData) - { - var pollingJob = BuildPollingJobInfo(eventData.Id, eventData.Name); - await JobStore.StoreAsync(pollingJob); - await JobScheduler.QueueAsync(pollingJob); - - var cleaningJob = BuildCleaningJobInfo(eventData.Id, eventData.Name); - await JobStore.StoreAsync(cleaningJob); - await JobScheduler.QueueAsync(cleaningJob); - - var checkingJob = BuildCheckingJobInfo(eventData.Id, eventData.Name); - await JobStore.StoreAsync(checkingJob); - await JobScheduler.QueueAsync(checkingJob); - } - - protected virtual JobInfo BuildPollingJobInfo(Guid tenantId, string tenantName) - { - return new JobInfo - { - Id = tenantId.ToString() + "_Polling", - Name = nameof(BackgroundPollingJob), - Group = "Polling", - Description = "Polling tasks to be executed", - Args = new Dictionary() { { nameof(JobInfo.TenantId), tenantId } }, - Status = JobStatus.Running, - BeginTime = DateTime.Now, - CreationTime = DateTime.Now, - Cron = Options.JobFetchCronExpression, - JobType = JobType.Period, - Priority = JobPriority.High, - Source = JobSource.System, - LockTimeOut = Options.JobFetchLockTimeOut, - TenantId = tenantId, - Type = typeof(BackgroundPollingJob).AssemblyQualifiedName, - }; - } - - protected virtual JobInfo BuildCleaningJobInfo(Guid tenantId, string tenantName) - { - return new JobInfo - { - Id = tenantId.ToString() + "_Cleaning", - Name = nameof(BackgroundCleaningJob), - Group = "Cleaning", - Description = "Cleaning tasks to be executed", - Args = new Dictionary() { { nameof(JobInfo.TenantId), tenantId } }, - Status = JobStatus.Running, - BeginTime = DateTime.Now, - CreationTime = DateTime.Now, - Cron = Options.JobCleanCronExpression, - JobType = JobType.Period, - Priority = JobPriority.High, - Source = JobSource.System, - TenantId = tenantId, - Type = typeof(BackgroundCleaningJob).AssemblyQualifiedName, - }; - } - - protected virtual JobInfo BuildCheckingJobInfo(Guid tenantId, string tenantName) - { - return new JobInfo - { - Id = tenantId.ToString() + "_Checking", - Name = nameof(BackgroundCheckingJob), - Group = "Checking", - Description = "Checking tasks to be executed", - Args = new Dictionary() { { nameof(JobInfo.TenantId), tenantId } }, - Status = JobStatus.Running, - BeginTime = DateTime.Now, - CreationTime = DateTime.Now, - Cron = Options.JobCheckCronExpression, - LockTimeOut = Options.JobCheckLockTimeOut, - JobType = JobType.Period, - Priority = JobPriority.High, - Source = JobSource.System, - TenantId = tenantId, - Type = typeof(BackgroundCheckingJob).AssemblyQualifiedName, - }; + await DataSeeder.SeedAsync(context); } } diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceDbMigrationEventHandler.cs index 834214234..08e2e475b 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceDbMigrationEventHandler.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService.EntityFrameworkCore/WebhookServiceDbMigrationEventHandler.cs @@ -15,8 +15,7 @@ public class WebhookServiceDbMigrationEventHandler : EfCoreDatabaseMigrationEven ITenantStore tenantStore, IAbpDistributedLock abpDistributedLock, IDistributedEventBus distributedEventBus, - ILoggerFactory loggerFactory, - IDataSeeder dataSeeder) + ILoggerFactory loggerFactory) : base( ConnectionStringNameAttribute.GetConnStringName(), currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory) diff --git a/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN/Abp/UI/Navigation/VueVbenAdmin/VueVbenAdminNavigationSeedContributor.cs b/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN/Abp/UI/Navigation/VueVbenAdmin/VueVbenAdminNavigationSeedContributor.cs index eb0e50fe0..366a020f1 100644 --- a/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN/Abp/UI/Navigation/VueVbenAdmin/VueVbenAdminNavigationSeedContributor.cs +++ b/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN/Abp/UI/Navigation/VueVbenAdmin/VueVbenAdminNavigationSeedContributor.cs @@ -76,7 +76,7 @@ public class VueVbenAdminNavigationSeedContributor : NavigationSeedContributor continue; } - var menuMeta = new Dictionary() + var menuMeta = new Dictionary(menu.ExtraProperties) { { "title", menu.DisplayName }, { "icon", menu.Icon ?? "" }, @@ -84,17 +84,6 @@ public class VueVbenAdminNavigationSeedContributor : NavigationSeedContributor { "hideTab", false }, { "ignoreAuth", false }, }; - foreach (var prop in menu.ExtraProperties) - { - if (menuMeta.ContainsKey(prop.Key)) - { - menuMeta[prop.Key] = prop.Value; - } - else - { - menuMeta.Add(prop.Key, prop.Value); - } - } var seedMenu = await SeedMenuAsync( layout: layout, @@ -129,8 +118,7 @@ public class VueVbenAdminNavigationSeedContributor : NavigationSeedContributor { continue; } - - var menuMeta = new Dictionary() + var menuMeta = new Dictionary(item.ExtraProperties) { { "title", item.DisplayName }, { "icon", item.Icon ?? "" }, @@ -138,17 +126,6 @@ public class VueVbenAdminNavigationSeedContributor : NavigationSeedContributor { "hideTab", false }, { "ignoreAuth", false }, }; - foreach (var prop in item.ExtraProperties) - { - if (menuMeta.ContainsKey(prop.Key)) - { - menuMeta[prop.Key] = prop.Value; - } - else - { - menuMeta.Add(prop.Key, prop.Value); - } - } var seedMenu = await SeedMenuAsync( layout: layout, @@ -189,6 +166,18 @@ public class VueVbenAdminNavigationSeedContributor : NavigationSeedContributor bool isPublic = false ) { + var menuMeta = new Dictionary(); + foreach (var item in data.Items) + { + menuMeta[item.Name] = item.DefaultValue; + } + if (meta != null) + { + foreach (var item in meta) + { + menuMeta[item.Key] = item.Value; + } + } var menu = await RouteDataSeeder.SeedMenuAsync( layout, name, @@ -200,19 +189,8 @@ public class VueVbenAdminNavigationSeedContributor : NavigationSeedContributor description, parentId, tenantId, - isPublic - ); - foreach (var item in data.Items) - { - menu.SetProperty(item.Name, item.DefaultValue); - } - if (meta != null) - { - foreach (var item in meta) - { - menu.SetProperty(item.Key, item.Value); - } - } + isPublic, + menuMeta); if (roles != null) { @@ -235,15 +213,17 @@ public class VueVbenAdminNavigationSeedContributor : NavigationSeedContributor private async Task SeedUIFrameworkDataAsync(Guid? tenantId) { - var data = await DataDictionaryDataSeeder - .SeedAsync( - "UI Framework", - CodeNumberGenerator.CreateCode(10), - "UI框架", - "UI Framework", - null, - tenantId, - true); + var data = new Data( + GuidGenerator.Create(), + "UI Framework", + CodeNumberGenerator.CreateCode(10), + "UI框架", + "UI Framework", + null, + tenantId) + { + IsStatic = true, + }; data.AddItem( GuidGenerator, @@ -254,6 +234,8 @@ public class VueVbenAdminNavigationSeedContributor : NavigationSeedContributor Options.UI, isStatic: true); + await DataDictionaryDataSeeder.SeedAsync(data); + return data.FindItem(Options.UI); } @@ -275,15 +257,17 @@ public class VueVbenAdminNavigationSeedContributor : NavigationSeedContributor private async Task SeedLayoutDataAsync(Guid? tenantId) { - var data = await DataDictionaryDataSeeder - .SeedAsync( - Options.LayoutName, - CodeNumberGenerator.CreateCode(10), - "Vben Admin 布局约束", - "Vben Admin Layout Meta Dictionary", - null, - tenantId, - true); + var data = new Data( + GuidGenerator.Create(), + Options.LayoutName, + CodeNumberGenerator.CreateCode(10), + "Vben Admin 布局约束", + "Vben Admin Layout Meta Dictionary", + null, + tenantId) + { + IsStatic = true, + }; data.AddItem( GuidGenerator, @@ -446,6 +430,8 @@ public class VueVbenAdminNavigationSeedContributor : NavigationSeedContributor ValueType.Boolean, "扩展的格式化frame,{token}: 在打开的iframe页面传递token请求头"); + await DataDictionaryDataSeeder.SeedAsync(data); + return data; } diff --git a/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin5/LINGYUN/Abp/UI/Navigation/VueVbenAdmin5/VueVbenAdmin5NavigationSeedContributor.cs b/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin5/LINGYUN/Abp/UI/Navigation/VueVbenAdmin5/VueVbenAdmin5NavigationSeedContributor.cs index 3928e8c8f..79f2be9d9 100644 --- a/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin5/LINGYUN/Abp/UI/Navigation/VueVbenAdmin5/VueVbenAdmin5NavigationSeedContributor.cs +++ b/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin5/LINGYUN/Abp/UI/Navigation/VueVbenAdmin5/VueVbenAdmin5NavigationSeedContributor.cs @@ -76,22 +76,11 @@ public class VueVbenAdmin5NavigationSeedContributor : NavigationSeedContributor continue; } - var menuMeta = new Dictionary() + var menuMeta = new Dictionary(menu.ExtraProperties) { - { "icon", menu.Icon ?? "" }, - { "order", menu.Order }, + ["icon"] = menu.Icon ?? "", + ["order"] = menu.Order }; - foreach (var prop in menu.ExtraProperties) - { - if (menuMeta.ContainsKey(prop.Key)) - { - menuMeta[prop.Key] = prop.Value; - } - else - { - menuMeta.Add(prop.Key, prop.Value); - } - } var seedMenu = await SeedMenuAsync( layout: layout, @@ -127,22 +116,11 @@ public class VueVbenAdmin5NavigationSeedContributor : NavigationSeedContributor continue; } - var menuMeta = new Dictionary() + var menuMeta = new Dictionary(item.ExtraProperties) { - { "icon", item.Icon ?? "" }, - { "order", item.Order }, + ["icon"] = item.Icon ?? "", + ["order"] = item.Order }; - foreach (var prop in item.ExtraProperties) - { - if (menuMeta.ContainsKey(prop.Key)) - { - menuMeta[prop.Key] = prop.Value; - } - else - { - menuMeta.Add(prop.Key, prop.Value); - } - } var seedMenu = await SeedMenuAsync( layout: layout, @@ -183,6 +161,18 @@ public class VueVbenAdmin5NavigationSeedContributor : NavigationSeedContributor bool isPublic = false ) { + var menuMeta = new Dictionary(); + foreach (var item in data.Items) + { + menuMeta[item.Name] = item.DefaultValue; + } + if (meta != null) + { + foreach (var item in meta) + { + menuMeta[item.Key] = item.Value; + } + } var menu = await RouteDataSeeder.SeedMenuAsync( layout, name, @@ -194,19 +184,8 @@ public class VueVbenAdmin5NavigationSeedContributor : NavigationSeedContributor description, parentId, tenantId, - isPublic - ); - foreach (var item in data.Items) - { - menu.SetProperty(item.Name, item.DefaultValue); - } - if (meta != null) - { - foreach (var item in meta) - { - menu.SetProperty(item.Key, item.Value); - } - } + isPublic, + menuMeta); if (roles != null) { @@ -229,15 +208,17 @@ public class VueVbenAdmin5NavigationSeedContributor : NavigationSeedContributor private async Task SeedUIFrameworkDataAsync(Guid? tenantId) { - var data = await DataDictionaryDataSeeder - .SeedAsync( - "UI Framework", - CodeNumberGenerator.CreateCode(30), - "UI框架", - "UI Framework", - null, - tenantId, - true); + var data = new Data( + GuidGenerator.Create(), + "UI Framework", + CodeNumberGenerator.CreateCode(30), + "UI框架", + "UI Framework", + null, + tenantId) + { + IsStatic = true, + }; data.AddItem( GuidGenerator, @@ -248,6 +229,8 @@ public class VueVbenAdmin5NavigationSeedContributor : NavigationSeedContributor Options.UI, isStatic: true); + await DataDictionaryDataSeeder.SeedAsync(data); + return data.FindItem(Options.UI); } @@ -269,16 +252,17 @@ public class VueVbenAdmin5NavigationSeedContributor : NavigationSeedContributor private async Task SeedLayoutDataAsync(Guid? tenantId) { - var data = await DataDictionaryDataSeeder - .SeedAsync( - Options.LayoutName, - CodeNumberGenerator.CreateCode(40), - "Vben5 Admin 布局约束", - "Vben5 Admin模板布局约束", - null, - tenantId, - true); - + var data = new Data( + GuidGenerator.Create(), + Options.LayoutName, + CodeNumberGenerator.CreateCode(40), + "Vben5 Admin 布局约束", + "Vben5 Admin模板布局约束", + null, + tenantId) + { + IsStatic = true, + }; data.AddItem( GuidGenerator, "title", @@ -460,6 +444,8 @@ public class VueVbenAdmin5NavigationSeedContributor : NavigationSeedContributor ValueType.Boolean, "用于配置当前路由不使用基础布局,仅在顶级时生效。默认情况下,所有的路由都会被包裹在基础布局中(包含顶部以及侧边等导航部件),如果你的页面不需要这些部件,可以设置 noBasicLayout 为 true。"); + await DataDictionaryDataSeeder.SeedAsync(data); + return data; } diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataDictionaryDataSeeder.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataDictionaryDataSeeder.cs index 352c5e16e..249269b57 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataDictionaryDataSeeder.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataDictionaryDataSeeder.cs @@ -1,6 +1,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using System.Xml.Linq; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; @@ -57,4 +58,17 @@ public class DataDictionaryDataSeeder : IDataDictionaryDataSeeder, ITransientDep return data; } } + + public async virtual Task SeedAsync( + Data data, + CancellationToken cancellationToken = default) + { + using (CurrentTenant.Change(data.TenantId)) + { + var existsData = await DataRepository.FindByNameAsync(data.Name, cancellationToken: cancellationToken); + existsData ??= await DataRepository.InsertAsync(data, true, cancellationToken); + + return existsData; + } + } } diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/IDataDictionaryDataSeeder.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/IDataDictionaryDataSeeder.cs index 76ed4b2dd..a62a175f2 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/IDataDictionaryDataSeeder.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/IDataDictionaryDataSeeder.cs @@ -15,4 +15,8 @@ public interface IDataDictionaryDataSeeder Guid? tenantId = null, bool isStatic = false, CancellationToken cancellationToken = default); + + Task SeedAsync( + Data data, + CancellationToken cancellationToken = default); } diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/IRouteDataSeeder.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/IRouteDataSeeder.cs index 8dd57f8c3..9b7a0155a 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/IRouteDataSeeder.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/IRouteDataSeeder.cs @@ -1,6 +1,7 @@ using LINGYUN.Platform.Layouts; using LINGYUN.Platform.Menus; using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -31,6 +32,7 @@ public interface IRouteDataSeeder Guid? parentId = null, Guid? tenantId = null, bool isPublic = false, + IDictionary meta = null, CancellationToken cancellationToken = default); Task SeedUserMenuAsync( diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/RouteDataSeeder.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/RouteDataSeeder.cs index b47fb8ada..95657f6e9 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/RouteDataSeeder.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Routes/RouteDataSeeder.cs @@ -1,9 +1,11 @@ using LINGYUN.Platform.Layouts; using LINGYUN.Platform.Menus; using System; +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; @@ -72,6 +74,7 @@ public class RouteDataSeeder : IRouteDataSeeder, ITransientDependency Guid? parentId = null, Guid? tenantId = null, bool isPublic = false, + IDictionary meta = null, CancellationToken cancellationToken = default) { if (parentId.HasValue) @@ -103,6 +106,14 @@ public class RouteDataSeeder : IRouteDataSeeder, ITransientDependency IsPublic = isPublic }; + if (meta != null) + { + foreach (var item in meta) + { + menu.SetProperty(item.Key, item.Value); + } + } + menu = await MenuRepository.InsertAsync(menu, cancellationToken: cancellationToken); }