Browse Source

feat: Adjust the initialization of the dynamic in module

pull/1416/head
colin 2 months ago
parent
commit
d361a6a59f
  1. 17
      aspnet-core/migrations/LY.MicroService.Applications.Single.DbMigrator/appsettings.json
  2. 32
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.MySql/SingleMigrationsEntityFrameworkCoreMySqlModule.cs
  3. 277
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/ClientDataSeederContributor.cs
  4. 178
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/OpenIddictDataSeederContributor.cs
  5. 3
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/RolePermissionDataSeedContributor.cs
  6. 4
      aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/SingleDbMigrationService.cs
  7. 6
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtectionManagement.Domain/LINGYUN/Abp/DataProtectionManagement/AbpDataProtectionManagementDomainModule.cs
  8. 79
      aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/AbpLocalizationManagementDomainModule.cs
  9. 121
      aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationDynamicInitializer.cs
  10. 9
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/AbpNotificationsDomainModule.cs
  11. 145
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/NotificationDynamicInitializer.cs
  12. 4
      aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/AbpSaasDomainModule.cs
  13. 13
      aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/AbpTextTemplatingDomainModule.cs
  14. 115
      aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionInitializer.cs
  15. 148
      aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateDynamicInitializer.cs
  16. 94
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN/Abp/WebhooksManagement/WebhookDefinitionInitializer.cs
  17. 150
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN/Abp/WebhooksManagement/WebhookDynamicInitializer.cs
  18. 15
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN/Abp/WebhooksManagement/WebhooksManagementDomainModule.cs
  19. 7
      aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs
  20. 6
      aspnet-core/services/LY.MicroService.Applications.Single/Properties/launchSettings.json
  21. 42
      aspnet-core/services/LY.MicroService.Applications.Single/appsettings.Development.json
  22. 6
      aspnet-core/services/LY.MicroService.Applications.Single/package.json

17
aspnet-core/migrations/LY.MicroService.Applications.Single.DbMigrator/appsettings.json

@ -14,7 +14,7 @@
"Clients": {
"VueAdmin": {
"ClientId": "vue-admin-client",
"RootUrl": "http://127.0.0.1:40080/"
"RootUrl": "http://localhost:5666/"
},
"InternalService": {
"ClientId": "InternalServiceClient",
@ -26,11 +26,22 @@
"Applications": {
"VueAdmin": {
"ClientId": "vue-admin-client",
"RootUrl": "http://127.0.0.1:40080/"
"ClientSecret": "1q2w3e*",
"RootUrls": [
"http://localhost:5666",
"http://localhost:30000"
]
},
"InternalService": {
"ClientId": "InternalServiceClient",
"ClientSecret": "1q2w3E*"
"ClientSecret": "1q2w3e*"
},
"VueOAuthClient": {
"ClientId": "vue-oauth-client",
"RootUrls": [
"http://localhost:5666",
"http://localhost:30000"
]
}
}
},

32
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore.MySql/SingleMigrationsEntityFrameworkCoreMySqlModule.cs

@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.MySQL;
using Volo.Abp.Guids;
@ -27,19 +28,26 @@ public class SingleMigrationsEntityFrameworkCoreMySqlModule : AbpModule
var dbProvider = Environment.GetEnvironmentVariable("APPLICATION_DATABASE_PROVIDER");
if ("MySql".Equals(dbProvider, StringComparison.InvariantCultureIgnoreCase))
{
var configuration = context.Services.GetConfiguration();
PreConfigure<CapOptions>(options =>
{
if (configuration.GetValue<bool>("CAP:IsEnabled"))
// TODO: MySQL EF 10提供商不可用,待完成后移除
// See: https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/issues/2007
throw new AbpInitializationException("MySQL EF 10 provider is unavailable. Please switch to another database infrastructure!")
{
options.UseMySql(
sqlOptions =>
{
configuration.GetSection("CAP:MySql").Bind(sqlOptions);
});
}
});
HelpLink = "https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/issues/2007",
};
//var configuration = context.Services.GetConfiguration();
//PreConfigure<CapOptions>(options =>
//{
// if (configuration.GetValue<bool>("CAP:IsEnabled"))
// {
// options.UseMySql(
// sqlOptions =>
// {
// configuration.GetSection("CAP:MySql").Bind(sqlOptions);
// });
// }
//});
}
}
public override void ConfigureServices(ServiceConfigurationContext context)

277
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/ClientDataSeederContributor.cs

@ -1,277 +0,0 @@
using Microsoft.Extensions.Configuration;
using OpenIddict.Abstractions;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
using Volo.Abp.OpenIddict.Applications;
using Volo.Abp.OpenIddict.Scopes;
using Volo.Abp.PermissionManagement;
namespace LY.MicroService.Applications.Single.EntityFrameworkCore.DataSeeder;
public class ClientDataSeederContributor : IDataSeedContributor, ITransientDependency
{
private readonly IOpenIddictApplicationManager _applicationManager;
private readonly IOpenIddictApplicationRepository _applicationRepository;
private readonly IOpenIddictScopeManager _scopeManager;
private readonly IOpenIddictScopeRepository _scopeRepository;
private readonly IPermissionDataSeeder _permissionDataSeeder;
private readonly IConfiguration _configuration;
private readonly ICurrentTenant _currentTenant;
public ClientDataSeederContributor(
IOpenIddictApplicationManager applicationManager,
IOpenIddictApplicationRepository applicationRepository,
IOpenIddictScopeManager scopeManager,
IOpenIddictScopeRepository scopeRepository,
IPermissionDataSeeder permissionDataSeeder,
IConfiguration configuration,
ICurrentTenant currentTenant)
{
_applicationManager = applicationManager;
_applicationRepository = applicationRepository;
_scopeManager = scopeManager;
_scopeRepository = scopeRepository;
_permissionDataSeeder = permissionDataSeeder;
_configuration = configuration;
_currentTenant = currentTenant;
}
public async virtual Task SeedAsync(DataSeedContext context)
{
using (_currentTenant.Change(context.TenantId))
{
await SeedOpenIddictAsync();
}
}
#region OpenIddict
private async Task SeedOpenIddictAsync()
{
await CreateScopeAsync("lingyun-abp-application");
await CreateApplicationAsync("lingyun-abp-application");
}
private async Task CreateScopeAsync(string scope)
{
if (await _scopeRepository.FindByNameAsync(scope) == null)
{
await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor()
{
Name = scope,
DisplayName = scope + " access",
DisplayNames =
{
[CultureInfo.GetCultureInfo("zh-Hans")] = "Abp API 应用程序访问",
[CultureInfo.GetCultureInfo("en")] = "Abp API Application Access"
},
Resources =
{
scope
}
});
}
}
private async Task CreateApplicationAsync(string scope)
{
var configurationSection = _configuration.GetSection("OpenIddict:Applications");
var vueClientId = configurationSection["VueAdmin:ClientId"];
if (!vueClientId.IsNullOrWhiteSpace())
{
var vueClientRootUrl = configurationSection["VueAdmin:RootUrl"].EnsureEndsWith('/');
if (await _applicationRepository.FindByClientIdAsync(vueClientId) == null)
{
await _applicationManager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = vueClientId,
ClientSecret = configurationSection["VueAdmin:ClientSecret"],
ApplicationType = OpenIddictConstants.ApplicationTypes.Web,
ConsentType = OpenIddictConstants.ConsentTypes.Explicit,
DisplayName = "Abp Vue Admin Client",
PostLogoutRedirectUris =
{
new Uri(vueClientRootUrl + "signout-callback"),
new Uri(vueClientRootUrl)
},
RedirectUris =
{
new Uri(vueClientRootUrl + "signin-callback"),
new Uri(vueClientRootUrl)
},
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization,
OpenIddictConstants.Permissions.Endpoints.Introspection,
OpenIddictConstants.Permissions.Endpoints.Revocation,
OpenIddictConstants.Permissions.Endpoints.EndSession,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.GrantTypes.Implicit,
OpenIddictConstants.Permissions.GrantTypes.Password,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
OpenIddictConstants.Permissions.GrantTypes.DeviceCode,
OpenIddictConstants.Permissions.GrantTypes.ClientCredentials,
OpenIddictConstants.Permissions.ResponseTypes.Code,
OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken,
OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken,
OpenIddictConstants.Permissions.ResponseTypes.CodeToken,
OpenIddictConstants.Permissions.ResponseTypes.IdToken,
OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken,
OpenIddictConstants.Permissions.ResponseTypes.None,
OpenIddictConstants.Permissions.ResponseTypes.Token,
OpenIddictConstants.Permissions.Scopes.Roles,
OpenIddictConstants.Permissions.Scopes.Profile,
OpenIddictConstants.Permissions.Scopes.Email,
OpenIddictConstants.Permissions.Scopes.Address,
OpenIddictConstants.Permissions.Scopes.Phone,
OpenIddictConstants.Permissions.Prefixes.Scope + scope
}
});
var vueClientPermissions = new string[1]
{
"AbpIdentity.UserLookup"
};
await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, vueClientId, vueClientPermissions);
}
}
var internalServiceClientId = configurationSection["InternalService:ClientId"];
if (!internalServiceClientId.IsNullOrWhiteSpace())
{
if (await _applicationRepository.FindByClientIdAsync(internalServiceClientId) == null)
{
await _applicationManager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = internalServiceClientId,
ClientSecret = configurationSection["InternalService:ClientSecret"] ?? "1q2w3e*",
ClientType = OpenIddictConstants.ClientTypes.Confidential,
ConsentType = OpenIddictConstants.ConsentTypes.Explicit,
ApplicationType = OpenIddictConstants.ApplicationTypes.Native,
DisplayName = "Abp Vue Admin Client",
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization,
OpenIddictConstants.Permissions.Endpoints.Introspection,
OpenIddictConstants.Permissions.Endpoints.Revocation,
OpenIddictConstants.Permissions.Endpoints.EndSession,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.GrantTypes.Implicit,
OpenIddictConstants.Permissions.GrantTypes.Password,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
OpenIddictConstants.Permissions.GrantTypes.DeviceCode,
OpenIddictConstants.Permissions.GrantTypes.ClientCredentials,
OpenIddictConstants.Permissions.ResponseTypes.Code,
OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken,
OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken,
OpenIddictConstants.Permissions.ResponseTypes.CodeToken,
OpenIddictConstants.Permissions.ResponseTypes.IdToken,
OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken,
OpenIddictConstants.Permissions.ResponseTypes.None,
OpenIddictConstants.Permissions.ResponseTypes.Token,
OpenIddictConstants.Permissions.Scopes.Roles,
OpenIddictConstants.Permissions.Scopes.Profile,
OpenIddictConstants.Permissions.Scopes.Email,
OpenIddictConstants.Permissions.Scopes.Address,
OpenIddictConstants.Permissions.Scopes.Phone,
OpenIddictConstants.Permissions.Prefixes.Scope + scope
}
});
var internalServicePermissions = new string[2]
{
"AbpIdentity.UserLookup","AbpIdentity.Users"
};
await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, internalServiceClientId, internalServicePermissions);
}
}
var oauthClientId = configurationSection["VueOAuthClient:ClientId"];
if (!oauthClientId.IsNullOrWhiteSpace())
{
var oauthClientRootUrls = configurationSection.GetSection("VueOAuthClient:RootUrls").Get<List<string>>();
if (await _applicationRepository.FindByClientIdAsync(oauthClientId) == null)
{
var application = new OpenIddictApplicationDescriptor
{
ClientId = oauthClientId,
ClientSecret = null,
ApplicationType = OpenIddictConstants.ApplicationTypes.Web,
ConsentType = OpenIddictConstants.ConsentTypes.Implicit,
DisplayName = "OAuth Client",
PostLogoutRedirectUris = { },
RedirectUris = { },
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization,
OpenIddictConstants.Permissions.Endpoints.Introspection,
OpenIddictConstants.Permissions.Endpoints.Revocation,
OpenIddictConstants.Permissions.Endpoints.EndSession,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
OpenIddictConstants.Permissions.ResponseTypes.Code,
OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken,
OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken,
OpenIddictConstants.Permissions.ResponseTypes.CodeToken,
OpenIddictConstants.Permissions.ResponseTypes.IdToken,
OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken,
OpenIddictConstants.Permissions.ResponseTypes.None,
OpenIddictConstants.Permissions.ResponseTypes.Token,
OpenIddictConstants.Permissions.Scopes.Roles,
OpenIddictConstants.Permissions.Scopes.Profile,
OpenIddictConstants.Permissions.Scopes.Email,
OpenIddictConstants.Permissions.Scopes.Address,
OpenIddictConstants.Permissions.Scopes.Phone,
OpenIddictConstants.Permissions.Prefixes.Scope + scope
}
};
oauthClientRootUrls.ForEach(url =>
{
application.PostLogoutRedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/')));
application.PostLogoutRedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/') + "signout-callback"));
application.RedirectUris.AddIfNotContains(new Uri(url));
application.RedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/') + "signin-callback"));
application.RedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/') + "swagger/oauth2-redirect.html"));
});
await _applicationManager.CreateAsync(application);
var oauthClientPermissions = new string[1]
{
"AbpIdentity.UserLookup"
};
await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, oauthClientId, oauthClientPermissions);
}
}
}
#endregion
}

178
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/OpenIddictDataSeederContributor.cs

@ -0,0 +1,178 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using OpenIddict.Abstractions;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.OpenIddict;
using Volo.Abp.OpenIddict.Applications;
using Volo.Abp.OpenIddict.Scopes;
using Volo.Abp.PermissionManagement;
namespace LY.MicroService.Applications.Single.EntityFrameworkCore.DataSeeder;
public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase, IDataSeedContributor, ITransientDependency
{
public ILogger<OpenIddictDataSeederContributor> Logger { protected get; set; }
protected IPermissionDataSeeder PermissionDataSeeder { get; }
public OpenIddictDataSeederContributor(
IConfiguration configuration,
IOpenIddictApplicationRepository openIddictApplicationRepository,
IAbpApplicationManager applicationManager,
IOpenIddictScopeRepository openIddictScopeRepository,
IOpenIddictScopeManager scopeManager,
IPermissionDataSeeder permissionDataSeeder)
: base(configuration, openIddictApplicationRepository, applicationManager, openIddictScopeRepository, scopeManager)
{
PermissionDataSeeder = permissionDataSeeder;
Logger = NullLogger<OpenIddictDataSeederContributor>.Instance;
}
public async virtual Task SeedAsync(DataSeedContext context)
{
var scope = "lingyun-abp-application";
Logger.LogInformation("Seeding the default scope...");
await CreateScopeAsync(scope);
Logger.LogInformation("Seeding the default applications...");
await CreateApplicationAsync(scope);
}
private async Task CreateScopeAsync(string scope)
{
await CreateScopesAsync(new OpenIddictScopeDescriptor
{
Name = scope,
DisplayName = scope + " access",
DisplayNames =
{
[CultureInfo.GetCultureInfo("zh-Hans")] = "Abp API 应用程序访问",
[CultureInfo.GetCultureInfo("en")] = "Abp API Application Access"
},
Resources =
{
scope
}
});
}
private async Task CreateApplicationAsync(string scope)
{
var configurationSection = Configuration.GetSection("OpenIddict:Applications");
var vueClientId = configurationSection["VueAdmin:ClientId"];
if (!vueClientId.IsNullOrWhiteSpace())
{
Logger.LogInformation("Seeding application {vueClientId}...", vueClientId);
var vueClientRootUrls = configurationSection.GetSection("VueAdmin:RootUrls").Get<List<string>>() ?? [];
var vueClientRedirectUrls = new List<string>();
var vueClientPostLogoutRedirectUrls = new List<string>();
vueClientRootUrls.ForEach(url =>
{
vueClientRedirectUrls.Add(url.EnsureEndsWith('/'));
vueClientRedirectUrls.Add(url.EnsureEndsWith('/') + "signin-callback");
vueClientPostLogoutRedirectUrls.Add(url.EnsureEndsWith('/'));
vueClientPostLogoutRedirectUrls.Add(url.EnsureEndsWith('/') + "signout-callback");
});
await CreateOrUpdateApplicationAsync(
OpenIddictConstants.ApplicationTypes.Web,
vueClientId,
OpenIddictConstants.ClientTypes.Confidential,
OpenIddictConstants.ConsentTypes.Explicit,
"Abp Vue Admin Client",
configurationSection["VueAdmin:ClientSecret"] ?? "1q2w3e*",
[OpenIddictConstants.GrantTypes.AuthorizationCode,
OpenIddictConstants.GrantTypes.Implicit,
OpenIddictConstants.GrantTypes.Password,
OpenIddictConstants.GrantTypes.RefreshToken],
[OpenIddictConstants.Scopes.OpenId,
OpenIddictConstants.Scopes.Email,
OpenIddictConstants.Scopes.Roles,
OpenIddictConstants.Scopes.Address,
OpenIddictConstants.Scopes.Phone,
OpenIddictConstants.Scopes.Profile,
OpenIddictConstants.Scopes.OfflineAccess,
scope],
vueClientRedirectUrls,
vueClientPostLogoutRedirectUrls);
var vueClientPermissions = new string[1]
{
"AbpIdentity.UserLookup"
};
await PermissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, vueClientId, vueClientPermissions);
}
var internalServiceClientId = configurationSection["InternalService:ClientId"];
if (!internalServiceClientId.IsNullOrWhiteSpace())
{
Logger.LogInformation("Seeding application {internalServiceClientId}...", internalServiceClientId);
await CreateOrUpdateApplicationAsync(
OpenIddictConstants.ApplicationTypes.Native,
internalServiceClientId,
OpenIddictConstants.ClientTypes.Confidential,
OpenIddictConstants.ConsentTypes.Explicit,
"Abp Internal Service Client",
configurationSection["InternalService:ClientSecret"] ?? "1q2w3e*",
[OpenIddictConstants.GrantTypes.ClientCredentials],
[OpenIddictConstants.ResponseTypes.Token, scope]);
}
var oauthClientId = configurationSection["VueOAuthClient:ClientId"];
if (!oauthClientId.IsNullOrWhiteSpace())
{
Logger.LogInformation("Seeding application {oauthClientId}...", oauthClientId);
var oauthClientRootUrls = configurationSection.GetSection("VueOAuthClient:RootUrls").Get<List<string>>() ?? [];
var oauthClientRedirectUrls = new List<string>();
var oauthClientPostLogoutRedirectUrls = new List<string>();
oauthClientRootUrls.ForEach(url =>
{
oauthClientRedirectUrls.Add(url.EnsureEndsWith('/'));
oauthClientRedirectUrls.Add(url.EnsureEndsWith('/') + "signin-callback");
oauthClientRedirectUrls.Add(url.EnsureEndsWith('/') + "swagger/oauth2-redirect.html");
oauthClientPostLogoutRedirectUrls.Add(url.EnsureEndsWith('/'));
oauthClientPostLogoutRedirectUrls.Add(url.EnsureEndsWith('/') + "signout-callback");
});
await CreateOrUpdateApplicationAsync(
OpenIddictConstants.ApplicationTypes.Web,
oauthClientId,
OpenIddictConstants.ClientTypes.Public,
OpenIddictConstants.ConsentTypes.Implicit,
"Abp OAuth Client",
null,
[OpenIddictConstants.GrantTypes.AuthorizationCode,
OpenIddictConstants.GrantTypes.RefreshToken],
[OpenIddictConstants.Scopes.OpenId,
OpenIddictConstants.Scopes.Email,
OpenIddictConstants.Scopes.Roles,
OpenIddictConstants.Scopes.Address,
OpenIddictConstants.Scopes.Phone,
OpenIddictConstants.Scopes.Profile,
OpenIddictConstants.Scopes.OfflineAccess,
scope],
oauthClientRedirectUrls,
oauthClientPostLogoutRedirectUrls);
var oauthClientPermissions = new string[1]
{
"AbpIdentity.UserLookup"
};
await PermissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, oauthClientId, oauthClientPermissions);
}
}
}

3
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/RolePermissionDataSeedContributor.cs

@ -4,12 +4,13 @@ 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 LY.MicroService.Applications.Single.EntityFrameworkCore.DataSeeder;
public class RolePermissionDataSeedContributor : IDataSeedContributor
public class RolePermissionDataSeedContributor : IDataSeedContributor, ITransientDependency
{
public ILogger<RolePermissionDataSeedContributor> Logger { protected get; set; }

4
aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/SingleDbMigrationService.cs

@ -29,7 +29,9 @@ public class SingleDbMigrationService : EfCoreRuntimeDatabaseMigratorBase<Single
ILoggerFactory loggerFactory,
IDataSeeder dataSeeder,
ITenantRepository tenantRepository)
: base("Platform-V70", unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory)
: base(
ConnectionStringNameAttribute.GetConnStringName<SingleMigrationsDbContext>(),
unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory)
{
DataSeeder = dataSeeder;
TenantRepository = tenantRepository;

6
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtectionManagement.Domain/LINGYUN/Abp/DataProtectionManagement/AbpDataProtectionManagementDomainModule.cs

@ -21,9 +21,9 @@ public class AbpDataProtectionManagementDomainModule : AbpModule
Configure<AbpDistributedEntityEventOptions>(options =>
{
options.EtoMappings.Add<EntityTypeInfo, EntityTypeInfoEto>();
options.EtoMappings.Add<RoleEntityRule, RoleEntityRuleEto>();
options.EtoMappings.Add<OrganizationUnitEntityRule, OrganizationUnitEntityRuleEto>();
options.EtoMappings.Add<EntityTypeInfo, EntityTypeInfoEto>(typeof(AbpDataProtectionManagementDomainModule));
options.EtoMappings.Add<RoleEntityRule, RoleEntityRuleEto>(typeof(AbpDataProtectionManagementDomainModule));
options.EtoMappings.Add<OrganizationUnitEntityRule, OrganizationUnitEntityRuleEto>(typeof(AbpDataProtectionManagementDomainModule));
options.AutoEventSelectors.Add<EntityTypeInfo>();
options.AutoEventSelectors.Add<RoleEntityRule>();

79
aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/AbpLocalizationManagementDomainModule.cs

@ -24,11 +24,19 @@ namespace LINGYUN.Abp.LocalizationManagement;
typeof(AbpLocalizationManagementDomainSharedModule))]
public class AbpLocalizationManagementDomainModule : AbpModule
{
private readonly CancellationTokenSource cancellationTokenSource = new();
private readonly CancellationTokenSource _cancellationTokenSource = new();
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMapperlyObjectMapper<AbpLocalizationManagementDomainModule>();
if (context.Services.IsDataMigrationEnvironment())
{
Configure<AbpLocalizationManagementOptions>(options =>
{
options.SaveStaticLocalizationsToDatabase = false;
});
}
Configure<AbpLocalizationOptions>(options =>
{
options.GlobalContributors.Add<LocalizationResourceContributor>();
@ -36,9 +44,9 @@ public class AbpLocalizationManagementDomainModule : AbpModule
Configure<AbpDistributedEntityEventOptions>(options =>
{
options.EtoMappings.Add<Text, TextEto>();
options.EtoMappings.Add<Language, LanguageEto>();
options.EtoMappings.Add<Resource, ResourceEto>();
options.EtoMappings.Add<Text, TextEto>(typeof(AbpLocalizationManagementDomainModule));
options.EtoMappings.Add<Language, LanguageEto>(typeof(AbpLocalizationManagementDomainModule));
options.EtoMappings.Add<Resource, ResourceEto>(typeof(AbpLocalizationManagementDomainModule));
});
// 定期更新本地化缓存缓解措施
@ -52,69 +60,14 @@ public class AbpLocalizationManagementDomainModule : AbpModule
public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
if (!context.ServiceProvider.IsDataMigrationEnvironment())
{
await SaveLocalizationAsync(context);
}
var rootServiceProvider = context.ServiceProvider.GetRequiredService<IRootServiceProvider>();
var initializer = rootServiceProvider.GetRequiredService<LocalizationDynamicInitializer>();
await initializer.InitializeAsync(true, _cancellationTokenSource.Token);
}
public override Task OnApplicationShutdownAsync(ApplicationShutdownContext context)
{
cancellationTokenSource.CancelAsync();
_cancellationTokenSource.CancelAsync();
return Task.CompletedTask;
}
private async Task SaveLocalizationAsync(ApplicationInitializationContext context)
{
var options = context.ServiceProvider.GetRequiredService<IOptions<AbpLocalizationManagementOptions>>();
if (options.Value.SaveStaticLocalizationsToDatabase)
{
var rootServiceProvider = context.ServiceProvider.GetRequiredService<IRootServiceProvider>();
await Task.Run(async () =>
{
using (var scope = rootServiceProvider.CreateScope())
{
var applicationLifetime = scope.ServiceProvider.GetService<IHostApplicationLifetime>();
var cancellationTokenProvider = scope.ServiceProvider.GetRequiredService<ICancellationTokenProvider>();
var cancellationToken = applicationLifetime?.ApplicationStopping ?? cancellationTokenSource.Token;
try
{
using (cancellationTokenProvider.Use(cancellationToken))
{
if (cancellationTokenProvider.Token.IsCancellationRequested)
{
return;
}
await Policy.Handle<Exception>()
.WaitAndRetryAsync(8,
retryAttempt => TimeSpan.FromSeconds(
RandomHelper.GetRandom((int)Math.Pow(2.0, retryAttempt) * 8, (int)Math.Pow(2.0, retryAttempt) * 12)))
.ExecuteAsync(async _ =>
{
try
{
await scope.ServiceProvider
.GetRequiredService<IStaticLocalizationSaver>()
.SaveAsync();
}
catch (Exception ex)
{
scope.ServiceProvider
.GetService<ILogger<AbpLocalizationModule>>()
?.LogException(ex);
throw;
}
},
cancellationTokenProvider.Token);
}
}
catch
{
}
}
});
}
}
}

121
aspnet-core/modules/localization-management/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationDynamicInitializer.cs

@ -0,0 +1,121 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Polly;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace LINGYUN.Abp.LocalizationManagement;
public class LocalizationDynamicInitializer : ITransientDependency
{
public ILogger<LocalizationDynamicInitializer> Logger { get; set; }
protected IServiceProvider ServiceProvider { get; }
protected IOptions<AbpLocalizationManagementOptions> Options { get; }
protected IHostApplicationLifetime ApplicationLifetime { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected IStaticLocalizationSaver StaticLocalizationSaver { get; }
public LocalizationDynamicInitializer(
IServiceProvider serviceProvider,
IOptions<AbpLocalizationManagementOptions> options,
ICancellationTokenProvider cancellationTokenProvider,
IStaticLocalizationSaver staticLocalizationSaver)
{
ServiceProvider = serviceProvider;
Options = options;
ApplicationLifetime = ServiceProvider.GetService<IHostApplicationLifetime>();
CancellationTokenProvider = cancellationTokenProvider;
StaticLocalizationSaver = staticLocalizationSaver;
Logger = NullLogger<LocalizationDynamicInitializer>.Instance;
}
public virtual Task InitializeAsync(bool runInBackground, CancellationToken cancellationToken = default)
{
if (!Options.Value.SaveStaticLocalizationsToDatabase)
{
return Task.CompletedTask;
}
if (runInBackground)
{
Task.Run(async () =>
{
if (cancellationToken == default && ApplicationLifetime?.ApplicationStopping != null)
{
cancellationToken = ApplicationLifetime.ApplicationStopping;
}
await ExecuteInitializationAsync(cancellationToken);
}, cancellationToken);
return Task.CompletedTask;
}
return ExecuteInitializationAsync(cancellationToken);
}
protected virtual async Task ExecuteInitializationAsync(CancellationToken cancellationToken)
{
try
{
using (CancellationTokenProvider.Use(cancellationToken))
{
if (CancellationTokenProvider.Token.IsCancellationRequested)
{
return;
}
await SaveStaticLocalizationToDatabaseAsync(cancellationToken);
if (CancellationTokenProvider.Token.IsCancellationRequested)
{
return;
}
}
}
catch
{
// No need to log here since inner calls log
}
}
protected virtual async Task SaveStaticLocalizationToDatabaseAsync(CancellationToken cancellationToken)
{
if (!Options.Value.SaveStaticLocalizationsToDatabase)
{
return;
}
await Policy
.Handle<Exception>(e => e is not OperationCanceledException)
.WaitAndRetryAsync(
8,
retryAttempt => TimeSpan.FromSeconds(
Volo.Abp.RandomHelper.GetRandom(
(int)Math.Pow(2, retryAttempt) * 8,
(int)Math.Pow(2, retryAttempt) * 12)
)
)
.ExecuteAsync(async _ =>
{
try
{
cancellationToken.ThrowIfCancellationRequested();
await StaticLocalizationSaver.SaveAsync();
}
catch (Exception ex)
{
Logger.LogException(ex);
throw; // Polly will catch it
}
}, cancellationToken);
}
}

9
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/AbpNotificationsDomainModule.cs

@ -4,6 +4,7 @@ using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Caching;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Mapperly;
using Volo.Abp.Modularity;
using Volo.Abp.Threading;
@ -38,11 +39,11 @@ public class AbpNotificationsDomainModule : AbpModule
AsyncHelper.RunSync(() => OnApplicationInitializationAsync(context));
}
public override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
return context.ServiceProvider
.GetRequiredService<NotificationDefinitionInitializer>()
.InitializeDynamicNotifications(_cancellationTokenSource.Token);
var rootServiceProvider = context.ServiceProvider.GetRequiredService<IRootServiceProvider>();
var initializer = rootServiceProvider.GetRequiredService<NotificationDynamicInitializer>();
await initializer.InitializeAsync(true, _cancellationTokenSource.Token);
}
public override Task OnApplicationShutdownAsync(ApplicationShutdownContext context)

145
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/NotificationDynamicInitializer.cs

@ -0,0 +1,145 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Polly;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace LINGYUN.Abp.Notifications;
public class NotificationDynamicInitializer : ITransientDependency
{
public ILogger<NotificationDynamicInitializer> Logger { get; set; }
protected IServiceProvider ServiceProvider { get; }
protected IOptions<AbpNotificationsManagementOptions> Options { get; }
protected IHostApplicationLifetime ApplicationLifetime { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected IDynamicNotificationDefinitionStore DynamicNotificationDefinitionStore { get; }
protected IStaticNotificationSaver StaticNotificationSaver { get; }
public NotificationDynamicInitializer(
IServiceProvider serviceProvider,
IOptions<AbpNotificationsManagementOptions> options,
ICancellationTokenProvider cancellationTokenProvider,
IDynamicNotificationDefinitionStore dynamicNotificationDefinitionStore,
IStaticNotificationSaver staticNotificationSaver)
{
ServiceProvider = serviceProvider;
Options = options;
CancellationTokenProvider = cancellationTokenProvider;
DynamicNotificationDefinitionStore = dynamicNotificationDefinitionStore;
StaticNotificationSaver = staticNotificationSaver;
ApplicationLifetime = ServiceProvider.GetService<IHostApplicationLifetime>();
Logger = NullLogger<NotificationDynamicInitializer>.Instance;
}
public virtual Task InitializeAsync(bool runInBackground, CancellationToken cancellationToken = default)
{
if (!Options.Value.SaveStaticNotificationsToDatabase && !Options.Value.IsDynamicNotificationsStoreEnabled)
{
return Task.CompletedTask;
}
if (runInBackground)
{
Task.Run(async () =>
{
if (cancellationToken == default && ApplicationLifetime?.ApplicationStopping != null)
{
cancellationToken = ApplicationLifetime.ApplicationStopping;
}
await ExecuteInitializationAsync(cancellationToken);
}, cancellationToken);
return Task.CompletedTask;
}
return ExecuteInitializationAsync(cancellationToken);
}
protected virtual async Task ExecuteInitializationAsync(CancellationToken cancellationToken)
{
try
{
using (CancellationTokenProvider.Use(cancellationToken))
{
if (CancellationTokenProvider.Token.IsCancellationRequested)
{
return;
}
await SaveStaticNotificationssToDatabaseAsync(cancellationToken);
if (CancellationTokenProvider.Token.IsCancellationRequested)
{
return;
}
await PreCacheDynamicNotificationsAsync(cancellationToken);
}
}
catch
{
// No need to log here since inner calls log
}
}
protected virtual async Task SaveStaticNotificationssToDatabaseAsync(CancellationToken cancellationToken)
{
if (!Options.Value.SaveStaticNotificationsToDatabase)
{
return;
}
await Policy
.Handle<Exception>(e => e is not OperationCanceledException)
.WaitAndRetryAsync(
8,
retryAttempt => TimeSpan.FromSeconds(
Volo.Abp.RandomHelper.GetRandom(
(int)Math.Pow(2, retryAttempt) * 8,
(int)Math.Pow(2, retryAttempt) * 12)
)
)
.ExecuteAsync(async _ =>
{
try
{
cancellationToken.ThrowIfCancellationRequested();
await StaticNotificationSaver.SaveAsync();
}
catch (Exception ex)
{
Logger.LogException(ex);
throw; // Polly will catch it
}
}, cancellationToken);
}
protected virtual async Task PreCacheDynamicNotificationsAsync(CancellationToken cancellationToken)
{
if (!Options.Value.IsDynamicNotificationsStoreEnabled)
{
return;
}
try
{
cancellationToken.ThrowIfCancellationRequested();
// Pre-cache notifications, so first request doesn't wait
await DynamicNotificationDefinitionStore.GetGroupsAsync();
}
catch (Exception ex)
{
Logger.LogException(ex);
throw; // It will be cached in Initialize()
}
}
}

4
aspnet-core/modules/saas/LINGYUN.Abp.Saas.Domain/LINGYUN/Abp/Saas/AbpSaasDomainModule.cs

@ -26,8 +26,8 @@ public class AbpSaasDomainModule : AbpModule
Configure<AbpDistributedEntityEventOptions>(options =>
{
options.EtoMappings.Add<Edition, EditionEto>();
options.EtoMappings.Add<Tenant, TenantEto>();
options.EtoMappings.Add<Edition, EditionEto>(typeof(AbpSaasDomainModule));
options.EtoMappings.Add<Tenant, TenantEto>(typeof(AbpSaasDomainModule));
options.AutoEventSelectors.Add<Edition>();
options.AutoEventSelectors.Add<Tenant>();

13
aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/AbpTextTemplatingDomainModule.cs

@ -4,6 +4,7 @@ using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Caching;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Mapperly;
using Volo.Abp.Modularity;
@ -27,8 +28,8 @@ public class AbpTextTemplatingDomainModule : AbpModule
Configure<AbpDistributedEntityEventOptions>(options =>
{
options.EtoMappings.Add<TextTemplate, TextTemplateEto>();
options.EtoMappings.Add<TextTemplateDefinition, TextTemplateDefinitionEto>();
options.EtoMappings.Add<TextTemplate, TextTemplateEto>(typeof(AbpTextTemplatingDomainModule));
options.EtoMappings.Add<TextTemplateDefinition, TextTemplateDefinitionEto>(typeof(AbpTextTemplatingDomainModule));
// TODO: CAP组件异常将导致应用无法启动, 临时禁用
// options.AutoEventSelectors.Add<TextTemplate>();
@ -49,11 +50,11 @@ public class AbpTextTemplatingDomainModule : AbpModule
AsyncHelper.RunSync(() => OnApplicationInitializationAsync(context));
}
public override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
return context.ServiceProvider
.GetRequiredService<TextTemplateDefinitionInitializer>()
.InitializeDynamicTemplates(_cancellationTokenSource.Token);
var rootServiceProvider = context.ServiceProvider.GetRequiredService<IRootServiceProvider>();
var initializer = rootServiceProvider.GetRequiredService<TextTemplateDynamicInitializer>();
await initializer.InitializeAsync(true, _cancellationTokenSource.Token);
}
public override Task OnApplicationShutdownAsync(ApplicationShutdownContext context)

115
aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionInitializer.cs

@ -1,115 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Polly;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace LINGYUN.Abp.TextTemplating;
public class TextTemplateDefinitionInitializer : ITransientDependency
{
protected IRootServiceProvider RootServiceProvider { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected AbpTextTemplatingCachingOptions TextTemplatingCachingOptions { get; }
public TextTemplateDefinitionInitializer(
IRootServiceProvider rootServiceProvider,
ICancellationTokenProvider cancellationTokenProvider,
IOptions<AbpTextTemplatingCachingOptions> textTemplatingCachingOptions)
{
RootServiceProvider = rootServiceProvider;
CancellationTokenProvider = cancellationTokenProvider;
TextTemplatingCachingOptions = textTemplatingCachingOptions.Value;
}
public async virtual Task InitializeDynamicTemplates(CancellationToken cancellationToken)
{
if (!TextTemplatingCachingOptions.SaveStaticTemplateDefinitionToDatabase && !TextTemplatingCachingOptions.IsDynamicTemplateDefinitionStoreEnabled)
{
return;
}
using var scope = RootServiceProvider.CreateScope();
var applicationLifetime = scope.ServiceProvider.GetService<IHostApplicationLifetime>();
var token = applicationLifetime?.ApplicationStopping ?? cancellationToken;
using (CancellationTokenProvider.Use(token))
{
if (CancellationTokenProvider.Token.IsCancellationRequested)
{
return;
}
await SaveStaticTemplateDefinitionsToDatabaseAsync(scope);
if (CancellationTokenProvider.Token.IsCancellationRequested)
{
return;
}
await PreCacheDynamicTemplateDefinitionsAsync(scope);
}
}
private async Task SaveStaticTemplateDefinitionsToDatabaseAsync(IServiceScope serviceScope)
{
if (!TextTemplatingCachingOptions.SaveStaticTemplateDefinitionToDatabase)
{
return;
}
await Policy
.Handle<Exception>()
.WaitAndRetryAsync(8, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt) * 10))
.ExecuteAsync(async _ =>
{
try
{
// ReSharper disable once AccessToDisposedClosure
var saver = serviceScope.ServiceProvider.GetRequiredService<IStaticTemplateSaver>();
await saver.SaveDefinitionTemplateAsync();
await saver.SaveTemplateContentAsync();
}
catch (Exception ex)
{
// ReSharper disable once AccessToDisposedClosure
serviceScope.ServiceProvider
.GetService<ILogger<TextTemplateDefinitionInitializer>>()?
.LogException(ex);
throw; // Polly will catch it
}
}, CancellationTokenProvider.Token);
}
private async Task PreCacheDynamicTemplateDefinitionsAsync(IServiceScope serviceScope)
{
if (!TextTemplatingCachingOptions.IsDynamicTemplateDefinitionStoreEnabled)
{
return;
}
try
{
// ReSharper disable once AccessToDisposedClosure
var store = serviceScope.ServiceProvider.GetRequiredService<ITemplateDefinitionStore>();
await store.GetAllAsync();
}
catch (Exception ex)
{
// ReSharper disable once AccessToDisposedClosure
serviceScope.ServiceProvider
.GetService<ILogger<TextTemplateDefinitionInitializer>>()?
.LogException(ex);
throw; // Polly will catch it
}
}
}

148
aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateDynamicInitializer.cs

@ -0,0 +1,148 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Polly;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace LINGYUN.Abp.TextTemplating;
public class TextTemplateDynamicInitializer : ITransientDependency
{
public ILogger<TextTemplateDynamicInitializer> Logger { get; set; }
protected IServiceProvider ServiceProvider { get; }
protected IOptions<AbpTextTemplatingCachingOptions> Options { get; }
protected IHostApplicationLifetime ApplicationLifetime { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected ITemplateDefinitionStore TemplateDefinitionStore { get; }
protected IStaticTemplateSaver StaticTemplateSaver { get; }
public TextTemplateDynamicInitializer(
IServiceProvider serviceProvider,
IOptions<AbpTextTemplatingCachingOptions> options,
ICancellationTokenProvider cancellationTokenProvider,
ITemplateDefinitionStore templateDefinitionStore,
IStaticTemplateSaver staticTemplateSaver)
{
ServiceProvider = serviceProvider;
Options = options;
ApplicationLifetime = ServiceProvider.GetService<IHostApplicationLifetime>();
CancellationTokenProvider = cancellationTokenProvider;
TemplateDefinitionStore = templateDefinitionStore;
StaticTemplateSaver = staticTemplateSaver;
Logger = NullLogger<TextTemplateDynamicInitializer>.Instance;
}
public virtual Task InitializeAsync(bool runInBackground, CancellationToken cancellationToken = default)
{
if (!Options.Value.SaveStaticTemplateDefinitionToDatabase && !Options.Value.IsDynamicTemplateDefinitionStoreEnabled)
{
return Task.CompletedTask;
}
if (runInBackground)
{
Task.Run(async () =>
{
if (cancellationToken == default && ApplicationLifetime?.ApplicationStopping != null)
{
cancellationToken = ApplicationLifetime.ApplicationStopping;
}
await ExecuteInitializationAsync(cancellationToken);
}, cancellationToken);
return Task.CompletedTask;
}
return ExecuteInitializationAsync(cancellationToken);
}
protected virtual async Task ExecuteInitializationAsync(CancellationToken cancellationToken)
{
try
{
using (CancellationTokenProvider.Use(cancellationToken))
{
if (CancellationTokenProvider.Token.IsCancellationRequested)
{
return;
}
await SaveStaticTextTemplatesToDatabaseAsync(cancellationToken);
if (CancellationTokenProvider.Token.IsCancellationRequested)
{
return;
}
await PreCacheDynamicTextTemplatesAsync(cancellationToken);
}
}
catch
{
// No need to log here since inner calls log
}
}
protected virtual async Task SaveStaticTextTemplatesToDatabaseAsync(CancellationToken cancellationToken)
{
if (!Options.Value.SaveStaticTemplateDefinitionToDatabase)
{
return;
}
await Policy
.Handle<Exception>(e => e is not OperationCanceledException)
.WaitAndRetryAsync(
8,
retryAttempt => TimeSpan.FromSeconds(
Volo.Abp.RandomHelper.GetRandom(
(int)Math.Pow(2, retryAttempt) * 8,
(int)Math.Pow(2, retryAttempt) * 12)
)
)
.ExecuteAsync(async _ =>
{
try
{
cancellationToken.ThrowIfCancellationRequested();
await StaticTemplateSaver.SaveDefinitionTemplateAsync();
await StaticTemplateSaver.SaveTemplateContentAsync();
}
catch (Exception ex)
{
Logger.LogException(ex);
throw; // Polly will catch it
}
}, cancellationToken);
}
protected virtual async Task PreCacheDynamicTextTemplatesAsync(CancellationToken cancellationToken)
{
if (!Options.Value.IsDynamicTemplateDefinitionStoreEnabled)
{
return;
}
try
{
cancellationToken.ThrowIfCancellationRequested();
// Pre-cache tempte definitions, so first request doesn't wait
await TemplateDefinitionStore.GetAllAsync();
}
catch (Exception ex)
{
Logger.LogException(ex);
throw; // It will be cached in Initialize()
}
}
}

94
aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN/Abp/WebhooksManagement/WebhookDefinitionInitializer.cs

@ -1,94 +0,0 @@
using LINGYUN.Abp.Webhooks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
using Volo.Abp.Uow;
namespace LINGYUN.Abp.WebhooksManagement;
public class WebhookDefinitionInitializer : ITransientDependency
{
protected IRootServiceProvider RootServiceProvider { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected WebhooksManagementOptions WebhooksManagementOptions { get; }
public WebhookDefinitionInitializer(
IRootServiceProvider rootServiceProvider,
ICancellationTokenProvider cancellationTokenProvider,
IOptions<WebhooksManagementOptions> webhooksManagementOptions)
{
RootServiceProvider = rootServiceProvider;
CancellationTokenProvider = cancellationTokenProvider;
WebhooksManagementOptions = webhooksManagementOptions.Value;
}
[UnitOfWork]
public async virtual Task InitializeDynamicWebhooks(CancellationToken cancellationToken)
{
if (!WebhooksManagementOptions.SaveStaticWebhooksToDatabase && !WebhooksManagementOptions.IsDynamicWebhookStoreEnabled)
{
return;
}
using var scope = RootServiceProvider.CreateScope();
var applicationLifetime = scope.ServiceProvider.GetService<IHostApplicationLifetime>();
var token = applicationLifetime?.ApplicationStopping ?? cancellationToken;
try
{
using (CancellationTokenProvider.Use(cancellationToken))
{
if (CancellationTokenProvider.Token.IsCancellationRequested)
{
return;
}
await SaveStaticNotificationsToDatabaseAsync(scope);
if (CancellationTokenProvider.Token.IsCancellationRequested)
{
return;
}
await PreCacheDynamicNotificationsAsync(scope);
}
}
catch (OperationCanceledException)
{
// ignore
}
catch (Exception ex)
{
scope.ServiceProvider
.GetService<ILogger<WebhookDefinitionInitializer>>()?
.LogException(ex);
}
}
private async Task SaveStaticNotificationsToDatabaseAsync(IServiceScope serviceScope)
{
if (!WebhooksManagementOptions.SaveStaticWebhooksToDatabase)
{
return;
}
var saver = serviceScope.ServiceProvider.GetRequiredService<IStaticWebhookSaver>();
await saver.SaveAsync();
}
private async Task PreCacheDynamicNotificationsAsync(IServiceScope serviceScope)
{
if (!WebhooksManagementOptions.IsDynamicWebhookStoreEnabled)
{
return;
}
var store = serviceScope.ServiceProvider.GetRequiredService<IDynamicWebhookDefinitionStore>();
await store.GetGroupsAsync();
}
}

150
aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN/Abp/WebhooksManagement/WebhookDynamicInitializer.cs

@ -0,0 +1,150 @@
using JetBrains.Annotations;
using LINGYUN.Abp.Webhooks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Polly;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace LINGYUN.Abp.WebhooksManagement;
public class WebhookDynamicInitializer : ITransientDependency
{
public ILogger<WebhookDynamicInitializer> Logger { get; set; }
protected IServiceProvider ServiceProvider { get; }
protected IOptions<WebhooksManagementOptions> Options { get; }
[CanBeNull]
protected IHostApplicationLifetime ApplicationLifetime { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected IDynamicWebhookDefinitionStore DynamicWebhookDefinitionStore { get; }
protected IStaticWebhookSaver StaticWebhookSaver { get; }
public WebhookDynamicInitializer(
IServiceProvider serviceProvider,
IOptions<WebhooksManagementOptions> options,
ICancellationTokenProvider cancellationTokenProvider,
IDynamicWebhookDefinitionStore dynamicWebhookDefinitionStore,
IStaticWebhookSaver staticWebhookSaver)
{
ServiceProvider = serviceProvider;
Options = options;
ApplicationLifetime = ServiceProvider.GetService<IHostApplicationLifetime>();
CancellationTokenProvider = cancellationTokenProvider;
DynamicWebhookDefinitionStore = dynamicWebhookDefinitionStore;
StaticWebhookSaver = staticWebhookSaver;
Logger = NullLogger<WebhookDynamicInitializer>.Instance;
}
public virtual Task InitializeAsync(bool runInBackground, CancellationToken cancellationToken = default)
{
if (!Options.Value.SaveStaticWebhooksToDatabase && !Options.Value.IsDynamicWebhookStoreEnabled)
{
return Task.CompletedTask;
}
if (runInBackground)
{
Task.Run(async () =>
{
if (cancellationToken == default && ApplicationLifetime?.ApplicationStopping != null)
{
cancellationToken = ApplicationLifetime.ApplicationStopping;
}
await ExecuteInitializationAsync(cancellationToken);
}, cancellationToken);
return Task.CompletedTask;
}
return ExecuteInitializationAsync(cancellationToken);
}
protected virtual async Task ExecuteInitializationAsync(CancellationToken cancellationToken)
{
try
{
using (CancellationTokenProvider.Use(cancellationToken))
{
if (CancellationTokenProvider.Token.IsCancellationRequested)
{
return;
}
await SaveStaticWebhooksToDatabaseAsync(cancellationToken);
if (CancellationTokenProvider.Token.IsCancellationRequested)
{
return;
}
await PreCacheDynamicWebhooksAsync(cancellationToken);
}
}
catch
{
// No need to log here since inner calls log
}
}
protected virtual async Task SaveStaticWebhooksToDatabaseAsync(CancellationToken cancellationToken)
{
if (!Options.Value.SaveStaticWebhooksToDatabase)
{
return;
}
await Policy
.Handle<Exception>(e => e is not OperationCanceledException)
.WaitAndRetryAsync(
8,
retryAttempt => TimeSpan.FromSeconds(
Volo.Abp.RandomHelper.GetRandom(
(int)Math.Pow(2, retryAttempt) * 8,
(int)Math.Pow(2, retryAttempt) * 12)
)
)
.ExecuteAsync(async _ =>
{
try
{
cancellationToken.ThrowIfCancellationRequested();
await StaticWebhookSaver.SaveAsync();
}
catch (Exception ex)
{
Logger.LogException(ex);
throw; // Polly will catch it
}
}, cancellationToken);
}
protected virtual async Task PreCacheDynamicWebhooksAsync(CancellationToken cancellationToken)
{
if (!Options.Value.IsDynamicWebhookStoreEnabled)
{
return;
}
try
{
cancellationToken.ThrowIfCancellationRequested();
// Pre-cache webhoks, so first request doesn't wait
await DynamicWebhookDefinitionStore.GetGroupsAsync();
}
catch (Exception ex)
{
Logger.LogException(ex);
throw; // It will be cached in Initialize()
}
}
}

15
aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN/Abp/WebhooksManagement/WebhooksManagementDomainModule.cs

@ -5,6 +5,7 @@ using System.Threading;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Mapperly;
using Volo.Abp.Modularity;
@ -28,9 +29,9 @@ public class WebhooksManagementDomainModule : AbpModule
Configure<AbpDistributedEntityEventOptions>(options =>
{
options.EtoMappings.Add<WebhookEventRecord, WebhookEventEto>();
options.EtoMappings.Add<WebhookSendRecord, WebhookSendAttemptEto>();
options.EtoMappings.Add<WebhookSubscription, WebhookSubscriptionEto>();
options.EtoMappings.Add<WebhookEventRecord, WebhookEventEto>(typeof(WebhooksManagementDomainModule));
options.EtoMappings.Add<WebhookSendRecord, WebhookSendAttemptEto>(typeof(WebhooksManagementDomainModule));
options.EtoMappings.Add<WebhookSubscription, WebhookSubscriptionEto>(typeof(WebhooksManagementDomainModule));
options.AutoEventSelectors.Add<WebhookEventRecord>();
options.AutoEventSelectors.Add<WebhookSendRecord>();
@ -88,11 +89,11 @@ public class WebhooksManagementDomainModule : AbpModule
AsyncHelper.RunSync(() => OnApplicationInitializationAsync(context));
}
public override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
return context.ServiceProvider
.GetRequiredService<WebhookDefinitionInitializer>()
.InitializeDynamicWebhooks(_cancellationTokenSource.Token);
var rootServiceProvider = context.ServiceProvider.GetRequiredService<IRootServiceProvider>();
var initializer = rootServiceProvider.GetRequiredService<WebhookDynamicInitializer>();
await initializer.InitializeAsync(true, _cancellationTokenSource.Token);
}
public override Task OnApplicationShutdownAsync(ApplicationShutdownContext context)

7
aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.SignalR;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling;
using VoloAbpExceptionHandlingOptions = Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingOptions;
namespace LY.MicroService.Applications.Single;
@ -785,6 +786,12 @@ public partial class MicroServiceApplicationsSingleModule
{
bundle.AddContributors(typeof(SingleGlobalScriptContributor));
});
options.StyleBundles
.Configure(LeptonXLiteThemeBundles.Styles.Global, bundle =>
{
bundle.AddFiles("/css/global-styles.css");
});
});
Configure<AbpAspNetCoreMvcOptions>(options =>

6
aspnet-core/services/LY.MicroService.Applications.Single/Properties/launchSettings.json

@ -12,7 +12,7 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://0.0.0.0:30001",
"applicationUrl": "http://0.0.0.0:30000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"APPLICATION_DATABASE_PROVIDER": "PostgreSql"
@ -22,7 +22,7 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://0.0.0.0:30001",
"applicationUrl": "http://0.0.0.0:30000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"APPLICATION_DATABASE_PROVIDER": "MySql"
@ -32,7 +32,7 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://0.0.0.0:30001",
"applicationUrl": "http://0.0.0.0:30000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"APPLICATION_DATABASE_PROVIDER": "SqlServer"

42
aspnet-core/services/LY.MicroService.Applications.Single/appsettings.Development.json

@ -1,22 +1,22 @@
{
"App": {
"ShowPii": true,
"SelfUrl": "http://127.0.0.1:30001/",
"CorsOrigins": [ "http://127.0.0.1:5666", "http://127.0.0.1:30001" ],
"SelfUrl": "http://localhost:30000/",
"CorsOrigins": [ "http://localhost:5666", "http://localhost:30000" ],
"Urls": {
"Applications": {
"MVC": {
"RootUrl": "http://127.0.0.1:30001/",
"RootUrl": "http://localhost:30000/",
"Urls": {
"Abp.Account.EmailConfirm": "Account/EmailConfirm",
"Abp.Account.EmailVerifyLogin": "Account/VerifyCode"
}
},
"STS": {
"RootUrl": "http://127.0.0.1:30001/"
"RootUrl": "http://localhost:30000/"
},
"VueVbenAdmin": {
"RootUrl": "http://127.0.0.1:3100",
"RootUrl": "http://localhost:3100",
"Urls": {
"Abp.Account.EmailConfirm": "account/email-confirm"
}
@ -38,7 +38,7 @@
"FailedRetryCount": 10
},
"RabbitMQ": {
"HostName": "127.0.0.1",
"HostName": "localhost",
"Port": 5672,
"UserName": "admin",
"Password": "123456",
@ -46,7 +46,7 @@
"VirtualHost": "/"
},
"Redis": {
"Configuration": "127.0.0.1"
"Configuration": "localhost"
}
},
"DistributedCache": {
@ -60,7 +60,7 @@
"DistributedLock": {
"IsEnabled": true,
"Redis": {
"Configuration": "127.0.0.1,defaultDatabase=14"
"Configuration": "localhost,defaultDatabase=14"
}
},
"Elsa": {
@ -81,7 +81,7 @@
"PublishWebhook": true
},
"Server": {
"BaseUrl": "http://127.0.0.1:30001"
"BaseUrl": "http://localhost:30000"
}
},
"Quartz": {
@ -93,20 +93,20 @@
},
"Redis": {
"IsEnabled": true,
"Configuration": "127.0.0.1,defaultDatabase=15,allowAdmin=true",
"Configuration": "localhost,defaultDatabase=15,allowAdmin=true",
"InstanceName": "LINGYUN.Abp.Application"
},
"Features": {
"Validation": {
"Redis": {
"Configuration": "127.0.0.1,defaultDatabase=13",
"Configuration": "localhost,defaultDatabase=13",
"InstanceName": "LINGYUN.Abp.Application"
}
}
},
"AuthServer": {
"UseOpenIddict": true,
"Authority": "http://127.0.0.1:30001/",
"Authority": "http://localhost:30000/",
"Audience": "lingyun-abp-application",
"RequireHttpsMetadata": false,
"SwaggerClientId": "vue-oauth-client"
@ -115,7 +115,7 @@
"Clients": {
"VueAdmin": {
"ClientId": "vue-admin-client",
"RootUrl": "http://127.0.0.1:3100/"
"RootUrl": "http://localhost:3100/"
},
"InternalService": {
"ClientId": "InternalServiceClient"
@ -126,7 +126,11 @@
"Applications": {
"VueAdmin": {
"ClientId": "vue-admin-client",
"RootUrl": "http://127.0.0.1:3100/"
"ClientSecret": "1q2w3e*",
"RootUrls": [
"http://localhost:5666",
"http://localhost:30000"
]
},
"InternalService": {
"ClientId": "InternalServiceClient",
@ -135,8 +139,8 @@
"VueOAuthClient": {
"ClientId": "vue-oauth-client",
"RootUrls": [
"http://127.0.0.1:5666",
"http://127.0.0.1:30001"
"http://localhost:5666",
"http://localhost:30000"
]
}
},
@ -207,12 +211,12 @@
}
},
"Elasticsearch": {
"NodeUris": "http://127.0.0.1:9200"
"NodeUris": "http://localhost:9200"
},
"Minio": {
"WithSSL": false,
"BucketName": "blobs",
"EndPoint": "127.0.0.1:19000",
"EndPoint": "localhost:19000",
"AccessKey": "ZD43kNpimiJf9mCuomTP",
"SecretKey": "w8IqMgi4Tnz0DGzN8jZ7IJWq7OEdbUnAU0jlZxQK",
"CreateBucketIfNotExists": false
@ -238,7 +242,7 @@
{
"Name": "Elasticsearch",
"Args": {
"nodeUris": "http://127.0.0.1:9200",
"nodeUris": "http://localhost:9200",
"indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}",
"autoRegisterTemplate": true,
"autoRegisterTemplateVersion": "ESv7"

6
aspnet-core/services/LY.MicroService.Applications.Single/package.json

@ -1,9 +1,9 @@
{
"version": "9.3.5",
"version": "10.0.2",
"name": "my-app-single",
"private": true,
"dependencies": {
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "4.3.5",
"@abp/qrcode": "9.3.5"
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "5.0.2",
"@abp/qrcode": "10.0.2"
}
}
Loading…
Cancel
Save