From 0ecba9619f479194d310ec1ca488440da23091e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=85=86=E9=91=AB?= Date: Mon, 8 Sep 2025 14:15:45 +0800 Subject: [PATCH] first commit --- .gitattributes | 1 + .gitignore | 265 +++ .prettierrc | 5 + KonSoft.sln | 139 ++ KonSoft.sln.DotSettings | 23 + NuGet.Config | 5 + README.md | 70 + .../KonSoft.AuthServer.csproj | 64 + .../KonSoftAuthServerModule.cs | 222 ++ .../KonSoftBrandingProvider.cs | 19 + .../KonSoft.AuthServer/Pages/Index.cshtml | 118 + .../KonSoft.AuthServer/Pages/Index.cshtml.cs | 35 + .../Pages/_ViewImports.cshtml | 4 + applications/KonSoft.AuthServer/Program.cs | 56 + .../Properties/launchSettings.json | 27 + .../KonSoft.AuthServer/abp.resourcemapping.js | 11 + .../appsettings.Development.json | 2 + .../KonSoft.AuthServer/appsettings.json | 17 + .../appsettings.secrets.json | 2 + applications/KonSoft.AuthServer/package.json | 8 + applications/KonSoft.AuthServer/web.config | 18 + .../wwwroot/global-styles.css | 6 + applications/KonSoft.AuthServer/yarn.lock | 322 +++ common.props | 19 + .../Controllers/WeatherForecastController.cs | 33 + .../KonSoft.InternalGateway.csproj | 13 + .../KonSoft.InternalGateway.http | 6 + gateways/KonSoft.InternalGateway/Program.cs | 25 + .../Properties/launchSettings.json | 41 + .../WeatherForecast.cs | 13 + .../appsettings.Development.json | 8 + .../KonSoft.InternalGateway/appsettings.json | 9 + .../Controllers/WeatherForecastController.cs | 33 + .../KonSoft.PublicGateway.csproj | 13 + .../KonSoft.PublicGateway.http | 6 + gateways/KonSoft.PublicGateway/Program.cs | 25 + .../Properties/launchSettings.json | 41 + .../KonSoft.PublicGateway/WeatherForecast.cs | 13 + .../appsettings.Development.json | 8 + .../KonSoft.PublicGateway/appsettings.json | 9 + .../AdminBrandingProvider.cs | 19 + .../AdminHttpApiHostModule.cs | 224 ++ .../Controllers/HomeController.cs | 12 + .../KonSoft.Admin.HttpApi.Host.csproj | 40 + .../KonSoft.Admin.HttpApi.Host/Program.cs | 56 + .../Properties/launchSettings.json | 27 + .../abp.resourcemapping.js | 11 + .../appsettings.Development.json | 2 + .../appsettings.json | 18 + .../appsettings.secrets.json | 2 + .../KonSoft.Admin.HttpApi.Host/package.json | 8 + .../KonSoft.Admin.HttpApi.Host/web.config | 18 + .../wwwroot/global-styles.css | 6 + .../logo/leptonx/logo-dark-thumbnail.png | Bin 0 -> 10695 bytes .../wwwroot/images/logo/leptonx/logo-dark.png | Bin 0 -> 38171 bytes .../logo/leptonx/logo-light-thumbnail.png | Bin 0 -> 9230 bytes .../images/logo/leptonx/logo-light.png | Bin 0 -> 33228 bytes .../KonSoft.Admin.HttpApi.Host/yarn.lock | 322 +++ .../Controllers/HomeController.cs | 12 + .../DispatchBrandingProvider.cs | 19 + .../DispatchHttpApiHostModule.cs | 224 ++ .../KonSoft.Dispatch.HttpApi.Host.csproj | 40 + .../KonSoft.Dispatch.HttpApi.Host/Program.cs | 56 + .../Properties/launchSettings.json | 27 + .../abp.resourcemapping.js | 11 + .../appsettings.Development.json | 2 + .../appsettings.json | 18 + .../appsettings.secrets.json | 2 + .../package.json | 8 + .../KonSoft.Dispatch.HttpApi.Host/web.config | 18 + .../wwwroot/global-styles.css | 6 + .../logo/leptonx/logo-dark-thumbnail.png | Bin 0 -> 10695 bytes .../wwwroot/images/logo/leptonx/logo-dark.png | Bin 0 -> 38171 bytes .../logo/leptonx/logo-light-thumbnail.png | Bin 0 -> 9230 bytes .../images/logo/leptonx/logo-light.png | Bin 0 -> 33228 bytes .../KonSoft.Dispatch.HttpApi.Host/yarn.lock | 322 +++ .../Controllers/HomeController.cs | 12 + .../KonSoft.Payment.HttpApi.Host.csproj | 40 + .../PaymentBrandingProvider.cs | 19 + .../PaymentHttpApiHostModule.cs | 224 ++ .../KonSoft.Payment.HttpApi.Host/Program.cs | 56 + .../Properties/launchSettings.json | 27 + .../abp.resourcemapping.js | 11 + .../appsettings.Development.json | 2 + .../appsettings.json | 18 + .../appsettings.secrets.json | 2 + .../KonSoft.Payment.HttpApi.Host/package.json | 8 + .../KonSoft.Payment.HttpApi.Host/web.config | 18 + .../wwwroot/global-styles.css | 6 + .../logo/leptonx/logo-dark-thumbnail.png | Bin 0 -> 10695 bytes .../wwwroot/images/logo/leptonx/logo-dark.png | Bin 0 -> 38171 bytes .../logo/leptonx/logo-light-thumbnail.png | Bin 0 -> 9230 bytes .../images/logo/leptonx/logo-light.png | Bin 0 -> 33228 bytes .../Controllers/HomeController.cs | 12 + .../KonSoft.Report.HttpApi.Host.csproj | 40 + .../KonSoft.Report.HttpApi.Host/Program.cs | 56 + .../Properties/launchSettings.json | 27 + .../ReportBrandingProvider.cs | 19 + .../ReportHttpApiHostModule.cs | 224 ++ .../abp.resourcemapping.js | 11 + .../appsettings.Development.json | 2 + .../appsettings.json | 18 + .../appsettings.secrets.json | 2 + .../KonSoft.Report.HttpApi.Host/package.json | 8 + .../KonSoft.Report.HttpApi.Host/web.config | 18 + .../wwwroot/global-styles.css | 6 + .../logo/leptonx/logo-dark-thumbnail.png | Bin 0 -> 10695 bytes .../wwwroot/images/logo/leptonx/logo-dark.png | Bin 0 -> 38171 bytes .../logo/leptonx/logo-light-thumbnail.png | Bin 0 -> 9230 bytes .../images/logo/leptonx/logo-light.png | Bin 0 -> 33228 bytes .../Controllers/HomeController.cs | 12 + ...nSoft.TenantManagement.HttpApi.Host.csproj | 40 + .../Program.cs | 56 + .../Properties/launchSettings.json | 27 + .../TenantManagementBrandingProvider.cs | 19 + .../TenantManagementHttpApiHostModule.cs | 224 ++ .../abp.resourcemapping.js | 11 + .../appsettings.Development.json | 2 + .../appsettings.json | 18 + .../appsettings.secrets.json | 2 + .../package.json | 8 + .../web.config | 18 + .../wwwroot/global-styles.css | 6 + .../logo/leptonx/logo-dark-thumbnail.png | Bin 0 -> 10695 bytes .../wwwroot/images/logo/leptonx/logo-dark.png | Bin 0 -> 38171 bytes .../logo/leptonx/logo-light-thumbnail.png | Bin 0 -> 9230 bytes .../images/logo/leptonx/logo-light.png | Bin 0 -> 33228 bytes .../AdminApplicationContractsModule.cs | 28 + .../AdminDtoExtensions.cs | 28 + ...KonSoft.Admin.Application.Contracts.csproj | 25 + .../AdminPermissionDefinitionProvider.cs | 20 + .../Permissions/AdminPermissions.cs | 9 + .../AdminAppService.cs | 17 + .../AdminApplicationAutoMapperProfile.cs | 13 + .../AdminApplicationModule.cs | 31 + .../KonSoft.Admin.Application.csproj | 25 + .../Properties/AssemblyInfo.cs | 2 + .../AdminDomainErrorCodes.cs | 6 + .../AdminDomainSharedModule.cs | 58 + .../AdminGlobalFeatureConfigurator.cs | 22 + .../AdminModuleExtensionConfigurator.cs | 73 + .../KonSoft.Admin.Domain.Shared.csproj | 32 + .../Localization/Admin/ar.json | 9 + .../Localization/Admin/cs.json | 9 + .../Localization/Admin/de.json | 9 + .../Localization/Admin/en-GB.json | 9 + .../Localization/Admin/en.json | 9 + .../Localization/Admin/es.json | 9 + .../Localization/Admin/fi.json | 9 + .../Localization/Admin/fr.json | 9 + .../Localization/Admin/hi.json | 9 + .../Localization/Admin/hr.json | 9 + .../Localization/Admin/hu.json | 9 + .../Localization/Admin/is.json | 9 + .../Localization/Admin/it.json | 9 + .../Localization/Admin/nl.json | 9 + .../Localization/Admin/pl-PL.json | 9 + .../Localization/Admin/pt-BR.json | 9 + .../Localization/Admin/ro-RO.json | 9 + .../Localization/Admin/ru.json | 9 + .../Localization/Admin/sk.json | 9 + .../Localization/Admin/sl.json | 9 + .../Localization/Admin/sv.json | 9 + .../Localization/Admin/tr.json | 9 + .../Localization/Admin/vi.json | 9 + .../Localization/Admin/zh-Hans.json | 9 + .../Localization/Admin/zh-Hant.json | 9 + .../Localization/AdminResource.cs | 9 + .../MultiTenancy/MultiTenancyConsts.cs | 10 + .../src/KonSoft.Admin.Domain/AdminConsts.cs | 8 + .../KonSoft.Admin.Domain/AdminDomainModule.cs | 68 + .../Data/AdminDbMigrationService.cs | 218 ++ .../Data/IAdminDbSchemaMigrator.cs | 8 + .../Data/NullAdminDbSchemaMigrator.cs | 15 + .../KonSoft.Admin.Domain.csproj | 28 + .../OpenIddictDataSeedContributor.cs | 327 +++ .../Properties/AssemblyInfo.cs | 3 + .../AdminSettingDefinitionProvider.cs | 12 + .../Settings/AdminSettings.cs | 9 + .../EntityFrameworkCore/AdminDbContext.cs | 86 + .../AdminDbContextFactory.cs | 36 + .../AdminEfCoreEntityExtensionMappings.cs | 44 + .../AdminEntityFrameworkCoreModule.cs | 57 + ...ntityFrameworkCoreAdminDbSchemaMigrator.cs | 34 + .../KonSoft.Admin.EntityFrameworkCore.csproj | 31 + .../20250908050617_Initial.Designer.cs | 2006 +++++++++++++++++ .../Migrations/20250908050617_Initial.cs | 1156 ++++++++++ .../Migrations/AdminDbContextModelSnapshot.cs | 2003 ++++++++++++++++ .../Properties/AssemblyInfo.cs | 2 + .../AdminHttpApiClientModule.cs | 38 + .../KonSoft.Admin.HttpApi.Client.csproj | 29 + .../AdminHttpApiModule.cs | 41 + .../Controllers/AdminController.cs | 14 + .../KonSoft.Admin.HttpApi.csproj | 24 + .../Models/Test/TestModel.cs | 10 + .../AdminApplicationTestBase.cs | 9 + .../AdminApplicationTestModule.cs | 12 + .../KonSoft.Admin.Application.Tests.csproj | 20 + .../Samples/SampleAppServiceTests.cs | 34 + .../AdminDomainTestBase.cs | 10 + .../AdminDomainTestModule.cs | 12 + .../KonSoft.Admin.Domain.Tests.csproj | 20 + .../Samples/SampleDomainTests.cs | 46 + .../AdminEntityFrameworkCoreCollection.cs | 9 + ...ntityFrameworkCoreCollectionFixtureBase.cs | 9 + .../AdminEntityFrameworkCoreFixture.cs | 11 + .../AdminEntityFrameworkCoreTestBase.cs | 8 + .../AdminEntityFrameworkCoreTestModule.cs | 82 + .../EfCoreSampleAppServiceTests.cs | 10 + .../Domains/EfCoreSampleDomainTests.cs | 10 + .../Samples/SampleRepositoryTests.cs | 44 + ...oft.Admin.EntityFrameworkCore.Tests.csproj | 21 + .../AdminConsoleApiClientModule.cs | 30 + .../ClientDemoService.cs | 25 + .../ConsoleTestAppHostedService.cs | 40 + ...Admin.HttpApi.Client.ConsoleTestApp.csproj | 33 + .../Program.cs | 22 + .../appsettings.json | 17 + .../appsettings.secrets.json | 2 + .../KonSoft.Admin.TestBase/AdminTestBase.cs | 60 + .../AdminTestBaseModule.cs | 47 + .../KonSoft.Admin.TestBase/AdminTestConsts.cs | 6 + .../AdminTestDataSeedContributor.cs | 15 + .../KonSoft.Admin.TestBase.csproj | 31 + .../Security/FakeCurrentPrincipalAccessor.cs | 25 + .../DispatchApplicationContractsModule.cs | 28 + .../DispatchDtoExtensions.cs | 28 + ...Soft.Dispatch.Application.Contracts.csproj | 25 + .../DispatchPermissionDefinitionProvider.cs | 20 + .../Permissions/DispatchPermissions.cs | 9 + .../DispatchAppService.cs | 17 + .../DispatchApplicationAutoMapperProfile.cs | 13 + .../DispatchApplicationModule.cs | 31 + .../KonSoft.Dispatch.Application.csproj | 25 + .../Properties/AssemblyInfo.cs | 2 + .../DbMigratorHostedService.cs | 51 + .../DispatchDbMigratorModule.cs | 21 + .../KonSoft.Dispatch.DbMigrator.csproj | 46 + .../KonSoft.Dispatch.DbMigrator/Program.cs | 41 + .../appsettings.json | 16 + .../appsettings.secrets.json | 2 + .../DispatchDomainErrorCodes.cs | 6 + .../DispatchDomainSharedModule.cs | 58 + .../DispatchGlobalFeatureConfigurator.cs | 22 + .../DispatchModuleExtensionConfigurator.cs | 73 + .../KonSoft.Dispatch.Domain.Shared.csproj | 32 + .../Localization/Dispatch/ar.json | 9 + .../Localization/Dispatch/cs.json | 9 + .../Localization/Dispatch/de.json | 9 + .../Localization/Dispatch/en-GB.json | 9 + .../Localization/Dispatch/en.json | 9 + .../Localization/Dispatch/es.json | 9 + .../Localization/Dispatch/fi.json | 9 + .../Localization/Dispatch/fr.json | 9 + .../Localization/Dispatch/hi.json | 9 + .../Localization/Dispatch/hr.json | 9 + .../Localization/Dispatch/hu.json | 9 + .../Localization/Dispatch/is.json | 9 + .../Localization/Dispatch/it.json | 9 + .../Localization/Dispatch/nl.json | 9 + .../Localization/Dispatch/pl-PL.json | 9 + .../Localization/Dispatch/pt-BR.json | 9 + .../Localization/Dispatch/ro-RO.json | 9 + .../Localization/Dispatch/ru.json | 9 + .../Localization/Dispatch/sk.json | 9 + .../Localization/Dispatch/sl.json | 9 + .../Localization/Dispatch/sv.json | 9 + .../Localization/Dispatch/tr.json | 9 + .../Localization/Dispatch/vi.json | 9 + .../Localization/Dispatch/zh-Hans.json | 9 + .../Localization/Dispatch/zh-Hant.json | 9 + .../Localization/DispatchResource.cs | 9 + .../MultiTenancy/MultiTenancyConsts.cs | 10 + .../Data/DispatchDbMigrationService.cs | 218 ++ .../Data/IDispatchDbSchemaMigrator.cs | 8 + .../Data/NullDispatchDbSchemaMigrator.cs | 15 + .../KonSoft.Dispatch.Domain/DispatchConsts.cs | 8 + .../DispatchDomainModule.cs | 68 + .../KonSoft.Dispatch.Domain.csproj | 28 + .../OpenIddictDataSeedContributor.cs | 327 +++ .../Properties/AssemblyInfo.cs | 3 + .../DispatchSettingDefinitionProvider.cs | 12 + .../Settings/DispatchSettings.cs | 9 + .../EntityFrameworkCore/DispatchDbContext.cs | 86 + .../DispatchDbContextFactory.cs | 36 + .../DispatchEfCoreEntityExtensionMappings.cs | 44 + .../DispatchEntityFrameworkCoreModule.cs | 57 + ...tyFrameworkCoreDispatchDbSchemaMigrator.cs | 34 + ...onSoft.Dispatch.EntityFrameworkCore.csproj | 31 + .../20250908052345_Initial.Designer.cs | 2006 +++++++++++++++++ .../Migrations/20250908052345_Initial.cs | 1156 ++++++++++ .../DispatchDbContextModelSnapshot.cs | 2003 ++++++++++++++++ .../Properties/AssemblyInfo.cs | 2 + .../DispatchHttpApiClientModule.cs | 38 + .../KonSoft.Dispatch.HttpApi.Client.csproj | 29 + .../Controllers/DispatchController.cs | 14 + .../DispatchHttpApiModule.cs | 41 + .../KonSoft.Dispatch.HttpApi.csproj | 24 + .../Models/Test/TestModel.cs | 10 + .../DispatchApplicationTestBase.cs | 9 + .../DispatchApplicationTestModule.cs | 12 + .../KonSoft.Dispatch.Application.Tests.csproj | 20 + .../Samples/SampleAppServiceTests.cs | 34 + .../DispatchDomainTestBase.cs | 10 + .../DispatchDomainTestModule.cs | 12 + .../KonSoft.Dispatch.Domain.Tests.csproj | 20 + .../Samples/SampleDomainTests.cs | 46 + .../EfCoreSampleAppServiceTests.cs | 10 + .../DispatchEntityFrameworkCoreCollection.cs | 9 + ...ntityFrameworkCoreCollectionFixtureBase.cs | 9 + .../DispatchEntityFrameworkCoreFixture.cs | 11 + .../DispatchEntityFrameworkCoreTestBase.cs | 8 + .../DispatchEntityFrameworkCoreTestModule.cs | 82 + .../Domains/EfCoreSampleDomainTests.cs | 10 + .../Samples/SampleRepositoryTests.cs | 44 + ....Dispatch.EntityFrameworkCore.Tests.csproj | 21 + .../ClientDemoService.cs | 25 + .../ConsoleTestAppHostedService.cs | 40 + .../DispatchConsoleApiClientModule.cs | 30 + ...patch.HttpApi.Client.ConsoleTestApp.csproj | 33 + .../Program.cs | 22 + .../appsettings.json | 17 + .../appsettings.secrets.json | 2 + .../DispatchTestBase.cs | 60 + .../DispatchTestBaseModule.cs | 47 + .../DispatchTestConsts.cs | 6 + .../DispatchTestDataSeedContributor.cs | 15 + .../KonSoft.Dispatch.TestBase.csproj | 31 + .../Security/FakeCurrentPrincipalAccessor.cs | 25 + ...nSoft.Payment.Application.Contracts.csproj | 25 + .../PaymentApplicationContractsModule.cs | 28 + .../PaymentDtoExtensions.cs | 28 + .../PaymentPermissionDefinitionProvider.cs | 20 + .../Permissions/PaymentPermissions.cs | 9 + .../KonSoft.Payment.Application.csproj | 25 + .../PaymentAppService.cs | 17 + .../PaymentApplicationAutoMapperProfile.cs | 13 + .../PaymentApplicationModule.cs | 31 + .../Properties/AssemblyInfo.cs | 2 + .../KonSoft.Payment.Domain.Shared.csproj | 32 + .../Localization/Payment/ar.json | 9 + .../Localization/Payment/cs.json | 9 + .../Localization/Payment/de.json | 9 + .../Localization/Payment/en-GB.json | 9 + .../Localization/Payment/en.json | 9 + .../Localization/Payment/es.json | 9 + .../Localization/Payment/fi.json | 9 + .../Localization/Payment/fr.json | 9 + .../Localization/Payment/hi.json | 9 + .../Localization/Payment/hr.json | 9 + .../Localization/Payment/hu.json | 9 + .../Localization/Payment/is.json | 9 + .../Localization/Payment/it.json | 9 + .../Localization/Payment/nl.json | 9 + .../Localization/Payment/pl-PL.json | 9 + .../Localization/Payment/pt-BR.json | 9 + .../Localization/Payment/ro-RO.json | 9 + .../Localization/Payment/ru.json | 9 + .../Localization/Payment/sk.json | 9 + .../Localization/Payment/sl.json | 9 + .../Localization/Payment/sv.json | 9 + .../Localization/Payment/tr.json | 9 + .../Localization/Payment/vi.json | 9 + .../Localization/Payment/zh-Hans.json | 9 + .../Localization/Payment/zh-Hant.json | 9 + .../Localization/PaymentResource.cs | 9 + .../MultiTenancy/MultiTenancyConsts.cs | 10 + .../PaymentDomainErrorCodes.cs | 6 + .../PaymentDomainSharedModule.cs | 58 + .../PaymentGlobalFeatureConfigurator.cs | 22 + .../PaymentModuleExtensionConfigurator.cs | 73 + .../Data/IPaymentDbSchemaMigrator.cs | 8 + .../Data/NullPaymentDbSchemaMigrator.cs | 15 + .../Data/PaymentDbMigrationService.cs | 218 ++ .../KonSoft.Payment.Domain.csproj | 28 + .../OpenIddictDataSeedContributor.cs | 327 +++ .../KonSoft.Payment.Domain/PaymentConsts.cs | 8 + .../PaymentDomainModule.cs | 68 + .../Properties/AssemblyInfo.cs | 3 + .../PaymentSettingDefinitionProvider.cs | 12 + .../Settings/PaymentSettings.cs | 9 + ...ityFrameworkCorePaymentDbSchemaMigrator.cs | 34 + .../EntityFrameworkCore/PaymentDbContext.cs | 86 + .../PaymentDbContextFactory.cs | 36 + .../PaymentEfCoreEntityExtensionMappings.cs | 44 + .../PaymentEntityFrameworkCoreModule.cs | 57 + ...KonSoft.Payment.EntityFrameworkCore.csproj | 31 + .../20250908052440_Initial.Designer.cs | 2006 +++++++++++++++++ .../Migrations/20250908052440_Initial.cs | 1156 ++++++++++ .../PaymentDbContextModelSnapshot.cs | 2003 ++++++++++++++++ .../Properties/AssemblyInfo.cs | 2 + .../KonSoft.Payment.HttpApi.Client.csproj | 29 + .../PaymentHttpApiClientModule.cs | 38 + .../Controllers/PaymentController.cs | 14 + .../KonSoft.Payment.HttpApi.csproj | 24 + .../Models/Test/TestModel.cs | 10 + .../PaymentHttpApiModule.cs | 41 + .../KonSoft.Payment.Application.Tests.csproj | 20 + .../PaymentApplicationTestBase.cs | 9 + .../PaymentApplicationTestModule.cs | 12 + .../Samples/SampleAppServiceTests.cs | 34 + .../KonSoft.Payment.Domain.Tests.csproj | 20 + .../PaymentDomainTestBase.cs | 10 + .../PaymentDomainTestModule.cs | 12 + .../Samples/SampleDomainTests.cs | 46 + .../EfCoreSampleAppServiceTests.cs | 10 + .../Domains/EfCoreSampleDomainTests.cs | 10 + .../PaymentEntityFrameworkCoreCollection.cs | 9 + ...ntityFrameworkCoreCollectionFixtureBase.cs | 9 + .../PaymentEntityFrameworkCoreFixture.cs | 11 + .../PaymentEntityFrameworkCoreTestBase.cs | 8 + .../PaymentEntityFrameworkCoreTestModule.cs | 82 + .../Samples/SampleRepositoryTests.cs | 44 + ...t.Payment.EntityFrameworkCore.Tests.csproj | 21 + .../ClientDemoService.cs | 25 + .../ConsoleTestAppHostedService.cs | 40 + ...yment.HttpApi.Client.ConsoleTestApp.csproj | 33 + .../PaymentConsoleApiClientModule.cs | 30 + .../Program.cs | 22 + .../appsettings.json | 17 + .../appsettings.secrets.json | 2 + .../KonSoft.Payment.TestBase.csproj | 31 + .../PaymentTestBase.cs | 60 + .../PaymentTestBaseModule.cs | 47 + .../PaymentTestConsts.cs | 6 + .../PaymentTestDataSeedContributor.cs | 15 + .../Security/FakeCurrentPrincipalAccessor.cs | 25 + ...onSoft.Report.Application.Contracts.csproj | 25 + .../ReportPermissionDefinitionProvider.cs | 20 + .../Permissions/ReportPermissions.cs | 9 + .../ReportApplicationContractsModule.cs | 28 + .../ReportDtoExtensions.cs | 28 + .../KonSoft.Report.Application.csproj | 25 + .../Properties/AssemblyInfo.cs | 2 + .../ReportAppService.cs | 17 + .../ReportApplicationAutoMapperProfile.cs | 13 + .../ReportApplicationModule.cs | 31 + .../KonSoft.Report.Domain.Shared.csproj | 32 + .../Localization/Report/ar.json | 9 + .../Localization/Report/cs.json | 9 + .../Localization/Report/de.json | 9 + .../Localization/Report/en-GB.json | 9 + .../Localization/Report/en.json | 9 + .../Localization/Report/es.json | 9 + .../Localization/Report/fi.json | 9 + .../Localization/Report/fr.json | 9 + .../Localization/Report/hi.json | 9 + .../Localization/Report/hr.json | 9 + .../Localization/Report/hu.json | 9 + .../Localization/Report/is.json | 9 + .../Localization/Report/it.json | 9 + .../Localization/Report/nl.json | 9 + .../Localization/Report/pl-PL.json | 9 + .../Localization/Report/pt-BR.json | 9 + .../Localization/Report/ro-RO.json | 9 + .../Localization/Report/ru.json | 9 + .../Localization/Report/sk.json | 9 + .../Localization/Report/sl.json | 9 + .../Localization/Report/sv.json | 9 + .../Localization/Report/tr.json | 9 + .../Localization/Report/vi.json | 9 + .../Localization/Report/zh-Hans.json | 9 + .../Localization/Report/zh-Hant.json | 9 + .../Localization/ReportResource.cs | 9 + .../MultiTenancy/MultiTenancyConsts.cs | 10 + .../ReportDomainErrorCodes.cs | 6 + .../ReportDomainSharedModule.cs | 58 + .../ReportGlobalFeatureConfigurator.cs | 22 + .../ReportModuleExtensionConfigurator.cs | 73 + .../Data/IReportDbSchemaMigrator.cs | 8 + .../Data/NullReportDbSchemaMigrator.cs | 15 + .../Data/ReportDbMigrationService.cs | 218 ++ .../KonSoft.Report.Domain.csproj | 28 + .../OpenIddictDataSeedContributor.cs | 327 +++ .../Properties/AssemblyInfo.cs | 3 + .../src/KonSoft.Report.Domain/ReportConsts.cs | 8 + .../ReportDomainModule.cs | 68 + .../ReportSettingDefinitionProvider.cs | 12 + .../Settings/ReportSettings.cs | 9 + ...tityFrameworkCoreReportDbSchemaMigrator.cs | 34 + .../EntityFrameworkCore/ReportDbContext.cs | 86 + .../ReportDbContextFactory.cs | 36 + .../ReportEfCoreEntityExtensionMappings.cs | 44 + .../ReportEntityFrameworkCoreModule.cs | 57 + .../KonSoft.Report.EntityFrameworkCore.csproj | 31 + .../Properties/AssemblyInfo.cs | 2 + .../KonSoft.Report.HttpApi.Client.csproj | 29 + .../ReportHttpApiClientModule.cs | 38 + .../Controllers/ReportController.cs | 14 + .../KonSoft.Report.HttpApi.csproj | 24 + .../Models/Test/TestModel.cs | 10 + .../ReportHttpApiModule.cs | 41 + .../KonSoft.Report.Application.Tests.csproj | 20 + .../ReportApplicationTestBase.cs | 9 + .../ReportApplicationTestModule.cs | 12 + .../Samples/SampleAppServiceTests.cs | 34 + .../KonSoft.Report.Domain.Tests.csproj | 20 + .../ReportDomainTestBase.cs | 10 + .../ReportDomainTestModule.cs | 12 + .../Samples/SampleDomainTests.cs | 46 + .../EfCoreSampleAppServiceTests.cs | 10 + .../Domains/EfCoreSampleDomainTests.cs | 10 + .../ReportEntityFrameworkCoreCollection.cs | 9 + ...ntityFrameworkCoreCollectionFixtureBase.cs | 9 + .../ReportEntityFrameworkCoreFixture.cs | 11 + .../ReportEntityFrameworkCoreTestBase.cs | 8 + .../ReportEntityFrameworkCoreTestModule.cs | 82 + .../Samples/SampleRepositoryTests.cs | 44 + ...ft.Report.EntityFrameworkCore.Tests.csproj | 21 + .../ClientDemoService.cs | 25 + .../ConsoleTestAppHostedService.cs | 40 + ...eport.HttpApi.Client.ConsoleTestApp.csproj | 33 + .../Program.cs | 22 + .../ReportConsoleApiClientModule.cs | 30 + .../appsettings.json | 17 + .../appsettings.secrets.json | 2 + .../KonSoft.Report.TestBase.csproj | 31 + .../KonSoft.Report.TestBase/ReportTestBase.cs | 60 + .../ReportTestBaseModule.cs | 47 + .../ReportTestConsts.cs | 6 + .../ReportTestDataSeedContributor.cs | 15 + .../Security/FakeCurrentPrincipalAccessor.cs | 25 + ...antManagement.Application.Contracts.csproj | 25 + ...tManagementPermissionDefinitionProvider.cs | 20 + .../TenantManagementPermissions.cs | 9 + ...antManagementApplicationContractsModule.cs | 28 + .../TenantManagementDtoExtensions.cs | 28 + ...onSoft.TenantManagement.Application.csproj | 25 + .../Properties/AssemblyInfo.cs | 2 + .../TenantManagementAppService.cs | 17 + ...tManagementApplicationAutoMapperProfile.cs | 13 + .../TenantManagementApplicationModule.cs | 31 + ...Soft.TenantManagement.Domain.Shared.csproj | 32 + .../Localization/TenantManagement/ar.json | 9 + .../Localization/TenantManagement/cs.json | 9 + .../Localization/TenantManagement/de.json | 9 + .../Localization/TenantManagement/en-GB.json | 9 + .../Localization/TenantManagement/en.json | 9 + .../Localization/TenantManagement/es.json | 9 + .../Localization/TenantManagement/fi.json | 9 + .../Localization/TenantManagement/fr.json | 9 + .../Localization/TenantManagement/hi.json | 9 + .../Localization/TenantManagement/hr.json | 9 + .../Localization/TenantManagement/hu.json | 9 + .../Localization/TenantManagement/is.json | 9 + .../Localization/TenantManagement/it.json | 9 + .../Localization/TenantManagement/nl.json | 9 + .../Localization/TenantManagement/pl-PL.json | 9 + .../Localization/TenantManagement/pt-BR.json | 9 + .../Localization/TenantManagement/ro-RO.json | 9 + .../Localization/TenantManagement/ru.json | 9 + .../Localization/TenantManagement/sk.json | 9 + .../Localization/TenantManagement/sl.json | 9 + .../Localization/TenantManagement/sv.json | 9 + .../Localization/TenantManagement/tr.json | 9 + .../Localization/TenantManagement/vi.json | 9 + .../TenantManagement/zh-Hans.json | 9 + .../TenantManagement/zh-Hant.json | 9 + .../Localization/TenantManagementResource.cs | 9 + .../MultiTenancy/MultiTenancyConsts.cs | 10 + .../TenantManagementDomainErrorCodes.cs | 6 + .../TenantManagementDomainSharedModule.cs | 58 + ...nantManagementGlobalFeatureConfigurator.cs | 22 + ...ntManagementModuleExtensionConfigurator.cs | 73 + .../Data/ITenantManagementDbSchemaMigrator.cs | 8 + .../NullTenantManagementDbSchemaMigrator.cs | 15 + .../TenantManagementDbMigrationService.cs | 218 ++ .../KonSoft.TenantManagement.Domain.csproj | 28 + .../OpenIddictDataSeedContributor.cs | 327 +++ .../Properties/AssemblyInfo.cs | 3 + ...nantManagementSettingDefinitionProvider.cs | 12 + .../Settings/TenantManagementSettings.cs | 9 + .../TenantManagementConsts.cs | 8 + .../TenantManagementDomainModule.cs | 68 + ...orkCoreTenantManagementDbSchemaMigrator.cs | 34 + .../TenantManagementDbContext.cs | 86 + .../TenantManagementDbContextFactory.cs | 36 + ...ManagementEfCoreEntityExtensionMappings.cs | 44 + ...nantManagementEntityFrameworkCoreModule.cs | 57 + ...enantManagement.EntityFrameworkCore.csproj | 31 + .../20250908052623_Initial.Designer.cs | 2006 +++++++++++++++++ .../Migrations/20250908052623_Initial.cs | 1156 ++++++++++ .../TenantManagementDbContextModelSnapshot.cs | 2003 ++++++++++++++++ .../Properties/AssemblyInfo.cs | 2 + ...oft.TenantManagement.HttpApi.Client.csproj | 29 + .../TenantManagementHttpApiClientModule.cs | 38 + .../Controllers/TenantManagementController.cs | 14 + .../KonSoft.TenantManagement.HttpApi.csproj | 24 + .../Models/Test/TestModel.cs | 10 + .../TenantManagementHttpApiModule.cs | 41 + ....TenantManagement.Application.Tests.csproj | 20 + .../Samples/SampleAppServiceTests.cs | 34 + .../TenantManagementApplicationTestBase.cs | 9 + .../TenantManagementApplicationTestModule.cs | 12 + ...nSoft.TenantManagement.Domain.Tests.csproj | 20 + .../Samples/SampleDomainTests.cs | 46 + .../TenantManagementDomainTestBase.cs | 10 + .../TenantManagementDomainTestModule.cs | 12 + .../EfCoreSampleAppServiceTests.cs | 10 + .../Domains/EfCoreSampleDomainTests.cs | 10 + .../Samples/SampleRepositoryTests.cs | 44 + ...ManagementEntityFrameworkCoreCollection.cs | 9 + ...ntityFrameworkCoreCollectionFixtureBase.cs | 9 + ...antManagementEntityFrameworkCoreFixture.cs | 11 + ...ntManagementEntityFrameworkCoreTestBase.cs | 8 + ...ManagementEntityFrameworkCoreTestModule.cs | 82 + ...anagement.EntityFrameworkCore.Tests.csproj | 21 + .../ClientDemoService.cs | 25 + .../ConsoleTestAppHostedService.cs | 40 + ...ement.HttpApi.Client.ConsoleTestApp.csproj | 33 + .../Program.cs | 22 + .../TenantManagementConsoleApiClientModule.cs | 30 + .../appsettings.json | 17 + .../appsettings.secrets.json | 2 + .../KonSoft.TenantManagement.TestBase.csproj | 31 + .../Security/FakeCurrentPrincipalAccessor.cs | 25 + .../TenantManagementTestBase.cs | 60 + .../TenantManagementTestBaseModule.cs | 47 + .../TenantManagementTestConsts.cs | 6 + ...TenantManagementTestDataSeedContributor.cs | 15 + shared/KonSoft.Shared/Class1.cs | 7 + shared/KonSoft.Shared/KonSoft.Shared.csproj | 9 + 622 files changed, 37941 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .prettierrc create mode 100644 KonSoft.sln create mode 100644 KonSoft.sln.DotSettings create mode 100644 NuGet.Config create mode 100644 README.md create mode 100644 applications/KonSoft.AuthServer/KonSoft.AuthServer.csproj create mode 100644 applications/KonSoft.AuthServer/KonSoftAuthServerModule.cs create mode 100644 applications/KonSoft.AuthServer/KonSoftBrandingProvider.cs create mode 100644 applications/KonSoft.AuthServer/Pages/Index.cshtml create mode 100644 applications/KonSoft.AuthServer/Pages/Index.cshtml.cs create mode 100644 applications/KonSoft.AuthServer/Pages/_ViewImports.cshtml create mode 100644 applications/KonSoft.AuthServer/Program.cs create mode 100644 applications/KonSoft.AuthServer/Properties/launchSettings.json create mode 100644 applications/KonSoft.AuthServer/abp.resourcemapping.js create mode 100644 applications/KonSoft.AuthServer/appsettings.Development.json create mode 100644 applications/KonSoft.AuthServer/appsettings.json create mode 100644 applications/KonSoft.AuthServer/appsettings.secrets.json create mode 100644 applications/KonSoft.AuthServer/package.json create mode 100644 applications/KonSoft.AuthServer/web.config create mode 100644 applications/KonSoft.AuthServer/wwwroot/global-styles.css create mode 100644 applications/KonSoft.AuthServer/yarn.lock create mode 100644 common.props create mode 100644 gateways/KonSoft.InternalGateway/Controllers/WeatherForecastController.cs create mode 100644 gateways/KonSoft.InternalGateway/KonSoft.InternalGateway.csproj create mode 100644 gateways/KonSoft.InternalGateway/KonSoft.InternalGateway.http create mode 100644 gateways/KonSoft.InternalGateway/Program.cs create mode 100644 gateways/KonSoft.InternalGateway/Properties/launchSettings.json create mode 100644 gateways/KonSoft.InternalGateway/WeatherForecast.cs create mode 100644 gateways/KonSoft.InternalGateway/appsettings.Development.json create mode 100644 gateways/KonSoft.InternalGateway/appsettings.json create mode 100644 gateways/KonSoft.PublicGateway/Controllers/WeatherForecastController.cs create mode 100644 gateways/KonSoft.PublicGateway/KonSoft.PublicGateway.csproj create mode 100644 gateways/KonSoft.PublicGateway/KonSoft.PublicGateway.http create mode 100644 gateways/KonSoft.PublicGateway/Program.cs create mode 100644 gateways/KonSoft.PublicGateway/Properties/launchSettings.json create mode 100644 gateways/KonSoft.PublicGateway/WeatherForecast.cs create mode 100644 gateways/KonSoft.PublicGateway/appsettings.Development.json create mode 100644 gateways/KonSoft.PublicGateway/appsettings.json create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/AdminBrandingProvider.cs create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/AdminHttpApiHostModule.cs create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/Controllers/HomeController.cs create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/KonSoft.Admin.HttpApi.Host.csproj create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/Program.cs create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/Properties/launchSettings.json create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/abp.resourcemapping.js create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/appsettings.Development.json create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/appsettings.json create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/appsettings.secrets.json create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/package.json create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/web.config create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/wwwroot/global-styles.css create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light-thumbnail.png create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png create mode 100644 microservices/KonSoft.Admin.HttpApi.Host/yarn.lock create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/Controllers/HomeController.cs create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/DispatchBrandingProvider.cs create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/DispatchHttpApiHostModule.cs create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/KonSoft.Dispatch.HttpApi.Host.csproj create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/Program.cs create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/Properties/launchSettings.json create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/abp.resourcemapping.js create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/appsettings.Development.json create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/appsettings.json create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/appsettings.secrets.json create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/package.json create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/web.config create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/global-styles.css create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light-thumbnail.png create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png create mode 100644 microservices/KonSoft.Dispatch.HttpApi.Host/yarn.lock create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/Controllers/HomeController.cs create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/KonSoft.Payment.HttpApi.Host.csproj create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/PaymentBrandingProvider.cs create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/PaymentHttpApiHostModule.cs create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/Program.cs create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/Properties/launchSettings.json create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/abp.resourcemapping.js create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/appsettings.Development.json create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/appsettings.json create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/appsettings.secrets.json create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/package.json create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/web.config create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/wwwroot/global-styles.css create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light-thumbnail.png create mode 100644 microservices/KonSoft.Payment.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png create mode 100644 microservices/KonSoft.Report.HttpApi.Host/Controllers/HomeController.cs create mode 100644 microservices/KonSoft.Report.HttpApi.Host/KonSoft.Report.HttpApi.Host.csproj create mode 100644 microservices/KonSoft.Report.HttpApi.Host/Program.cs create mode 100644 microservices/KonSoft.Report.HttpApi.Host/Properties/launchSettings.json create mode 100644 microservices/KonSoft.Report.HttpApi.Host/ReportBrandingProvider.cs create mode 100644 microservices/KonSoft.Report.HttpApi.Host/ReportHttpApiHostModule.cs create mode 100644 microservices/KonSoft.Report.HttpApi.Host/abp.resourcemapping.js create mode 100644 microservices/KonSoft.Report.HttpApi.Host/appsettings.Development.json create mode 100644 microservices/KonSoft.Report.HttpApi.Host/appsettings.json create mode 100644 microservices/KonSoft.Report.HttpApi.Host/appsettings.secrets.json create mode 100644 microservices/KonSoft.Report.HttpApi.Host/package.json create mode 100644 microservices/KonSoft.Report.HttpApi.Host/web.config create mode 100644 microservices/KonSoft.Report.HttpApi.Host/wwwroot/global-styles.css create mode 100644 microservices/KonSoft.Report.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png create mode 100644 microservices/KonSoft.Report.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png create mode 100644 microservices/KonSoft.Report.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light-thumbnail.png create mode 100644 microservices/KonSoft.Report.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/Controllers/HomeController.cs create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/KonSoft.TenantManagement.HttpApi.Host.csproj create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/Program.cs create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/Properties/launchSettings.json create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/TenantManagementBrandingProvider.cs create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/TenantManagementHttpApiHostModule.cs create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/abp.resourcemapping.js create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/appsettings.Development.json create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/appsettings.json create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/appsettings.secrets.json create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/package.json create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/web.config create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/global-styles.css create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light-thumbnail.png create mode 100644 microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png create mode 100644 modules/admin/src/KonSoft.Admin.Application.Contracts/AdminApplicationContractsModule.cs create mode 100644 modules/admin/src/KonSoft.Admin.Application.Contracts/AdminDtoExtensions.cs create mode 100644 modules/admin/src/KonSoft.Admin.Application.Contracts/KonSoft.Admin.Application.Contracts.csproj create mode 100644 modules/admin/src/KonSoft.Admin.Application.Contracts/Permissions/AdminPermissionDefinitionProvider.cs create mode 100644 modules/admin/src/KonSoft.Admin.Application.Contracts/Permissions/AdminPermissions.cs create mode 100644 modules/admin/src/KonSoft.Admin.Application/AdminAppService.cs create mode 100644 modules/admin/src/KonSoft.Admin.Application/AdminApplicationAutoMapperProfile.cs create mode 100644 modules/admin/src/KonSoft.Admin.Application/AdminApplicationModule.cs create mode 100644 modules/admin/src/KonSoft.Admin.Application/KonSoft.Admin.Application.csproj create mode 100644 modules/admin/src/KonSoft.Admin.Application/Properties/AssemblyInfo.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/AdminDomainErrorCodes.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/AdminDomainSharedModule.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/AdminGlobalFeatureConfigurator.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/AdminModuleExtensionConfigurator.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/KonSoft.Admin.Domain.Shared.csproj create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/ar.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/cs.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/de.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/en-GB.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/en.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/es.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/fi.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/fr.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/hi.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/hr.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/hu.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/is.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/it.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/nl.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/pl-PL.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/pt-BR.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/ro-RO.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/ru.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/sk.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/sl.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/sv.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/tr.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/vi.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/zh-Hans.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/zh-Hant.json create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/AdminResource.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain/AdminConsts.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain/AdminDomainModule.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain/Data/AdminDbMigrationService.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain/Data/IAdminDbSchemaMigrator.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain/Data/NullAdminDbSchemaMigrator.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain/KonSoft.Admin.Domain.csproj create mode 100644 modules/admin/src/KonSoft.Admin.Domain/OpenIddict/OpenIddictDataSeedContributor.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain/Properties/AssemblyInfo.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain/Settings/AdminSettingDefinitionProvider.cs create mode 100644 modules/admin/src/KonSoft.Admin.Domain/Settings/AdminSettings.cs create mode 100644 modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminDbContext.cs create mode 100644 modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminDbContextFactory.cs create mode 100644 modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminEfCoreEntityExtensionMappings.cs create mode 100644 modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminEntityFrameworkCoreModule.cs create mode 100644 modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreAdminDbSchemaMigrator.cs create mode 100644 modules/admin/src/KonSoft.Admin.EntityFrameworkCore/KonSoft.Admin.EntityFrameworkCore.csproj create mode 100644 modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Migrations/20250908050617_Initial.Designer.cs create mode 100644 modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Migrations/20250908050617_Initial.cs create mode 100644 modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Migrations/AdminDbContextModelSnapshot.cs create mode 100644 modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Properties/AssemblyInfo.cs create mode 100644 modules/admin/src/KonSoft.Admin.HttpApi.Client/AdminHttpApiClientModule.cs create mode 100644 modules/admin/src/KonSoft.Admin.HttpApi.Client/KonSoft.Admin.HttpApi.Client.csproj create mode 100644 modules/admin/src/KonSoft.Admin.HttpApi/AdminHttpApiModule.cs create mode 100644 modules/admin/src/KonSoft.Admin.HttpApi/Controllers/AdminController.cs create mode 100644 modules/admin/src/KonSoft.Admin.HttpApi/KonSoft.Admin.HttpApi.csproj create mode 100644 modules/admin/src/KonSoft.Admin.HttpApi/Models/Test/TestModel.cs create mode 100644 modules/admin/test/KonSoft.Admin.Application.Tests/AdminApplicationTestBase.cs create mode 100644 modules/admin/test/KonSoft.Admin.Application.Tests/AdminApplicationTestModule.cs create mode 100644 modules/admin/test/KonSoft.Admin.Application.Tests/KonSoft.Admin.Application.Tests.csproj create mode 100644 modules/admin/test/KonSoft.Admin.Application.Tests/Samples/SampleAppServiceTests.cs create mode 100644 modules/admin/test/KonSoft.Admin.Domain.Tests/AdminDomainTestBase.cs create mode 100644 modules/admin/test/KonSoft.Admin.Domain.Tests/AdminDomainTestModule.cs create mode 100644 modules/admin/test/KonSoft.Admin.Domain.Tests/KonSoft.Admin.Domain.Tests.csproj create mode 100644 modules/admin/test/KonSoft.Admin.Domain.Tests/Samples/SampleDomainTests.cs create mode 100644 modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreCollection.cs create mode 100644 modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreCollectionFixtureBase.cs create mode 100644 modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreFixture.cs create mode 100644 modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreTestBase.cs create mode 100644 modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreTestModule.cs create mode 100644 modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs create mode 100644 modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs create mode 100644 modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs create mode 100644 modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/KonSoft.Admin.EntityFrameworkCore.Tests.csproj create mode 100644 modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/AdminConsoleApiClientModule.cs create mode 100644 modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs create mode 100644 modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs create mode 100644 modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/KonSoft.Admin.HttpApi.Client.ConsoleTestApp.csproj create mode 100644 modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/Program.cs create mode 100644 modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/appsettings.json create mode 100644 modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json create mode 100644 modules/admin/test/KonSoft.Admin.TestBase/AdminTestBase.cs create mode 100644 modules/admin/test/KonSoft.Admin.TestBase/AdminTestBaseModule.cs create mode 100644 modules/admin/test/KonSoft.Admin.TestBase/AdminTestConsts.cs create mode 100644 modules/admin/test/KonSoft.Admin.TestBase/AdminTestDataSeedContributor.cs create mode 100644 modules/admin/test/KonSoft.Admin.TestBase/KonSoft.Admin.TestBase.csproj create mode 100644 modules/admin/test/KonSoft.Admin.TestBase/Security/FakeCurrentPrincipalAccessor.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/DispatchApplicationContractsModule.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/DispatchDtoExtensions.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/KonSoft.Dispatch.Application.Contracts.csproj create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/Permissions/DispatchPermissionDefinitionProvider.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/Permissions/DispatchPermissions.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Application/DispatchAppService.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Application/DispatchApplicationAutoMapperProfile.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Application/DispatchApplicationModule.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Application/KonSoft.Dispatch.Application.csproj create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Application/Properties/AssemblyInfo.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.DbMigrator/DbMigratorHostedService.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.DbMigrator/DispatchDbMigratorModule.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.DbMigrator/KonSoft.Dispatch.DbMigrator.csproj create mode 100644 modules/dispatch/src/KonSoft.Dispatch.DbMigrator/Program.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.DbMigrator/appsettings.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.DbMigrator/appsettings.secrets.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchDomainErrorCodes.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchDomainSharedModule.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchGlobalFeatureConfigurator.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchModuleExtensionConfigurator.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/KonSoft.Dispatch.Domain.Shared.csproj create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/ar.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/cs.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/de.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/en-GB.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/en.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/es.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/fi.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/fr.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/hi.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/hr.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/hu.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/is.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/it.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/nl.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/pl-PL.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/pt-BR.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/ro-RO.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/ru.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/sk.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/sl.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/sv.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/tr.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/vi.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/zh-Hans.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/zh-Hant.json create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/DispatchResource.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain/Data/DispatchDbMigrationService.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain/Data/IDispatchDbSchemaMigrator.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain/Data/NullDispatchDbSchemaMigrator.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain/DispatchConsts.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain/DispatchDomainModule.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain/KonSoft.Dispatch.Domain.csproj create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain/OpenIddict/OpenIddictDataSeedContributor.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain/Properties/AssemblyInfo.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain/Settings/DispatchSettingDefinitionProvider.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.Domain/Settings/DispatchSettings.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchDbContext.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchDbContextFactory.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchEfCoreEntityExtensionMappings.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchEntityFrameworkCoreModule.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreDispatchDbSchemaMigrator.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/KonSoft.Dispatch.EntityFrameworkCore.csproj create mode 100644 modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Migrations/20250908052345_Initial.Designer.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Migrations/20250908052345_Initial.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Migrations/DispatchDbContextModelSnapshot.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Properties/AssemblyInfo.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.HttpApi.Client/DispatchHttpApiClientModule.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.HttpApi.Client/KonSoft.Dispatch.HttpApi.Client.csproj create mode 100644 modules/dispatch/src/KonSoft.Dispatch.HttpApi/Controllers/DispatchController.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.HttpApi/DispatchHttpApiModule.cs create mode 100644 modules/dispatch/src/KonSoft.Dispatch.HttpApi/KonSoft.Dispatch.HttpApi.csproj create mode 100644 modules/dispatch/src/KonSoft.Dispatch.HttpApi/Models/Test/TestModel.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.Application.Tests/DispatchApplicationTestBase.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.Application.Tests/DispatchApplicationTestModule.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.Application.Tests/KonSoft.Dispatch.Application.Tests.csproj create mode 100644 modules/dispatch/test/KonSoft.Dispatch.Application.Tests/Samples/SampleAppServiceTests.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/DispatchDomainTestBase.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/DispatchDomainTestModule.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/KonSoft.Dispatch.Domain.Tests.csproj create mode 100644 modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/Samples/SampleDomainTests.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreCollection.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreCollectionFixtureBase.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreFixture.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreTestBase.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreTestModule.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/KonSoft.Dispatch.EntityFrameworkCore.Tests.csproj create mode 100644 modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/DispatchConsoleApiClientModule.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp.csproj create mode 100644 modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/Program.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/appsettings.json create mode 100644 modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json create mode 100644 modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestBase.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestBaseModule.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestConsts.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestDataSeedContributor.cs create mode 100644 modules/dispatch/test/KonSoft.Dispatch.TestBase/KonSoft.Dispatch.TestBase.csproj create mode 100644 modules/dispatch/test/KonSoft.Dispatch.TestBase/Security/FakeCurrentPrincipalAccessor.cs create mode 100644 modules/payment/src/KonSoft.Payment.Application.Contracts/KonSoft.Payment.Application.Contracts.csproj create mode 100644 modules/payment/src/KonSoft.Payment.Application.Contracts/PaymentApplicationContractsModule.cs create mode 100644 modules/payment/src/KonSoft.Payment.Application.Contracts/PaymentDtoExtensions.cs create mode 100644 modules/payment/src/KonSoft.Payment.Application.Contracts/Permissions/PaymentPermissionDefinitionProvider.cs create mode 100644 modules/payment/src/KonSoft.Payment.Application.Contracts/Permissions/PaymentPermissions.cs create mode 100644 modules/payment/src/KonSoft.Payment.Application/KonSoft.Payment.Application.csproj create mode 100644 modules/payment/src/KonSoft.Payment.Application/PaymentAppService.cs create mode 100644 modules/payment/src/KonSoft.Payment.Application/PaymentApplicationAutoMapperProfile.cs create mode 100644 modules/payment/src/KonSoft.Payment.Application/PaymentApplicationModule.cs create mode 100644 modules/payment/src/KonSoft.Payment.Application/Properties/AssemblyInfo.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/KonSoft.Payment.Domain.Shared.csproj create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/ar.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/cs.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/de.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/en-GB.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/en.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/es.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/fi.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/fr.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/hi.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/hr.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/hu.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/is.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/it.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/nl.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/pl-PL.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/pt-BR.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/ro-RO.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/ru.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/sk.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/sl.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/sv.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/tr.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/vi.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/zh-Hans.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/zh-Hant.json create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/PaymentResource.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentDomainErrorCodes.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentDomainSharedModule.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentGlobalFeatureConfigurator.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentModuleExtensionConfigurator.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain/Data/IPaymentDbSchemaMigrator.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain/Data/NullPaymentDbSchemaMigrator.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain/Data/PaymentDbMigrationService.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain/KonSoft.Payment.Domain.csproj create mode 100644 modules/payment/src/KonSoft.Payment.Domain/OpenIddict/OpenIddictDataSeedContributor.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain/PaymentConsts.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain/PaymentDomainModule.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain/Properties/AssemblyInfo.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain/Settings/PaymentSettingDefinitionProvider.cs create mode 100644 modules/payment/src/KonSoft.Payment.Domain/Settings/PaymentSettings.cs create mode 100644 modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCorePaymentDbSchemaMigrator.cs create mode 100644 modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentDbContext.cs create mode 100644 modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentDbContextFactory.cs create mode 100644 modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentEfCoreEntityExtensionMappings.cs create mode 100644 modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentEntityFrameworkCoreModule.cs create mode 100644 modules/payment/src/KonSoft.Payment.EntityFrameworkCore/KonSoft.Payment.EntityFrameworkCore.csproj create mode 100644 modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Migrations/20250908052440_Initial.Designer.cs create mode 100644 modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Migrations/20250908052440_Initial.cs create mode 100644 modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Migrations/PaymentDbContextModelSnapshot.cs create mode 100644 modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Properties/AssemblyInfo.cs create mode 100644 modules/payment/src/KonSoft.Payment.HttpApi.Client/KonSoft.Payment.HttpApi.Client.csproj create mode 100644 modules/payment/src/KonSoft.Payment.HttpApi.Client/PaymentHttpApiClientModule.cs create mode 100644 modules/payment/src/KonSoft.Payment.HttpApi/Controllers/PaymentController.cs create mode 100644 modules/payment/src/KonSoft.Payment.HttpApi/KonSoft.Payment.HttpApi.csproj create mode 100644 modules/payment/src/KonSoft.Payment.HttpApi/Models/Test/TestModel.cs create mode 100644 modules/payment/src/KonSoft.Payment.HttpApi/PaymentHttpApiModule.cs create mode 100644 modules/payment/test/KonSoft.Payment.Application.Tests/KonSoft.Payment.Application.Tests.csproj create mode 100644 modules/payment/test/KonSoft.Payment.Application.Tests/PaymentApplicationTestBase.cs create mode 100644 modules/payment/test/KonSoft.Payment.Application.Tests/PaymentApplicationTestModule.cs create mode 100644 modules/payment/test/KonSoft.Payment.Application.Tests/Samples/SampleAppServiceTests.cs create mode 100644 modules/payment/test/KonSoft.Payment.Domain.Tests/KonSoft.Payment.Domain.Tests.csproj create mode 100644 modules/payment/test/KonSoft.Payment.Domain.Tests/PaymentDomainTestBase.cs create mode 100644 modules/payment/test/KonSoft.Payment.Domain.Tests/PaymentDomainTestModule.cs create mode 100644 modules/payment/test/KonSoft.Payment.Domain.Tests/Samples/SampleDomainTests.cs create mode 100644 modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs create mode 100644 modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs create mode 100644 modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreCollection.cs create mode 100644 modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreCollectionFixtureBase.cs create mode 100644 modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreFixture.cs create mode 100644 modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreTestBase.cs create mode 100644 modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreTestModule.cs create mode 100644 modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs create mode 100644 modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/KonSoft.Payment.EntityFrameworkCore.Tests.csproj create mode 100644 modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs create mode 100644 modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs create mode 100644 modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/KonSoft.Payment.HttpApi.Client.ConsoleTestApp.csproj create mode 100644 modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/PaymentConsoleApiClientModule.cs create mode 100644 modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/Program.cs create mode 100644 modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/appsettings.json create mode 100644 modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json create mode 100644 modules/payment/test/KonSoft.Payment.TestBase/KonSoft.Payment.TestBase.csproj create mode 100644 modules/payment/test/KonSoft.Payment.TestBase/PaymentTestBase.cs create mode 100644 modules/payment/test/KonSoft.Payment.TestBase/PaymentTestBaseModule.cs create mode 100644 modules/payment/test/KonSoft.Payment.TestBase/PaymentTestConsts.cs create mode 100644 modules/payment/test/KonSoft.Payment.TestBase/PaymentTestDataSeedContributor.cs create mode 100644 modules/payment/test/KonSoft.Payment.TestBase/Security/FakeCurrentPrincipalAccessor.cs create mode 100644 modules/report/src/KonSoft.Report.Application.Contracts/KonSoft.Report.Application.Contracts.csproj create mode 100644 modules/report/src/KonSoft.Report.Application.Contracts/Permissions/ReportPermissionDefinitionProvider.cs create mode 100644 modules/report/src/KonSoft.Report.Application.Contracts/Permissions/ReportPermissions.cs create mode 100644 modules/report/src/KonSoft.Report.Application.Contracts/ReportApplicationContractsModule.cs create mode 100644 modules/report/src/KonSoft.Report.Application.Contracts/ReportDtoExtensions.cs create mode 100644 modules/report/src/KonSoft.Report.Application/KonSoft.Report.Application.csproj create mode 100644 modules/report/src/KonSoft.Report.Application/Properties/AssemblyInfo.cs create mode 100644 modules/report/src/KonSoft.Report.Application/ReportAppService.cs create mode 100644 modules/report/src/KonSoft.Report.Application/ReportApplicationAutoMapperProfile.cs create mode 100644 modules/report/src/KonSoft.Report.Application/ReportApplicationModule.cs create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/KonSoft.Report.Domain.Shared.csproj create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/ar.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/cs.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/de.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/en-GB.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/en.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/es.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/fi.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/fr.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/hi.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/hr.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/hu.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/is.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/it.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/nl.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/pl-PL.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/pt-BR.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/ro-RO.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/ru.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/sk.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/sl.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/sv.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/tr.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/vi.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/zh-Hans.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/zh-Hant.json create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/Localization/ReportResource.cs create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/ReportDomainErrorCodes.cs create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/ReportDomainSharedModule.cs create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/ReportGlobalFeatureConfigurator.cs create mode 100644 modules/report/src/KonSoft.Report.Domain.Shared/ReportModuleExtensionConfigurator.cs create mode 100644 modules/report/src/KonSoft.Report.Domain/Data/IReportDbSchemaMigrator.cs create mode 100644 modules/report/src/KonSoft.Report.Domain/Data/NullReportDbSchemaMigrator.cs create mode 100644 modules/report/src/KonSoft.Report.Domain/Data/ReportDbMigrationService.cs create mode 100644 modules/report/src/KonSoft.Report.Domain/KonSoft.Report.Domain.csproj create mode 100644 modules/report/src/KonSoft.Report.Domain/OpenIddict/OpenIddictDataSeedContributor.cs create mode 100644 modules/report/src/KonSoft.Report.Domain/Properties/AssemblyInfo.cs create mode 100644 modules/report/src/KonSoft.Report.Domain/ReportConsts.cs create mode 100644 modules/report/src/KonSoft.Report.Domain/ReportDomainModule.cs create mode 100644 modules/report/src/KonSoft.Report.Domain/Settings/ReportSettingDefinitionProvider.cs create mode 100644 modules/report/src/KonSoft.Report.Domain/Settings/ReportSettings.cs create mode 100644 modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreReportDbSchemaMigrator.cs create mode 100644 modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportDbContext.cs create mode 100644 modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportDbContextFactory.cs create mode 100644 modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportEfCoreEntityExtensionMappings.cs create mode 100644 modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportEntityFrameworkCoreModule.cs create mode 100644 modules/report/src/KonSoft.Report.EntityFrameworkCore/KonSoft.Report.EntityFrameworkCore.csproj create mode 100644 modules/report/src/KonSoft.Report.EntityFrameworkCore/Properties/AssemblyInfo.cs create mode 100644 modules/report/src/KonSoft.Report.HttpApi.Client/KonSoft.Report.HttpApi.Client.csproj create mode 100644 modules/report/src/KonSoft.Report.HttpApi.Client/ReportHttpApiClientModule.cs create mode 100644 modules/report/src/KonSoft.Report.HttpApi/Controllers/ReportController.cs create mode 100644 modules/report/src/KonSoft.Report.HttpApi/KonSoft.Report.HttpApi.csproj create mode 100644 modules/report/src/KonSoft.Report.HttpApi/Models/Test/TestModel.cs create mode 100644 modules/report/src/KonSoft.Report.HttpApi/ReportHttpApiModule.cs create mode 100644 modules/report/test/KonSoft.Report.Application.Tests/KonSoft.Report.Application.Tests.csproj create mode 100644 modules/report/test/KonSoft.Report.Application.Tests/ReportApplicationTestBase.cs create mode 100644 modules/report/test/KonSoft.Report.Application.Tests/ReportApplicationTestModule.cs create mode 100644 modules/report/test/KonSoft.Report.Application.Tests/Samples/SampleAppServiceTests.cs create mode 100644 modules/report/test/KonSoft.Report.Domain.Tests/KonSoft.Report.Domain.Tests.csproj create mode 100644 modules/report/test/KonSoft.Report.Domain.Tests/ReportDomainTestBase.cs create mode 100644 modules/report/test/KonSoft.Report.Domain.Tests/ReportDomainTestModule.cs create mode 100644 modules/report/test/KonSoft.Report.Domain.Tests/Samples/SampleDomainTests.cs create mode 100644 modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs create mode 100644 modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs create mode 100644 modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreCollection.cs create mode 100644 modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreCollectionFixtureBase.cs create mode 100644 modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreFixture.cs create mode 100644 modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreTestBase.cs create mode 100644 modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreTestModule.cs create mode 100644 modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs create mode 100644 modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/KonSoft.Report.EntityFrameworkCore.Tests.csproj create mode 100644 modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs create mode 100644 modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs create mode 100644 modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/KonSoft.Report.HttpApi.Client.ConsoleTestApp.csproj create mode 100644 modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/Program.cs create mode 100644 modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/ReportConsoleApiClientModule.cs create mode 100644 modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/appsettings.json create mode 100644 modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json create mode 100644 modules/report/test/KonSoft.Report.TestBase/KonSoft.Report.TestBase.csproj create mode 100644 modules/report/test/KonSoft.Report.TestBase/ReportTestBase.cs create mode 100644 modules/report/test/KonSoft.Report.TestBase/ReportTestBaseModule.cs create mode 100644 modules/report/test/KonSoft.Report.TestBase/ReportTestConsts.cs create mode 100644 modules/report/test/KonSoft.Report.TestBase/ReportTestDataSeedContributor.cs create mode 100644 modules/report/test/KonSoft.Report.TestBase/Security/FakeCurrentPrincipalAccessor.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/KonSoft.TenantManagement.Application.Contracts.csproj create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/Permissions/TenantManagementPermissionDefinitionProvider.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/Permissions/TenantManagementPermissions.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/TenantManagementApplicationContractsModule.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/TenantManagementDtoExtensions.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Application/KonSoft.TenantManagement.Application.csproj create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Application/Properties/AssemblyInfo.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Application/TenantManagementAppService.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Application/TenantManagementApplicationAutoMapperProfile.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Application/TenantManagementApplicationModule.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/KonSoft.TenantManagement.Domain.Shared.csproj create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/ar.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/cs.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/de.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/en-GB.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/en.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/es.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/fi.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/fr.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/hi.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/hr.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/hu.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/is.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/it.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/nl.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/pl-PL.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/pt-BR.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/ro-RO.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/ru.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/sk.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/sl.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/sv.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/tr.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/vi.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/zh-Hans.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/zh-Hant.json create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagementResource.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementDomainErrorCodes.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementDomainSharedModule.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementGlobalFeatureConfigurator.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementModuleExtensionConfigurator.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain/Data/ITenantManagementDbSchemaMigrator.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain/Data/NullTenantManagementDbSchemaMigrator.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain/Data/TenantManagementDbMigrationService.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain/KonSoft.TenantManagement.Domain.csproj create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain/OpenIddict/OpenIddictDataSeedContributor.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain/Properties/AssemblyInfo.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain/Settings/TenantManagementSettingDefinitionProvider.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain/Settings/TenantManagementSettings.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain/TenantManagementConsts.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.Domain/TenantManagementDomainModule.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreTenantManagementDbSchemaMigrator.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementDbContext.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementDbContextFactory.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementEfCoreEntityExtensionMappings.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementEntityFrameworkCoreModule.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/KonSoft.TenantManagement.EntityFrameworkCore.csproj create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Migrations/20250908052623_Initial.Designer.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Migrations/20250908052623_Initial.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Migrations/TenantManagementDbContextModelSnapshot.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Properties/AssemblyInfo.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.HttpApi.Client/KonSoft.TenantManagement.HttpApi.Client.csproj create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.HttpApi.Client/TenantManagementHttpApiClientModule.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/Controllers/TenantManagementController.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/KonSoft.TenantManagement.HttpApi.csproj create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/Models/Test/TestModel.cs create mode 100644 modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/TenantManagementHttpApiModule.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/KonSoft.TenantManagement.Application.Tests.csproj create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/Samples/SampleAppServiceTests.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/TenantManagementApplicationTestBase.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/TenantManagementApplicationTestModule.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/KonSoft.TenantManagement.Domain.Tests.csproj create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/Samples/SampleDomainTests.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/TenantManagementDomainTestBase.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/TenantManagementDomainTestModule.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreCollection.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreCollectionFixtureBase.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreFixture.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreTestBase.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreTestModule.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/KonSoft.TenantManagement.EntityFrameworkCore.Tests.csproj create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp.csproj create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/Program.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/TenantManagementConsoleApiClientModule.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/appsettings.json create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.TestBase/KonSoft.TenantManagement.TestBase.csproj create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.TestBase/Security/FakeCurrentPrincipalAccessor.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestBase.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestBaseModule.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestConsts.cs create mode 100644 modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestDataSeedContributor.cs create mode 100644 shared/KonSoft.Shared/Class1.cs create mode 100644 shared/KonSoft.Shared/KonSoft.Shared.csproj diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c941e52 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +**/wwwroot/libs/** linguist-vendored diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e1e932f --- /dev/null +++ b/.gitignore @@ -0,0 +1,265 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# Admin +src/KonSoft.Admin.Web/Logs/* +src/KonSoft.Admin.Web.Host/Logs/* +src/KonSoft.Admin.AuthServer/Logs/* +src/KonSoft.Admin.HttpApi.Host/Logs/* +src/KonSoft.Admin.HttpApi.Host/Logs/* +src/KonSoft.Admin.DbMigrator/Logs/* +src/KonSoft.Admin.Blazor.Server/Logs/* +src/KonSoft.Admin.Blazor.Server.Tiered/Logs/* + +# Use abp install-libs to restore. +**/wwwroot/libs/* diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..56af76b --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "singleQuote": true, + "useTabs": false, + "tabWidth": 4 +} diff --git a/KonSoft.sln b/KonSoft.sln new file mode 100644 index 0000000..7115e4f --- /dev/null +++ b/KonSoft.sln @@ -0,0 +1,139 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36414.22 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "applications", "applications", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gateways", "gateways", "{C5AC3FEE-4315-4D82-A142-5068D5A6DD73}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "microservices", "microservices", "{4CBFE8AF-968B-453D-B763-3D0437C0883D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{327E64CE-CB3C-480A-AB52-816B8A5329B6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{7EFFD2C6-2041-4967-A715-0F817D70C433}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KonSoft.AuthServer", "applications\KonSoft.AuthServer\KonSoft.AuthServer.csproj", "{D02078B5-294E-DA0D-DD69-46FDEFBD76F9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KonSoft.InternalGateway", "gateways\KonSoft.InternalGateway\KonSoft.InternalGateway.csproj", "{14E3D6EA-528D-4983-9EC8-77FEE4BC2FED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KonSoft.PublicGateway", "gateways\KonSoft.PublicGateway\KonSoft.PublicGateway.csproj", "{AEBC7053-743F-4F80-BD10-8ED6A8A7B3EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KonSoft.Admin.HttpApi.Host", "microservices\KonSoft.Admin.HttpApi.Host\KonSoft.Admin.HttpApi.Host.csproj", "{97BC949A-9142-B129-10FE-0D9381A49C05}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KonSoft.Dispatch.HttpApi.Host", "microservices\KonSoft.Dispatch.HttpApi.Host\KonSoft.Dispatch.HttpApi.Host.csproj", "{D422C785-D6D0-8F6B-A6C3-2B0E5497B923}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KonSoft.Payment.HttpApi.Host", "microservices\KonSoft.Payment.HttpApi.Host\KonSoft.Payment.HttpApi.Host.csproj", "{9A034977-0FBC-A3C8-8432-9FDD073F215A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KonSoft.Report.HttpApi.Host", "microservices\KonSoft.Report.HttpApi.Host\KonSoft.Report.HttpApi.Host.csproj", "{1C89424B-DA16-8840-4AB0-C446CFBD634C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KonSoft.TenantManagement.HttpApi.Host", "microservices\KonSoft.TenantManagement.HttpApi.Host\KonSoft.TenantManagement.HttpApi.Host.csproj", "{3641CA05-99C5-2245-C663-6CE00730E87C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin", "admin", "{A53664DF-71AE-4C8E-A2DC-A60605FDF57C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dispatch", "dispatch", "{75A22B51-A986-48BD-A633-383DA18DE644}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "payment", "payment", "{244E1153-5BE5-4DC2-BA9D-2988BA25F208}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "report", "report", "{AAF02051-771B-4CC0-BD17-1A3643F83E09}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tenant-management", "tenant-management", "{CF59695F-7948-4743-A467-42E4B4C9EECA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EBCB740D-07E7-4CED-A422-90EB824B9021}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{68C52E9A-2894-4F56-B121-EBDEB8AEE5FE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9EDB9917-F429-447B-915D-7D51D38DB33E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{73DCA9DB-1A3D-449F-8957-924B2CF8B7B1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B93EB51F-E75E-4735-8BC8-382015B4DBD5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{026D8210-9B71-4296-9DD8-D4E178802E4D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7FEC24C5-6DA6-4844-B409-0361AB1C192C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6C762F40-30BB-4CDA-951B-01D45F7C2B53}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E67FA5C3-132C-4F47-B6A6-8FA4376C70BB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{1C06151A-45F0-4D48-8303-3D4CBE9517F7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KonSoft.Shared", "shared\KonSoft.Shared\KonSoft.Shared.csproj", "{345B5CDA-DC77-4956-BF96-80707EC1B5B2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D02078B5-294E-DA0D-DD69-46FDEFBD76F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D02078B5-294E-DA0D-DD69-46FDEFBD76F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D02078B5-294E-DA0D-DD69-46FDEFBD76F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D02078B5-294E-DA0D-DD69-46FDEFBD76F9}.Release|Any CPU.Build.0 = Release|Any CPU + {14E3D6EA-528D-4983-9EC8-77FEE4BC2FED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14E3D6EA-528D-4983-9EC8-77FEE4BC2FED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14E3D6EA-528D-4983-9EC8-77FEE4BC2FED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14E3D6EA-528D-4983-9EC8-77FEE4BC2FED}.Release|Any CPU.Build.0 = Release|Any CPU + {AEBC7053-743F-4F80-BD10-8ED6A8A7B3EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AEBC7053-743F-4F80-BD10-8ED6A8A7B3EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AEBC7053-743F-4F80-BD10-8ED6A8A7B3EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AEBC7053-743F-4F80-BD10-8ED6A8A7B3EE}.Release|Any CPU.Build.0 = Release|Any CPU + {97BC949A-9142-B129-10FE-0D9381A49C05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {97BC949A-9142-B129-10FE-0D9381A49C05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {97BC949A-9142-B129-10FE-0D9381A49C05}.Release|Any CPU.ActiveCfg = Release|Any CPU + {97BC949A-9142-B129-10FE-0D9381A49C05}.Release|Any CPU.Build.0 = Release|Any CPU + {D422C785-D6D0-8F6B-A6C3-2B0E5497B923}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D422C785-D6D0-8F6B-A6C3-2B0E5497B923}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D422C785-D6D0-8F6B-A6C3-2B0E5497B923}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D422C785-D6D0-8F6B-A6C3-2B0E5497B923}.Release|Any CPU.Build.0 = Release|Any CPU + {9A034977-0FBC-A3C8-8432-9FDD073F215A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A034977-0FBC-A3C8-8432-9FDD073F215A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A034977-0FBC-A3C8-8432-9FDD073F215A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A034977-0FBC-A3C8-8432-9FDD073F215A}.Release|Any CPU.Build.0 = Release|Any CPU + {1C89424B-DA16-8840-4AB0-C446CFBD634C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1C89424B-DA16-8840-4AB0-C446CFBD634C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C89424B-DA16-8840-4AB0-C446CFBD634C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1C89424B-DA16-8840-4AB0-C446CFBD634C}.Release|Any CPU.Build.0 = Release|Any CPU + {3641CA05-99C5-2245-C663-6CE00730E87C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3641CA05-99C5-2245-C663-6CE00730E87C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3641CA05-99C5-2245-C663-6CE00730E87C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3641CA05-99C5-2245-C663-6CE00730E87C}.Release|Any CPU.Build.0 = Release|Any CPU + {345B5CDA-DC77-4956-BF96-80707EC1B5B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {345B5CDA-DC77-4956-BF96-80707EC1B5B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {345B5CDA-DC77-4956-BF96-80707EC1B5B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {345B5CDA-DC77-4956-BF96-80707EC1B5B2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {D02078B5-294E-DA0D-DD69-46FDEFBD76F9} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {14E3D6EA-528D-4983-9EC8-77FEE4BC2FED} = {C5AC3FEE-4315-4D82-A142-5068D5A6DD73} + {AEBC7053-743F-4F80-BD10-8ED6A8A7B3EE} = {C5AC3FEE-4315-4D82-A142-5068D5A6DD73} + {97BC949A-9142-B129-10FE-0D9381A49C05} = {4CBFE8AF-968B-453D-B763-3D0437C0883D} + {D422C785-D6D0-8F6B-A6C3-2B0E5497B923} = {4CBFE8AF-968B-453D-B763-3D0437C0883D} + {9A034977-0FBC-A3C8-8432-9FDD073F215A} = {4CBFE8AF-968B-453D-B763-3D0437C0883D} + {1C89424B-DA16-8840-4AB0-C446CFBD634C} = {4CBFE8AF-968B-453D-B763-3D0437C0883D} + {3641CA05-99C5-2245-C663-6CE00730E87C} = {4CBFE8AF-968B-453D-B763-3D0437C0883D} + {A53664DF-71AE-4C8E-A2DC-A60605FDF57C} = {327E64CE-CB3C-480A-AB52-816B8A5329B6} + {75A22B51-A986-48BD-A633-383DA18DE644} = {327E64CE-CB3C-480A-AB52-816B8A5329B6} + {244E1153-5BE5-4DC2-BA9D-2988BA25F208} = {327E64CE-CB3C-480A-AB52-816B8A5329B6} + {AAF02051-771B-4CC0-BD17-1A3643F83E09} = {327E64CE-CB3C-480A-AB52-816B8A5329B6} + {CF59695F-7948-4743-A467-42E4B4C9EECA} = {327E64CE-CB3C-480A-AB52-816B8A5329B6} + {EBCB740D-07E7-4CED-A422-90EB824B9021} = {A53664DF-71AE-4C8E-A2DC-A60605FDF57C} + {68C52E9A-2894-4F56-B121-EBDEB8AEE5FE} = {A53664DF-71AE-4C8E-A2DC-A60605FDF57C} + {9EDB9917-F429-447B-915D-7D51D38DB33E} = {75A22B51-A986-48BD-A633-383DA18DE644} + {73DCA9DB-1A3D-449F-8957-924B2CF8B7B1} = {75A22B51-A986-48BD-A633-383DA18DE644} + {B93EB51F-E75E-4735-8BC8-382015B4DBD5} = {244E1153-5BE5-4DC2-BA9D-2988BA25F208} + {026D8210-9B71-4296-9DD8-D4E178802E4D} = {244E1153-5BE5-4DC2-BA9D-2988BA25F208} + {7FEC24C5-6DA6-4844-B409-0361AB1C192C} = {AAF02051-771B-4CC0-BD17-1A3643F83E09} + {6C762F40-30BB-4CDA-951B-01D45F7C2B53} = {AAF02051-771B-4CC0-BD17-1A3643F83E09} + {E67FA5C3-132C-4F47-B6A6-8FA4376C70BB} = {CF59695F-7948-4743-A467-42E4B4C9EECA} + {1C06151A-45F0-4D48-8303-3D4CBE9517F7} = {CF59695F-7948-4743-A467-42E4B4C9EECA} + {345B5CDA-DC77-4956-BF96-80707EC1B5B2} = {7EFFD2C6-2041-4967-A715-0F817D70C433} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {28315BFD-90E7-4E14-A2EA-F3D23AF4126F} + EndGlobalSection +EndGlobal diff --git a/KonSoft.sln.DotSettings b/KonSoft.sln.DotSettings new file mode 100644 index 0000000..cb0b2c9 --- /dev/null +++ b/KonSoft.sln.DotSettings @@ -0,0 +1,23 @@ + + True + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + Required + Required + Required + Required + False + True + False + False + True + False + False + SQL + \ No newline at end of file diff --git a/NuGet.Config b/NuGet.Config new file mode 100644 index 0000000..bdc4519 --- /dev/null +++ b/NuGet.Config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8643a3c --- /dev/null +++ b/README.md @@ -0,0 +1,70 @@ +# KonSoft.Admin + +## About this solution + +This is a layered startup solution based on [Domain Driven Design (DDD)](https://abp.io/docs/latest/framework/architecture/domain-driven-design) practises. All the fundamental ABP modules are already installed. + +### Pre-requirements + +* [.NET 8.0+ SDK](https://dotnet.microsoft.com/download/dotnet) +* [Node v18 or 20](https://nodejs.org/en) +* [Redis](https://redis.io/) + +### Configurations + +The solution comes with a default configuration that works out of the box. However, you may consider to change the following configuration before running your solution: + +* Check the `ConnectionStrings` in `appsettings.json` files under the `KonSoft.Admin.AuthServer`, `KonSoft.Admin.HttpApi.Host` and `KonSoft.Admin.DbMigrator` projects and change it if you need. + +### Before running the application + +#### Generating a Signing Certificate + +In the production environment, you need to use a production signing certificate. ABP Framework sets up signing and encryption certificates in your application and expects an `openiddict.pfx` file in your application. + +This certificate is already generated by ABP CLI, so most of the time you don't need to generate it yourself. However, if you need to generate a certificate, you can use the following command: + +```bash +dotnet dev-certs https -v -ep openiddict.pfx -p dbe188cc-9b2a-4799-836b-bda7987d57b2 +``` + +> `dbe188cc-9b2a-4799-836b-bda7987d57b2` is the password of the certificate, you can change it to any password you want. + +It is recommended to use **two** RSA certificates, distinct from the certificate(s) used for HTTPS: one for encryption, one for signing. + +For more information, please refer to: https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html#registering-a-certificate-recommended-for-production-ready-scenarios + +> Also, see the [Configuring OpenIddict](https://abp.io/docs/latest/deployment/configuring-openiddict#production-environment) documentation for more information. + +#### Install Client-Side Libraries + +Run the following command in the directory of your final application: + +```bash +abp install-libs +``` + +> This command installs all NPM packages for MVC/Razor Pages and Blazor Server UIs and this command is already run by the ABP CLI, so most of the time you don't need to run this command manually. + +#### Create the Database + +Run `KonSoft.Admin.DbMigrator` to create the initial database. This should be done in the first run. It is also needed if a new database migration is added to the solution later. + +### Solution structure + +This is a layered monolith application that consists of the following applications: + +* `KonSoft.Admin.DbMigrator`: A console application which applies the migrations and also seeds the initial data. It is useful on development as well as on production environment. +* `KonSoft.Admin.AuthServer`: ASP.NET Core MVC / Razor Pages application that is integrated OAuth 2.0(`OpenIddict`) and account modules. It is used to authenticate users and issue tokens. +* `KonSoft.Admin.HttpApi.Host`: ASP.NET Core API application that is used to expose the APIs to the clients. + +### Deploying the application + +Deploying an ABP application is not different than deploying any .NET or ASP.NET Core application. However, there are some topics that you should care about when you are deploying your applications. You can check ABP's [Deployment documentation](https://abp.io/docs/latest/deployment) before deploying your application. + +### Additional resources + +You can see the following resources to learn more about your solution and the ABP Framework: + +* [Web Application Development Tutorial](https://abp.io/docs/latest/tutorials/book-store/part-01?UI=Blazor&DB=EF) +* [Application Startup Template Structure](https://abp.io/docs/latest/solution-templates/layered-web-application) diff --git a/applications/KonSoft.AuthServer/KonSoft.AuthServer.csproj b/applications/KonSoft.AuthServer/KonSoft.AuthServer.csproj new file mode 100644 index 0000000..2279469 --- /dev/null +++ b/applications/KonSoft.AuthServer/KonSoft.AuthServer.csproj @@ -0,0 +1,64 @@ + + + + + + net8.0 + enable + KonSoft + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + true + true + true + false + true + KonSoft-4681b4fd-151f-4221-84a4-929d86723e4c + + + + + + + + + + + + Always + + + Always + + + + + + + Always + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/applications/KonSoft.AuthServer/KonSoftAuthServerModule.cs b/applications/KonSoft.AuthServer/KonSoftAuthServerModule.cs new file mode 100644 index 0000000..e22f244 --- /dev/null +++ b/applications/KonSoft.AuthServer/KonSoftAuthServerModule.cs @@ -0,0 +1,222 @@ +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; +using System; +using System.IO; +using System.Linq; +using Localization.Resources.AbpUi; +using Medallion.Threading; +using Medallion.Threading.Redis; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using KonSoft.EntityFrameworkCore; +using KonSoft.Localization; +using KonSoft.MultiTenancy; +using StackExchange.Redis; +using Volo.Abp; +using Volo.Abp.Account; +using Volo.Abp.Account.Web; +using Volo.Abp.AspNetCore.Mvc.UI; +using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Auditing; +using Volo.Abp.Autofac; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Caching; +using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.DistributedLocking; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict; +using Volo.Abp.Security.Claims; +using Volo.Abp.UI.Navigation.Urls; +using Volo.Abp.UI; +using Volo.Abp.VirtualFileSystem; +using Volo.Abp.Account.Localization; + +namespace KonSoft; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpCachingStackExchangeRedisModule), + typeof(AbpDistributedLockingModule), + typeof(AbpAccountWebOpenIddictModule), + typeof(AbpAccountApplicationModule), + typeof(AbpAccountHttpApiModule), + typeof(AbpAspNetCoreMvcUiBasicThemeModule), + typeof(KonSoftEntityFrameworkCoreModule), + typeof(AbpAspNetCoreSerilogModule) + )] +public class KonSoftAuthServerModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + PreConfigure(builder => + { + builder.AddValidation(options => + { + options.AddAudiences("KonSoft"); + options.UseLocalServer(); + options.UseAspNetCore(); + }); + }); + + if (!hostingEnvironment.IsDevelopment()) + { + PreConfigure(options => + { + options.AddDevelopmentEncryptionAndSigningCertificate = false; + }); + + PreConfigure(serverBuilder => + { + serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", "59464dba-b66e-48cd-8b81-2e4a9c08c977"); + }); + } + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + Configure(options => + { + options.Resources + .Get() + .AddBaseTypes( + typeof(AbpUiResource), + typeof(AccountResource) + ); + }); + + Configure(options => + { + options.StyleBundles.Configure( + BasicThemeBundles.Styles.Global, + bundle => + { + bundle.AddFiles("/global-styles.css"); + } + ); + }); + + Configure(options => + { + //options.IsEnabledForGetRequests = true; + options.ApplicationName = "AuthServer"; + }); + + if (hostingEnvironment.IsDevelopment()) + { + Configure(options => + { + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}KonSoft.Domain.Shared")); + options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}KonSoft.Domain")); + }); + } + + Configure(options => + { + options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; + options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"]?.Split(',') ?? Array.Empty()); + + options.Applications["Angular"].RootUrl = configuration["App:ClientUrl"]; + options.Applications["Angular"].Urls[AccountUrlNames.PasswordReset] = "account/reset-password"; + }); + + Configure(options => + { + options.IsJobExecutionEnabled = false; + }); + + Configure(options => + { + options.KeyPrefix = "KonSoft:"; + }); + + var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("KonSoft"); + if (!hostingEnvironment.IsDevelopment()) + { + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "KonSoft-Protection-Keys"); + } + + context.Services.AddSingleton(sp => + { + var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); + return new RedisDistributedSynchronizationProvider(connection.GetDatabase()); + }); + + context.Services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + builder + .WithOrigins( + configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToArray() ?? Array.Empty() + ) + .WithAbpExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + + context.Services.Configure(options => + { + options.IsDynamicClaimsEnabled = true; + }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + var env = context.GetEnvironment(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseAbpRequestLocalization(); + + if (!env.IsDevelopment()) + { + app.UseErrorPage(); + } + + app.UseCorrelationId(); + app.UseStaticFiles(); + app.UseRouting(); + app.UseCors(); + app.UseAuthentication(); + app.UseAbpOpenIddictValidation(); + + if (MultiTenancyConsts.IsEnabled) + { + app.UseMultiTenancy(); + } + + app.UseUnitOfWork(); + app.UseDynamicClaims(); + app.UseAuthorization(); + + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + app.UseConfiguredEndpoints(); + } +} diff --git a/applications/KonSoft.AuthServer/KonSoftBrandingProvider.cs b/applications/KonSoft.AuthServer/KonSoftBrandingProvider.cs new file mode 100644 index 0000000..fd0bc22 --- /dev/null +++ b/applications/KonSoft.AuthServer/KonSoftBrandingProvider.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Localization; +using KonSoft.Localization; +using Volo.Abp.Ui.Branding; +using Volo.Abp.DependencyInjection; + +namespace KonSoft; + +[Dependency(ReplaceServices = true)] +public class KonSoftBrandingProvider : DefaultBrandingProvider +{ + private IStringLocalizer _localizer; + + public KonSoftBrandingProvider(IStringLocalizer localizer) + { + _localizer = localizer; + } + + public override string AppName => _localizer["AppName"]; +} diff --git a/applications/KonSoft.AuthServer/Pages/Index.cshtml b/applications/KonSoft.AuthServer/Pages/Index.cshtml new file mode 100644 index 0000000..79acd9d --- /dev/null +++ b/applications/KonSoft.AuthServer/Pages/Index.cshtml @@ -0,0 +1,118 @@ +@page +@using Microsoft.AspNetCore.Http.Extensions +@using Microsoft.AspNetCore.Mvc.Localization +@using KonSoft.Pages +@using KonSoft.Localization +@using Volo.Abp.Users +@using Volo.Abp.AspNetCore.Mvc.UI.Theming +@using Volo.Abp.Ui.Branding +@model IndexModel +@inject IHtmlLocalizer L +@inject ICurrentUser CurrentUser +@inject IBrandingProvider BrandingProvider +@inject ITheme Theme + +@{ + Layout = Theme.GetEmptyLayout(); +} + +@section styles { + +} + +
+
+ + + +
+
diff --git a/applications/KonSoft.AuthServer/Pages/Index.cshtml.cs b/applications/KonSoft.AuthServer/Pages/Index.cshtml.cs new file mode 100644 index 0000000..cfa19b7 --- /dev/null +++ b/applications/KonSoft.AuthServer/Pages/Index.cshtml.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Threading.Tasks; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Localization; +using Volo.Abp.OpenIddict.Applications; + +namespace KonSoft.Pages; + +public class IndexModel : AbpPageModel +{ + public List? Applications { get; protected set; } + + public IReadOnlyList? Languages { get; protected set; } + + public string? CurrentLanguage { get; protected set; } + + protected IOpenIddictApplicationRepository OpenIdApplicationRepository { get; } + + protected ILanguageProvider LanguageProvider { get; } + + public IndexModel(IOpenIddictApplicationRepository openIdApplicationRepository, ILanguageProvider languageProvider) + { + OpenIdApplicationRepository = openIdApplicationRepository; + LanguageProvider = languageProvider; + } + + public async Task OnGetAsync() + { + Applications = await OpenIdApplicationRepository.GetListAsync(); + + Languages = await LanguageProvider.GetLanguagesAsync(); + CurrentLanguage = CultureInfo.CurrentCulture.DisplayName; + } +} diff --git a/applications/KonSoft.AuthServer/Pages/_ViewImports.cshtml b/applications/KonSoft.AuthServer/Pages/_ViewImports.cshtml new file mode 100644 index 0000000..c1da1f5 --- /dev/null +++ b/applications/KonSoft.AuthServer/Pages/_ViewImports.cshtml @@ -0,0 +1,4 @@ +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling \ No newline at end of file diff --git a/applications/KonSoft.AuthServer/Program.cs b/applications/KonSoft.AuthServer/Program.cs new file mode 100644 index 0000000..3431a6e --- /dev/null +++ b/applications/KonSoft.AuthServer/Program.cs @@ -0,0 +1,56 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Events; + +namespace KonSoft; + +public class Program +{ + public async static Task Main(string[] args) + { + Log.Logger = new LoggerConfiguration() +#if DEBUG + .MinimumLevel.Debug() +#else + .MinimumLevel.Information() +#endif + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) + .Enrich.FromLogContext() + .WriteTo.Async(c => c.File("Logs/logs.txt")) + .WriteTo.Async(c => c.Console()) + .CreateLogger(); + + try + { + Log.Information("Starting KonSoft.AuthServer."); + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .UseSerilog(); + await builder.AddApplicationAsync(); + var app = builder.Build(); + await app.InitializeApplicationAsync(); + await app.RunAsync(); + return 0; + } + catch (Exception ex) + { + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "KonSoft.AuthServer terminated unexpectedly!"); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + } +} diff --git a/applications/KonSoft.AuthServer/Properties/launchSettings.json b/applications/KonSoft.AuthServer/Properties/launchSettings.json new file mode 100644 index 0000000..67f6051 --- /dev/null +++ b/applications/KonSoft.AuthServer/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44322", + "sslPort": 44322 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "KonSoft.AuthServer": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44322", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/applications/KonSoft.AuthServer/abp.resourcemapping.js b/applications/KonSoft.AuthServer/abp.resourcemapping.js new file mode 100644 index 0000000..98822e4 --- /dev/null +++ b/applications/KonSoft.AuthServer/abp.resourcemapping.js @@ -0,0 +1,11 @@ +module.exports = { + aliases: { + + }, + clean: [ + + ], + mappings: { + + } +}; \ No newline at end of file diff --git a/applications/KonSoft.AuthServer/appsettings.Development.json b/applications/KonSoft.AuthServer/appsettings.Development.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/applications/KonSoft.AuthServer/appsettings.Development.json @@ -0,0 +1,2 @@ +{ +} diff --git a/applications/KonSoft.AuthServer/appsettings.json b/applications/KonSoft.AuthServer/appsettings.json new file mode 100644 index 0000000..275efe5 --- /dev/null +++ b/applications/KonSoft.AuthServer/appsettings.json @@ -0,0 +1,17 @@ +{ + "App": { + "SelfUrl": "https://localhost:44322", + "ClientUrl": "http://localhost:4200", + "CorsOrigins": "https://*.KonSoft.com,http://localhost:4200,https://localhost:44316,https://localhost:44370", + "RedirectAllowedUrls": "http://localhost:4200,https://localhost:44319,https://localhost:44316,https://localhost:44347" + }, + "ConnectionStrings": { + "Default": "Host=localhost;Port=5432;Database=KonSoft;User ID=root;Password=myPassword;" + }, + "Redis": { + "Configuration": "127.0.0.1" + }, + "StringEncryption": { + "DefaultPassPhrase": "kxtywyrXW4i7vijT" + } +} diff --git a/applications/KonSoft.AuthServer/appsettings.secrets.json b/applications/KonSoft.AuthServer/appsettings.secrets.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/applications/KonSoft.AuthServer/appsettings.secrets.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/applications/KonSoft.AuthServer/package.json b/applications/KonSoft.AuthServer/package.json new file mode 100644 index 0000000..84d9043 --- /dev/null +++ b/applications/KonSoft.AuthServer/package.json @@ -0,0 +1,8 @@ +{ + "version": "1.0.0", + "name": "my-app-authserver", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.basic": "~8.3.4" + } +} diff --git a/applications/KonSoft.AuthServer/web.config b/applications/KonSoft.AuthServer/web.config new file mode 100644 index 0000000..a0bbf07 --- /dev/null +++ b/applications/KonSoft.AuthServer/web.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/applications/KonSoft.AuthServer/wwwroot/global-styles.css b/applications/KonSoft.AuthServer/wwwroot/global-styles.css new file mode 100644 index 0000000..74db4bd --- /dev/null +++ b/applications/KonSoft.AuthServer/wwwroot/global-styles.css @@ -0,0 +1,6 @@ +/* Your Global Styles */ + +:root .lpx-brand-logo { + --lpx-logo: url('/images/logo/leptonx/logo-light.png'); + --lpx-logo-icon: url('/images/logo/leptonx/logo-light-thumbnail.png'); +} \ No newline at end of file diff --git a/applications/KonSoft.AuthServer/yarn.lock b/applications/KonSoft.AuthServer/yarn.lock new file mode 100644 index 0000000..dd67ef4 --- /dev/null +++ b/applications/KonSoft.AuthServer/yarn.lock @@ -0,0 +1,322 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@abp/aspnetcore.mvc.ui.theme.basic@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-8.3.4.tgz#75708276b2d9162d4f208ebf566fb0a7343636a7" + integrity sha512-m5NBySj8tPbXwMKI1hUfYDzGVxvcU4JGJsSDegetuiulZYm59tPnfdwBeM0zSqx72UPowu/2oDwJsgjODVrDlg== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~8.3.4" + +"@abp/aspnetcore.mvc.ui.theme.shared@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-8.3.4.tgz#169ae0893302ced9256f94174d9bb870e49f446c" + integrity sha512-bZy8iAIN0QfNJXCRg+RR1NxqTzNDSXRPBx+ksFtDxY6FzMJvwwSOmHF0wqsMLj1xpwXjijWaVWQ2RM/7scDWmw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~8.3.4" + "@abp/bootstrap" "~8.3.4" + "@abp/bootstrap-datepicker" "~8.3.4" + "@abp/bootstrap-daterangepicker" "~8.3.4" + "@abp/datatables.net-bs5" "~8.3.4" + "@abp/font-awesome" "~8.3.4" + "@abp/jquery-form" "~8.3.4" + "@abp/jquery-validation-unobtrusive" "~8.3.4" + "@abp/lodash" "~8.3.4" + "@abp/luxon" "~8.3.4" + "@abp/malihu-custom-scrollbar-plugin" "~8.3.4" + "@abp/moment" "~8.3.4" + "@abp/select2" "~8.3.4" + "@abp/sweetalert2" "~8.3.4" + "@abp/timeago" "~8.3.4" + "@abp/toastr" "~8.3.4" + +"@abp/aspnetcore.mvc.ui@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-8.3.4.tgz#041d83f34541081d9e0f37c36c302cbe871a4897" + integrity sha512-sjGE/EoNM98mXNYPze2C7GPP+TNpv4TLIt416ojaqtxru60oddr4VWrOGuhaqUCO2jJes3OwFZi5PY3hVOBbYw== + dependencies: + ansi-colors "^4.1.3" + +"@abp/bootstrap-datepicker@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-8.3.4.tgz#072f4a3cea93e3a1bb1de13b355201648929f84c" + integrity sha512-txilFovf9zT1w+fTkyI3eZdiISjaxc/+wRRFKwrkVH+0xEgaiR41svKm6sjWBORxgTddlGas87SZJvYY3IKBjA== + dependencies: + bootstrap-datepicker "^1.10.0" + +"@abp/bootstrap-daterangepicker@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-8.3.4.tgz#b0f65611ca4fafdf2b551f9f139868eae6e22e9a" + integrity sha512-bYkYjk1zTdWcM4DGwnDoU+4pDvs1S8hkNWhrnpP0o8oRoJiesO8Aeda+82rtydtWnxHg+HkDC0iYFFqaNuHvbg== + dependencies: + bootstrap-daterangepicker "^3.1.0" + +"@abp/bootstrap@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-8.3.4.tgz#744bb4d30d4c269ce8e6a7d16c6777dd3cd9fe1e" + integrity sha512-GXCLFFmPNaR3DjQYSaqACL5sH/M9FPia2OKAAMOd796+NmcoFpT+S7l4C6ihqeQc4bjFm0voB8QklueGWx6r8A== + dependencies: + "@abp/core" "~8.3.4" + bootstrap "^5.3.3" + +"@abp/core@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-8.3.4.tgz#12635bc2ac325a426334150502a32fefa4ec3767" + integrity sha512-wImAdZABahaQe6mmZAZlPfYZ3PEhL7eEq+18c1WFO0xeD98oxqi8H1X7+3ABjyFscIh9LIxJVaD3RJ9OHCc5bw== + dependencies: + "@abp/utils" "~8.3.4" + +"@abp/datatables.net-bs5@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-8.3.4.tgz#efc28fa57144c7b495a4aeea38df962807ca20df" + integrity sha512-u85aXjqYIJJfOsMq6oNqfxNgxQqV6vOEnJ32vrH294ceW8RzUxHA+G/ZkGRLLRGWVuxuARD/UXzEotH5sd1Ssw== + dependencies: + "@abp/datatables.net" "~8.3.4" + datatables.net-bs5 "^2.0.8" + +"@abp/datatables.net@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-8.3.4.tgz#23a3155a2d84247a29a6b80ff98d1d5f6422a245" + integrity sha512-cwE9TFoRoszmI3zNVaYJtqjSPtwkL9dhCfE02zsmJo8GBdFAlbzAmQenfQiWb3BZhvUvKKN20e+og9S8qoCbXA== + dependencies: + "@abp/jquery" "~8.3.4" + datatables.net "^2.0.8" + +"@abp/font-awesome@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-8.3.4.tgz#f79f7b439f9ffadfc03be3a415a977eab21fa5a1" + integrity sha512-5+D5XKnrZROtg9PJ2zex52gbphXGK/7ZIUsszEg8rOIc/niXggaZLmuDcYJwOEzIkwpGO9OvYy7lc0tHv/Pr4g== + dependencies: + "@abp/core" "~8.3.4" + "@fortawesome/fontawesome-free" "^6.5.2" + +"@abp/jquery-form@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-8.3.4.tgz#c1705bd5213ab5c2b895dd5bd9f3e54f3d94cf54" + integrity sha512-vFjWbTbHQyIsk5SS7Cc+5YrJ15ORjJU+YWVPchI0qoug26for06a7lDGpazWMadxx3iPL7cKLqneOqaVtHkgJA== + dependencies: + "@abp/jquery" "~8.3.4" + jquery-form "^4.3.0" + +"@abp/jquery-validation-unobtrusive@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-8.3.4.tgz#e89eafed89787bcb5221c0ba89832b79a7396d19" + integrity sha512-+kJA5vfvxkrj/iW4Q84BrMTrAGOhC2Hb5czAKr6c60Prmayk5hcakZdXc3wDBHREBLVAq1Muk4AtEJZmaKIeaA== + dependencies: + "@abp/jquery-validation" "~8.3.4" + jquery-validation-unobtrusive "^4.0.0" + +"@abp/jquery-validation@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-8.3.4.tgz#a445592d80edc6b6b1334ece2007b3084c329cc6" + integrity sha512-XvL0H3IRuSHwpPKUyJmW6PH8KwPDt9NllMqPGreRANF8l5IU10hOLEeP2BnGFfGMqFwqUMh+eJRar5yZcegkmg== + dependencies: + "@abp/jquery" "~8.3.4" + jquery-validation "^1.20.1" + +"@abp/jquery@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-8.3.4.tgz#2dc3f5f124ac65b5f45d29749ebb5d6cf17db23b" + integrity sha512-Zx2rErtgc0gxjX5PURjp6sjDQfzxBChUE9YWN37Xh+Ysm3tTGcXlF0Emwl94MZ640NfmYRpG4AWdik6kbaU5Wg== + dependencies: + "@abp/core" "~8.3.4" + jquery "~3.7.1" + +"@abp/lodash@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-8.3.4.tgz#b0ef4e82a788ae7389a31793c3bad6702efdbe33" + integrity sha512-yGd/oLds0jpTgTpmkFYOEomS4K15DGcffMP3N1t0qKLgTaBYTQzeugHVgQ0baufC+OvLjumDNuu3eHjBJewwKg== + dependencies: + "@abp/core" "~8.3.4" + lodash "^4.17.21" + +"@abp/luxon@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-8.3.4.tgz#f152b2d7b62bd27f3d27aa3a1794b868bf06a1a4" + integrity sha512-l1nvfqdhHBgHBPK+bLClAEprRK3K5zx5Jar93o5++6r3zXUhYi5OUHUxl+LuGn8MXLvHJVGL41irHl6sYjFSww== + dependencies: + "@abp/core" "~8.3.4" + luxon "^3.4.4" + +"@abp/malihu-custom-scrollbar-plugin@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-8.3.4.tgz#0868214884e3e0b94dade0e8e78c01741d71106a" + integrity sha512-uKRk8+HCvXtpmvof5W09908AkivlweErTE62b0JhkrJVIlYt/0LC1MmB/qHHBfPj6OK05HYGBi3inr7fNAPXEQ== + dependencies: + "@abp/core" "~8.3.4" + malihu-custom-scrollbar-plugin "^3.1.5" + +"@abp/moment@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-8.3.4.tgz#a5809520dc50b50402ade4ac630c6ec985fd4518" + integrity sha512-61J8drO3OqkaaAn66xBg6jCws1iV6zutjYQvpEXLdGBA9Kvw2J87GSomxJ4mcIo/5+jzrVro6JYaCfKWY8b1dw== + dependencies: + moment "^2.30.1" + +"@abp/select2@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-8.3.4.tgz#1731b465760e0515d0d4280f38189c9366fecda5" + integrity sha512-sPtYstFVvMTT8fdXRIfHeODIgSN2ufWm6zCMGH7C0cST3FF59M4m/MtdKGBlA/itzHPxeDv7A6dy4Aw4l7Gk4Q== + dependencies: + "@abp/core" "~8.3.4" + select2 "^4.0.13" + +"@abp/sweetalert2@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-8.3.4.tgz#c0768ca4fe0a9926b8f33d8bf5251d3e4202cd2f" + integrity sha512-6HqxISh+FodwUsCrR3nX49RQDhzHtDlz8ul42TecUMsGa96qX2lvwnoWkXAHLG3mdLRy62Z0dhJ1JKMfrPeJeg== + dependencies: + "@abp/core" "~8.3.4" + sweetalert2 "^11.3.6" + +"@abp/timeago@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-8.3.4.tgz#26ca0bec90d861f9f4af714061b370950551c839" + integrity sha512-cDARYysPn5Rr/9rqVn7S4sBWbeEpaIXr8NKwGZqNOzMF2g283SkLKrkQJBWIC6Pn2lVeIB7AV1+GtVn81V/nnw== + dependencies: + "@abp/jquery" "~8.3.4" + timeago "^1.6.7" + +"@abp/toastr@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-8.3.4.tgz#cb433bc4ed2e302f2704ad0456c99d6f12fd0529" + integrity sha512-29C9GgwlumrHgt1iZ4lArDnlXfSvmCHDehxkbDutrkC1m257UxQaOID11us2UeCs3JobueQcLlQKD/LqnDB4xA== + dependencies: + "@abp/jquery" "~8.3.4" + toastr "^2.1.4" + +"@abp/utils@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-8.3.4.tgz#4b06575a110e85e2a360294f678b782818e1ab10" + integrity sha512-7Lq3wdk/07vKgQnR56DTmdSuYRABMe0XTGPJRS5F91DVbggeJyDUaqifVvOeurF/3CZJOS7fJpoIHQXeUveFtQ== + dependencies: + just-compare "^2.3.0" + +"@fortawesome/fontawesome-free@^6.5.2": + version "6.7.2" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.2.tgz#8249de9b7e22fcb3ceb5e66090c30a1d5492b81a" + integrity sha512-JUOtgFW6k9u4Y+xeIaEiLr3+cjoUPiAuLXoyKOJSia6Duzb7pq+A76P9ZdPDoAoxHdHzq6gE9/jKBGXlZT8FbA== + +ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +bootstrap-datepicker@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/bootstrap-datepicker/-/bootstrap-datepicker-1.10.0.tgz#61612bbe8bf0a69a5bce32bbcdda93ebb6ccf24a" + integrity sha512-lWxtSYddAQOpbAO8UhYhHLcK6425eWoSjb5JDvZU3ePHEPF6A3eUr51WKaFy4PccU19JRxUG6wEU3KdhtKfvpg== + dependencies: + jquery ">=3.4.0 <4.0.0" + +bootstrap-daterangepicker@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bootstrap-daterangepicker/-/bootstrap-daterangepicker-3.1.0.tgz#632e6fb2de4b6360c5c0a9d5f6adb9aace051fe8" + integrity sha512-oaQZx6ZBDo/dZNyXGVi2rx5GmFXThyQLAxdtIqjtLlYVaQUfQALl5JZMJJZzyDIX7blfy4ppZPAJ10g8Ma4d/g== + dependencies: + jquery ">=1.10" + moment "^2.9.0" + +bootstrap@^5.3.3: + version "5.3.8" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.8.tgz#6401a10057a22752d21f4e19055508980656aeed" + integrity sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg== + +datatables.net-bs5@^2.0.8: + version "2.3.3" + resolved "https://registry.yarnpkg.com/datatables.net-bs5/-/datatables.net-bs5-2.3.3.tgz#8bf3aec484a69e373f6007038eaac0cc0ef4ee15" + integrity sha512-IPtC57k3KyZaLzIYTHies23Cm2zqaKfD6lkxy/aOAUUAtsg35l53VqNY9y84AEySYG3YLghMHVBvl2ckUhvm0A== + dependencies: + datatables.net "2.3.3" + jquery ">=1.7" + +datatables.net@2.3.3, datatables.net@^2.0.8: + version "2.3.3" + resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-2.3.3.tgz#fe4f96bdbc4cf47c8d11162a7af525ca6a3683d2" + integrity sha512-SWL3za6nheY6gdoiLgCc++tYmxbwrmv2bjrEiII9rXBWXXSbOZct6pjR3FueMVRM5jmt7pQcXiGovfuFDnutQg== + dependencies: + jquery ">=1.7" + +jquery-form@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/jquery-form/-/jquery-form-4.3.0.tgz#7d3961c314a1f2d15298f4af1d3943f54f4149c6" + integrity sha512-q3uaVCEWdLOYUCI6dpNdwf/7cJFOsUgdpq6r0taxtGQ5NJSkOzofyWm4jpOuJ5YxdmL1FI5QR+q+HB63HHLGnQ== + dependencies: + jquery ">=1.7.2" + +jquery-mousewheel@>=3.0.6: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.2.2.tgz#48c833f6260ee0c46d438a999e7d0060ec9eed0b" + integrity sha512-JP71xTAg08ZY3hcs9ZbYUZ5i+dkSsz4yRl/zpWkAmtzc+kMs5EfPkpkINSidiLYMaR0MTo3DfFGF9WIezMsFQQ== + dependencies: + jquery ">=1.2.6" + +jquery-validation-unobtrusive@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-4.0.0.tgz#dfcf25a558496a2c883db6021d10f5398d15f99d" + integrity sha512-1ervYFFv6LX/rp7ktuLnMakHNG0piNRDyROI8Ir3hL1vPIwylAehB1AY3BPrYJnzW3WmwWryZq+Bz4sazZK9iQ== + dependencies: + jquery "^3.6.0" + jquery-validation ">=1.19" + +jquery-validation@>=1.19, jquery-validation@^1.20.1: + version "1.21.0" + resolved "https://registry.yarnpkg.com/jquery-validation/-/jquery-validation-1.21.0.tgz#78fc05ab76020912a246af3661b3f54a438bca93" + integrity sha512-xNot0rlUIgu7duMcQ5qb6MGkGL/Z1PQaRJQoZAURW9+a/2PGOUxY36o/WyNeP2T9R6jvWB8Z9lUVvvQWI/Zs5w== + +jquery@>=1.10, jquery@>=1.12.0, jquery@>=1.2.6, "jquery@>=1.5.0 <4.0", jquery@>=1.7, jquery@>=1.7.2, "jquery@>=3.4.0 <4.0.0", jquery@^3.6.0, jquery@~3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" + integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== + +just-compare@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/just-compare/-/just-compare-2.3.0.tgz#a2adcc1d1940536263275f5a1ef1298bcacfeda7" + integrity sha512-6shoR7HDT+fzfL3gBahx1jZG3hWLrhPAf+l7nCwahDdT9XDtosB9kIF0ZrzUp5QY8dJWfQVr5rnsPqsbvflDzg== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +luxon@^3.4.4: + version "3.7.2" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.7.2.tgz#d697e48f478553cca187a0f8436aff468e3ba0ba" + integrity sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew== + +malihu-custom-scrollbar-plugin@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-3.1.5.tgz#310cecc5e59415a1c29e9dfb5d2b6e01d66a29ef" + integrity sha512-lwW3LgI+CNDMPnP4ED2la6oYxWMkCXlnhex+s2wuOLhFDFGnGmQuTQVdRK9bvDLpxs10sGlfErVufJy9ztfgJQ== + dependencies: + jquery-mousewheel ">=3.0.6" + +moment@^2.30.1, moment@^2.9.0: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + +select2@^4.0.13: + version "4.0.13" + resolved "https://registry.yarnpkg.com/select2/-/select2-4.0.13.tgz#0dbe377df3f96167c4c1626033e924372d8ef44d" + integrity sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw== + +sweetalert2@^11.3.6: + version "11.23.0" + resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-11.23.0.tgz#ba8a051b1e94215c762af08692171b7b4611c4c1" + integrity sha512-cKzzbC3C1sIs7o9XAMw4E8F9kBtGXsBDUsd2JZ8JM/dqa+nzWwSGM+9LLYILZWzWHzX9W+HJNHyBlbHPVS/krw== + +timeago@^1.6.7: + version "1.6.7" + resolved "https://registry.yarnpkg.com/timeago/-/timeago-1.6.7.tgz#afd467c29a911e697fc22a81888c7c3022783cb5" + integrity sha512-FikcjN98+ij0siKH4VO4dZ358PR3oDDq4Vdl1+sN9gWz1/+JXGr3uZbUShYH/hL7bMhcTpPbplJU5Tej4b4jbQ== + dependencies: + jquery ">=1.5.0 <4.0" + +toastr@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/toastr/-/toastr-2.1.4.tgz#8b43be64fb9d0c414871446f2db8e8ca4e95f181" + integrity sha512-LIy77F5n+sz4tefMmFOntcJ6HL0Fv3k1TDnNmFZ0bU/GcvIIfy6eG2v7zQmMiYgaalAiUv75ttFrPn5s0gyqlA== + dependencies: + jquery ">=1.12.0" diff --git a/common.props b/common.props new file mode 100644 index 0000000..22d34c4 --- /dev/null +++ b/common.props @@ -0,0 +1,19 @@ + + + latest + 1.0.0 + $(NoWarn);CS1591 + app + + + + + $(NoWarn);0436 + + + + + + + + \ No newline at end of file diff --git a/gateways/KonSoft.InternalGateway/Controllers/WeatherForecastController.cs b/gateways/KonSoft.InternalGateway/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..2fcaf5e --- /dev/null +++ b/gateways/KonSoft.InternalGateway/Controllers/WeatherForecastController.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.Mvc; + +namespace KonSoft.InternalGateway.Controllers +{ + [ApiController] + [Route("[controller]")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git a/gateways/KonSoft.InternalGateway/KonSoft.InternalGateway.csproj b/gateways/KonSoft.InternalGateway/KonSoft.InternalGateway.csproj new file mode 100644 index 0000000..5419ef0 --- /dev/null +++ b/gateways/KonSoft.InternalGateway/KonSoft.InternalGateway.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/gateways/KonSoft.InternalGateway/KonSoft.InternalGateway.http b/gateways/KonSoft.InternalGateway/KonSoft.InternalGateway.http new file mode 100644 index 0000000..95c5e0b --- /dev/null +++ b/gateways/KonSoft.InternalGateway/KonSoft.InternalGateway.http @@ -0,0 +1,6 @@ +@KonSoft.InternalGateway_HostAddress = http://localhost:5090 + +GET {{KonSoft.InternalGateway_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/gateways/KonSoft.InternalGateway/Program.cs b/gateways/KonSoft.InternalGateway/Program.cs new file mode 100644 index 0000000..48863a6 --- /dev/null +++ b/gateways/KonSoft.InternalGateway/Program.cs @@ -0,0 +1,25 @@ +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/gateways/KonSoft.InternalGateway/Properties/launchSettings.json b/gateways/KonSoft.InternalGateway/Properties/launchSettings.json new file mode 100644 index 0000000..407c599 --- /dev/null +++ b/gateways/KonSoft.InternalGateway/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:15968", + "sslPort": 44395 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5090", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7264;http://localhost:5090", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/gateways/KonSoft.InternalGateway/WeatherForecast.cs b/gateways/KonSoft.InternalGateway/WeatherForecast.cs new file mode 100644 index 0000000..3905db0 --- /dev/null +++ b/gateways/KonSoft.InternalGateway/WeatherForecast.cs @@ -0,0 +1,13 @@ +namespace KonSoft.InternalGateway +{ + public class WeatherForecast + { + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} diff --git a/gateways/KonSoft.InternalGateway/appsettings.Development.json b/gateways/KonSoft.InternalGateway/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/gateways/KonSoft.InternalGateway/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/gateways/KonSoft.InternalGateway/appsettings.json b/gateways/KonSoft.InternalGateway/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/gateways/KonSoft.InternalGateway/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/gateways/KonSoft.PublicGateway/Controllers/WeatherForecastController.cs b/gateways/KonSoft.PublicGateway/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..7d2536e --- /dev/null +++ b/gateways/KonSoft.PublicGateway/Controllers/WeatherForecastController.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.Mvc; + +namespace KonSoft.PublicGateway.Controllers +{ + [ApiController] + [Route("[controller]")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git a/gateways/KonSoft.PublicGateway/KonSoft.PublicGateway.csproj b/gateways/KonSoft.PublicGateway/KonSoft.PublicGateway.csproj new file mode 100644 index 0000000..5419ef0 --- /dev/null +++ b/gateways/KonSoft.PublicGateway/KonSoft.PublicGateway.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/gateways/KonSoft.PublicGateway/KonSoft.PublicGateway.http b/gateways/KonSoft.PublicGateway/KonSoft.PublicGateway.http new file mode 100644 index 0000000..66040bf --- /dev/null +++ b/gateways/KonSoft.PublicGateway/KonSoft.PublicGateway.http @@ -0,0 +1,6 @@ +@KonSoft.PublicGateway_HostAddress = http://localhost:5214 + +GET {{KonSoft.PublicGateway_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/gateways/KonSoft.PublicGateway/Program.cs b/gateways/KonSoft.PublicGateway/Program.cs new file mode 100644 index 0000000..48863a6 --- /dev/null +++ b/gateways/KonSoft.PublicGateway/Program.cs @@ -0,0 +1,25 @@ +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/gateways/KonSoft.PublicGateway/Properties/launchSettings.json b/gateways/KonSoft.PublicGateway/Properties/launchSettings.json new file mode 100644 index 0000000..aacf6d5 --- /dev/null +++ b/gateways/KonSoft.PublicGateway/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:30296", + "sslPort": 44320 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5214", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7029;http://localhost:5214", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/gateways/KonSoft.PublicGateway/WeatherForecast.cs b/gateways/KonSoft.PublicGateway/WeatherForecast.cs new file mode 100644 index 0000000..2577b66 --- /dev/null +++ b/gateways/KonSoft.PublicGateway/WeatherForecast.cs @@ -0,0 +1,13 @@ +namespace KonSoft.PublicGateway +{ + public class WeatherForecast + { + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} diff --git a/gateways/KonSoft.PublicGateway/appsettings.Development.json b/gateways/KonSoft.PublicGateway/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/gateways/KonSoft.PublicGateway/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/gateways/KonSoft.PublicGateway/appsettings.json b/gateways/KonSoft.PublicGateway/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/gateways/KonSoft.PublicGateway/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/microservices/KonSoft.Admin.HttpApi.Host/AdminBrandingProvider.cs b/microservices/KonSoft.Admin.HttpApi.Host/AdminBrandingProvider.cs new file mode 100644 index 0000000..6c1ffde --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/AdminBrandingProvider.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Localization; +using KonSoft.Admin.Localization; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Ui.Branding; + +namespace KonSoft.Admin; + +[Dependency(ReplaceServices = true)] +public class AdminBrandingProvider : DefaultBrandingProvider +{ + private IStringLocalizer _localizer; + + public AdminBrandingProvider(IStringLocalizer localizer) + { + _localizer = localizer; + } + + public override string AppName => _localizer["AppName"]; +} diff --git a/microservices/KonSoft.Admin.HttpApi.Host/AdminHttpApiHostModule.cs b/microservices/KonSoft.Admin.HttpApi.Host/AdminHttpApiHostModule.cs new file mode 100644 index 0000000..85f450e --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/AdminHttpApiHostModule.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Extensions.DependencyInjection; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using KonSoft.Admin.EntityFrameworkCore; +using KonSoft.Admin.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling; +using Microsoft.OpenApi.Models; +using OpenIddict.Validation.AspNetCore; +using Volo.Abp; +using Volo.Abp.Account; +using Volo.Abp.Account.Web; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.Security.Claims; +using Volo.Abp.Swashbuckle; +using Volo.Abp.UI.Navigation.Urls; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.Admin; + +[DependsOn( + typeof(AdminHttpApiModule), + typeof(AbpAutofacModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(AdminApplicationModule), + typeof(AdminEntityFrameworkCoreModule), + typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule), + typeof(AbpAccountWebOpenIddictModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpSwashbuckleModule) +)] +public class AdminHttpApiHostModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(builder => + { + builder.AddValidation(options => + { + options.AddAudiences("Admin"); + options.UseLocalServer(); + options.UseAspNetCore(); + }); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + ConfigureAuthentication(context); + ConfigureBundles(); + ConfigureUrls(configuration); + ConfigureConventionalControllers(); + ConfigureVirtualFileSystem(context); + ConfigureCors(context, configuration); + ConfigureSwaggerServices(context, configuration); + } + + private void ConfigureAuthentication(ServiceConfigurationContext context) + { + context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme); + context.Services.Configure(options => + { + options.IsDynamicClaimsEnabled = true; + }); + } + + private void ConfigureBundles() + { + Configure(options => + { + options.StyleBundles.Configure( + LeptonXLiteThemeBundles.Styles.Global, + bundle => + { + bundle.AddFiles("/global-styles.css"); + } + ); + }); + } + + private void ConfigureUrls(IConfiguration configuration) + { + Configure(options => + { + options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; + options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"]?.Split(',') ?? Array.Empty()); + + options.Applications["Angular"].RootUrl = configuration["App:ClientUrl"]; + options.Applications["Angular"].Urls[AccountUrlNames.PasswordReset] = "account/reset-password"; + }); + } + + private void ConfigureVirtualFileSystem(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + if (hostingEnvironment.IsDevelopment()) + { + Configure(options => + { + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Admin.Domain.Shared")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Admin.Domain")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Admin.Application.Contracts")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Admin.Application")); + }); + } + } + + private void ConfigureConventionalControllers() + { + Configure(options => + { + options.ConventionalControllers.Create(typeof(AdminApplicationModule).Assembly); + }); + } + + private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration) + { + context.Services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"]!, + new Dictionary + { + {"Admin", "Admin API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Admin API", Version = "v1" }); + options.DocInclusionPredicate((docName, description) => true); + options.CustomSchemaIds(type => type.FullName); + }); + } + + private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration) + { + context.Services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + builder + .WithOrigins(configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToArray() ?? Array.Empty()) + .WithAbpExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + var env = context.GetEnvironment(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseAbpRequestLocalization(); + + if (!env.IsDevelopment()) + { + app.UseErrorPage(); + } + + app.UseCorrelationId(); + app.UseStaticFiles(); + app.UseRouting(); + app.UseCors(); + app.UseAuthentication(); + app.UseAbpOpenIddictValidation(); + + if (MultiTenancyConsts.IsEnabled) + { + app.UseMultiTenancy(); + } + app.UseUnitOfWork(); + app.UseDynamicClaims(); + app.UseAuthorization(); + + app.UseSwagger(); + app.UseAbpSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "Admin API"); + + var configuration = context.ServiceProvider.GetRequiredService(); + c.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + c.OAuthScopes("Admin"); + }); + + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + app.UseConfiguredEndpoints(); + } +} diff --git a/microservices/KonSoft.Admin.HttpApi.Host/Controllers/HomeController.cs b/microservices/KonSoft.Admin.HttpApi.Host/Controllers/HomeController.cs new file mode 100644 index 0000000..caf536b --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/Controllers/HomeController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace KonSoft.Admin.Controllers; + +public class HomeController : AbpController +{ + public ActionResult Index() + { + return Redirect("~/swagger"); + } +} diff --git a/microservices/KonSoft.Admin.HttpApi.Host/KonSoft.Admin.HttpApi.Host.csproj b/microservices/KonSoft.Admin.HttpApi.Host/KonSoft.Admin.HttpApi.Host.csproj new file mode 100644 index 0000000..98cca8f --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/KonSoft.Admin.HttpApi.Host.csproj @@ -0,0 +1,40 @@ + + + + + + net8.0 + enable + KonSoft.Admin + true + KonSoft.Admin-4681b4fd-151f-4221-84a4-929d86723e4c + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/microservices/KonSoft.Admin.HttpApi.Host/Program.cs b/microservices/KonSoft.Admin.HttpApi.Host/Program.cs new file mode 100644 index 0000000..6d2ff4d --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/Program.cs @@ -0,0 +1,56 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Events; + +namespace KonSoft.Admin; + +public class Program +{ + public async static Task Main(string[] args) + { + Log.Logger = new LoggerConfiguration() +#if DEBUG + .MinimumLevel.Debug() +#else + .MinimumLevel.Information() +#endif + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) + .Enrich.FromLogContext() + .WriteTo.Async(c => c.File("Logs/logs.txt")) + .WriteTo.Async(c => c.Console()) + .CreateLogger(); + + try + { + Log.Information("Starting KonSoft.Admin.HttpApi.Host."); + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .UseSerilog(); + await builder.AddApplicationAsync(); + var app = builder.Build(); + await app.InitializeApplicationAsync(); + await app.RunAsync(); + return 0; + } + catch (Exception ex) + { + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + } +} diff --git a/microservices/KonSoft.Admin.HttpApi.Host/Properties/launchSettings.json b/microservices/KonSoft.Admin.HttpApi.Host/Properties/launchSettings.json new file mode 100644 index 0000000..1116d11 --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44350", + "sslPort": 44350 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "KonSoft.Admin.HttpApi.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44350", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/microservices/KonSoft.Admin.HttpApi.Host/abp.resourcemapping.js b/microservices/KonSoft.Admin.HttpApi.Host/abp.resourcemapping.js new file mode 100644 index 0000000..4a2ad45 --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/abp.resourcemapping.js @@ -0,0 +1,11 @@ +module.exports = { + aliases: { + + }, + clean: [ + + ], + mappings: { + + } +}; diff --git a/microservices/KonSoft.Admin.HttpApi.Host/appsettings.Development.json b/microservices/KonSoft.Admin.HttpApi.Host/appsettings.Development.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/appsettings.Development.json @@ -0,0 +1,2 @@ +{ +} diff --git a/microservices/KonSoft.Admin.HttpApi.Host/appsettings.json b/microservices/KonSoft.Admin.HttpApi.Host/appsettings.json new file mode 100644 index 0000000..8096818 --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/appsettings.json @@ -0,0 +1,18 @@ +{ + "App": { + "SelfUrl": "https://localhost:44350", + "CorsOrigins": "https://*.Admin.com", + "RedirectAllowedUrls": "" + }, + "ConnectionStrings": { + "Default": "Host=localhost;Port=5432;Database=Admin;User ID=root;Password=myPassword;" + }, + "AuthServer": { + "Authority": "https://localhost:44350", + "RequireHttpsMetadata": false, + "SwaggerClientId": "Admin_Swagger" + }, + "StringEncryption": { + "DefaultPassPhrase": "YXM86JJ7EFsh21K9" + } +} diff --git a/microservices/KonSoft.Admin.HttpApi.Host/appsettings.secrets.json b/microservices/KonSoft.Admin.HttpApi.Host/appsettings.secrets.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/appsettings.secrets.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/microservices/KonSoft.Admin.HttpApi.Host/package.json b/microservices/KonSoft.Admin.HttpApi.Host/package.json new file mode 100644 index 0000000..b8d616a --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/package.json @@ -0,0 +1,8 @@ +{ + "version": "1.0.0", + "name": "my-app", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~3.3.4" + } +} diff --git a/microservices/KonSoft.Admin.HttpApi.Host/web.config b/microservices/KonSoft.Admin.HttpApi.Host/web.config new file mode 100644 index 0000000..fc25838 --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/web.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/microservices/KonSoft.Admin.HttpApi.Host/wwwroot/global-styles.css b/microservices/KonSoft.Admin.HttpApi.Host/wwwroot/global-styles.css new file mode 100644 index 0000000..74db4bd --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/wwwroot/global-styles.css @@ -0,0 +1,6 @@ +/* Your Global Styles */ + +:root .lpx-brand-logo { + --lpx-logo: url('/images/logo/leptonx/logo-light.png'); + --lpx-logo-icon: url('/images/logo/leptonx/logo-light-thumbnail.png'); +} \ No newline at end of file diff --git a/microservices/KonSoft.Admin.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png b/microservices/KonSoft.Admin.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..9734a07a4d4539d3081bb897ffc8d5e75dab8798 GIT binary patch literal 10695 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 iRGz-n4VZ}kM?W?F&FYYBo literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.Admin.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png b/microservices/KonSoft.Admin.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a3bbe82224deec74650461230f66d609eda717e3 GIT binary patch literal 38171 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 MU)LDY2zE;NA05R;CIA2c literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.Admin.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png b/microservices/KonSoft.Admin.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png new file mode 100644 index 0000000000000000000000000000000000000000..761fb4443d597661e7700574e52b787d7ed7255b GIT binary patch literal 33228 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 nuxmBTJ6Y+ll0437Z literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.Admin.HttpApi.Host/yarn.lock b/microservices/KonSoft.Admin.HttpApi.Host/yarn.lock new file mode 100644 index 0000000..1dfe9d4 --- /dev/null +++ b/microservices/KonSoft.Admin.HttpApi.Host/yarn.lock @@ -0,0 +1,322 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@abp/aspnetcore.mvc.ui.theme.leptonxlite@~3.3.4": + version "3.3.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.leptonxlite/-/aspnetcore.mvc.ui.theme.leptonxlite-3.3.4.tgz#fb6879075aec2f06e0302e941dcefbe519b18e1d" + integrity sha512-5rrwwZ9n2/yePo+GnHuUsP0TelCwRwCQjYyQFdF/Nd4B3UNQVO/AXQc0Ep3+vHhUxSL386j6ObZYu14VdjPg2g== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~8.3.4" + +"@abp/aspnetcore.mvc.ui.theme.shared@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-8.3.4.tgz#169ae0893302ced9256f94174d9bb870e49f446c" + integrity sha512-bZy8iAIN0QfNJXCRg+RR1NxqTzNDSXRPBx+ksFtDxY6FzMJvwwSOmHF0wqsMLj1xpwXjijWaVWQ2RM/7scDWmw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~8.3.4" + "@abp/bootstrap" "~8.3.4" + "@abp/bootstrap-datepicker" "~8.3.4" + "@abp/bootstrap-daterangepicker" "~8.3.4" + "@abp/datatables.net-bs5" "~8.3.4" + "@abp/font-awesome" "~8.3.4" + "@abp/jquery-form" "~8.3.4" + "@abp/jquery-validation-unobtrusive" "~8.3.4" + "@abp/lodash" "~8.3.4" + "@abp/luxon" "~8.3.4" + "@abp/malihu-custom-scrollbar-plugin" "~8.3.4" + "@abp/moment" "~8.3.4" + "@abp/select2" "~8.3.4" + "@abp/sweetalert2" "~8.3.4" + "@abp/timeago" "~8.3.4" + "@abp/toastr" "~8.3.4" + +"@abp/aspnetcore.mvc.ui@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-8.3.4.tgz#041d83f34541081d9e0f37c36c302cbe871a4897" + integrity sha512-sjGE/EoNM98mXNYPze2C7GPP+TNpv4TLIt416ojaqtxru60oddr4VWrOGuhaqUCO2jJes3OwFZi5PY3hVOBbYw== + dependencies: + ansi-colors "^4.1.3" + +"@abp/bootstrap-datepicker@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-8.3.4.tgz#072f4a3cea93e3a1bb1de13b355201648929f84c" + integrity sha512-txilFovf9zT1w+fTkyI3eZdiISjaxc/+wRRFKwrkVH+0xEgaiR41svKm6sjWBORxgTddlGas87SZJvYY3IKBjA== + dependencies: + bootstrap-datepicker "^1.10.0" + +"@abp/bootstrap-daterangepicker@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-8.3.4.tgz#b0f65611ca4fafdf2b551f9f139868eae6e22e9a" + integrity sha512-bYkYjk1zTdWcM4DGwnDoU+4pDvs1S8hkNWhrnpP0o8oRoJiesO8Aeda+82rtydtWnxHg+HkDC0iYFFqaNuHvbg== + dependencies: + bootstrap-daterangepicker "^3.1.0" + +"@abp/bootstrap@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-8.3.4.tgz#744bb4d30d4c269ce8e6a7d16c6777dd3cd9fe1e" + integrity sha512-GXCLFFmPNaR3DjQYSaqACL5sH/M9FPia2OKAAMOd796+NmcoFpT+S7l4C6ihqeQc4bjFm0voB8QklueGWx6r8A== + dependencies: + "@abp/core" "~8.3.4" + bootstrap "^5.3.3" + +"@abp/core@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-8.3.4.tgz#12635bc2ac325a426334150502a32fefa4ec3767" + integrity sha512-wImAdZABahaQe6mmZAZlPfYZ3PEhL7eEq+18c1WFO0xeD98oxqi8H1X7+3ABjyFscIh9LIxJVaD3RJ9OHCc5bw== + dependencies: + "@abp/utils" "~8.3.4" + +"@abp/datatables.net-bs5@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-8.3.4.tgz#efc28fa57144c7b495a4aeea38df962807ca20df" + integrity sha512-u85aXjqYIJJfOsMq6oNqfxNgxQqV6vOEnJ32vrH294ceW8RzUxHA+G/ZkGRLLRGWVuxuARD/UXzEotH5sd1Ssw== + dependencies: + "@abp/datatables.net" "~8.3.4" + datatables.net-bs5 "^2.0.8" + +"@abp/datatables.net@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-8.3.4.tgz#23a3155a2d84247a29a6b80ff98d1d5f6422a245" + integrity sha512-cwE9TFoRoszmI3zNVaYJtqjSPtwkL9dhCfE02zsmJo8GBdFAlbzAmQenfQiWb3BZhvUvKKN20e+og9S8qoCbXA== + dependencies: + "@abp/jquery" "~8.3.4" + datatables.net "^2.0.8" + +"@abp/font-awesome@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-8.3.4.tgz#f79f7b439f9ffadfc03be3a415a977eab21fa5a1" + integrity sha512-5+D5XKnrZROtg9PJ2zex52gbphXGK/7ZIUsszEg8rOIc/niXggaZLmuDcYJwOEzIkwpGO9OvYy7lc0tHv/Pr4g== + dependencies: + "@abp/core" "~8.3.4" + "@fortawesome/fontawesome-free" "^6.5.2" + +"@abp/jquery-form@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-8.3.4.tgz#c1705bd5213ab5c2b895dd5bd9f3e54f3d94cf54" + integrity sha512-vFjWbTbHQyIsk5SS7Cc+5YrJ15ORjJU+YWVPchI0qoug26for06a7lDGpazWMadxx3iPL7cKLqneOqaVtHkgJA== + dependencies: + "@abp/jquery" "~8.3.4" + jquery-form "^4.3.0" + +"@abp/jquery-validation-unobtrusive@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-8.3.4.tgz#e89eafed89787bcb5221c0ba89832b79a7396d19" + integrity sha512-+kJA5vfvxkrj/iW4Q84BrMTrAGOhC2Hb5czAKr6c60Prmayk5hcakZdXc3wDBHREBLVAq1Muk4AtEJZmaKIeaA== + dependencies: + "@abp/jquery-validation" "~8.3.4" + jquery-validation-unobtrusive "^4.0.0" + +"@abp/jquery-validation@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-8.3.4.tgz#a445592d80edc6b6b1334ece2007b3084c329cc6" + integrity sha512-XvL0H3IRuSHwpPKUyJmW6PH8KwPDt9NllMqPGreRANF8l5IU10hOLEeP2BnGFfGMqFwqUMh+eJRar5yZcegkmg== + dependencies: + "@abp/jquery" "~8.3.4" + jquery-validation "^1.20.1" + +"@abp/jquery@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-8.3.4.tgz#2dc3f5f124ac65b5f45d29749ebb5d6cf17db23b" + integrity sha512-Zx2rErtgc0gxjX5PURjp6sjDQfzxBChUE9YWN37Xh+Ysm3tTGcXlF0Emwl94MZ640NfmYRpG4AWdik6kbaU5Wg== + dependencies: + "@abp/core" "~8.3.4" + jquery "~3.7.1" + +"@abp/lodash@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-8.3.4.tgz#b0ef4e82a788ae7389a31793c3bad6702efdbe33" + integrity sha512-yGd/oLds0jpTgTpmkFYOEomS4K15DGcffMP3N1t0qKLgTaBYTQzeugHVgQ0baufC+OvLjumDNuu3eHjBJewwKg== + dependencies: + "@abp/core" "~8.3.4" + lodash "^4.17.21" + +"@abp/luxon@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-8.3.4.tgz#f152b2d7b62bd27f3d27aa3a1794b868bf06a1a4" + integrity sha512-l1nvfqdhHBgHBPK+bLClAEprRK3K5zx5Jar93o5++6r3zXUhYi5OUHUxl+LuGn8MXLvHJVGL41irHl6sYjFSww== + dependencies: + "@abp/core" "~8.3.4" + luxon "^3.4.4" + +"@abp/malihu-custom-scrollbar-plugin@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-8.3.4.tgz#0868214884e3e0b94dade0e8e78c01741d71106a" + integrity sha512-uKRk8+HCvXtpmvof5W09908AkivlweErTE62b0JhkrJVIlYt/0LC1MmB/qHHBfPj6OK05HYGBi3inr7fNAPXEQ== + dependencies: + "@abp/core" "~8.3.4" + malihu-custom-scrollbar-plugin "^3.1.5" + +"@abp/moment@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-8.3.4.tgz#a5809520dc50b50402ade4ac630c6ec985fd4518" + integrity sha512-61J8drO3OqkaaAn66xBg6jCws1iV6zutjYQvpEXLdGBA9Kvw2J87GSomxJ4mcIo/5+jzrVro6JYaCfKWY8b1dw== + dependencies: + moment "^2.30.1" + +"@abp/select2@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-8.3.4.tgz#1731b465760e0515d0d4280f38189c9366fecda5" + integrity sha512-sPtYstFVvMTT8fdXRIfHeODIgSN2ufWm6zCMGH7C0cST3FF59M4m/MtdKGBlA/itzHPxeDv7A6dy4Aw4l7Gk4Q== + dependencies: + "@abp/core" "~8.3.4" + select2 "^4.0.13" + +"@abp/sweetalert2@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-8.3.4.tgz#c0768ca4fe0a9926b8f33d8bf5251d3e4202cd2f" + integrity sha512-6HqxISh+FodwUsCrR3nX49RQDhzHtDlz8ul42TecUMsGa96qX2lvwnoWkXAHLG3mdLRy62Z0dhJ1JKMfrPeJeg== + dependencies: + "@abp/core" "~8.3.4" + sweetalert2 "^11.3.6" + +"@abp/timeago@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-8.3.4.tgz#26ca0bec90d861f9f4af714061b370950551c839" + integrity sha512-cDARYysPn5Rr/9rqVn7S4sBWbeEpaIXr8NKwGZqNOzMF2g283SkLKrkQJBWIC6Pn2lVeIB7AV1+GtVn81V/nnw== + dependencies: + "@abp/jquery" "~8.3.4" + timeago "^1.6.7" + +"@abp/toastr@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-8.3.4.tgz#cb433bc4ed2e302f2704ad0456c99d6f12fd0529" + integrity sha512-29C9GgwlumrHgt1iZ4lArDnlXfSvmCHDehxkbDutrkC1m257UxQaOID11us2UeCs3JobueQcLlQKD/LqnDB4xA== + dependencies: + "@abp/jquery" "~8.3.4" + toastr "^2.1.4" + +"@abp/utils@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-8.3.4.tgz#4b06575a110e85e2a360294f678b782818e1ab10" + integrity sha512-7Lq3wdk/07vKgQnR56DTmdSuYRABMe0XTGPJRS5F91DVbggeJyDUaqifVvOeurF/3CZJOS7fJpoIHQXeUveFtQ== + dependencies: + just-compare "^2.3.0" + +"@fortawesome/fontawesome-free@^6.5.2": + version "6.7.2" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.2.tgz#8249de9b7e22fcb3ceb5e66090c30a1d5492b81a" + integrity sha512-JUOtgFW6k9u4Y+xeIaEiLr3+cjoUPiAuLXoyKOJSia6Duzb7pq+A76P9ZdPDoAoxHdHzq6gE9/jKBGXlZT8FbA== + +ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +bootstrap-datepicker@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/bootstrap-datepicker/-/bootstrap-datepicker-1.10.0.tgz#61612bbe8bf0a69a5bce32bbcdda93ebb6ccf24a" + integrity sha512-lWxtSYddAQOpbAO8UhYhHLcK6425eWoSjb5JDvZU3ePHEPF6A3eUr51WKaFy4PccU19JRxUG6wEU3KdhtKfvpg== + dependencies: + jquery ">=3.4.0 <4.0.0" + +bootstrap-daterangepicker@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bootstrap-daterangepicker/-/bootstrap-daterangepicker-3.1.0.tgz#632e6fb2de4b6360c5c0a9d5f6adb9aace051fe8" + integrity sha512-oaQZx6ZBDo/dZNyXGVi2rx5GmFXThyQLAxdtIqjtLlYVaQUfQALl5JZMJJZzyDIX7blfy4ppZPAJ10g8Ma4d/g== + dependencies: + jquery ">=1.10" + moment "^2.9.0" + +bootstrap@^5.3.3: + version "5.3.8" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.8.tgz#6401a10057a22752d21f4e19055508980656aeed" + integrity sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg== + +datatables.net-bs5@^2.0.8: + version "2.3.3" + resolved "https://registry.yarnpkg.com/datatables.net-bs5/-/datatables.net-bs5-2.3.3.tgz#8bf3aec484a69e373f6007038eaac0cc0ef4ee15" + integrity sha512-IPtC57k3KyZaLzIYTHies23Cm2zqaKfD6lkxy/aOAUUAtsg35l53VqNY9y84AEySYG3YLghMHVBvl2ckUhvm0A== + dependencies: + datatables.net "2.3.3" + jquery ">=1.7" + +datatables.net@2.3.3, datatables.net@^2.0.8: + version "2.3.3" + resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-2.3.3.tgz#fe4f96bdbc4cf47c8d11162a7af525ca6a3683d2" + integrity sha512-SWL3za6nheY6gdoiLgCc++tYmxbwrmv2bjrEiII9rXBWXXSbOZct6pjR3FueMVRM5jmt7pQcXiGovfuFDnutQg== + dependencies: + jquery ">=1.7" + +jquery-form@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/jquery-form/-/jquery-form-4.3.0.tgz#7d3961c314a1f2d15298f4af1d3943f54f4149c6" + integrity sha512-q3uaVCEWdLOYUCI6dpNdwf/7cJFOsUgdpq6r0taxtGQ5NJSkOzofyWm4jpOuJ5YxdmL1FI5QR+q+HB63HHLGnQ== + dependencies: + jquery ">=1.7.2" + +jquery-mousewheel@>=3.0.6: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.2.2.tgz#48c833f6260ee0c46d438a999e7d0060ec9eed0b" + integrity sha512-JP71xTAg08ZY3hcs9ZbYUZ5i+dkSsz4yRl/zpWkAmtzc+kMs5EfPkpkINSidiLYMaR0MTo3DfFGF9WIezMsFQQ== + dependencies: + jquery ">=1.2.6" + +jquery-validation-unobtrusive@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-4.0.0.tgz#dfcf25a558496a2c883db6021d10f5398d15f99d" + integrity sha512-1ervYFFv6LX/rp7ktuLnMakHNG0piNRDyROI8Ir3hL1vPIwylAehB1AY3BPrYJnzW3WmwWryZq+Bz4sazZK9iQ== + dependencies: + jquery "^3.6.0" + jquery-validation ">=1.19" + +jquery-validation@>=1.19, jquery-validation@^1.20.1: + version "1.21.0" + resolved "https://registry.yarnpkg.com/jquery-validation/-/jquery-validation-1.21.0.tgz#78fc05ab76020912a246af3661b3f54a438bca93" + integrity sha512-xNot0rlUIgu7duMcQ5qb6MGkGL/Z1PQaRJQoZAURW9+a/2PGOUxY36o/WyNeP2T9R6jvWB8Z9lUVvvQWI/Zs5w== + +jquery@>=1.10, jquery@>=1.12.0, jquery@>=1.2.6, "jquery@>=1.5.0 <4.0", jquery@>=1.7, jquery@>=1.7.2, "jquery@>=3.4.0 <4.0.0", jquery@^3.6.0, jquery@~3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" + integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== + +just-compare@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/just-compare/-/just-compare-2.3.0.tgz#a2adcc1d1940536263275f5a1ef1298bcacfeda7" + integrity sha512-6shoR7HDT+fzfL3gBahx1jZG3hWLrhPAf+l7nCwahDdT9XDtosB9kIF0ZrzUp5QY8dJWfQVr5rnsPqsbvflDzg== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +luxon@^3.4.4: + version "3.7.2" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.7.2.tgz#d697e48f478553cca187a0f8436aff468e3ba0ba" + integrity sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew== + +malihu-custom-scrollbar-plugin@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-3.1.5.tgz#310cecc5e59415a1c29e9dfb5d2b6e01d66a29ef" + integrity sha512-lwW3LgI+CNDMPnP4ED2la6oYxWMkCXlnhex+s2wuOLhFDFGnGmQuTQVdRK9bvDLpxs10sGlfErVufJy9ztfgJQ== + dependencies: + jquery-mousewheel ">=3.0.6" + +moment@^2.30.1, moment@^2.9.0: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + +select2@^4.0.13: + version "4.0.13" + resolved "https://registry.yarnpkg.com/select2/-/select2-4.0.13.tgz#0dbe377df3f96167c4c1626033e924372d8ef44d" + integrity sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw== + +sweetalert2@^11.3.6: + version "11.23.0" + resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-11.23.0.tgz#ba8a051b1e94215c762af08692171b7b4611c4c1" + integrity sha512-cKzzbC3C1sIs7o9XAMw4E8F9kBtGXsBDUsd2JZ8JM/dqa+nzWwSGM+9LLYILZWzWHzX9W+HJNHyBlbHPVS/krw== + +timeago@^1.6.7: + version "1.6.7" + resolved "https://registry.yarnpkg.com/timeago/-/timeago-1.6.7.tgz#afd467c29a911e697fc22a81888c7c3022783cb5" + integrity sha512-FikcjN98+ij0siKH4VO4dZ358PR3oDDq4Vdl1+sN9gWz1/+JXGr3uZbUShYH/hL7bMhcTpPbplJU5Tej4b4jbQ== + dependencies: + jquery ">=1.5.0 <4.0" + +toastr@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/toastr/-/toastr-2.1.4.tgz#8b43be64fb9d0c414871446f2db8e8ca4e95f181" + integrity sha512-LIy77F5n+sz4tefMmFOntcJ6HL0Fv3k1TDnNmFZ0bU/GcvIIfy6eG2v7zQmMiYgaalAiUv75ttFrPn5s0gyqlA== + dependencies: + jquery ">=1.12.0" diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/Controllers/HomeController.cs b/microservices/KonSoft.Dispatch.HttpApi.Host/Controllers/HomeController.cs new file mode 100644 index 0000000..9c0bb17 --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/Controllers/HomeController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace KonSoft.Dispatch.Controllers; + +public class HomeController : AbpController +{ + public ActionResult Index() + { + return Redirect("~/swagger"); + } +} diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/DispatchBrandingProvider.cs b/microservices/KonSoft.Dispatch.HttpApi.Host/DispatchBrandingProvider.cs new file mode 100644 index 0000000..8337c66 --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/DispatchBrandingProvider.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Localization; +using KonSoft.Dispatch.Localization; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Ui.Branding; + +namespace KonSoft.Dispatch; + +[Dependency(ReplaceServices = true)] +public class DispatchBrandingProvider : DefaultBrandingProvider +{ + private IStringLocalizer _localizer; + + public DispatchBrandingProvider(IStringLocalizer localizer) + { + _localizer = localizer; + } + + public override string AppName => _localizer["AppName"]; +} diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/DispatchHttpApiHostModule.cs b/microservices/KonSoft.Dispatch.HttpApi.Host/DispatchHttpApiHostModule.cs new file mode 100644 index 0000000..dbf0e2f --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/DispatchHttpApiHostModule.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Extensions.DependencyInjection; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using KonSoft.Dispatch.EntityFrameworkCore; +using KonSoft.Dispatch.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling; +using Microsoft.OpenApi.Models; +using OpenIddict.Validation.AspNetCore; +using Volo.Abp; +using Volo.Abp.Account; +using Volo.Abp.Account.Web; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.Security.Claims; +using Volo.Abp.Swashbuckle; +using Volo.Abp.UI.Navigation.Urls; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.Dispatch; + +[DependsOn( + typeof(DispatchHttpApiModule), + typeof(AbpAutofacModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(DispatchApplicationModule), + typeof(DispatchEntityFrameworkCoreModule), + typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule), + typeof(AbpAccountWebOpenIddictModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpSwashbuckleModule) +)] +public class DispatchHttpApiHostModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(builder => + { + builder.AddValidation(options => + { + options.AddAudiences("Dispatch"); + options.UseLocalServer(); + options.UseAspNetCore(); + }); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + ConfigureAuthentication(context); + ConfigureBundles(); + ConfigureUrls(configuration); + ConfigureConventionalControllers(); + ConfigureVirtualFileSystem(context); + ConfigureCors(context, configuration); + ConfigureSwaggerServices(context, configuration); + } + + private void ConfigureAuthentication(ServiceConfigurationContext context) + { + context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme); + context.Services.Configure(options => + { + options.IsDynamicClaimsEnabled = true; + }); + } + + private void ConfigureBundles() + { + Configure(options => + { + options.StyleBundles.Configure( + LeptonXLiteThemeBundles.Styles.Global, + bundle => + { + bundle.AddFiles("/global-styles.css"); + } + ); + }); + } + + private void ConfigureUrls(IConfiguration configuration) + { + Configure(options => + { + options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; + options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"]?.Split(',') ?? Array.Empty()); + + options.Applications["Angular"].RootUrl = configuration["App:ClientUrl"]; + options.Applications["Angular"].Urls[AccountUrlNames.PasswordReset] = "account/reset-password"; + }); + } + + private void ConfigureVirtualFileSystem(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + if (hostingEnvironment.IsDevelopment()) + { + Configure(options => + { + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Dispatch.Domain.Shared")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Dispatch.Domain")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Dispatch.Application.Contracts")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Dispatch.Application")); + }); + } + } + + private void ConfigureConventionalControllers() + { + Configure(options => + { + options.ConventionalControllers.Create(typeof(DispatchApplicationModule).Assembly); + }); + } + + private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration) + { + context.Services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"]!, + new Dictionary + { + {"Dispatch", "Dispatch API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Dispatch API", Version = "v1" }); + options.DocInclusionPredicate((docName, description) => true); + options.CustomSchemaIds(type => type.FullName); + }); + } + + private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration) + { + context.Services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + builder + .WithOrigins(configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToArray() ?? Array.Empty()) + .WithAbpExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + var env = context.GetEnvironment(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseAbpRequestLocalization(); + + if (!env.IsDevelopment()) + { + app.UseErrorPage(); + } + + app.UseCorrelationId(); + app.UseStaticFiles(); + app.UseRouting(); + app.UseCors(); + app.UseAuthentication(); + app.UseAbpOpenIddictValidation(); + + if (MultiTenancyConsts.IsEnabled) + { + app.UseMultiTenancy(); + } + app.UseUnitOfWork(); + app.UseDynamicClaims(); + app.UseAuthorization(); + + app.UseSwagger(); + app.UseAbpSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "Dispatch API"); + + var configuration = context.ServiceProvider.GetRequiredService(); + c.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + c.OAuthScopes("Dispatch"); + }); + + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + app.UseConfiguredEndpoints(); + } +} diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/KonSoft.Dispatch.HttpApi.Host.csproj b/microservices/KonSoft.Dispatch.HttpApi.Host/KonSoft.Dispatch.HttpApi.Host.csproj new file mode 100644 index 0000000..4626828 --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/KonSoft.Dispatch.HttpApi.Host.csproj @@ -0,0 +1,40 @@ + + + + + + net8.0 + enable + KonSoft.Dispatch + true + KonSoft.Dispatch-4681b4fd-151f-4221-84a4-929d86723e4c + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/Program.cs b/microservices/KonSoft.Dispatch.HttpApi.Host/Program.cs new file mode 100644 index 0000000..caa2139 --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/Program.cs @@ -0,0 +1,56 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Events; + +namespace KonSoft.Dispatch; + +public class Program +{ + public async static Task Main(string[] args) + { + Log.Logger = new LoggerConfiguration() +#if DEBUG + .MinimumLevel.Debug() +#else + .MinimumLevel.Information() +#endif + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) + .Enrich.FromLogContext() + .WriteTo.Async(c => c.File("Logs/logs.txt")) + .WriteTo.Async(c => c.Console()) + .CreateLogger(); + + try + { + Log.Information("Starting KonSoft.Dispatch.HttpApi.Host."); + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .UseSerilog(); + await builder.AddApplicationAsync(); + var app = builder.Build(); + await app.InitializeApplicationAsync(); + await app.RunAsync(); + return 0; + } + catch (Exception ex) + { + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + } +} diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/Properties/launchSettings.json b/microservices/KonSoft.Dispatch.HttpApi.Host/Properties/launchSettings.json new file mode 100644 index 0000000..10bade1 --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44321", + "sslPort": 44321 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "KonSoft.Dispatch.HttpApi.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44321", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/abp.resourcemapping.js b/microservices/KonSoft.Dispatch.HttpApi.Host/abp.resourcemapping.js new file mode 100644 index 0000000..4a2ad45 --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/abp.resourcemapping.js @@ -0,0 +1,11 @@ +module.exports = { + aliases: { + + }, + clean: [ + + ], + mappings: { + + } +}; diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/appsettings.Development.json b/microservices/KonSoft.Dispatch.HttpApi.Host/appsettings.Development.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/appsettings.Development.json @@ -0,0 +1,2 @@ +{ +} diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/appsettings.json b/microservices/KonSoft.Dispatch.HttpApi.Host/appsettings.json new file mode 100644 index 0000000..094bd17 --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/appsettings.json @@ -0,0 +1,18 @@ +{ + "App": { + "SelfUrl": "https://localhost:44321", + "CorsOrigins": "https://*.Dispatch.com", + "RedirectAllowedUrls": "" + }, + "ConnectionStrings": { + "Default": "Host=localhost;Port=5432;Database=Dispatch;User ID=root;Password=myPassword;" + }, + "AuthServer": { + "Authority": "https://localhost:44321", + "RequireHttpsMetadata": false, + "SwaggerClientId": "Dispatch_Swagger" + }, + "StringEncryption": { + "DefaultPassPhrase": "AcY4JMdp6hCRgMYj" + } +} diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/appsettings.secrets.json b/microservices/KonSoft.Dispatch.HttpApi.Host/appsettings.secrets.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/appsettings.secrets.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/package.json b/microservices/KonSoft.Dispatch.HttpApi.Host/package.json new file mode 100644 index 0000000..b8d616a --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/package.json @@ -0,0 +1,8 @@ +{ + "version": "1.0.0", + "name": "my-app", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~3.3.4" + } +} diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/web.config b/microservices/KonSoft.Dispatch.HttpApi.Host/web.config new file mode 100644 index 0000000..729e3cd --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/web.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/global-styles.css b/microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/global-styles.css new file mode 100644 index 0000000..74db4bd --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/global-styles.css @@ -0,0 +1,6 @@ +/* Your Global Styles */ + +:root .lpx-brand-logo { + --lpx-logo: url('/images/logo/leptonx/logo-light.png'); + --lpx-logo-icon: url('/images/logo/leptonx/logo-light-thumbnail.png'); +} \ No newline at end of file diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png b/microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..9734a07a4d4539d3081bb897ffc8d5e75dab8798 GIT binary patch literal 10695 zcmXwfc_5VE7x!b!*v5=(h0F}HFGUz4v)C%K?+FQ!J!H)?7?O~$?0c56WEp#wEQMq# z!q^#O~(Tiw^&Fc)8o-rar>$>!lUapXHwM1Z4% zti`3z{~c>4_s`5aFKXDQtR$Gm1wv*F%lpXjt?Gn&2Q0?tJXJyIf zTxU8osOenIQT(|=YsO7uZQUVRHFI0=7Q4}{8_In{T_XRc=G(bv3_h+qprb)!;>10GOR8_pH9Vy$lZ* zh;F@BeJSF2uDYbHvTrWy9uxq0!+EE_)Hh4fH!{2mZVYZ7ymsV=$H^sD=)*N;wF=agg~NvBCFK&{UB6*tpv z6Uff6?a>=!&BjdtutE1yiCv%}WQ)>?mc>H^0D!w-S!2v_XajG;N3p58vN?;VbOok* zo^po|i0*Pi!#f5*0Pqw(xAVaxl$#0&btBsOaPCykk-jK!0Q2|PUpBq6w8I+H0>7w< zv%C(6lRGRI07a{_LRREJX)FM!iJu%D>7D6uQ0i{2MNhICQ;a)lghV{{)$%l3%B2B- z%}oWc6N$1Uayfc#F#U7|FMAX`cN(Gs;(#L_dtF*UCcH`A2Y<{O{LAt1c4iMR6At4e(X@)BN|E3-d%CXPF0RRNS;?L8< z8}$D_;`>Jp#fkT=koKHkO=_T(VE-Q0YEnh?Ed-f_%kH{ zu<+Q;52(9TJgykDpz)e|3_|%UcJCZc$c7tXD5Xy!pXC9V({O$SWv#Dh13;?lh&~6M z4gn4T#!xvk78T1C1_03GKxKLXz;NuhM_|YEUp9Jpk70clD!>;j5KvPLJ*#Pl`ta=O zOQ*jYHTbyfP`<@=x2^9=m8Npdzq$T*;u9~(N8-Qj@BP?BN_}I}#+z^{8Ux&7^6eY$ z8m+Q4VUK;1K22g?I|NlmoZXVXD0$EXy6;3C`54Y##9C)E#dlzQcz4G2YCTxfLzVF_2xLyzGp zmrPa`*~=_xY!{7a>l#MAMiT4Ig#GQx=93FSD+TCe6Nlg@L)V0NTZM|-h7W`LX&q8Q zu8y;jjpF&ER#wWrr3_+_Y`2H1y8mY1JCADNS4ZK>a zJ_;7!k}?zutBx$5v%90hl|3?G>1P+@@gSkf^PyhJN?>8iCoVWGL!9iKs93f~q+=oM z?a}=l0b8?q#$ToFm@M+>Qv~sTLi~f{BYtEsP0o&7{%jgx;rd_Q2DU`K3W{*j$(}~4 z_VbIJ1r=3SDz)=^fg4Ek4|p=m~E%DQ7JYc z(GWfA@5{@iAlcMM__<)RNr>V07gZ%rLkhT3Esdffi037rg~p#Jp6PQz1-j`2Bs4%! zDddY4G(Pdc;@;=KAyX{+YH<*Rg%|isBt(FjzRFp(W=1C(Qr)PO-SmhQoOk=#a+Y6T zWi6w66wl(rhKxb$Yi#gE8R0vX%<;DcU-?7(XP%n1R6K6Ic9f@X+QTDt=vw(#Y9!v$ zO4%tIRI$e?sbo0DTA`qsW-*ojn$`{cbOkM+ezBkULyyjNY^eXqAUIoPXov2;HFUU@EnBAQHnrcX?62S2-}9_8?c#n=^iyHsyUV#tUah55i07-J z;4-nAQWewb;eK$UEF!s8?#FLyt;mHakgY}PqRvv^6_PugDN%)C=DOp2=%>u8naufQ z(Ah*>%ec7*pZniET$kdLSUUbsyu5F`U42BJMDuPTS8fg8fv0bmNGp;zS4W%<+HWAq zTg}2~5cJSRQJXxZ@KR(ZLZ6D1oN3dd6R5drCG0;M`}G1Lf{IGX!3_3rkS@dbB(f-N zn8Q>ZAB>;{DM?_lr}GKxLpa?gDYW8hY}j@%*z`v_q`KGns1Cfr2*-jT`xf{K{>~y- z+jMy}4)~CO!HMZ}Y-l-(L7{Ub;Bo&Uff=v7+oSO`bG zE6FQwi_u>U{g;uVwtf-e9f)mQ?$r6_D|;i4_myO27CICrkMEJNVZ{^MWdtu)VG(?BoV1jt#W-MD_baZ@=S1VdY2 z-?ILM2l8m*k#`yKka%QQ>Z<@~G>n)ldDJ^_U0$IYf#&9rL8ysnL~2PU7KVc0XsS!+ zf+;6ERlyY3ZUAbh+RY0>KitdP@Hf+dK;WF_2lWezzjCu;7^|}}k6RvP(3xQI^}Mc% zAlZH)dx@%~RJ{tJ2f-Ybpyl`KJYe*TDK7&SIHUcik(2@!`n>A;>7YYL1T!AuiX?eJ zEyyD=61BfGfvkIXI3ydmr}>OIja^1S?H(cTQ5Iq}cFdd>&005bQbWVF zFzIHH%NXua?)>A;nZ&z*dVx{xkYW3NrN|%5%l`$;t>n8!bTI{BzLf(MlRYsMB!%|$C8SA~AeGno84-@@5RuANBU!3&Ui7<$pe<3Q#?s!7a(y;7M^|g zENJn3c?LI0+Jm)Rw0V(%7(tQ7&A5k}T6?pQKvV*Iq>=-MNVf9%*vF$vT_CC+CI(6p zHGR_(yWTFo`p5_U?dA_oirmmmbxoaDSBAY_sqdkMS1MbTqv_{TW=6qBm<>`RnKzAI zWt4k9uJK2e%fru6sOttf>&gRP1M!;1doY!TmBqM>fy$R~Dl`)dqo7NRA}gZNCeS4*Q7ubIMR1l4xQL?M@3SnPBfJ#@T46a_!E zXN3Q?cDhbBN zww6wA&>MeVGW~n@Da*ps%9?(`q3ke3GTJKhPiWOdQ!eQiPdi3U&dT>w9?gPDnXfcL zQ)-%NqxZ!(r!j{svAaU~&pvotZYp@UW6A zFTLUU0WdkPg$U$_!5J7*0?MKTRo$RRIr%=o-`U!b6{L6$L}{!wFOHMkn^@v%%z+iJ zG@0#52J#-Q&?0T1mz6tjKkj+l=E`A6ja&J`ph(`Ress~y;+8^Wn%(Wt;rGa}^|sC4 zn1?81RvxCA3)&12i{#AV_uVt-dLz^{Um+5SvRg+w!Q?VBLv^OI#qi~dFTu!6PlyFM z0pk&;yeK31gDr2Lb5Ic^+44OMW>_1DI^zm6#N$5xzEZhI86QY!u11{voC62{5URry zD35#lJGHFsz<^D#B%HeHu_J;wKt+=$gesCKcasq)9DizxsxX^T=ar*R8&qGr1Lg+# z6=!2)?rVhZ3qN}JS-!icE<%EUb{gpvD`jwyn4G9#kt(k#Va!uuD%;B%qZ+ zj3EeGID-8dzLdD2YaR4g?0*6|ZoA6_P+BUDKHa1MnpXybK%*qz8qiG&p{>%Q^q(24R}+7bsPL<}}kdGw;3!ej>%`QX}}^*y0g ze`{ZiNrHVfvpf~aFuCnGagyhn@YIyM*I0MlqYnK1;!P1`-Ao!LK@?Yz=^0q%Sp2W5 z^h`c^ZXxgf)3ZOJ$INyeGJmxXlXL#|J+Ra z4O9EOljYa)F8OZWG9)~&Ve#u}GuVPpo1rp>m6~16dRj^nSx$nu)L$44j!t;77{Mep zZ^A2y1bG*o5OSMWP(N=y@oRyr+3Kr~?B=)fH3(;nRu=KP~=$s*;{P#@AT; zUsnkDOpOs71<1{g`OlnsTuY)xuhX-2b2!e03~MZSx_*~sEVMo4GqdRD__Qd73$XND znkf{M&E8LED&@``v&fvkyFJN`^OmCV!;<^YZkAT zN6CnEsI8#%rN4@zrCKJ6P8)=aWnea19l1ar9D^?T(J)u(tw^!sqBnuLL0cN$LEKb8 zJfnVi*r|V?2x4Fy-V@U*hQsC94_!#^f`WHVS!~Cnu9%_>&9pwaZ8li)_D&Ivc?%h-H_kd-15tG*s0|j>VK`8s&`9&n>1kU+KA^1$g0gA!eHAU28E8W)@zQ2G9G&C6zXkrHpyUFzUBhg;qntzZ&xPXgf#-=!UHf>@cKfN`!oBy%dE zS3z8SE6NE-$R50xSE~i6lM=W|$(>?`O^Vuhpz-&0b-hKdk)>n*{V zP#QL8knsH<@|n+V$Y0pu;oML$PK29WBscUUH2*(yUT+8$fm70e6-JHCrV5dWJX{rU#yPJoC{3ayIWTd|JCB!03I>%vdlIN3Z(8+aUXgT2|@i_a-+;L3%wwF)? zZJd1ms`NGS@PQDqY&&rWOSp5&a_OW$9u4PWTAZ&zGX zXG^=zFJ$VB{@^FSyelD5(e46BkLXD<)7cZ9L-=^&aA(cg}|6cI;+A8L*6CFYCF+ zy0bM_fgqRCh#B)-haITFh<$7MBSGr&W+DGpR!X^z?gZ>$>9yF@@*%xl<%*66^3caBp z{)$d&@Fx^prz+@EK+IN#eE)LCB`{+%Na{6{UfJsqg6Ea}Tq5Xz|NF}EgMagDLl%UB z0)GRAv5|P=R}qp8UtCv;rSBZ5e)kJ(*!B@vYrRnfLP}#XgaY;v|7x4HuGJRfP~2X1 zc3p(Y{{Ck56@z;?r?cGt*fbZ~m$3KT}zHq4xm) z_uwQ>I3Wj96;6)%#Vm95VaUBcfB#T}s$adN;BUDmZgdfg81-X++4>+1HhJ~t+%e*2 z2CbHL($!Plx#>q&3RAAK=VjVCr|vMHG5*}!@Cey(FVmSBnz75?JltoY@{2x4h4=2X z-&{KzVn@iyNIZKJXJw^OS@~N5)9-lGZ&`M4M`<(U(LbAXuChegA%+zc=I8Eo?f|nk zc>VotFVp0&sJf*+#~b`U_g=BVO5>g$3>0&~aw468v=?|0?VkB;5srL;aIt?Ea<+HU zT#C0%cJ5y>pSh>Vdb#>eawe1Q!?s3~d?(xf4{o-nQeS$mmyu&{JNBHeU+mub{$v%i z(;|>|ww-R_8C}Mf7v?<}jnpqq`As=BJf~VAS9#pRblNToTiQ08DK9^KE4%iHK%{X? zZ_*Pm5GJs}bC{W4gA7ByVB70ND{Io}ZsS(8cUHA5B~NSYJ16iV3{ur6$8j#V)cLZoDx#iDMKTacL8&M>3T6-PEd{FdN zn+2r&LeJ}=(dnXd4??g7oAX;yI9<0eWKtSoJdj=(+kaGZdti~={@TQ5JMNFgad5BW zl*fES;1}BqINMQ<@mfP8*3G699KkI2zOqR8jo97x&(DR)VjFzo$MiRXp7X~+@(6TJ z4+C|xJbbD-Cgwsu&sq-m{JeAegFL{2ChwzY+rbsVE-f)?+1pC@kwQe?e_GlK% zR(csyZzA<%PqrH9mD=7-d6AuEgf^7sa>b}G8gu)fe305w5YP0SVNz1>El#Gh$v-J| z4>9l0)Kew0f1{SMJWIa8AD3U*m|cy&QyQxVj19%x7Ja)aM2Xy&mF2udu>0I|f#xwL zu@&WT>?F}^+%)VN*e&YY{!v7x^``DF2gPZ49$Ovl6UT;D1{xpK*?+vm0popYW52Ew zu~#8?dg}JlY1xMd>olLMe7VEqmdMD}-}9>q!k%rDHbdW6;&=+g^400RWQWKf3J#ED zxyjm3)8a`lpIba7&Jv2_=fB3ha~~eb|3)lfl3>eOJbm`9etRh(=oL9;@+umy-&oPm z+^xA9uea{iwEmuD_o`$w#KOJ3HKpO9Jk3}0g8?p$H}uva#U}{jhHPp4zL83W?`|TCqymrEQV>V3>zKakt7ieB!nupv zL&yJ4BVKFJU`sYOKq$iPXP2}7J96c^g4N1^Ng}kqG29z*+k5!kFu+tx%AQ#Z2Pp(1 z>7myJv>MlM*OOvnR~<^`-Xy3yWx%dsE~_pjjy|s5X%V}LPcUb4Q^h19;YCrMRvt~` z`vD&#K*nB^vtt{sTR0=_mp_j01kTX~2v(FUYhy0`h3-aL z84L6}{B~;tnZ%THCF$ewzq5O#Pq9x|5C>`Q`4J$b?O7YV7V=ofwV6Di{-N(L%dWd9 zGtXZoK`4ALe?Nv;Yz=yC$?)N(mt52b-2|keBv%g{jZY}@wSJH*X#Ni^Wx%xNkqG;>AF4P|&V3+%3rrBjSjl?@3~9?j~#1%M%FomIx?mnxh9BYBt0Wcp;eErv~t|ndpBZ+5z)-J zmO0ZguDt&!@j*+D!W(6km&ye2Lsw@<5omRY5T#ss6XcV`6X82;3BqNoAkOZT8lfyp z)p1fs>Acq=TL^Tu#l{Q0X8N#_9L<8KCdHsf{J+exj>Pb*7JVy%TSTukIW#LzbqHXZXbOA>+8nWD!~ z8z-oYs7w&y64e4k6wX>xX4<_+pU%9lDj+rDLZ^NaZYz?aiWxk>(Gqf#5bSRo4y;0= zFyKyu!A2JN8&fFQ&(hNf<-5t~`IZJJl;xRvajhJ;Z)K&)A$R3fmfJY3+>FDel39(q3Fw5|RI*Yu*sb=_s?n<`+HlWHu}3fQ4AG2nL<7LQ4VDDXH|;(nfWlvvnV42K!#m3L2axwxqSWMO5oh2g0UM>6-dt%n=kj zv!gOVnVOEh_P@4AD8ErxnBd`qDK+uImt}3IP}LW_Y7jRDNj^!mSzWQ5(EGQ`HZH5C zS^`(Wg2FaqQ661BvyTL9AnYwPcOLgNd4HIxX3c54dk5SJ*HjXq>3T%apM-+{6eSCBTCQN9r$-$iMCmue_%&hdwsDko>K_(*#wegK};b|Psn z(D6uB3lKiNO0jCcyqFNq&8DSSA|bkPQF2gGs%kG^NHd&T5Kh%n|9Vhyckz#B9|bQP zp^PwFJqIw(St7a01w()l@)*VQ+zPg6)}{ICSo3~4dj97OGN6ECq))Wo`4Y(cwHgm6 zz_mEAH^|8<8HKbu;~|c>94in{7k*NKr77~N(gUu^g}6O$$N$0S^o@!?Vv7X|jmeEy zp0h9(il`A_*O$xZpw9JslT_3Td8jaUx*tlb%6%*|L(FMj&F}U#c!|5`PGH~-_R>IJ zCz-~=4N*d#N-F!l1VLW9VpE;_kFH)v4NI15myVZ@!d1EkEPmeL-$nMSCm7Q&APoZS zE@QwqHb|b#21(s=t6^M5RBZtC&=@2B&O7b?7xz!qO5q|nLl(~+zNhF=LSt3DAe{mt z5Rz9#fRnruRs;s`7c(#%Vn4^(PC@W=bsPkKeVGt`M`(>CsT!DQ;ugs%0FDhf(7olt`ysO5yOIXRgv{S||+H z%kJ{;S9eTL*gZ=yJRAf;%i;Qj1Hh>pFEeN;0gM0XIEnlG$xPq;Q=|h9n)Yg8f+D@E zl7Z5mOI7;#>HALqwLjln!Id1Df&)^_KAU3KWSA;sw0I7m+7;?5ilI+kZW%Qi_9hB_ zKY1zkw#>1KIvmgc!F zm9`w}_o?3Xb5IE+zgXH^NAdB*V6p8(Gnvfvj!H_LBh%X>|IpH_Yw|R7fNA9Qo9RYI zL{qE|52^VU@k^CjAee@ld#cJK^*+4%aoIZWmKDQbCMe}``?Y@z~)}@VOZaN@4~Wh7WVU>2Ece6mlZFXDUNH z+Ucx0etPtBc*7S1t$YV2#jr-|Mz?HY2_=_&h9VaeUcU?idzViQ#KOM2oOU~XfAT`t zFkQZnVT*@@;x=re1;NcGhc`VZrnG$MS2M=!lBb&93=Bm6Jy7z7|9Ao6kX9+vId?ld zXeE^{?jiWjH)dQGLIdT{c0c!ErJVcc9joC-x;76e*NJfu{&|N-MDmI8+*!&r3haRc zT|)-}7cK~JP4`KJ@gg10VKmJ&XTg~daqa1}q+kc(CB$4vLw{G^t+|g&$C4>vrLSYw zu{LEl1Oh@$Q8`BIBYijeO@wg=KN0ofz^_0qkr^AMp z@4`yd5;!02&3(g01V)(fbkaDxOmQd}#fq?$CGVTNJ?@LNS=h=xJTPDTM8hX_m!&c` zsabec?cC{1Di4F}2mCb{XiY@If!sfCBdalu>D>0Yg2{b>b$xO z9lEu7_05A+eDRPkej#VFb0=RAWAA_McQot8IFUO?T4jwO1F1$h84(#_ zY5<^YvVmX#BG|YgWyPbgNnzc1Cgg?&#uGq*4f{mh;~{+t`-l?2q)?ASDSI@>4wgci zipoVUp@q+qDN4B<-d;IO^fHC&6naghgQcC0Vh~(X2?%9?BGjo68URo`1`%cSaJ-g& zN`Wl?6k3~)F(we{v`{%D5r z1_%|+eE<8DM{&g_>t@rhQ=XfTfzZT`YxFJ;-}~Z(nE}0`8-6&<#YG$qka`hOJ_Vto z24L9#mm<^v;5?WJgwD&1Tf2Hyp=l{|Ux{cY`r=d&corVOhPh_=b`ABkZ(i2>Oe+iJ z-iwrR>qDVCGz#iF2{;PHND4bW$hfx+n0o-gLpz+eloeI1>5!M97|@~Ejf}R1%TV>J zdbb?|KpDwNUs+ZVt}3p2 zHDc^CWtGM6Gran9wiBX}dk<)zNo2{*!HLy6BDi{8#z-#;%LHJ^5(O iRGz-n4VZ}kM?W?F&FYYBo literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png b/microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a3bbe82224deec74650461230f66d609eda717e3 GIT binary patch literal 38171 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 MU)LDY2zE;NA05R;CIA2c literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png b/microservices/KonSoft.Dispatch.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png new file mode 100644 index 0000000000000000000000000000000000000000..761fb4443d597661e7700574e52b787d7ed7255b GIT binary patch literal 33228 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 nuxmBTJ6Y+ll0437Z literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.Dispatch.HttpApi.Host/yarn.lock b/microservices/KonSoft.Dispatch.HttpApi.Host/yarn.lock new file mode 100644 index 0000000..1dfe9d4 --- /dev/null +++ b/microservices/KonSoft.Dispatch.HttpApi.Host/yarn.lock @@ -0,0 +1,322 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@abp/aspnetcore.mvc.ui.theme.leptonxlite@~3.3.4": + version "3.3.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.leptonxlite/-/aspnetcore.mvc.ui.theme.leptonxlite-3.3.4.tgz#fb6879075aec2f06e0302e941dcefbe519b18e1d" + integrity sha512-5rrwwZ9n2/yePo+GnHuUsP0TelCwRwCQjYyQFdF/Nd4B3UNQVO/AXQc0Ep3+vHhUxSL386j6ObZYu14VdjPg2g== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~8.3.4" + +"@abp/aspnetcore.mvc.ui.theme.shared@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-8.3.4.tgz#169ae0893302ced9256f94174d9bb870e49f446c" + integrity sha512-bZy8iAIN0QfNJXCRg+RR1NxqTzNDSXRPBx+ksFtDxY6FzMJvwwSOmHF0wqsMLj1xpwXjijWaVWQ2RM/7scDWmw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~8.3.4" + "@abp/bootstrap" "~8.3.4" + "@abp/bootstrap-datepicker" "~8.3.4" + "@abp/bootstrap-daterangepicker" "~8.3.4" + "@abp/datatables.net-bs5" "~8.3.4" + "@abp/font-awesome" "~8.3.4" + "@abp/jquery-form" "~8.3.4" + "@abp/jquery-validation-unobtrusive" "~8.3.4" + "@abp/lodash" "~8.3.4" + "@abp/luxon" "~8.3.4" + "@abp/malihu-custom-scrollbar-plugin" "~8.3.4" + "@abp/moment" "~8.3.4" + "@abp/select2" "~8.3.4" + "@abp/sweetalert2" "~8.3.4" + "@abp/timeago" "~8.3.4" + "@abp/toastr" "~8.3.4" + +"@abp/aspnetcore.mvc.ui@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-8.3.4.tgz#041d83f34541081d9e0f37c36c302cbe871a4897" + integrity sha512-sjGE/EoNM98mXNYPze2C7GPP+TNpv4TLIt416ojaqtxru60oddr4VWrOGuhaqUCO2jJes3OwFZi5PY3hVOBbYw== + dependencies: + ansi-colors "^4.1.3" + +"@abp/bootstrap-datepicker@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-8.3.4.tgz#072f4a3cea93e3a1bb1de13b355201648929f84c" + integrity sha512-txilFovf9zT1w+fTkyI3eZdiISjaxc/+wRRFKwrkVH+0xEgaiR41svKm6sjWBORxgTddlGas87SZJvYY3IKBjA== + dependencies: + bootstrap-datepicker "^1.10.0" + +"@abp/bootstrap-daterangepicker@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-8.3.4.tgz#b0f65611ca4fafdf2b551f9f139868eae6e22e9a" + integrity sha512-bYkYjk1zTdWcM4DGwnDoU+4pDvs1S8hkNWhrnpP0o8oRoJiesO8Aeda+82rtydtWnxHg+HkDC0iYFFqaNuHvbg== + dependencies: + bootstrap-daterangepicker "^3.1.0" + +"@abp/bootstrap@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-8.3.4.tgz#744bb4d30d4c269ce8e6a7d16c6777dd3cd9fe1e" + integrity sha512-GXCLFFmPNaR3DjQYSaqACL5sH/M9FPia2OKAAMOd796+NmcoFpT+S7l4C6ihqeQc4bjFm0voB8QklueGWx6r8A== + dependencies: + "@abp/core" "~8.3.4" + bootstrap "^5.3.3" + +"@abp/core@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-8.3.4.tgz#12635bc2ac325a426334150502a32fefa4ec3767" + integrity sha512-wImAdZABahaQe6mmZAZlPfYZ3PEhL7eEq+18c1WFO0xeD98oxqi8H1X7+3ABjyFscIh9LIxJVaD3RJ9OHCc5bw== + dependencies: + "@abp/utils" "~8.3.4" + +"@abp/datatables.net-bs5@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-8.3.4.tgz#efc28fa57144c7b495a4aeea38df962807ca20df" + integrity sha512-u85aXjqYIJJfOsMq6oNqfxNgxQqV6vOEnJ32vrH294ceW8RzUxHA+G/ZkGRLLRGWVuxuARD/UXzEotH5sd1Ssw== + dependencies: + "@abp/datatables.net" "~8.3.4" + datatables.net-bs5 "^2.0.8" + +"@abp/datatables.net@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-8.3.4.tgz#23a3155a2d84247a29a6b80ff98d1d5f6422a245" + integrity sha512-cwE9TFoRoszmI3zNVaYJtqjSPtwkL9dhCfE02zsmJo8GBdFAlbzAmQenfQiWb3BZhvUvKKN20e+og9S8qoCbXA== + dependencies: + "@abp/jquery" "~8.3.4" + datatables.net "^2.0.8" + +"@abp/font-awesome@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-8.3.4.tgz#f79f7b439f9ffadfc03be3a415a977eab21fa5a1" + integrity sha512-5+D5XKnrZROtg9PJ2zex52gbphXGK/7ZIUsszEg8rOIc/niXggaZLmuDcYJwOEzIkwpGO9OvYy7lc0tHv/Pr4g== + dependencies: + "@abp/core" "~8.3.4" + "@fortawesome/fontawesome-free" "^6.5.2" + +"@abp/jquery-form@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-8.3.4.tgz#c1705bd5213ab5c2b895dd5bd9f3e54f3d94cf54" + integrity sha512-vFjWbTbHQyIsk5SS7Cc+5YrJ15ORjJU+YWVPchI0qoug26for06a7lDGpazWMadxx3iPL7cKLqneOqaVtHkgJA== + dependencies: + "@abp/jquery" "~8.3.4" + jquery-form "^4.3.0" + +"@abp/jquery-validation-unobtrusive@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-8.3.4.tgz#e89eafed89787bcb5221c0ba89832b79a7396d19" + integrity sha512-+kJA5vfvxkrj/iW4Q84BrMTrAGOhC2Hb5czAKr6c60Prmayk5hcakZdXc3wDBHREBLVAq1Muk4AtEJZmaKIeaA== + dependencies: + "@abp/jquery-validation" "~8.3.4" + jquery-validation-unobtrusive "^4.0.0" + +"@abp/jquery-validation@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-8.3.4.tgz#a445592d80edc6b6b1334ece2007b3084c329cc6" + integrity sha512-XvL0H3IRuSHwpPKUyJmW6PH8KwPDt9NllMqPGreRANF8l5IU10hOLEeP2BnGFfGMqFwqUMh+eJRar5yZcegkmg== + dependencies: + "@abp/jquery" "~8.3.4" + jquery-validation "^1.20.1" + +"@abp/jquery@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-8.3.4.tgz#2dc3f5f124ac65b5f45d29749ebb5d6cf17db23b" + integrity sha512-Zx2rErtgc0gxjX5PURjp6sjDQfzxBChUE9YWN37Xh+Ysm3tTGcXlF0Emwl94MZ640NfmYRpG4AWdik6kbaU5Wg== + dependencies: + "@abp/core" "~8.3.4" + jquery "~3.7.1" + +"@abp/lodash@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-8.3.4.tgz#b0ef4e82a788ae7389a31793c3bad6702efdbe33" + integrity sha512-yGd/oLds0jpTgTpmkFYOEomS4K15DGcffMP3N1t0qKLgTaBYTQzeugHVgQ0baufC+OvLjumDNuu3eHjBJewwKg== + dependencies: + "@abp/core" "~8.3.4" + lodash "^4.17.21" + +"@abp/luxon@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-8.3.4.tgz#f152b2d7b62bd27f3d27aa3a1794b868bf06a1a4" + integrity sha512-l1nvfqdhHBgHBPK+bLClAEprRK3K5zx5Jar93o5++6r3zXUhYi5OUHUxl+LuGn8MXLvHJVGL41irHl6sYjFSww== + dependencies: + "@abp/core" "~8.3.4" + luxon "^3.4.4" + +"@abp/malihu-custom-scrollbar-plugin@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-8.3.4.tgz#0868214884e3e0b94dade0e8e78c01741d71106a" + integrity sha512-uKRk8+HCvXtpmvof5W09908AkivlweErTE62b0JhkrJVIlYt/0LC1MmB/qHHBfPj6OK05HYGBi3inr7fNAPXEQ== + dependencies: + "@abp/core" "~8.3.4" + malihu-custom-scrollbar-plugin "^3.1.5" + +"@abp/moment@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-8.3.4.tgz#a5809520dc50b50402ade4ac630c6ec985fd4518" + integrity sha512-61J8drO3OqkaaAn66xBg6jCws1iV6zutjYQvpEXLdGBA9Kvw2J87GSomxJ4mcIo/5+jzrVro6JYaCfKWY8b1dw== + dependencies: + moment "^2.30.1" + +"@abp/select2@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-8.3.4.tgz#1731b465760e0515d0d4280f38189c9366fecda5" + integrity sha512-sPtYstFVvMTT8fdXRIfHeODIgSN2ufWm6zCMGH7C0cST3FF59M4m/MtdKGBlA/itzHPxeDv7A6dy4Aw4l7Gk4Q== + dependencies: + "@abp/core" "~8.3.4" + select2 "^4.0.13" + +"@abp/sweetalert2@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-8.3.4.tgz#c0768ca4fe0a9926b8f33d8bf5251d3e4202cd2f" + integrity sha512-6HqxISh+FodwUsCrR3nX49RQDhzHtDlz8ul42TecUMsGa96qX2lvwnoWkXAHLG3mdLRy62Z0dhJ1JKMfrPeJeg== + dependencies: + "@abp/core" "~8.3.4" + sweetalert2 "^11.3.6" + +"@abp/timeago@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-8.3.4.tgz#26ca0bec90d861f9f4af714061b370950551c839" + integrity sha512-cDARYysPn5Rr/9rqVn7S4sBWbeEpaIXr8NKwGZqNOzMF2g283SkLKrkQJBWIC6Pn2lVeIB7AV1+GtVn81V/nnw== + dependencies: + "@abp/jquery" "~8.3.4" + timeago "^1.6.7" + +"@abp/toastr@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-8.3.4.tgz#cb433bc4ed2e302f2704ad0456c99d6f12fd0529" + integrity sha512-29C9GgwlumrHgt1iZ4lArDnlXfSvmCHDehxkbDutrkC1m257UxQaOID11us2UeCs3JobueQcLlQKD/LqnDB4xA== + dependencies: + "@abp/jquery" "~8.3.4" + toastr "^2.1.4" + +"@abp/utils@~8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-8.3.4.tgz#4b06575a110e85e2a360294f678b782818e1ab10" + integrity sha512-7Lq3wdk/07vKgQnR56DTmdSuYRABMe0XTGPJRS5F91DVbggeJyDUaqifVvOeurF/3CZJOS7fJpoIHQXeUveFtQ== + dependencies: + just-compare "^2.3.0" + +"@fortawesome/fontawesome-free@^6.5.2": + version "6.7.2" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.2.tgz#8249de9b7e22fcb3ceb5e66090c30a1d5492b81a" + integrity sha512-JUOtgFW6k9u4Y+xeIaEiLr3+cjoUPiAuLXoyKOJSia6Duzb7pq+A76P9ZdPDoAoxHdHzq6gE9/jKBGXlZT8FbA== + +ansi-colors@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +bootstrap-datepicker@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/bootstrap-datepicker/-/bootstrap-datepicker-1.10.0.tgz#61612bbe8bf0a69a5bce32bbcdda93ebb6ccf24a" + integrity sha512-lWxtSYddAQOpbAO8UhYhHLcK6425eWoSjb5JDvZU3ePHEPF6A3eUr51WKaFy4PccU19JRxUG6wEU3KdhtKfvpg== + dependencies: + jquery ">=3.4.0 <4.0.0" + +bootstrap-daterangepicker@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bootstrap-daterangepicker/-/bootstrap-daterangepicker-3.1.0.tgz#632e6fb2de4b6360c5c0a9d5f6adb9aace051fe8" + integrity sha512-oaQZx6ZBDo/dZNyXGVi2rx5GmFXThyQLAxdtIqjtLlYVaQUfQALl5JZMJJZzyDIX7blfy4ppZPAJ10g8Ma4d/g== + dependencies: + jquery ">=1.10" + moment "^2.9.0" + +bootstrap@^5.3.3: + version "5.3.8" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.8.tgz#6401a10057a22752d21f4e19055508980656aeed" + integrity sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg== + +datatables.net-bs5@^2.0.8: + version "2.3.3" + resolved "https://registry.yarnpkg.com/datatables.net-bs5/-/datatables.net-bs5-2.3.3.tgz#8bf3aec484a69e373f6007038eaac0cc0ef4ee15" + integrity sha512-IPtC57k3KyZaLzIYTHies23Cm2zqaKfD6lkxy/aOAUUAtsg35l53VqNY9y84AEySYG3YLghMHVBvl2ckUhvm0A== + dependencies: + datatables.net "2.3.3" + jquery ">=1.7" + +datatables.net@2.3.3, datatables.net@^2.0.8: + version "2.3.3" + resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-2.3.3.tgz#fe4f96bdbc4cf47c8d11162a7af525ca6a3683d2" + integrity sha512-SWL3za6nheY6gdoiLgCc++tYmxbwrmv2bjrEiII9rXBWXXSbOZct6pjR3FueMVRM5jmt7pQcXiGovfuFDnutQg== + dependencies: + jquery ">=1.7" + +jquery-form@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/jquery-form/-/jquery-form-4.3.0.tgz#7d3961c314a1f2d15298f4af1d3943f54f4149c6" + integrity sha512-q3uaVCEWdLOYUCI6dpNdwf/7cJFOsUgdpq6r0taxtGQ5NJSkOzofyWm4jpOuJ5YxdmL1FI5QR+q+HB63HHLGnQ== + dependencies: + jquery ">=1.7.2" + +jquery-mousewheel@>=3.0.6: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.2.2.tgz#48c833f6260ee0c46d438a999e7d0060ec9eed0b" + integrity sha512-JP71xTAg08ZY3hcs9ZbYUZ5i+dkSsz4yRl/zpWkAmtzc+kMs5EfPkpkINSidiLYMaR0MTo3DfFGF9WIezMsFQQ== + dependencies: + jquery ">=1.2.6" + +jquery-validation-unobtrusive@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-4.0.0.tgz#dfcf25a558496a2c883db6021d10f5398d15f99d" + integrity sha512-1ervYFFv6LX/rp7ktuLnMakHNG0piNRDyROI8Ir3hL1vPIwylAehB1AY3BPrYJnzW3WmwWryZq+Bz4sazZK9iQ== + dependencies: + jquery "^3.6.0" + jquery-validation ">=1.19" + +jquery-validation@>=1.19, jquery-validation@^1.20.1: + version "1.21.0" + resolved "https://registry.yarnpkg.com/jquery-validation/-/jquery-validation-1.21.0.tgz#78fc05ab76020912a246af3661b3f54a438bca93" + integrity sha512-xNot0rlUIgu7duMcQ5qb6MGkGL/Z1PQaRJQoZAURW9+a/2PGOUxY36o/WyNeP2T9R6jvWB8Z9lUVvvQWI/Zs5w== + +jquery@>=1.10, jquery@>=1.12.0, jquery@>=1.2.6, "jquery@>=1.5.0 <4.0", jquery@>=1.7, jquery@>=1.7.2, "jquery@>=3.4.0 <4.0.0", jquery@^3.6.0, jquery@~3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" + integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== + +just-compare@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/just-compare/-/just-compare-2.3.0.tgz#a2adcc1d1940536263275f5a1ef1298bcacfeda7" + integrity sha512-6shoR7HDT+fzfL3gBahx1jZG3hWLrhPAf+l7nCwahDdT9XDtosB9kIF0ZrzUp5QY8dJWfQVr5rnsPqsbvflDzg== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +luxon@^3.4.4: + version "3.7.2" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.7.2.tgz#d697e48f478553cca187a0f8436aff468e3ba0ba" + integrity sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew== + +malihu-custom-scrollbar-plugin@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-3.1.5.tgz#310cecc5e59415a1c29e9dfb5d2b6e01d66a29ef" + integrity sha512-lwW3LgI+CNDMPnP4ED2la6oYxWMkCXlnhex+s2wuOLhFDFGnGmQuTQVdRK9bvDLpxs10sGlfErVufJy9ztfgJQ== + dependencies: + jquery-mousewheel ">=3.0.6" + +moment@^2.30.1, moment@^2.9.0: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + +select2@^4.0.13: + version "4.0.13" + resolved "https://registry.yarnpkg.com/select2/-/select2-4.0.13.tgz#0dbe377df3f96167c4c1626033e924372d8ef44d" + integrity sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw== + +sweetalert2@^11.3.6: + version "11.23.0" + resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-11.23.0.tgz#ba8a051b1e94215c762af08692171b7b4611c4c1" + integrity sha512-cKzzbC3C1sIs7o9XAMw4E8F9kBtGXsBDUsd2JZ8JM/dqa+nzWwSGM+9LLYILZWzWHzX9W+HJNHyBlbHPVS/krw== + +timeago@^1.6.7: + version "1.6.7" + resolved "https://registry.yarnpkg.com/timeago/-/timeago-1.6.7.tgz#afd467c29a911e697fc22a81888c7c3022783cb5" + integrity sha512-FikcjN98+ij0siKH4VO4dZ358PR3oDDq4Vdl1+sN9gWz1/+JXGr3uZbUShYH/hL7bMhcTpPbplJU5Tej4b4jbQ== + dependencies: + jquery ">=1.5.0 <4.0" + +toastr@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/toastr/-/toastr-2.1.4.tgz#8b43be64fb9d0c414871446f2db8e8ca4e95f181" + integrity sha512-LIy77F5n+sz4tefMmFOntcJ6HL0Fv3k1TDnNmFZ0bU/GcvIIfy6eG2v7zQmMiYgaalAiUv75ttFrPn5s0gyqlA== + dependencies: + jquery ">=1.12.0" diff --git a/microservices/KonSoft.Payment.HttpApi.Host/Controllers/HomeController.cs b/microservices/KonSoft.Payment.HttpApi.Host/Controllers/HomeController.cs new file mode 100644 index 0000000..2974e46 --- /dev/null +++ b/microservices/KonSoft.Payment.HttpApi.Host/Controllers/HomeController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace KonSoft.Payment.Controllers; + +public class HomeController : AbpController +{ + public ActionResult Index() + { + return Redirect("~/swagger"); + } +} diff --git a/microservices/KonSoft.Payment.HttpApi.Host/KonSoft.Payment.HttpApi.Host.csproj b/microservices/KonSoft.Payment.HttpApi.Host/KonSoft.Payment.HttpApi.Host.csproj new file mode 100644 index 0000000..c60b2bc --- /dev/null +++ b/microservices/KonSoft.Payment.HttpApi.Host/KonSoft.Payment.HttpApi.Host.csproj @@ -0,0 +1,40 @@ + + + + + + net8.0 + enable + KonSoft.Payment + true + KonSoft.Payment-4681b4fd-151f-4221-84a4-929d86723e4c + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/microservices/KonSoft.Payment.HttpApi.Host/PaymentBrandingProvider.cs b/microservices/KonSoft.Payment.HttpApi.Host/PaymentBrandingProvider.cs new file mode 100644 index 0000000..92e730d --- /dev/null +++ b/microservices/KonSoft.Payment.HttpApi.Host/PaymentBrandingProvider.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Localization; +using KonSoft.Payment.Localization; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Ui.Branding; + +namespace KonSoft.Payment; + +[Dependency(ReplaceServices = true)] +public class PaymentBrandingProvider : DefaultBrandingProvider +{ + private IStringLocalizer _localizer; + + public PaymentBrandingProvider(IStringLocalizer localizer) + { + _localizer = localizer; + } + + public override string AppName => _localizer["AppName"]; +} diff --git a/microservices/KonSoft.Payment.HttpApi.Host/PaymentHttpApiHostModule.cs b/microservices/KonSoft.Payment.HttpApi.Host/PaymentHttpApiHostModule.cs new file mode 100644 index 0000000..dd75b40 --- /dev/null +++ b/microservices/KonSoft.Payment.HttpApi.Host/PaymentHttpApiHostModule.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Extensions.DependencyInjection; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using KonSoft.Payment.EntityFrameworkCore; +using KonSoft.Payment.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling; +using Microsoft.OpenApi.Models; +using OpenIddict.Validation.AspNetCore; +using Volo.Abp; +using Volo.Abp.Account; +using Volo.Abp.Account.Web; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.Security.Claims; +using Volo.Abp.Swashbuckle; +using Volo.Abp.UI.Navigation.Urls; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.Payment; + +[DependsOn( + typeof(PaymentHttpApiModule), + typeof(AbpAutofacModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(PaymentApplicationModule), + typeof(PaymentEntityFrameworkCoreModule), + typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule), + typeof(AbpAccountWebOpenIddictModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpSwashbuckleModule) +)] +public class PaymentHttpApiHostModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(builder => + { + builder.AddValidation(options => + { + options.AddAudiences("Payment"); + options.UseLocalServer(); + options.UseAspNetCore(); + }); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + ConfigureAuthentication(context); + ConfigureBundles(); + ConfigureUrls(configuration); + ConfigureConventionalControllers(); + ConfigureVirtualFileSystem(context); + ConfigureCors(context, configuration); + ConfigureSwaggerServices(context, configuration); + } + + private void ConfigureAuthentication(ServiceConfigurationContext context) + { + context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme); + context.Services.Configure(options => + { + options.IsDynamicClaimsEnabled = true; + }); + } + + private void ConfigureBundles() + { + Configure(options => + { + options.StyleBundles.Configure( + LeptonXLiteThemeBundles.Styles.Global, + bundle => + { + bundle.AddFiles("/global-styles.css"); + } + ); + }); + } + + private void ConfigureUrls(IConfiguration configuration) + { + Configure(options => + { + options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; + options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"]?.Split(',') ?? Array.Empty()); + + options.Applications["Angular"].RootUrl = configuration["App:ClientUrl"]; + options.Applications["Angular"].Urls[AccountUrlNames.PasswordReset] = "account/reset-password"; + }); + } + + private void ConfigureVirtualFileSystem(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + if (hostingEnvironment.IsDevelopment()) + { + Configure(options => + { + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Payment.Domain.Shared")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Payment.Domain")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Payment.Application.Contracts")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Payment.Application")); + }); + } + } + + private void ConfigureConventionalControllers() + { + Configure(options => + { + options.ConventionalControllers.Create(typeof(PaymentApplicationModule).Assembly); + }); + } + + private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration) + { + context.Services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"]!, + new Dictionary + { + {"Payment", "Payment API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Payment API", Version = "v1" }); + options.DocInclusionPredicate((docName, description) => true); + options.CustomSchemaIds(type => type.FullName); + }); + } + + private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration) + { + context.Services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + builder + .WithOrigins(configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToArray() ?? Array.Empty()) + .WithAbpExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + var env = context.GetEnvironment(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseAbpRequestLocalization(); + + if (!env.IsDevelopment()) + { + app.UseErrorPage(); + } + + app.UseCorrelationId(); + app.UseStaticFiles(); + app.UseRouting(); + app.UseCors(); + app.UseAuthentication(); + app.UseAbpOpenIddictValidation(); + + if (MultiTenancyConsts.IsEnabled) + { + app.UseMultiTenancy(); + } + app.UseUnitOfWork(); + app.UseDynamicClaims(); + app.UseAuthorization(); + + app.UseSwagger(); + app.UseAbpSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "Payment API"); + + var configuration = context.ServiceProvider.GetRequiredService(); + c.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + c.OAuthScopes("Payment"); + }); + + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + app.UseConfiguredEndpoints(); + } +} diff --git a/microservices/KonSoft.Payment.HttpApi.Host/Program.cs b/microservices/KonSoft.Payment.HttpApi.Host/Program.cs new file mode 100644 index 0000000..dfd86a7 --- /dev/null +++ b/microservices/KonSoft.Payment.HttpApi.Host/Program.cs @@ -0,0 +1,56 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Events; + +namespace KonSoft.Payment; + +public class Program +{ + public async static Task Main(string[] args) + { + Log.Logger = new LoggerConfiguration() +#if DEBUG + .MinimumLevel.Debug() +#else + .MinimumLevel.Information() +#endif + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) + .Enrich.FromLogContext() + .WriteTo.Async(c => c.File("Logs/logs.txt")) + .WriteTo.Async(c => c.Console()) + .CreateLogger(); + + try + { + Log.Information("Starting KonSoft.Payment.HttpApi.Host."); + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .UseSerilog(); + await builder.AddApplicationAsync(); + var app = builder.Build(); + await app.InitializeApplicationAsync(); + await app.RunAsync(); + return 0; + } + catch (Exception ex) + { + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + } +} diff --git a/microservices/KonSoft.Payment.HttpApi.Host/Properties/launchSettings.json b/microservices/KonSoft.Payment.HttpApi.Host/Properties/launchSettings.json new file mode 100644 index 0000000..6ed65af --- /dev/null +++ b/microservices/KonSoft.Payment.HttpApi.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44355", + "sslPort": 44355 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "KonSoft.Payment.HttpApi.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44355", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/microservices/KonSoft.Payment.HttpApi.Host/abp.resourcemapping.js b/microservices/KonSoft.Payment.HttpApi.Host/abp.resourcemapping.js new file mode 100644 index 0000000..4a2ad45 --- /dev/null +++ b/microservices/KonSoft.Payment.HttpApi.Host/abp.resourcemapping.js @@ -0,0 +1,11 @@ +module.exports = { + aliases: { + + }, + clean: [ + + ], + mappings: { + + } +}; diff --git a/microservices/KonSoft.Payment.HttpApi.Host/appsettings.Development.json b/microservices/KonSoft.Payment.HttpApi.Host/appsettings.Development.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/microservices/KonSoft.Payment.HttpApi.Host/appsettings.Development.json @@ -0,0 +1,2 @@ +{ +} diff --git a/microservices/KonSoft.Payment.HttpApi.Host/appsettings.json b/microservices/KonSoft.Payment.HttpApi.Host/appsettings.json new file mode 100644 index 0000000..ab7bc0b --- /dev/null +++ b/microservices/KonSoft.Payment.HttpApi.Host/appsettings.json @@ -0,0 +1,18 @@ +{ + "App": { + "SelfUrl": "https://localhost:44355", + "CorsOrigins": "https://*.Payment.com", + "RedirectAllowedUrls": "" + }, + "ConnectionStrings": { + "Default": "Host=localhost;Port=5432;Database=Payment;User ID=root;Password=myPassword;" + }, + "AuthServer": { + "Authority": "https://localhost:44355", + "RequireHttpsMetadata": false, + "SwaggerClientId": "Payment_Swagger" + }, + "StringEncryption": { + "DefaultPassPhrase": "ex1X6Pe2UOTsR6Tv" + } +} diff --git a/microservices/KonSoft.Payment.HttpApi.Host/appsettings.secrets.json b/microservices/KonSoft.Payment.HttpApi.Host/appsettings.secrets.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/microservices/KonSoft.Payment.HttpApi.Host/appsettings.secrets.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/microservices/KonSoft.Payment.HttpApi.Host/package.json b/microservices/KonSoft.Payment.HttpApi.Host/package.json new file mode 100644 index 0000000..b8d616a --- /dev/null +++ b/microservices/KonSoft.Payment.HttpApi.Host/package.json @@ -0,0 +1,8 @@ +{ + "version": "1.0.0", + "name": "my-app", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~3.3.4" + } +} diff --git a/microservices/KonSoft.Payment.HttpApi.Host/web.config b/microservices/KonSoft.Payment.HttpApi.Host/web.config new file mode 100644 index 0000000..d8a82b4 --- /dev/null +++ b/microservices/KonSoft.Payment.HttpApi.Host/web.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/microservices/KonSoft.Payment.HttpApi.Host/wwwroot/global-styles.css b/microservices/KonSoft.Payment.HttpApi.Host/wwwroot/global-styles.css new file mode 100644 index 0000000..74db4bd --- /dev/null +++ b/microservices/KonSoft.Payment.HttpApi.Host/wwwroot/global-styles.css @@ -0,0 +1,6 @@ +/* Your Global Styles */ + +:root .lpx-brand-logo { + --lpx-logo: url('/images/logo/leptonx/logo-light.png'); + --lpx-logo-icon: url('/images/logo/leptonx/logo-light-thumbnail.png'); +} \ No newline at end of file diff --git a/microservices/KonSoft.Payment.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png b/microservices/KonSoft.Payment.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..9734a07a4d4539d3081bb897ffc8d5e75dab8798 GIT binary patch literal 10695 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 iRGz-n4VZ}kM?W?F&FYYBo literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.Payment.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png b/microservices/KonSoft.Payment.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a3bbe82224deec74650461230f66d609eda717e3 GIT binary patch literal 38171 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 MU)LDY2zE;NA05R;CIA2c literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.Payment.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png b/microservices/KonSoft.Payment.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png new file mode 100644 index 0000000000000000000000000000000000000000..761fb4443d597661e7700574e52b787d7ed7255b GIT binary patch literal 33228 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 nuxmBTJ6Y+ll0437Z literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.Report.HttpApi.Host/Controllers/HomeController.cs b/microservices/KonSoft.Report.HttpApi.Host/Controllers/HomeController.cs new file mode 100644 index 0000000..1175391 --- /dev/null +++ b/microservices/KonSoft.Report.HttpApi.Host/Controllers/HomeController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace KonSoft.Report.Controllers; + +public class HomeController : AbpController +{ + public ActionResult Index() + { + return Redirect("~/swagger"); + } +} diff --git a/microservices/KonSoft.Report.HttpApi.Host/KonSoft.Report.HttpApi.Host.csproj b/microservices/KonSoft.Report.HttpApi.Host/KonSoft.Report.HttpApi.Host.csproj new file mode 100644 index 0000000..e860229 --- /dev/null +++ b/microservices/KonSoft.Report.HttpApi.Host/KonSoft.Report.HttpApi.Host.csproj @@ -0,0 +1,40 @@ + + + + + + net8.0 + enable + KonSoft.Report + true + KonSoft.Report-4681b4fd-151f-4221-84a4-929d86723e4c + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/microservices/KonSoft.Report.HttpApi.Host/Program.cs b/microservices/KonSoft.Report.HttpApi.Host/Program.cs new file mode 100644 index 0000000..54c2ba8 --- /dev/null +++ b/microservices/KonSoft.Report.HttpApi.Host/Program.cs @@ -0,0 +1,56 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Events; + +namespace KonSoft.Report; + +public class Program +{ + public async static Task Main(string[] args) + { + Log.Logger = new LoggerConfiguration() +#if DEBUG + .MinimumLevel.Debug() +#else + .MinimumLevel.Information() +#endif + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) + .Enrich.FromLogContext() + .WriteTo.Async(c => c.File("Logs/logs.txt")) + .WriteTo.Async(c => c.Console()) + .CreateLogger(); + + try + { + Log.Information("Starting KonSoft.Report.HttpApi.Host."); + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .UseSerilog(); + await builder.AddApplicationAsync(); + var app = builder.Build(); + await app.InitializeApplicationAsync(); + await app.RunAsync(); + return 0; + } + catch (Exception ex) + { + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + } +} diff --git a/microservices/KonSoft.Report.HttpApi.Host/Properties/launchSettings.json b/microservices/KonSoft.Report.HttpApi.Host/Properties/launchSettings.json new file mode 100644 index 0000000..e200271 --- /dev/null +++ b/microservices/KonSoft.Report.HttpApi.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44340", + "sslPort": 44340 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "KonSoft.Report.HttpApi.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44340", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/microservices/KonSoft.Report.HttpApi.Host/ReportBrandingProvider.cs b/microservices/KonSoft.Report.HttpApi.Host/ReportBrandingProvider.cs new file mode 100644 index 0000000..ae370f7 --- /dev/null +++ b/microservices/KonSoft.Report.HttpApi.Host/ReportBrandingProvider.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Localization; +using KonSoft.Report.Localization; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Ui.Branding; + +namespace KonSoft.Report; + +[Dependency(ReplaceServices = true)] +public class ReportBrandingProvider : DefaultBrandingProvider +{ + private IStringLocalizer _localizer; + + public ReportBrandingProvider(IStringLocalizer localizer) + { + _localizer = localizer; + } + + public override string AppName => _localizer["AppName"]; +} diff --git a/microservices/KonSoft.Report.HttpApi.Host/ReportHttpApiHostModule.cs b/microservices/KonSoft.Report.HttpApi.Host/ReportHttpApiHostModule.cs new file mode 100644 index 0000000..31254ad --- /dev/null +++ b/microservices/KonSoft.Report.HttpApi.Host/ReportHttpApiHostModule.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Extensions.DependencyInjection; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using KonSoft.Report.EntityFrameworkCore; +using KonSoft.Report.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling; +using Microsoft.OpenApi.Models; +using OpenIddict.Validation.AspNetCore; +using Volo.Abp; +using Volo.Abp.Account; +using Volo.Abp.Account.Web; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.Security.Claims; +using Volo.Abp.Swashbuckle; +using Volo.Abp.UI.Navigation.Urls; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.Report; + +[DependsOn( + typeof(ReportHttpApiModule), + typeof(AbpAutofacModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(ReportApplicationModule), + typeof(ReportEntityFrameworkCoreModule), + typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule), + typeof(AbpAccountWebOpenIddictModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpSwashbuckleModule) +)] +public class ReportHttpApiHostModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(builder => + { + builder.AddValidation(options => + { + options.AddAudiences("Report"); + options.UseLocalServer(); + options.UseAspNetCore(); + }); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + ConfigureAuthentication(context); + ConfigureBundles(); + ConfigureUrls(configuration); + ConfigureConventionalControllers(); + ConfigureVirtualFileSystem(context); + ConfigureCors(context, configuration); + ConfigureSwaggerServices(context, configuration); + } + + private void ConfigureAuthentication(ServiceConfigurationContext context) + { + context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme); + context.Services.Configure(options => + { + options.IsDynamicClaimsEnabled = true; + }); + } + + private void ConfigureBundles() + { + Configure(options => + { + options.StyleBundles.Configure( + LeptonXLiteThemeBundles.Styles.Global, + bundle => + { + bundle.AddFiles("/global-styles.css"); + } + ); + }); + } + + private void ConfigureUrls(IConfiguration configuration) + { + Configure(options => + { + options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; + options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"]?.Split(',') ?? Array.Empty()); + + options.Applications["Angular"].RootUrl = configuration["App:ClientUrl"]; + options.Applications["Angular"].Urls[AccountUrlNames.PasswordReset] = "account/reset-password"; + }); + } + + private void ConfigureVirtualFileSystem(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + if (hostingEnvironment.IsDevelopment()) + { + Configure(options => + { + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Report.Domain.Shared")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Report.Domain")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Report.Application.Contracts")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.Report.Application")); + }); + } + } + + private void ConfigureConventionalControllers() + { + Configure(options => + { + options.ConventionalControllers.Create(typeof(ReportApplicationModule).Assembly); + }); + } + + private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration) + { + context.Services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"]!, + new Dictionary + { + {"Report", "Report API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Report API", Version = "v1" }); + options.DocInclusionPredicate((docName, description) => true); + options.CustomSchemaIds(type => type.FullName); + }); + } + + private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration) + { + context.Services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + builder + .WithOrigins(configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToArray() ?? Array.Empty()) + .WithAbpExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + var env = context.GetEnvironment(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseAbpRequestLocalization(); + + if (!env.IsDevelopment()) + { + app.UseErrorPage(); + } + + app.UseCorrelationId(); + app.UseStaticFiles(); + app.UseRouting(); + app.UseCors(); + app.UseAuthentication(); + app.UseAbpOpenIddictValidation(); + + if (MultiTenancyConsts.IsEnabled) + { + app.UseMultiTenancy(); + } + app.UseUnitOfWork(); + app.UseDynamicClaims(); + app.UseAuthorization(); + + app.UseSwagger(); + app.UseAbpSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "Report API"); + + var configuration = context.ServiceProvider.GetRequiredService(); + c.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + c.OAuthScopes("Report"); + }); + + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + app.UseConfiguredEndpoints(); + } +} diff --git a/microservices/KonSoft.Report.HttpApi.Host/abp.resourcemapping.js b/microservices/KonSoft.Report.HttpApi.Host/abp.resourcemapping.js new file mode 100644 index 0000000..4a2ad45 --- /dev/null +++ b/microservices/KonSoft.Report.HttpApi.Host/abp.resourcemapping.js @@ -0,0 +1,11 @@ +module.exports = { + aliases: { + + }, + clean: [ + + ], + mappings: { + + } +}; diff --git a/microservices/KonSoft.Report.HttpApi.Host/appsettings.Development.json b/microservices/KonSoft.Report.HttpApi.Host/appsettings.Development.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/microservices/KonSoft.Report.HttpApi.Host/appsettings.Development.json @@ -0,0 +1,2 @@ +{ +} diff --git a/microservices/KonSoft.Report.HttpApi.Host/appsettings.json b/microservices/KonSoft.Report.HttpApi.Host/appsettings.json new file mode 100644 index 0000000..582f153 --- /dev/null +++ b/microservices/KonSoft.Report.HttpApi.Host/appsettings.json @@ -0,0 +1,18 @@ +{ + "App": { + "SelfUrl": "https://localhost:44340", + "CorsOrigins": "https://*.Report.com", + "RedirectAllowedUrls": "" + }, + "ConnectionStrings": { + "Default": "Host=localhost;Port=5432;Database=Report;User ID=root;Password=myPassword;" + }, + "AuthServer": { + "Authority": "https://localhost:44340", + "RequireHttpsMetadata": false, + "SwaggerClientId": "Report_Swagger" + }, + "StringEncryption": { + "DefaultPassPhrase": "aRnRGh9BVWKdfQXb" + } +} diff --git a/microservices/KonSoft.Report.HttpApi.Host/appsettings.secrets.json b/microservices/KonSoft.Report.HttpApi.Host/appsettings.secrets.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/microservices/KonSoft.Report.HttpApi.Host/appsettings.secrets.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/microservices/KonSoft.Report.HttpApi.Host/package.json b/microservices/KonSoft.Report.HttpApi.Host/package.json new file mode 100644 index 0000000..b8d616a --- /dev/null +++ b/microservices/KonSoft.Report.HttpApi.Host/package.json @@ -0,0 +1,8 @@ +{ + "version": "1.0.0", + "name": "my-app", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~3.3.4" + } +} diff --git a/microservices/KonSoft.Report.HttpApi.Host/web.config b/microservices/KonSoft.Report.HttpApi.Host/web.config new file mode 100644 index 0000000..aee1cd4 --- /dev/null +++ b/microservices/KonSoft.Report.HttpApi.Host/web.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/microservices/KonSoft.Report.HttpApi.Host/wwwroot/global-styles.css b/microservices/KonSoft.Report.HttpApi.Host/wwwroot/global-styles.css new file mode 100644 index 0000000..74db4bd --- /dev/null +++ b/microservices/KonSoft.Report.HttpApi.Host/wwwroot/global-styles.css @@ -0,0 +1,6 @@ +/* Your Global Styles */ + +:root .lpx-brand-logo { + --lpx-logo: url('/images/logo/leptonx/logo-light.png'); + --lpx-logo-icon: url('/images/logo/leptonx/logo-light-thumbnail.png'); +} \ No newline at end of file diff --git a/microservices/KonSoft.Report.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png b/microservices/KonSoft.Report.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..9734a07a4d4539d3081bb897ffc8d5e75dab8798 GIT binary patch literal 10695 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 iRGz-n4VZ}kM?W?F&FYYBo literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.Report.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png b/microservices/KonSoft.Report.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a3bbe82224deec74650461230f66d609eda717e3 GIT binary patch literal 38171 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 MU)LDY2zE;NA05R;CIA2c literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.Report.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png b/microservices/KonSoft.Report.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png new file mode 100644 index 0000000000000000000000000000000000000000..761fb4443d597661e7700574e52b787d7ed7255b GIT binary patch literal 33228 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 nuxmBTJ6Y+ll0437Z literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/Controllers/HomeController.cs b/microservices/KonSoft.TenantManagement.HttpApi.Host/Controllers/HomeController.cs new file mode 100644 index 0000000..be4fe40 --- /dev/null +++ b/microservices/KonSoft.TenantManagement.HttpApi.Host/Controllers/HomeController.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace KonSoft.TenantManagement.Controllers; + +public class HomeController : AbpController +{ + public ActionResult Index() + { + return Redirect("~/swagger"); + } +} diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/KonSoft.TenantManagement.HttpApi.Host.csproj b/microservices/KonSoft.TenantManagement.HttpApi.Host/KonSoft.TenantManagement.HttpApi.Host.csproj new file mode 100644 index 0000000..2126148 --- /dev/null +++ b/microservices/KonSoft.TenantManagement.HttpApi.Host/KonSoft.TenantManagement.HttpApi.Host.csproj @@ -0,0 +1,40 @@ + + + + + + net8.0 + enable + KonSoft.TenantManagement + true + KonSoft.TenantManagement-4681b4fd-151f-4221-84a4-929d86723e4c + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/Program.cs b/microservices/KonSoft.TenantManagement.HttpApi.Host/Program.cs new file mode 100644 index 0000000..26cedfb --- /dev/null +++ b/microservices/KonSoft.TenantManagement.HttpApi.Host/Program.cs @@ -0,0 +1,56 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Events; + +namespace KonSoft.TenantManagement; + +public class Program +{ + public async static Task Main(string[] args) + { + Log.Logger = new LoggerConfiguration() +#if DEBUG + .MinimumLevel.Debug() +#else + .MinimumLevel.Information() +#endif + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) + .Enrich.FromLogContext() + .WriteTo.Async(c => c.File("Logs/logs.txt")) + .WriteTo.Async(c => c.Console()) + .CreateLogger(); + + try + { + Log.Information("Starting KonSoft.TenantManagement.HttpApi.Host."); + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .UseSerilog(); + await builder.AddApplicationAsync(); + var app = builder.Build(); + await app.InitializeApplicationAsync(); + await app.RunAsync(); + return 0; + } + catch (Exception ex) + { + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "Host terminated unexpectedly!"); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + } +} diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/Properties/launchSettings.json b/microservices/KonSoft.TenantManagement.HttpApi.Host/Properties/launchSettings.json new file mode 100644 index 0000000..c10ca48 --- /dev/null +++ b/microservices/KonSoft.TenantManagement.HttpApi.Host/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:44316", + "sslPort": 44316 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "KonSoft.TenantManagement.HttpApi.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:44316", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/TenantManagementBrandingProvider.cs b/microservices/KonSoft.TenantManagement.HttpApi.Host/TenantManagementBrandingProvider.cs new file mode 100644 index 0000000..ac30d7f --- /dev/null +++ b/microservices/KonSoft.TenantManagement.HttpApi.Host/TenantManagementBrandingProvider.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Localization; +using KonSoft.TenantManagement.Localization; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Ui.Branding; + +namespace KonSoft.TenantManagement; + +[Dependency(ReplaceServices = true)] +public class TenantManagementBrandingProvider : DefaultBrandingProvider +{ + private IStringLocalizer _localizer; + + public TenantManagementBrandingProvider(IStringLocalizer localizer) + { + _localizer = localizer; + } + + public override string AppName => _localizer["AppName"]; +} diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/TenantManagementHttpApiHostModule.cs b/microservices/KonSoft.TenantManagement.HttpApi.Host/TenantManagementHttpApiHostModule.cs new file mode 100644 index 0000000..adf740c --- /dev/null +++ b/microservices/KonSoft.TenantManagement.HttpApi.Host/TenantManagementHttpApiHostModule.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Extensions.DependencyInjection; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using KonSoft.TenantManagement.EntityFrameworkCore; +using KonSoft.TenantManagement.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling; +using Microsoft.OpenApi.Models; +using OpenIddict.Validation.AspNetCore; +using Volo.Abp; +using Volo.Abp.Account; +using Volo.Abp.Account.Web; +using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.Security.Claims; +using Volo.Abp.Swashbuckle; +using Volo.Abp.UI.Navigation.Urls; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.TenantManagement; + +[DependsOn( + typeof(TenantManagementHttpApiModule), + typeof(AbpAutofacModule), + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(TenantManagementApplicationModule), + typeof(TenantManagementEntityFrameworkCoreModule), + typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule), + typeof(AbpAccountWebOpenIddictModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpSwashbuckleModule) +)] +public class TenantManagementHttpApiHostModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(builder => + { + builder.AddValidation(options => + { + options.AddAudiences("TenantManagement"); + options.UseLocalServer(); + options.UseAspNetCore(); + }); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + ConfigureAuthentication(context); + ConfigureBundles(); + ConfigureUrls(configuration); + ConfigureConventionalControllers(); + ConfigureVirtualFileSystem(context); + ConfigureCors(context, configuration); + ConfigureSwaggerServices(context, configuration); + } + + private void ConfigureAuthentication(ServiceConfigurationContext context) + { + context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme); + context.Services.Configure(options => + { + options.IsDynamicClaimsEnabled = true; + }); + } + + private void ConfigureBundles() + { + Configure(options => + { + options.StyleBundles.Configure( + LeptonXLiteThemeBundles.Styles.Global, + bundle => + { + bundle.AddFiles("/global-styles.css"); + } + ); + }); + } + + private void ConfigureUrls(IConfiguration configuration) + { + Configure(options => + { + options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; + options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"]?.Split(',') ?? Array.Empty()); + + options.Applications["Angular"].RootUrl = configuration["App:ClientUrl"]; + options.Applications["Angular"].Urls[AccountUrlNames.PasswordReset] = "account/reset-password"; + }); + } + + private void ConfigureVirtualFileSystem(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + if (hostingEnvironment.IsDevelopment()) + { + Configure(options => + { + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.TenantManagement.Domain.Shared")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.TenantManagement.Domain")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.TenantManagement.Application.Contracts")); + options.FileSets.ReplaceEmbeddedByPhysical( + Path.Combine(hostingEnvironment.ContentRootPath, + $"..{Path.DirectorySeparatorChar}KonSoft.TenantManagement.Application")); + }); + } + } + + private void ConfigureConventionalControllers() + { + Configure(options => + { + options.ConventionalControllers.Create(typeof(TenantManagementApplicationModule).Assembly); + }); + } + + private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration) + { + context.Services.AddAbpSwaggerGenWithOAuth( + configuration["AuthServer:Authority"]!, + new Dictionary + { + {"TenantManagement", "TenantManagement API"} + }, + options => + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "TenantManagement API", Version = "v1" }); + options.DocInclusionPredicate((docName, description) => true); + options.CustomSchemaIds(type => type.FullName); + }); + } + + private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration) + { + context.Services.AddCors(options => + { + options.AddDefaultPolicy(builder => + { + builder + .WithOrigins(configuration["App:CorsOrigins"]? + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToArray() ?? Array.Empty()) + .WithAbpExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + var env = context.GetEnvironment(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseAbpRequestLocalization(); + + if (!env.IsDevelopment()) + { + app.UseErrorPage(); + } + + app.UseCorrelationId(); + app.UseStaticFiles(); + app.UseRouting(); + app.UseCors(); + app.UseAuthentication(); + app.UseAbpOpenIddictValidation(); + + if (MultiTenancyConsts.IsEnabled) + { + app.UseMultiTenancy(); + } + app.UseUnitOfWork(); + app.UseDynamicClaims(); + app.UseAuthorization(); + + app.UseSwagger(); + app.UseAbpSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "TenantManagement API"); + + var configuration = context.ServiceProvider.GetRequiredService(); + c.OAuthClientId(configuration["AuthServer:SwaggerClientId"]); + c.OAuthScopes("TenantManagement"); + }); + + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + app.UseConfiguredEndpoints(); + } +} diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/abp.resourcemapping.js b/microservices/KonSoft.TenantManagement.HttpApi.Host/abp.resourcemapping.js new file mode 100644 index 0000000..4a2ad45 --- /dev/null +++ b/microservices/KonSoft.TenantManagement.HttpApi.Host/abp.resourcemapping.js @@ -0,0 +1,11 @@ +module.exports = { + aliases: { + + }, + clean: [ + + ], + mappings: { + + } +}; diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/appsettings.Development.json b/microservices/KonSoft.TenantManagement.HttpApi.Host/appsettings.Development.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/microservices/KonSoft.TenantManagement.HttpApi.Host/appsettings.Development.json @@ -0,0 +1,2 @@ +{ +} diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/appsettings.json b/microservices/KonSoft.TenantManagement.HttpApi.Host/appsettings.json new file mode 100644 index 0000000..e08f2ba --- /dev/null +++ b/microservices/KonSoft.TenantManagement.HttpApi.Host/appsettings.json @@ -0,0 +1,18 @@ +{ + "App": { + "SelfUrl": "https://localhost:44316", + "CorsOrigins": "https://*.TenantManagement.com", + "RedirectAllowedUrls": "" + }, + "ConnectionStrings": { + "Default": "Host=localhost;Port=5432;Database=TenantManagement;User ID=root;Password=myPassword;" + }, + "AuthServer": { + "Authority": "https://localhost:44316", + "RequireHttpsMetadata": false, + "SwaggerClientId": "TenantManagement_Swagger" + }, + "StringEncryption": { + "DefaultPassPhrase": "FUFDAYrpYDaw4Tsl" + } +} diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/appsettings.secrets.json b/microservices/KonSoft.TenantManagement.HttpApi.Host/appsettings.secrets.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/microservices/KonSoft.TenantManagement.HttpApi.Host/appsettings.secrets.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/package.json b/microservices/KonSoft.TenantManagement.HttpApi.Host/package.json new file mode 100644 index 0000000..b8d616a --- /dev/null +++ b/microservices/KonSoft.TenantManagement.HttpApi.Host/package.json @@ -0,0 +1,8 @@ +{ + "version": "1.0.0", + "name": "my-app", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~3.3.4" + } +} diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/web.config b/microservices/KonSoft.TenantManagement.HttpApi.Host/web.config new file mode 100644 index 0000000..407dc06 --- /dev/null +++ b/microservices/KonSoft.TenantManagement.HttpApi.Host/web.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/global-styles.css b/microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/global-styles.css new file mode 100644 index 0000000..74db4bd --- /dev/null +++ b/microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/global-styles.css @@ -0,0 +1,6 @@ +/* Your Global Styles */ + +:root .lpx-brand-logo { + --lpx-logo: url('/images/logo/leptonx/logo-light.png'); + --lpx-logo-icon: url('/images/logo/leptonx/logo-light-thumbnail.png'); +} \ No newline at end of file diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png b/microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark-thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..9734a07a4d4539d3081bb897ffc8d5e75dab8798 GIT binary patch literal 10695 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 iRGz-n4VZ}kM?W?F&FYYBo literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png b/microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/images/logo/leptonx/logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a3bbe82224deec74650461230f66d609eda717e3 GIT binary patch literal 38171 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 MU)LDY2zE;NA05R;CIA2c literal 0 HcmV?d00001 diff --git a/microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png b/microservices/KonSoft.TenantManagement.HttpApi.Host/wwwroot/images/logo/leptonx/logo-light.png new file mode 100644 index 0000000000000000000000000000000000000000..761fb4443d597661e7700574e52b787d7ed7255b GIT binary patch literal 33228 zcmYg%1z3~s_xI?Q6hz9Pgb7M_sUVC7l`ctXkQ@Uf^ovLh8C{BkQloo>0f;c9dm!D- zfD!Kl!tej?y1cx2;y(R3=RWs&BD6JCsK~FAgFqlE)yEHYK_F5D2!z){N(@}7`ub-J z_>au(v7sjjL_vS{4-b@*b`1o&0aAUasP8+nGTs=;sS+X{klgx~nS9R%OFZ$)ifa57 z4a2)K&!?g9WS_4Md$_F4u~yuq@63IT!Nb|4(m)GC# z@LxTo-ztQcsuU)#9VRo&%X5%UPYw6JRDP(e{4kJzE8Qp9C*^ZZBY0h~W7_7x+VFFS zM=99+ZbwzemZ`DX-HuZqh@aPL5cY|&=E&)QUB_0PjbHU)Ri6YP#Mw{5Y6R52KC;oK z%5vS1iE**4;ABR%-;LQUGcfn0*56Y3Fm=(&op%c;sac z6G5&Z5`}FYYneU43hSu+!v`tWG0M zx_sf0y}Zx#OZZwxCXD-%U>jUP6}goVOm^{5EYT}EJivJ8zu-)Vl(|5hALGrK>RIc4 zMt{zW8#Jc9B0h<;!=?3fOEmW``P^6R6^S8Ig9~5^M;>btT|67&AP?P6m{fj>N1vN` zaSe35HJn<|AuJ1c$N6u;1gh3v)xxYPc)6Hwp+kyRn(p5nx{F7G2S@bOP;@PB{+GNq zIcoIEIE9knUz>dcVPD?7c(Cc|h!%#_bYJAk<%Jl)6Y9V`N{s!8;(+UyqWgC6X(PcH z@@M-Z(QcP(ZW#57tXI9lZzi{S0(i;#81uy<+BKgY*sB!rUy;vtZbe96YMQTt{0gZS zFUv1spR>3)`{~BYfjU=sz4nD$eP441y+wY33cBYOkHIUL`iOkE^OBQ~PXw6A%_*#Wa%7vT}yVnUHjs>1sQp*5y+v7&a?XNR@(h<&P{G+YMod)w#I8yN~5Qn2Y( zANDyf)#H}$n41*9b1(b-7wbZr9{|NgH<{_>cR1Q#)PO+tZHOaUC{>B2y-nH{bV))$2Z4u-;8( z$d2UuRrLzjpV+ZwWtefdBi_aj3HEvCd%?umSE@MHs+-YT!`ZEn{{G0HOXly~G#`Te=> zD0&oc?UAHKkiQ!QInycRs3m4dq%k4<;zFMcMaS=dZ|{Y>x6e6S*qZ#x^&D|)ufo6f z1JVCQ#D`!ncNj4RU!G0fD>Kj(zAzx~BNlE+jiX*MSe?C=9Wz6BhThG0RvoRcaDOmY zc$F?ex#mTR?NElgu4mGWSbn^Ew2&(X9d_?6*qmtPLCh6O#2AB6jor=#rakUk5{cgH z6%-zhE0j+xBgaq*JG)N7g*uKEj^{PsGy^>R;48O!c$OD|-{XfYyzWw};kilR)4A4= zYd;du_ ztUaO-fgUGKGFhizr$}UYvPR4bIblTp59W6sWj$=NesD@7a3?o_H4i;T#tNpr#OMV8 z-oEX{i<2ffE%CQ-$-OCa%si0Nt$x^a!N?@dnH$X>l!9lZ;3ZP`ZIgT(X$9IF>&f>e z(;U8Av_J8ym6H9DNBvJUzxa< zHTZbE(y8w9ZQfmK0TL4~Tq@A3a6HrSFof&bY>ZsY1^BoTWHxO2rLiCOwc=kNMik@k z#z{vILCk{KTlFsNIhoF3wi1n)g&w>sD8yHce~25jQv#l?dv(}081Wi{a=*+E+CYrT zCA7Qws|E*(UF~Trm7yGxKS8+p{dKrlOW)?Ioc#mR_jV|7E7@L6F`;NFKL^PYixwR< z;;4|SQKI2OE4=2tA}Xu7dc32mR>x~=r2#wzaZe=4B)E_7hL#?RbU`z2{nLj+34q7~ zt~%q3T;IYDF~@)vk#QOa0@{t$iK@t%uQIzL7qs8@h;%mPx_-Tq$ja5n#6j+44OnuC zDX61B#uy=;A#kzY-cz2ZVo6L)~h`3C*vE12o9#o0o z(_>sdD3nH}bk-$UZo^EmneH;j-MFj7#XuwA2X2aUs^Q2wUcbr+{$IB2xuLJ5I0cud zaOX5UkyIGP+_`6P%j5zqzW0lCdis&7ktG($)%=Z@P(=h$^_>LKU#8lH|Fp?uUqgs# zal5S{tnCRg1Qo}FL_i_o_u@jhX3~W2vW~VXcyX8{oG+8;1r{F4mA}>0OYu*-1)vIg zUPFQ}5joVlj^otSwYi=*4xvW;M$Bg9UQ{;Ssh=HQca+BZ-H4s1#U0w=v$emES8zW0 zuwl{uHJ}XaBh&eBvEZ(XY54w1LZ$P9IdCWkTV?nnlw_oP=#zHk4h~S!Ohl>ba`E*Q3mSfE@ zC08vtcGE!D&2R31w}8w%FGR^{f7Sc?!)lJt`0OEEM2RFB{{L8S8W_=QgAcGzoD4pZBt^h!0QdeM=z(KaWdPqpkLSsEJJ_@!px}x5kNNQrfqlTsiXw-3 z%V##brx^tU>o3moeDLIm1|M&`P7`h(1*{J^>fKx=PR+Y`Akunv4sge|P0iS5&d;*g zT+y@e(Y~LXpq*zpiCf^GiZKI{<;Z3@=)BgzFS?ykbu%th(~03cr(`|TRs@^N*ILLkJky2Ld^sJt595YeZ5_CnP{E(y zhoIu)#(!s3%wdLSw3NiB88LMKy|YKtJ&ee%UL&l})C8WpQ;c7Mfri{RPTG^h|yKry8ly_WYQg&CHG$(OuP+=9TU~iqj6~)7w{M$V`p<;Hyh`GW`tQ!jQ z50bl!Ul_{$f)#|GsBrw2ef`5nl=WRI5Q99kRH9@Seq>WFVxLtL3n*wcgEY#?l->6& ze4n*7_vDJOt5!vw0iw6RquqwN7@yalsYwx?>o>W1^th0~!r3<;BKrLbY|&T4oK6=X z^frT3vM?+~9e=`DPcgQuL!RVCojmzFCsQ+DIDB*N=9@aF2R!tGckwC%#bje>8T7Y7 z1}sHh9}q*Of@Hw1np;Wx8wD~Li$G7kG+!frQOAUTTRK5HDhG39KyvT5THgf)S48L;<-6#*vqGy_!Yy@ zkXzD;$vk{>QY$n0J(+Ja{t%{!nD~VsN zm9*mDOiu{9(q|h(_-K!hTINZ6z;-NhZq+tTLpW;#&T zFV*fAC>5V5*~^&mtE7tsW7K`NdN<=5e)Z`k;EPd5_`Hqi6wi8X*CX-D9s3CZY8r9l zzg_Y3E=(0k2)c(C^7c3Wgd>JLoYe$HHDqQ^9{ehzVF#>TTbLUDYaZGM0+U1g>KE_o z2C$RxE+)_DNq}N8BW{)&Ei9MxJlAB2j*#~#cO}z`2_NnW@Zh!nWNHCeC&?&fDE0fV z7Xqpc-a6wJF|N`-uZt-*Vu@TELayZQpx{YF$F^RqqNe^bO0htt;_u$ zn`tT$DdCX^a;H0xfn?rbt`IoUf@F0f%l~OQ;x&0XaqW5_&kgvIom+I6lGGh@Xphyz z19WcUP#%E?jGIdA=(-dkj{+VL9FS{S!vVjraVZZ0E9E)-72edu5A;{Ox`3(^i|2`aMQX!AmBntPf369q9=T8g8Z7e- z1NfS-ukUJ*_=xtPaD^f4pU)=mgXDc!7bb8@+Sa*SgTd2(p)EJk5npoeCOfeM6$Q=o zFvD^yyV*<7ceYa^NRKJY70f=yMQRiJK{o?58tqWVmrT>}^em+fa z8LQbbm{FaCyJ3Rwwp`}GU|GO$MD(Bh2?ZjjPKzDy z3%yWa0#Rd|fAS>l)bC8-xrmUuosKhI8?H?wWMx_>d$ps>{=a4JXX?!3{rp+O#0q-y z4j01prjY6lw1`Km&ne-bcUkoaW4nMguDqm1(On<@Iz}xaa7d{sKbxE@!0g1X%Z`yE z@qlXX9>V{0PzC${3=j?I9&xLlJ6#hAmwg0ZI@ii3ea0&vDjMvgzAenbQ+v+zUbPXi zP3E*fAcL9-4auzh!ghEd+>?lE>DZTD*J8+~(J)a-Ha^au3h&NJJLdVP`8WJUwmZ>)*1i>kS&XPFPLNK@n2`R2eam=4YugAUdQ^oSF!7r5Iyb*PLS2 z_Wh?oEN*)_;M=~GtJeDz(q264`<4IL_3nGUr?|9msnX;zP=P3=8;2YNyXssyoFs&! zA(7{T&mL#f82>ba4516#^s zS%NE~3C7-Fi5|lx3$6Kp(!y_U5%M?nO$gU<-vN^Cxn2@`gU(mIo@a+P=jac8()Tj~4-0XYw|J7ydo*`` z$NUQ)pCeZd-J$24M*kc(U4lSfit43&AkX8ir!^eD>H(a<5&^4Z>Rg^Tn&G?7_r}~z zUXsd15P%d`{7TN*m|{O|@XAa#C%wino_K}@A9$pnC*ut**ks{0jTPa(xe4XY8x`Fu zu|nH~+?$;bn&C+2`%(Mv#M$vcG*CJ4xxq3m+L4B*2U?l4;Hq=qdZgveEkuC)bG8b< zC46u;p;zs#ppQ(rs_(Wok~0AM?pB7`dHcqyEBv1@*dte$!~3~t55({#BYMerkDt?` zjP%Lh*9&Amx<+kI3Y3`G%T+W}zaNT3pOroTNm4VO*+xQUvJqOF?fmmaWA!;07*s2) z;*ZDZy@GT6@}d3NLULBdLNi)8>j7`1D>fz0k8e4vvx1Keo8g25uip?t#0s4mTZn(` zo+r|U_AW>q-q5cbO~?Dm+U?Y{mSH7sd<(Soz7ddLXU26O2@!UGr6&<{QKaKsR;*o*_BME2i#s zHLUwe+i zZ`e+aQ!)c?ZyAIDK1jEEl}jBc$p`1o-xPfAcp(=B|e?@R#FZj*V2oIzGtax}v&S#H#H z&X!V^t0OK|T^7p(YKA|aMboyT1c{^xAxOYm;HIfmuqz~>VEp--f9%R0r%qF?dVjDf zUAYuCv*p$5JAhwNA_yvSpDay93D_e7`O>*AT&e=7Vn85X%V>TBkD(E_q3K5Gb*Lb` zYgGRn;?4{lQE%~;*IZxk;V(pI>4}tEz3V~ zHHAO>KP@XrHN#u4hN;O#N=%H?&pigZ6Aau_XVG3h>cYA(EU!HZ0ud%*{&_g@K9+}N z#O*^u>Eeap>B;pVCmV*zK(MTVP?XGsMmVt9kGTxg)k+qp{U_#P*}5PQ4OrFRS%Pv$ z+{7T2;m>8Hhj1a&X&SZnt0%SFGjGRu#Sluu`NbYR_B%t1<2~uYKoBTtlpL{BFGhJ4 z%Ic za(%UWM8O>PEO5-FrAU)WdbCu%I6)N`B>yzuc<>l`_v2n*?U#2Wr%{R5x>u9LO*}Dd zrpK;**Iwb$?>CN}A;h-<#%~W#q7#G*6V7m3)vi$Z#pv{lbiZ0ln4iD1vm`1d{)@&y z!KcnIeRmy-pg)bHkHw>Khfin1DM%43-tvfR-~$0$z`D;en^eo{=Px4A56pOY!rG;z z;WOd#(Yx8Za*8Qg6+J985-W*%ieYk2=kUN3oVW^(>IrI%o>qp7j|Hro63yC@OhDJ9 zE0gJ?CKh}W*<|eIog3@yPwT{tx5qQDf+d{*MITkAx!9v47$LO)Foy*Zvzr=ko9vZq zxed!v^JrQWxo8IYTVQJ41&UqF2UmZ*!WMeLH%|{Lj*GhXLW_6vOXjho3G!E&gGCsp zfV`g5q}_hp_I!-stP{odPrcywk5mr=dfaIauB)&Fn%4V}1r(oOgZR@qNYV#5~_Bm@oOu>%q)5 zQQ1xisWg}e*H1n^XWiJmE2Y|YmDMTdiIn4@y(7XqP}E^woC21&U721!SVt=HOtwOq zuT)SrM&txN8arHl*zlezo-GU3MpDbsNW-^SE(gQsnX=-0c%GL1$}Rs3-qD$HTyZX8 zu+W?Hdl&p5oaO8G`}yuwVz|bR$l%h*r+Vl*-=tRoY`5+)OJOUQYdQDHZ;f$7VyuB$ zGkof`-_ECCd&IUldhU2>htCPdct@de)pJ9ig+pYH2ovu>@DWY#hhpk~qjcJ2A1T_C z9IHA2Tl5Q=KBc}HZ^UBb`` zISFz%_Cj)&bSA^Zer1e0t*-nCvxtDYvOH_-+lCk&3n(Lz)v*y45f-Xej_LHbZM?U| zJ&UC>Lgi%$Dke3Z*+dL_CUS)VMfsbCH*rS{u9}d_=g%*KL+_vRS;&jn6AS{o5ROLv z8~R($x3b|XEi9^uOrKTGOEx(AL&blRO(~AQZyCUqvU2(?R7cTzM_#Wx2dV|R2_a)p zT$sAkhb5nE(_^KV`j2s>2vS7YNu8#6U%t8dylBuiWtWrlaC65`tqNT8I&X~Bp}0rd z^G;6#aXXW$!2J(`UUHbi4_ZVcv2VsSfLzTLrnbg?ujqhK^Kdr#3tfaOJ2_%#Qp<{7 zX4gWs4k4lH&|~{Rw61f2K2;LhkVFGsES^x&K;=Fh+V};`{gSI>QTqrg;Uf=4~S`T9!e<}by#1@-b-~#$roiUEcoO#rf-LZytc^X;QqXn+; zz`kc$)+LrJ>yBfBK@HB9ge+`C)zs^@?0k}{H}!i4W)nkL+7o#`tN&AwmNaUmhDz|Z zxp`?be6H2poU7`UcH59hz8h-w5!U6OlGdb;yNFT8dd={AKYE&mkP&-3N8^Zs@Z#mdB?f?zYel8QRrdy?4Zau&eu zZqaU`!)Vn{=SH>(-RKdIvAx#by>*F~r`EbduvFb~v+Ex}?tXG7fjI;^A8}N{Y>=%I zFL#t1ODCdBEUCh;0YYKW68c+)O4Gx7*-_wM1ijqnzSo}1hQXsK@X+{N9e zSnr2uARi(*w=mUTZVkg2#@rJ1*H87_+;9lu@@jGGsqJ7G$x%8vKL_3 zP)&a4QSF|oe7|ta{fzRU2)wo%$czoSFRua$ek1ccbt(YgcoiFxS=K+?j z*lli=EZoNQZ+xy|#H^*#^iYG%fsw`S$iGQXJ%CINzVm##h(Gkd!9;ar&hROdJfLQQ z&yEyHlu@oBT(X^b^*0z-de(b9;QmNe92w%_2@46!;iQSgy@P{M?c*aiwf3Utiv_SC z(KZX#;aw5}%_wMYokctQu_NO)*X}ErJ-d*0^--1Fi2M4jidwc+-yk#J&wJj*=skl> zZY-t!-f7&>w(j-qwnJiE6L?^HQ)@tdPmOW+NZGHF?Kg;Wn9&H2F(#fbhYZlvc zc443ik<-2~*iR(**>SJFXHx^2gOie-S(sZg!-xL)T6af+(NH@)lS1;Zgy zncu)_P~vjfixF$LC2fvKlS$in1?<$be@?SdWnYz` z122jP$BjaU)W!7EbxScFKP_#hQ!P}nXqaF)g@1c7hKxbkUd#E80lWoMyBNPm|IxK{ zyUOyDmyo@=7!w5hBGqur9SX#}hYLpK3X=QDv z#g%wPHdhv~NqO@-MZD=@f!wFE=mRTsq5GtACc9@L26$pS7#uGZr+>6OdTj;ka1ky{ZSNxd_GG)ay|p5)z9(G_$D6i%AVH=>>SrETe9J3I<~S2`tG*U-|G2o z)<8L!^NxzN87@n3P2*?dnieu9uy21y!(5Q%O?V6tE0$)qlc?VH9&yziSVf_Qs^)eW z{YMXvRoz|(_fa`&yM+FZ%1n&J*A>*Tq(P4p)^MgjW|4%bzt>(b4;i^UE~M{aWWX_| zU)4XJh&T8!K4jT)RL@XMAsYZv@|4<}f*(>F|al8tsYeABD6{6Y`(cc$s|q+X`b znXdMot!vNvYfFbucHkW=bL5Oo8wmF-=sIV%LVG^)WBi^&fEK`X)s1y_ zr-j7GpQ?IyIx#QyDW}Ai+m{}EU2TBYJd*8aP#)njD0RrRHu8lzkDysOy01k3TK4Y6 zqttvZf5hBfj@?igXSlZ~csi6gAh{tNs(_uSiU?CXsRd){**}JJEgYC?RYo>s;yqbU5FZV?&Xd{e zE=H-Wo!SwMHCs_=_vzTWx4F3(t*yE@%c2Js8UercCi3ue<{P2UCb=}^dGQ>!(F4ffiNP9ZYer@c_B>RMIhLhaZbC^bzpM3fwc}Jns45^nZBHb`7GU8|$ zI514zA1WtL2)L6J2ipuuPdkgs^5=9c!LLHO9@T>*#yGUpvp=#hiJ-_3PUg>)xZK&E zNRiO;ML5!Bcb>tmN1&wXZmtSlaw8RgAUAo!n3>OL0ONe#hSZRlfd@OzR5Ju-7iix& z{I_8vycX6G@n_lY*e+GFG~O)G%ypD?=YGem6&QYFGR*m4Jpim-S{WFo_UlfJI&+)- z*_JHRo6`N4@@6v}B#4ZpMp&POxc@04C{9c(w$X1pGn=Vwl+ar7w$fUI)mk0f;ke4r zqeCT)J#`|8P!JgcU9vRWg?Sxrw*7~3n+>*(WGYL%YH~Vacl`Ra6T2sd4Z71{iTN^u z^NB3!v}*_~$X%~8fU&wJT*+n^^% zS`+H>?a|EgvaCT*n0%r2AG1LRT+fn!_f(}vA7a{3(7=^a{Gt6vEqd4=?}35AtX4;k z3g@K1kk%FPYd~u>FphS4LV9(3!m$`vJ#M0PSKrgHx&HQ#K%c9elFpe4u-%4_dzfl< zw|WkS?y4?a!R`Flp#!hK{VuZUjZx+?k{LNF1ZGzJ+P6DNcO{4Kp;;OH#~nktSWZr3 zc2hY*nj>K?)GTuqdR}#vF5+jBr8);%%x;U1uO7bxBzqsUNpSNW!MNi(#rrV>K`dg{ z(ULN=`PF}Cy{Cin=?=I#oCw(3ABU{?w^ExiK>_;U& z#kPaDfilAyb{w!i0X{ zxLlL2Ux^V8Vqx?ye1N;zj0JrL{O+?wyED2?Sa!~fP1A=;-sxKLZ??d%xn8e|Bh{9z zQ|VcW4C|Kd7SWjNncuQqB7?Cbt+GUC&_ylGrVy_73yf8#ZgV;nxpt0rW-2OS#~p4>_f&VgpWaI7 zHc>+ldKdJpUny2;hQAzqElCU!3(pj+@PB_`?9dFaNi1yWTekl;;;KCAcx!l9`w~N6TX*=i5Nd zU!$4(m({E>S9DcaG*zpyCZd;SqNvqN@RN$`k*ms=wNNgjDtc(6G1^dTH_2=n%Q-7Q zG4Gbw51gy7JRz}!_ZRQ7Gv2e1vlstGct3!cME9&f23ia%pQ@iaKYOH&k(7jAzW2^pB{Y=6lpIgvLddtC5k%u*7p2FCeh9b|9I`zbRhScN8FpI zM~S7Y1?KFAc45@W5x-YMcZ?dBH8XkF`rxv2Mj4KE*wjVD_7$Gy6?ZNFpT`BKlsieG zxDgw~c9rdR9KZGlzb5F)RJJADrpCC<;^5)_hoMscKfbN+gDKDY^jr4d+=InfRZu^H z!pX3~KB|1N|I<3==#$RtRGJbcyfXD=2+|stc&!0d(B&0c5CMJr-TfvD^uE@VL}$tR zBlh(ep;gC!{Y9b}OS2oV(*X#tR-V@I*_A2eVyJArjx(ShuEBsO_A$;^6|%da9-Xik znzThlOv6OJbo-Bpzq>K+E0#Ma%@lXWWY+i@Ox`%q-~X^+C8Sn#7I9*e#qVyJKmXMX z2b+6)b#r^}jxXCj%;Zk)Pq1i5FW>&Dsu-!%LR+F4*LK2Gu^J=w0oW5`sh0kmK9=b{ z1e#tzoBj9Eh*Ni)usAGx?@Xe(86Ygr9HCb6<)KU!hLw_%+p0&;`sdCk=rJve~0Z`>p{2M~HYa=Jd z#`H4%8{ObN+GWpD7dhk{`_rm7QJX3Nf{A7Jvn;UbES(7T%gYRi>tqj^mzOugaS2ym z$Bg_an0$0F8`mn&EZE(^+6KKpn2^Zq1cLs#UUXLgf6(VDCO3*ffSF}}YgmF(Wa8QG zic3r8t@|CwXsa}B(L2@XAEb#hdk4bji1Z0K6p1=EquiBuWoGn7r?J?D^zGj2KYknC znhV~u7fSINKfG1@{=olxZNqAY4F67wcwuDp&O3Y0J`t?oE$1CYd+x^L7+}~ABST;5 zW<+K!a(~-{Z*`A?wmM1QBmHp8lI6P+*Fm9VnXfz0x8VZa|FVFhFs)Ka?$;=he;H9v z%OPYUgf0jqJU=z&ujxvlZ^#}z7)3TMvsDf{t=~S{w$w3@=bIzJPhLxwbYIx0HD&NE zOkLB+)FSV_vMd)7KcO1MLT8{&PTdvQ8rPreiejkD`zq7BeaAwtvt$2Aob8IJ+N6;l zDMEd>CQHzqNh4gPTbVRbT{w@v8O|Zk{6b^M{5Tqa4Lh^L{B^r&`j7h~m}b@;%|`n3 zJ}Y>|NK1StF=pq#i8)s}VZ}k%3;i}xm$KHfZWiyaz3tJSL_ANu^r}8}GIt%{;EV7c zdfzJn*^H5M&N3lx3T%zxiPFOK8LTZHTci9I!UIq&{OJv2S~Et^Ng$fLRdc;fUUFZn ziypj&^x&ST?3cJC?eD&k5w+6Yg!wQaGh&4DVss|&2kBa7vXG0c*1HQD(D{JDo9`na zH|Ke`#dm+n!Cq(|%2;*yH3Fx+;<>xbX={heIq>D3=f~x9OsW}1bko#8BUJv1#KU754X80C8 z^jp*9U-O&}-j!*~(LA>l;_v|Og;xw|_>g#zYC&eY{wnRN2W+%HXon7p^&b~&%Xg{E zA1w52jnMNMUzVcw(p}YQ@uJz$2vcU(P&2Uew>4p^b)g>v7>MKgJ zp7T-bLvL0*%hZ=1oF9oHCzmG}Hn#rejUJ>XR;`Q{yWp%BKEy7M?yUW}qlW8W{?2++ zZTt#(HOdR<_Q~ED7R}d#Gzq$wUGL5i0r&tW+a%9mX1CH%SMbIyBFN6DPe|bPmNXHU zV;<-W)xu`Dg8U12%nxW6w;x*6Qj7l&wq+1^FSHgoY^f4Nu!4sfHt52Zy-#e9a$^FY zv_Mugwu9uaOca|{9qdd(MEm{5qsbdNWIKA&%LF`Dv}5T7HENleCX5kG_*dUT$ytUo zMDa$zeT%fMWTu`A77qJ7GnaoAo=(dqL9GhZ~KA4lb36 zqr>jJuMFswC=4rQoHJvesZe~j(lG$+4@)K(%Nq^fyG|64ZK|f}YiZ{R7|<=Wg4gPR zqis?*Oef!pkJ(yl;i)0G;MW7`n!ry(}v}$AlpUcEbv1r;Jlb zxKxre>6Cx+%YBodp22|sWzAq&jq88!sTQ5=iS;>Sy`YFqQMOTGu+@av<4x)eu~dl)0sbQpuPP+QF z>!DoRDL?na)@u}lE0efi7Tye$@%n1_C^IpJu9yITbDYK9X1E5=kIsf*8Q&9bgO;1H z`~i!0rDYEND#3o|jha#Lw4+fK@yix>InP0dXf{e+ThQ2XpgED68L2jJ)q9mSIwuRL z``B}7n33nchz0VyAhnq56$#Pol})J{w+1Z`^tz@Tz>)_c*XO^VB)MEu$PnLMKkBS*hXps&HU2&Q(lx&%-R@21E||vc-C02d>2j={ zpj@k=;qhaAB2;;8yUH}A-aPLr?)hffjB?RSfv zO_4L72ITWx05n$zKrD;kC_$%ZH*deJpQw3azl|V!zv0@^{6#5A>gFd8IDyf@K;@P2^`qy~U%>`Fo!ml0E$QL(HptWktVqZXz#My*0->Z;KU z|Eg(s$NJ+}in6vrajJWt_r1)erjKrII-U=*7(7Q>S6iYn^YnYEy-6`{k1=#$%gkD~ z{83&nY4C#43iDh|U`pu^Z`66fA(!=e@Q!FQyvG8*tVMSbN0-t4ofabD&yiSgGyJ3qLomGZxH%{zC>Ek{Mp$af@-!raz7wE;2(Jawr zK%l6Xtc$hEcs~OKO&4E0FbCK-5bqOga9XlIu?0jk7b2LnP zVB4UDz-(s^2gtC0pQ+x=TP^#wBn%G0l?dxcw zf5I1J_ZQYiiIZ$i=gEw?0b}s4^m7JQL;c~Fv%8C&db#nuZ10)Yc=?8bZ4p_Wp&y-l zksHGIc!v!v*-v3USfO=m=8xu0O=by=86!tBL>lx8PY|YIr6fv#0)`q1ot#9vM~b3G_It<4UK$pe;@7i$B0_X)3fImh~C zU;RuqM>|g***8y)XBHs&bT8e)k|=j!*3glS<1Qz*W&rkF5H4zEGOGE{Z$)BPKCt^cOcK=ZG9w}%IH#QS zaIs8gE9vtG)kF)`)5zjT!a4F@%B8RCObcRk6Pv1ps|j<(QZGmmJ4fKXFU9v#KM%`B zK7|sAhV{0s$tb@!jBa5cjXSEmD%u_l><4QPDx4jVKUq2aGv*GdSvV$9;7;netA zPDdq#YiFQ}5TaeRBsO!@E6iVfQZ0~pzisxG<}Ay9o6FO>B=utYx70s`31Gk-vN5)N z;|xGa8}MpZrl|w-Vf54d;dVnG$FeU&7FzOpJ4X?~QS+{(bnKqB6aMefH(eJE+H5 zCXqcn3mwZiCPfl1i)69{?aeS?cib2i?OyjsLdzF*ucN>Wm!<`6-_VRr#4brP8ub6xSxxJ2h?d9mY6@0nh^mC-ZerYz(H zV@K)+@9E~KB^v)EE=)7uGzh7EQUw_9r;$X5oTQ+Yd1*sU7-Zvb(I{>yxjVGS({D*f zeKz%t=>dw$Y{p1n#NwL`-gXT*NRr0@4r7BhkGqaGfDee=iJIYOLd*ASrP`c6hyzW( zMzx|~dS?}8_PwS~ugXPw2cCq1NTANfe$kMhU<50Ue;tLLoO}`05M7SwU=_4wm>jew zP3RMQTu&3I9j2C5)%oC;XPSfjRq$eCG|rZwrm-@0XUy9!uDE!|Le+eFv}OE{acZY$ zkf!*uJSJ;B?yoXZ()_3*yJl>4*SjQpo$ZMMPYBn`@!X8W6PJhkX9RhJP9csde-CHM z^Teo-ca+n+_}Mwvz#WN7G-|E0$tw56sA-inzGeaqKjX%a8Mq84Nxzus#0!%0a>+H) z{*GlGX_@_8ea1Xbp$_G%6~~8xs`dW` zzf^clMk#6e1-_=HBMmO zS|4tGX4k4ftp@AgC@M6>`CAL%xvy)Z$C(W$T({5YLUnF8gc+?Dx138_Y|L2E_tAok zWGDSe){I{nZXVcb0I=ab*a#~yXBZXi80VoCP|VBOhN@LR9L}w$;RA-LiBcH)w1B=> zp}8RQw{lBNZWpUceI@XX7eLA>YNV5f?dy9l zi6BEC(JL&xwCC#@ox{a;+F;-Ez|%sygnY)T77E!W~CkwNEU zaty=^b2j}6?o)$;1})C8=Y7D~!!m5HS@=8wt!}smIdJ3;1xiAkUGvfHxE6NuA3R@L z#`Szg%;U+ldBqcQ*XV$+)0~UC8T`KjP*m(Cy-;J066qm!?2zlcW%jJSnQl4AiV(75 z9J^Hp9HN~A!J6laS1!JQT9IBe-AEwPf2v-p*={!?HIiTsm48~-{@U-|IUagf4BB(> zp9UV3rc^q+w$#8F)KafKLKSC_>+rh1=UJm1da)fVQ$JySr}`{bpH@*UEA}sC|hOUM8mB|0MWu<&fI` zUlM9!e+w({7-T4eyFQ$vD>7qXVvN9cYYI8hYWx@zBO!Tl3nn-|LAZIcB1>Gr+KEiG~lj@j`M-7 z;aUy7MQ-PVFfF~s-17pkdLAVu)}w4L;dAS+SHg8Lv)_B#n+6{5mod?H$&%(fXUKc9 z>#s991WXgm*5&0-wz;z`RZIDC&QNFBIlI{)=UlIzJ9g2Dx8=d%07Kbzfxs79pVTm^ z)>vJH>HptI{8g#4@@*(#r}WMvppc}@h82_i$q zG2c+P|D9W`Vd06|M|0!e;|7;4zI7bw^s3$G{JZf(`u4V=h+yITy*fdW+> z?xgNm;p>>_j{*ewHF3Epz5b3{Rj^nf{UCu)*dy4fp|0$31fLw#6LN+a#V$OuSYw`z zaK{c*(0dyGU?7EAMBvC$o8|&GGd0%M12b_<;ikZp@z`M_dF;+{dkPFZ(&$jCm8Eu0 zkKkyWp}xv&wA1fPXJln;7)7AD>!GV}Mi#Z(f1Dc1VtM*(&ffn~d9JZ{(4Pv*ztLyDdtIai<`^J!Gcd1C8D_bQ>+;{^g= z-Z)RLd*6VgYRBos$LYg4QX{gny%KUT0x@b;QMcL@EY*%~GdyjO$=_9oW#9DLRe#eE zu0CM8ZZ7`tB4l74CxfDqx=V)0oWWYQ%9~MT-<3Ec#fCht-jZB;F8@!5t8Z=_lwzWm zdL?F)e2+NY&1J9tR5AJZe1(e8DKtu$QD(p~%x@K^1Xxjfdp<-Iac#f@^QxXgS2?qeC z5o#5rHJa?l7rEGqbrwvT)+)-wUv*;k$5*Od>w9rszdulEtn9+3-W~!;Cdg}ao`O}7 zxdYfpKx!KVa^r3p;9Jgf0biwba)sg5=Fe}wM)~VDiIO8&PuAwEO-bI!C0I|K)Y+}p zTLSZ!x(?#!z*NDZ+0zW)yD9g$ep|YMvytg>?=KFqAOnOC{RuA3434?O6+^eay^aC| zKbk3}BIOWm;T+uq((B36Q{;DFpeHk5O9=Uo7VNHeRTK>zMqf#VkP?Kk#k3}y10M>U zU?&~Wmhk1wf*L8W8Qw(if5;zwvQ}b~3sfEHjtM_ajzf0V=^Fi<)ogkk95ZDEi%)@x zi_X%cJDYCp4SOiMvB!01UwB7g4|qDZI6fy^*ZMssVHxU-Y5l&p7d55!KZT@)PZ;+B zJXuj`oix)~D!s@6W(Zit5^0DRDvL-u4>=+QJc>M<;pw=RZLyUp1QUWUrm4 zKCvdxrQW?$^E<`w9(Wb?zeWey(g-l`HK;Zz##fiL{$6&C2^~HeotsnIh*5V0H>rvQtH#&lL4);{b~=~l35XVmZ!!+gW`Enjn^Tm1NLaM zqPda~8^+5$UwbMn7?U3=I1dzA-ZZt3S|yUT@{DJ_V98PlC^*@aQLAr=C{h-_U%b^H z6DHfg-P~H$(&pYw^}^z`MxsjzxJiJ-w7P)i2-f+g*0;aP+Lhv@Q>a7n@>T%9-lj49 za6JZi+RUVkp}cab0&ZQasb53ee>cgU8Xi)-PL(_}Z);NE{OS~e6$< zqfDo}3KJ8bH`r*s1!SeBs0_iQv4h)BeX2N69zB|qP4P51Q(n8sc9$zmD8LOt;aHm`T}@S*x>q(iyANfA?s%UnulYB)807 z>N&F@SK2ZBfs@Wix?LB27d@HQ6|Agc1=rueIKX(hsEU~GmtwnO+71HUXG?AR6EM{t zd2{^Qe=Z&*68GTMR`O1idvn3F8?8Jf3{O&)k7iih;JXb<`02{=D9!iO8MO#sCee*J zwkIj23LEySoLFf#?<{rd^kmIr!g>_cmR-Lh3n=RMRlmD}`5@B%K0~_dK@q`-s)`Mm z^4l|2-unJZVNz_$M=1EGLQS;BG~psAfd8OL_WS#lk>aoxE|{2`?#;axZArG%+RfFU zyiyP`nmF|PRtj--iH7hqsIQx`4uO(2`xd9QIVfNH>Klh{-YXbN;5Fa&fcJ3qofGV$ z*I)RD3V&-IkR;FU#R;dx2@L$%j#f-R}`bRT*kl5w{{ZMf|`ziFB^*?s`taR3DAA6{$l?5|r6 z867W8{^VYm3hq1(`@=6UU4J%otVcm>2r(V{$Coa^&WZOskQf_E5Jd6xY~H=mlj%rX z9{LSk$?z`%em1SWDA`0^$J~5#L^*MDc8&s)>I7T-i|)d^0&DD#5?Xf7yps8756+RW zci6BXe#csP0EJM2;u+SFxB(hq)3NFl8K}Hbu{?H-XDIvr`wice6@`GUJF*>S%XZjK&&sMzoY@=~twdmT%pgCpUGFDBTtiQMwIqkl|TEcpg>=~{1v>C0{ zkEM{aFY8mjYCc4=sz60l&Lsn9`$%@{R+jU^P5wu;6J9Ex=K2m6O$Q58EnE=Rb%o0- z6P4j;4Xrx_O~KpmfCt|%H3#J1X~0VNjbLL^FQD^jk1V+rb+*|bzNggsOt?~ea_{B} zEIu3K&8)m06J0;K1pSLOPgFw&XSM~%Qxo{4@{K5NUXPIn9iIJ27Gv7F811JNV8nrN zn2^jgMOxWs#nby(#h*7|n|DE`F7ngAOvGcf+l8Up-sSA!V`tzyizD#h?KqkJIYG=VejpV zKHxst`UxFN&qu2bp&w@r2j06lzFN5`*u>u<vy`gXAPFRyF1DK2iJ^Sd0)_ss>o1KyRL{s(zKk4AJnV%|+-YN6GRtzdt# zV1K2uAZz&6iT6Ww6AmAifo(bIoc{f7*{mwI3AJO%K0V4UUbzNWgNc7J`L^4p|D%Lm z@^25`|7VW!jzhJAEjkkg>@VJQlRusHug-88w)a{!Oi7tsvIZnVhxF(i+Mka9nuLXS zdG1=Ra;oFSGj}T@xOFF88Vx*UkKl>>o8)LEnIp5RC^o_!mVNiJFf2LN1?;KsvqzS< z&uEd>W{yNOx($`;ij18=4-pdqotd<&o#Eav?G6tX?@IZLkwe};Y~ow(E2A8Q|C8d5 z9Gn%)xQ4QRbIMYI><}FYQQL=-JQWI@H?`JBq~j$ZJ`+05YD~5LA{D0@-35k7kAyl_ zMPcvx!_CsIO~g3b8U&Ln>i!BoADTFOc)UCQ@BT{z&fHyWlc=3;V8 z=$xmW20!VrFT!QdrfX03BlEh0*lOdSmkv=`ZnMdl)@FILtn#|?xczW|+5Wn;}_I04siKvAu0qu zZkVsDqiGkMZ81Mv1?JXiB8=-xJ3^c1Jpw*6ng_hauSfyV;oD^Dlvmruf3Vd#OzBAQ znveeVGVfi*uMVHX)dU@R0?ABB1ITehJknV;!x#R%e?`?(#W!6~AUx zp8s5E$=mPGpmoqfOZdGO?oq(veaZ)N*_?R?^PKI3=XW1gohw%6{aq;;3aYnlj|K-E zX;zP=?O&4{6Ao2e6bia-?Uou<_76C@HQSDlx+9Z@-&?072fs_7k;M){3k?Jd{j`{# zx6w59b^~TZ9~YE4y6MCgF>L_egiQG$$2>INb$|;^^;ows6wGnTb#xmUQ~0jlb_OV@ zCcios{U>hqY)mX}P~%t)33$ooBf;v9hJ_42^Dnw0+Y?qxp~sv%J8tzVJpElftIdQ@ z@#cus_Jl{n(e~G@zbquUdgS)uecXPbm%=dXLJ@LjV=*i1bF6cgwnPz`mO5eWKz}r% zuiN68-_A49kl$5`{4u{LYg$ zSDMvZ9p~r(H8~^DyimircAn2PE%h;WRFWiKch>VE{78{R=Vuc?yvU1w5gP%W8zzw0 za%8*p)B(2|-mP(=hJ+doza9y-gXh2QBp^sK5kV#hA!~l$uB7?%OT*rOoEmMTcYH=q z99S5uU*`0qYv^7~@J2>A0XiwN-Dxxi!wA%u=#I4$kaBi+U z9XIBE)RBw?{~%x-8=69MZ*+LU7UabO;I~#yh+6NKA!NAo-5xIXhxA-9kd&}~6&{1B2D!WR}Ic*X?}JkN8njX<^v%mBz9Gka@)-lLX+atb)* zA8&i*YtD1{jx0Mi_Q2r`Uq&Dyw&78SwPnYU+R`@o%d<)83%+I7-(&J*hH5W zFPJDs3%+tx8&Q~dDq4%p5vTf}1)jUy-;qZ5tL8@I7Z==sVx0hdj*6Lj`Mzl8 z2O|##Z+^RCqpz#jy1()@K6gNb)M6ku4s8BsltPlhM|n)C|MMJY#lu?y&pSiG<`2fp ziCkdt!HMt64H-7vr!9tjyS4-4svrjx5$KjVkM79h6{yfP&Q1b;+~~f=xH; zZ|rAZP5 z7PAG?Fytf8eI+@D^no1k1ME1`G02Q%xgePNcDtDC$ef5|k!zI{13t_4j<0O@xNKhA zIgSk7KclHauB9+^6Xq>%v-!j->rft(RbP%vaZ)^pH|BnF0H8d@^2kce*Bn6&zw;?< zt3bdp&ccP@U5?H5N}SyPHT6>We(1lIa=1NeDmcfIKT!>cs9QepBG0&mJhpbIR@zxU zUWaM<7!>XeX-7g4r+Dm0Qtb~+r~qrYY5k;PFZ>4BfixqfdDS+lrr@PW(rzt9#&Qi( zZ0gDV@97uHVWVC3K)N+YCFBgMD8+@{*c<&*^lw2}fY|^nBJe+HWS0wwrT})*My|4; z%+5ohKAV0mlFxw76xkv*i1rBk${yHILe7Jfz^b{Ri&-nYBb7K?KNWRSp!oPJHCz{d zPrYgm!>cu+TfVEU(|X{9Y05&148WGMs%uk?w1Ps}k%On~eNr03;=a{#_r*2Lx<#HK*EaQ0WzX&YP&28Lik66u~`zg+kMLf zVPcCdZaHkqZ=3Sk8$yG(Lxa8vZY&dgE99y&vaN#??%;$EJ7=G@lPgZQxH_0CmQZKdQN?9*&Wv#G_cAtX>F z6MqG(T`I1@=>JS_X)7EC`kGCg@y)w#jhw6y>XmQkary%c4Z!PZ80VGi)_kp2W^ob8 zB*?XGc1->c!rU)y?U_1e8e3JU@LVk}ZP@P>N&gF<(9o{1rSD34Is}Q)U z+VQBNJYJW7?@NLWWs?U-&~qii70exy6T5peq8aVpQ=p|5XBhxQjh!HC8R;uOgVzgK za5esl4u+k%FbXT}zML&?&ZQMurQ%rjS_xl#x@^U>pj}`jr8u%UX2OIk9FqqYE8bTB zXB@_lZxX~$(NKk(m|E|CtTWKaWuoH-THVsa;$M#r-OeeeN~mv6f5txcULE@dO z&*Yv;M*Oe|QAa7L?}QbJ5&$FXqlWROt+0~GsUvxz`~V?AadZAaVh_i5MIH+O z0);i;Z>U#sqpKa-XZFMwb^*)6we53{NWE0c4z^jW0vK&mRwH=uje_CUut~h)Y8-dz z<$k=7s5%IN#yR>J^S(N4-`l7WML!4;X`8g_K~JuKVVN+gidq2whAxd&-ssaHu1RgBL&7k? zq4GeNbP!3VwP447%p`N=W=3qbuJLtWZArtsbFP@!rk3eQnBvMiTy?Krn;DS+{>Nbo zsI8qBNpqyUZja|Azv{wk_af;)a**2|qLk^$DuDlqGeD>EJY%S9^Lq1u<4ss_f{s(I^VmEm~gx`aSgPg#3#)A1eGf9=3kNPFEbDNR~oZGBc+8 zEiMx7;?ECf2hQRJ*f%y_poG6TLq7 z^TY0W0UjJDq$e-ibtPv+w;g6M`rL+cUJ2k@>vLfB3;z`>CEX?R13USm^3N7T9LVCx zUOhM2RI1590L#i{@?@Svyh)@qHfuYk87ffvC7lS-an?#o`R|slL)H zB+rIg&;q}?GfyVMzCAK+tYB9-H%cQSz_x|jpI#19tbCUQ)nf^>ZN^UwADN8@CtK;J z@r%N|&3^~vt6}PCO59IwDc9aGA5AM=|0wzHbmiX?xZ4I;UQcjW<4kOn?n$ud+7P3` z|2F{_260^TbVub;ZHkKv1~{CJIwlL}T<~4yaVkpw==IJH_b!Zi#lB=#d+7}t*C0B* z+9m-)n@h_jzg|xaVw?0no6goEnF2pWls?@Mi1|_aasT9SmTf*_0 z@Xb8FEJdR^N^N4I1|sSIZlxWts-7dsOR{_*xY1lB4Wk$P;rXC8xD=-v-7=q+w8zVY zt=8i;_7BqCrP4zkymRgb$=fk;&}CP!mj`junwSdJBcXSuq&!!PYRtlf;1DVB$U2;Totcl*0Qiqqp70lh81u`{CIf?kqW#G=wLHK`K^ zKZG!1RC=5sQ!x@qr*FSVAbmB5?T7I0UhqWIEsO1V%-YhUMyFrGL~b=sUf`?1EIK3P zlF!VQ?ehg^Pc^Kn+NQwMhE9zgprg+)I@s++_9+r0?ul%Q#vAtDC)Q%dOv0vC%WCJB z0+N;64A}*pmM?EFo)-^)#l0OWrPU~$_-Z}Z{Qe+Tjr7REL zB%(Z;&S;J2yq$S>AMYpUh6j8I!P8<^Mx-2`YGo3QRJ6cF;`!FkzttvfSQg1K-t?z5 z#Bx%djeSmiE?wIjZsI713UA{%zO2Yl z>ihR(+&1OrI7R99DfI6=ksY^FPGJSY%jl6u6cHqC*B}?Qfo}p)IWbqWF=f(dZ|Ip5 z6V|`0`YqWRH0_52i59=ou!yuAneIs#3`x~R1-Zn$^^)DKOay|RlG zxDFG$nF}J5w%j6Qj{&h^CenP?*4wiqOYK)540ko07vwH+f~s&!W>}vo!dp`k0bxD@ z5&NM;FUS>5P`w%lN8tqf(ll%_jr(3b8gHA~9vJF^7}l|mPEqae`HoB)pLbjSbgjL^ zwk4t!`21HQ*0FcLeA(qsR5mw}a5dly0(%?Z>`jW!%9yc)t*cbSn|>T7;E#3gz1bro z&eVOp6U-=$L!|=CMvBMVCcOYM)gYCg17p!S+!d)jK9>Ox?Nht>$(Hb6d?}%{zj<%* zTHM>7^g)f8hHFiJ)9rLDpw;uc zbq&c&KnL@~C+SW_YW|=zbOR0Om0O)#7Chh{BE znl@#PSNCPZ>3S*^w+!5TOv*uE;R*Ki{;e71B_Xfx;Rkt{^#_jeZULq?!IbH5JKT|y zJH71Ev31fkS}OrP!xba+LkB`THOqRBDDtBH8H5QT6Ls^u8RFqOCXvuLr%_g=>4J#d zc$E>BhC|ja`r7jPuX`8&)=3+@aSKl#yHWWweD}?|njNMhIyQ-vI{*P9)J4y8=q(NI z_ZWg1J)=n1>%I#zAq4k1&`H!dOV61c+D^7PhOb&L9`u)e{) zUo;X9p6%%Ffw~)r{*|?JZQR%U@bo+8J~-o`_0{h+NeOj-3ms645zvR`Zdv_~?N*|N zj5l2ie+B5{^;Jodd!1jdOPQ71dnGWi$7gh(()?x0TX2eTeSNscP4m$saG|bMH?6<+ zvSmH@r(tzcLbx^wfJISc+=`^Iisc9{_OQlj26f1`Z&}|}@Tgt!d*9P0wWclBO|A|9 z>FC-P;8wNY{n};zVZxp{&<0c+X-Rxf#9RE8240>M#*+^=o3_lP-*6teeyi`Cl?baw zlPSqmpGzFmWJaLl5@$;UPhgP13N zxxd-nsf4VVISo zEeh+sO}+-$kS`l9;jAsQT`64=TSvtlwN>X>+^QwpP)J}s0|+Gy5B)|Jj0*bHThW3a z+{{F*D282zd{;lpUcX>g{?;moM}{LQiu^@$jsIP0zTY#z7S%*ht{-x8&#jBC4txzZ zN8U`7Y)$=QWpB+q4gBPc!}*Zol1Jv}GQYIVb$l*!OO*8<i2=Cp(RYh+dN!4tH z7S2!QAFXDrE&F6NjBe+$Y#`VhB^d=b%6@0L;GS+ZJpFD^UOtqf$>f>_x~(?%=HZ}rW+fjrS~7&jOpr3!@2aY;g_ ziYU`-!=KTpgjJxdylGkYry?J5$bVk>`{!_=QdmUN{d8Q2b!&_i&tUpd0sblN4G-fp zFCPGE!Y+$K9d_g8tWwXM!_;N1|Mq(TKlusm#?s){_MwF z=tyXFLZa%$iuOy9Z(iAX(%}b16DKteFS10p`sVs?{MF|=TI1hIon;!_BcG`>&$N(5 zW|@~c>F>7XgUn6UE%S&TD9S^Y-6`X?kD>XW5Lvi+ZCaOU0{kj0qJFHtsZKeEi9K2? z-2?IF%G#6r%V z&CtMy$OD_WYTn;t_d8^L{>wo#Y}YucC5{D>xCz0!Ek({%W>D(wfaK#_3VyH2$7s^D zU2wo649JNPX0O>(<7h{&ssl&_ek$0MM*tWzl8xIOcXd8>F8 z$$VO$CzsHZ%rTlvJ3zBZ820dI^jH~l!>m(+KO1UCOP5UL>EszlKEC(9N4cKbq0HQR zOCp#l#wWS*MNERWzrfX|KYg7+c;kxf-=2$IDT!`oj#8uvE~!O8d#&Pn<>gS+ z8E^fjYH&vK58LUbTrkta)O0=vw`bS2l=6TB;%*>I8^y9^BljUTzSFN>j8%Bg=d{*v z{X{)AcGkeB)MNi!?T_HRN8cFEns)dzuvfZqJx^QKcx|_>|5B+~1d~-vdRks?`*)TF z!6w+?QS?(uac!x`xr^Sevhy*bu@7~4!&0f}?F{)KBATC)?Ujod=Y z9`lM@&X|+zmT|?4Nv2R{KD{MH%#RnT917VdTmC)4=j+X?4HiSoa0nOd{tD$Irl07j zSFb3A6EGFri0C^>c3s$*L9Z{^G-{tp^GOHT4U6wh8UN+u#wA@WhscQVeuL^=LbGib zS*8c-T)(!cO8H-z6`%>JZl2?%sZn-I?1GpEfT zYQ1W4V7?r>&l7LcKR@xE89FcJCMVT8dUu>gI4~bs?lZwXD*==|A8Vo%qJn5u+S0W6 z)uORannkoE>E8m+s!8X`h)JhRrH}VA+JTR|N~=!b*N4j_>B*m*#npYExklE6onv4x zjqUQ6(v%lZc&$ns+3L&X02r6W>FewVJS{BGw6>YR!bSR+xaIiDkpSezJ_Xp?u!M)* zf%ycMX=>b&XWlBH{;QZkfKj-I#jqo*P+(Gf_1LfD#j9a&k4PbYT|2yi_lZ-|_|N(d z>x+F`x7Zr9HZ9)}FoVpXoZSbijY^n0g;z57e)j-h5O0Dn$gfbyMt^Y61QM3HT?+>~ z_u!vxE420Prgcb4aY|wFZw;E0{!XvF%mJ(Q$EsYn^rKMl>VS;RdzC!<*`dhe(F+kV zuj@Zi;w|&--_N01g|FEMBFR}8P1|Yc+2Je%qzC){*hPYeKZG*0|PR{!Gx@)afAQ>#Wi0o|`}DtoqE7z`T4QpJt?pMMMzlfWZep7i??%hMjeuIsn8-3X!Cbu8NHeH za2v|fot#rXmA!+ysA4qbe7jToQs^T)E)61iU4W1N+$Fdhy2L2_=rZ<<@{SnYYD5q1AZh7517Y4 z)s9d~yX$@(vUJW%ohd_sxkI?LJugLp_32?u%Izc6m#Nb6y+!A*bbq)L$GT#|E4}1m zmT_TkVkY&D$7rg4hy4Y1VO&vd4d8_X)xovX7 zxNY}!2U)hUzKI+1S7w`l8y1wn|AZ-IFPL|J&{}EXtfEMN%O30~AO2HOoH;%?c_~}h z>1e5>GguX&wbbhR>QyjQUeWSn@ZXx<6c4t(4NGyF@QUGZ4*U@&rot)pmK!hezO{58 zm_0XWT{$cM=L&901`&7fEIw%#sW`cgx$*(&Sh!5SrS|0cgt(5c_D;02gxT1Vh&g57 zXk6YCs`{=c^#5b_7qJO`z~*3eUnFc@81{W|AiuqBrQ;dxw`U*yQSUO?(T=3hRSPw5 zxr}pS?2#22WwHSs64(-Xgp6=VMcUyj9^!1|oknJ9rsJ`W%R^0(Ma+n#xWxW^(NDe0 zrrp;u`ol_?BAx zOba~r3^w-;JWCd3p2OXt;8%0Sz`S(U;$v8Ks_i62dR1||Z@x&m9J=kxVY7sDQv&gn zj{As`e7H~Z>i4HV6B?d^VRWQU4`j1H*exY=K3P)EdAS2on#DS$KI811ZtY~|F-4OA z_CL4p0i($QpY3u=7Rw=ryZ@UZONWrb4oW(ih8N!o&s=XEweNV<3s;n2fjH-8`HN9y zQuLmh3($RG_sQN_eAt6_Jh2?m){8RLTbZk1CZ3OjXDw(5)^0UrpXg#KVRc$mGC(Wrob6a?p2oESM5_b z-%vVl{rghv7i^Pl58wep&prOK<{@nIDD#m#OQNsasfBUB`#6q}oP+%3reF`OiU7wm za$}*UhTgcu9&(c8`TCyBF=K#K7Q0HOGTL$lWoEC-j7cG#mRM?#@gF=d`bwYy<4A_uBfa&j8g5Vy z17o3k#sVae-}S+#K`{&Pe6|})k#*r!opw|d<@93?|%7kS-u3TdPsm;N|XF@TPBiav7EBZ*zrc8mFhp#jZ z0uc>>Uk0^5K-tQs5^_CKsP$6lYYD~kyXwZVLeGjNBPdIL?|)4@53!lWQk=|PNMVj% zkaEWI^$zo{y16cWQlax$N)jnm$#Bq02?b>MlRWTc(itB927)a>cEv0PkK^??h zi2&b3fu5Z~%TEbCkDi?Lq~=y|^2P(_}H zvn(ncZDw_I?>Zy+^LQ#ALm&y$EZO3j{NK6>^W);;bh*xRh?=8BafKj%$1c9TH3TgZ1uJ*z(K5DOXA z3Pg#%90SV8ggW4X&VecU2bt zuMpwRq$!CmslOkzP;v&6>^iMT^>y;wcS2WtE(N;fpelPwW!W`qUweaCp~S-2ntjz_ zWhhOWoWJ-fh`J2gBZxKI<#=_*V0G-Y>CfnEfjQp_Q}%IVo3DL^B}nhuQgP`8h|>2x zoKD1;rf}U&!q_z&Y{TMc0h5m`nrs+m-NE-RKVH)JAIWi+PBw?4fJ_@ z#aGZmOlR0?l9cV|xRYOq*ad@bsAdrvB(L@0&sOrd(g2~xmfka(Xe}Pf31_XxJ?T>7 z`*EIe^!y|czS*!xH%p!V==C?H6G~U*NwHIAwCau;7m~8oe<=Q@3!;nkC?QJi*iI1I zCRS@VN35c#_f|Mci@t6oZvD;Qj5k`j9b?opXROJeqfu9n+ge4zVfU+gZpx=-Gmq)HKrsUXXPr z{L)v2Vx~_8%0Mnjl)6aJ=i^A>2 zy~3KHly8rMq)L%w0zsBWjSJPK)R4~J`5%1*iVDD-9!+n{TW zseuQXV34U%(L#PH6{PbHYW!dSvxHNWpFkP`Mbp>y6?fjb=l62v3%%|g|93NrU!{%eB-UD|ISxSWi zYOaL)%ccdhi%nx%G6rx*%y%PF$mM=H8I(KE^&eJi?BZm1E+-y+G^9Qkt-D9Q?t6q16KqgOy&~}EdXF8*e zdDo#f-`(@(5(u5&zv66Q7tA!qwk8rQqm^AdqfJA9MvI0%w8BK?VmDMM;Ti~E0LX@Y zwF(TnCBc?z1Rz5s9=e}SEok_Z$-OT(L?#xcWyWDZ%0mhcYG`|(T)if7S-yr8wm&>O z?UR4saQ(Vuc=?S1CSRuFbRsYDlaCdqO$yGYTNE}Uh-1%3(fMDR;BkDpfaRpNqsXwo znVZ|!ng00Grk_};rK1BVH!|M=LZ=AB4>NdWW#6s1@14AWt!LMfETy{W$|9G`Vfyjy z&JwprsZwH%C`9S`*7WR|9`20#Rw6oUN7J>(m%c1x5DSDa1k|x7dTOlAE+*`8YrA!*m1n?hO)%Ps=8wq@0@$;0E zPnzsJ{Ps<>zc0(pJqipW6PzT~j0*FlSG_vhNY$_Rma#Gu7LCiSIPJlv9&7u;J3BeS^t_NrLC_HpPtcl#C-|4-dLTQENLKO>MRPy2L}) z9b+RX|4bmXHFM14V$5BIKIF37)byQX;vnFhhZxzO%8#EO1*bdsN1sPGPm9l!)YL|O zbpwIq!}BIwO_a$$#))VRI*Ucq(L@UeF$wR*TH!Nr)~9uI2cva&?zc4+?#wR*9%79- zi5LRl7OX-sL?#?$auB3&JVS_Hypfh`!bt%{h-YczyV$DR_@&YDliGri&NdYa^XvAP zUB3-oGXGZ$6w+uwVQby_8f!ia`(N8`x{=n4F(Ri1KK@wNwCfJO3M~{Eso;|JPt0O_xil&-btFE9AE^SClFjRo!Kq&B*5jPLJ@&GphVx z&eaoN((62d9wdk_s!BvEAGqcHxN=eo5wZ_B6{ZF`5Dz@y`W%!%JN_{wluqRlk6^y> z*_SIu=KL3LpEM8Kaz&X$&^sqw8d@U1N<2E?jm)QXDd*J5IoQ9FwGf$J(9+{~L6yh+ z4$H}JeIE;X8LDF9lmGq9SBYXK@^X}BRZ85d_erO`n`6{?(;O$V(Gx+iWCE$FI zp8zVZ6-uC+_H`cat<8Q-Xh(doq8i(Dt|!#-S5ZZq`a zCPvn~)1OWnA-JnCS_%|K+wCO^Rc^QbwIV6F4!JG9O$LdV3cdN)NI+W;_w#K(`I9iY4wWe>bBDGpFiPW@|k)jRv@>}>k=*yu9#O_?(q_3X+guO3JJ z8JFI&O_iu0E;csUa}d6@*~X;t?{{KMCX#{7s=UE96G@Z9hxDiTVz1MATZjG^j?UQi nuxmBTJ6Y+ll0437Z literal 0 HcmV?d00001 diff --git a/modules/admin/src/KonSoft.Admin.Application.Contracts/AdminApplicationContractsModule.cs b/modules/admin/src/KonSoft.Admin.Application.Contracts/AdminApplicationContractsModule.cs new file mode 100644 index 0000000..a4da8ef --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Application.Contracts/AdminApplicationContractsModule.cs @@ -0,0 +1,28 @@ +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Admin; + +[DependsOn( + typeof(AdminDomainSharedModule), + typeof(AbpAccountApplicationContractsModule), + typeof(AbpFeatureManagementApplicationContractsModule), + typeof(AbpIdentityApplicationContractsModule), + typeof(AbpPermissionManagementApplicationContractsModule), + typeof(AbpSettingManagementApplicationContractsModule), + typeof(AbpTenantManagementApplicationContractsModule), + typeof(AbpObjectExtendingModule) +)] +public class AdminApplicationContractsModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + AdminDtoExtensions.Configure(); + } +} diff --git a/modules/admin/src/KonSoft.Admin.Application.Contracts/AdminDtoExtensions.cs b/modules/admin/src/KonSoft.Admin.Application.Contracts/AdminDtoExtensions.cs new file mode 100644 index 0000000..2b4f57c --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Application.Contracts/AdminDtoExtensions.cs @@ -0,0 +1,28 @@ +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.Admin; + +public static class AdminDtoExtensions +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can add extension properties to DTOs + * defined in the depended modules. + * + * Example: + * + * ObjectExtensionManager.Instance + * .AddOrUpdateProperty("Title"); + * + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Object-Extensions + */ + }); + } +} diff --git a/modules/admin/src/KonSoft.Admin.Application.Contracts/KonSoft.Admin.Application.Contracts.csproj b/modules/admin/src/KonSoft.Admin.Application.Contracts/KonSoft.Admin.Application.Contracts.csproj new file mode 100644 index 0000000..21d8796 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Application.Contracts/KonSoft.Admin.Application.Contracts.csproj @@ -0,0 +1,25 @@ + + + + + + net8.0 + enable + KonSoft.Admin + + + + + + + + + + + + + + + + + diff --git a/modules/admin/src/KonSoft.Admin.Application.Contracts/Permissions/AdminPermissionDefinitionProvider.cs b/modules/admin/src/KonSoft.Admin.Application.Contracts/Permissions/AdminPermissionDefinitionProvider.cs new file mode 100644 index 0000000..c11e790 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Application.Contracts/Permissions/AdminPermissionDefinitionProvider.cs @@ -0,0 +1,20 @@ +using KonSoft.Admin.Localization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; + +namespace KonSoft.Admin.Permissions; + +public class AdminPermissionDefinitionProvider : PermissionDefinitionProvider +{ + public override void Define(IPermissionDefinitionContext context) + { + var myGroup = context.AddGroup(AdminPermissions.GroupName); + //Define your own permissions here. Example: + //myGroup.AddPermission(AdminPermissions.MyPermission1, L("Permission:MyPermission1")); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/modules/admin/src/KonSoft.Admin.Application.Contracts/Permissions/AdminPermissions.cs b/modules/admin/src/KonSoft.Admin.Application.Contracts/Permissions/AdminPermissions.cs new file mode 100644 index 0000000..5fe4774 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Application.Contracts/Permissions/AdminPermissions.cs @@ -0,0 +1,9 @@ +namespace KonSoft.Admin.Permissions; + +public static class AdminPermissions +{ + public const string GroupName = "Admin"; + + //Add your own permission names. Example: + //public const string MyPermission1 = GroupName + ".MyPermission1"; +} diff --git a/modules/admin/src/KonSoft.Admin.Application/AdminAppService.cs b/modules/admin/src/KonSoft.Admin.Application/AdminAppService.cs new file mode 100644 index 0000000..58ac913 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Application/AdminAppService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using KonSoft.Admin.Localization; +using Volo.Abp.Application.Services; + +namespace KonSoft.Admin; + +/* Inherit your application services from this class. + */ +public abstract class AdminAppService : ApplicationService +{ + protected AdminAppService() + { + LocalizationResource = typeof(AdminResource); + } +} diff --git a/modules/admin/src/KonSoft.Admin.Application/AdminApplicationAutoMapperProfile.cs b/modules/admin/src/KonSoft.Admin.Application/AdminApplicationAutoMapperProfile.cs new file mode 100644 index 0000000..4c9d249 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Application/AdminApplicationAutoMapperProfile.cs @@ -0,0 +1,13 @@ +using AutoMapper; + +namespace KonSoft.Admin; + +public class AdminApplicationAutoMapperProfile : Profile +{ + public AdminApplicationAutoMapperProfile() + { + /* You can configure your AutoMapper mapping configuration here. + * Alternatively, you can split your mapping configurations + * into multiple profile classes for a better organization. */ + } +} diff --git a/modules/admin/src/KonSoft.Admin.Application/AdminApplicationModule.cs b/modules/admin/src/KonSoft.Admin.Application/AdminApplicationModule.cs new file mode 100644 index 0000000..4b8589a --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Application/AdminApplicationModule.cs @@ -0,0 +1,31 @@ +using Volo.Abp.Account; +using Volo.Abp.AutoMapper; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Admin; + +[DependsOn( + typeof(AdminDomainModule), + typeof(AbpAccountApplicationModule), + typeof(AdminApplicationContractsModule), + typeof(AbpIdentityApplicationModule), + typeof(AbpPermissionManagementApplicationModule), + typeof(AbpTenantManagementApplicationModule), + typeof(AbpFeatureManagementApplicationModule), + typeof(AbpSettingManagementApplicationModule) + )] +public class AdminApplicationModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.AddMaps(); + }); + } +} diff --git a/modules/admin/src/KonSoft.Admin.Application/KonSoft.Admin.Application.csproj b/modules/admin/src/KonSoft.Admin.Application/KonSoft.Admin.Application.csproj new file mode 100644 index 0000000..c9569eb --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Application/KonSoft.Admin.Application.csproj @@ -0,0 +1,25 @@ + + + + + + net8.0 + enable + KonSoft.Admin + + + + + + + + + + + + + + + + + diff --git a/modules/admin/src/KonSoft.Admin.Application/Properties/AssemblyInfo.cs b/modules/admin/src/KonSoft.Admin.Application/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..12c97cf --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Application/Properties/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.Admin.Application.Tests")] diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/AdminDomainErrorCodes.cs b/modules/admin/src/KonSoft.Admin.Domain.Shared/AdminDomainErrorCodes.cs new file mode 100644 index 0000000..78050c5 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/AdminDomainErrorCodes.cs @@ -0,0 +1,6 @@ +namespace KonSoft.Admin; + +public static class AdminDomainErrorCodes +{ + /* You can add your business exception error codes here, as constants */ +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/AdminDomainSharedModule.cs b/modules/admin/src/KonSoft.Admin.Domain.Shared/AdminDomainSharedModule.cs new file mode 100644 index 0000000..e998a5d --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/AdminDomainSharedModule.cs @@ -0,0 +1,58 @@ +using KonSoft.Admin.Localization; +using Volo.Abp.AuditLogging; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Localization.ExceptionHandling; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; +using Volo.Abp.Validation.Localization; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.Admin; + +[DependsOn( + typeof(AbpAuditLoggingDomainSharedModule), + typeof(AbpBackgroundJobsDomainSharedModule), + typeof(AbpFeatureManagementDomainSharedModule), + typeof(AbpIdentityDomainSharedModule), + typeof(AbpOpenIddictDomainSharedModule), + typeof(AbpPermissionManagementDomainSharedModule), + typeof(AbpSettingManagementDomainSharedModule), + typeof(AbpTenantManagementDomainSharedModule) + )] +public class AdminDomainSharedModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + AdminGlobalFeatureConfigurator.Configure(); + AdminModuleExtensionConfigurator.Configure(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddBaseTypes(typeof(AbpValidationResource)) + .AddVirtualJson("/Localization/Admin"); + + options.DefaultResourceType = typeof(AdminResource); + }); + + Configure(options => + { + options.MapCodeNamespace("Admin", typeof(AdminResource)); + }); + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/AdminGlobalFeatureConfigurator.cs b/modules/admin/src/KonSoft.Admin.Domain.Shared/AdminGlobalFeatureConfigurator.cs new file mode 100644 index 0000000..4ca98e9 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/AdminGlobalFeatureConfigurator.cs @@ -0,0 +1,22 @@ +using Volo.Abp.Threading; + +namespace KonSoft.Admin; + +public static class AdminGlobalFeatureConfigurator +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can configure (enable/disable) global features of the used modules here. + * + * YOU CAN SAFELY DELETE THIS CLASS AND REMOVE ITS USAGES IF YOU DON'T NEED TO IT! + * + * Please refer to the documentation to lear more about the Global Features System: + * https://docs.abp.io/en/abp/latest/Global-Features + */ + }); + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/AdminModuleExtensionConfigurator.cs b/modules/admin/src/KonSoft.Admin.Domain.Shared/AdminModuleExtensionConfigurator.cs new file mode 100644 index 0000000..5e99900 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/AdminModuleExtensionConfigurator.cs @@ -0,0 +1,73 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.Admin; + +public static class AdminModuleExtensionConfigurator +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + ConfigureExistingProperties(); + ConfigureExtraProperties(); + }); + } + + private static void ConfigureExistingProperties() + { + /* You can change max lengths for properties of the + * entities defined in the modules used by your application. + * + * Example: Change user and role name max lengths + + AbpUserConsts.MaxNameLength = 99; + IdentityRoleConsts.MaxNameLength = 99; + + * Notice: It is not suggested to change property lengths + * unless you really need it. Go with the standard values wherever possible. + * + * If you are using EF Core, you will need to run the add-migration command after your changes. + */ + } + + private static void ConfigureExtraProperties() + { + /* You can configure extra properties for the + * entities defined in the modules used by your application. + * + * This class can be used to define these extra properties + * with a high level, easy to use API. + * + * Example: Add a new property to the user entity of the identity module + + ObjectExtensionManager.Instance.Modules() + .ConfigureIdentity(identity => + { + identity.ConfigureUser(user => + { + user.AddOrUpdateProperty( //property type: string + "SocialSecurityNumber", //property name + property => + { + //validation rules + property.Attributes.Add(new RequiredAttribute()); + property.Attributes.Add(new StringLengthAttribute(64) {MinimumLength = 4}); + + property.Configuration[IdentityModuleExtensionConsts.ConfigurationNames.AllowUserToEdit] = true; + + //...other configurations for this property + } + ); + }); + }); + + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Module-Entity-Extensions + */ + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/KonSoft.Admin.Domain.Shared.csproj b/modules/admin/src/KonSoft.Admin.Domain.Shared/KonSoft.Admin.Domain.Shared.csproj new file mode 100644 index 0000000..10d847b --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/KonSoft.Admin.Domain.Shared.csproj @@ -0,0 +1,32 @@ + + + + + + net8.0 + enable + KonSoft.Admin + true + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/ar.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/ar.json new file mode 100644 index 0000000..6e22c84 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/ar.json @@ -0,0 +1,9 @@ +{ + "culture": "ar", + "texts": { + "AppName": "Admin", + "Menu:Home": "الصفحة الرئيسية", + "Welcome": "مرحباً", + "LongWelcomeMessage": "مرحبا بكم في التطبيق. هذا مشروع بدء تشغيل يعتمد على إطار عمل ABP. لمزيد من المعلومات ، يرجى زيارة abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/cs.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/cs.json new file mode 100644 index 0000000..f51319b --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/cs.json @@ -0,0 +1,9 @@ +{ + "culture": "cs", + "texts": { + "AppName": "Admin", + "Menu:Home": "Úvod", + "Welcome": "Vítejte", + "LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/de.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/de.json new file mode 100644 index 0000000..f61fc79 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/de.json @@ -0,0 +1,9 @@ +{ + "culture": "de", + "texts": { + "AppName": "Admin", + "Menu:Home": "Home", + "Welcome": "Willkommen", + "LongWelcomeMessage": "Willkommen bei der Anwendung. Dies ist ein Startup-Projekt, das auf dem ABP-Framework basiert. Weitere Informationen finden Sie unter abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/en-GB.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/en-GB.json new file mode 100644 index 0000000..12522c5 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/en-GB.json @@ -0,0 +1,9 @@ +{ + "culture": "en-GB", + "texts": { + "AppName": "Admin", + "Menu:Home": "Home", + "Welcome": "Welcome", + "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/en.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/en.json new file mode 100644 index 0000000..0beddd9 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/en.json @@ -0,0 +1,9 @@ +{ + "culture": "en", + "texts": { + "AppName": "Admin", + "Menu:Home": "Home", + "Welcome": "Welcome", + "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/es.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/es.json new file mode 100644 index 0000000..6cb7865 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/es.json @@ -0,0 +1,9 @@ +{ + "culture": "es", + "texts": { + "AppName": "Admin", + "Menu:Home": "Inicio", + "Welcome": "Bienvenido", + "LongWelcomeMessage": "Bienvenido a la aplicación, este es un proyecto base basado en el framework ABP. Para más información, visita abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/fi.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/fi.json new file mode 100644 index 0000000..f1fc483 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/fi.json @@ -0,0 +1,9 @@ +{ + "culture": "fi", + "texts": { + "AppName": "Admin", + "Menu:Home": "Koti", + "Welcome": "Tervetuloa", + "LongWelcomeMessage": "Tervetuloa sovellukseen. Tämä on ABP-kehykseen perustuva käynnistysprojekti. Lisätietoja on osoitteessa abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/fr.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/fr.json new file mode 100644 index 0000000..7210a33 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/fr.json @@ -0,0 +1,9 @@ +{ + "culture": "fr", + "texts": { + "AppName": "Admin", + "Menu:Home": "Accueil", + "Welcome": "Bienvenue", + "LongWelcomeMessage": "Bienvenue dans l'application. Il s'agit d'un projet de démarrage basé sur le framework ABP. Pour plus d'informations, visitez abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/hi.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/hi.json new file mode 100644 index 0000000..f0d0767 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/hi.json @@ -0,0 +1,9 @@ +{ + "culture": "hi", + "texts": { + "AppName": "Admin", + "Menu:Home": "घर", + "Welcome": "स्वागत हे", + "LongWelcomeMessage": "आवेदन करने के लिए आपका स्वागत है। यह एबीपी ढांचे पर आधारित एक स्टार्टअप परियोजना है। अधिक जानकारी के लिए, abp.io पर जाएं।" + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/hr.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/hr.json new file mode 100644 index 0000000..ad592b1 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/hr.json @@ -0,0 +1,9 @@ +{ + "culture": "hr", + "texts": { + "AppName": "Admin", + "Menu:Home": "Početna", + "Welcome": "Dobrodošli", + "LongWelcomeMessage": "Dobrodošli u aplikaciju. Ovo je startup projekt temeljen na ABP framework-u. Za više informacija posjetite abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/hu.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/hu.json new file mode 100644 index 0000000..fc9e6e7 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/hu.json @@ -0,0 +1,9 @@ +{ + "culture": "hu", + "texts": { + "AppName": "Admin", + "Menu:Home": "Kezdőlap", + "Welcome": "Üdvözlöm", + "LongWelcomeMessage": "Üdvözöljük az alkalmazásban. Ez egy ABP keretrendszeren alapuló startup projekt. További információkért látogasson el az abp.io oldalra." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/is.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/is.json new file mode 100644 index 0000000..1f29976 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/is.json @@ -0,0 +1,9 @@ +{ + "culture": "is", + "texts": { + "AppName": "Admin", + "Menu:Home": "Heim", + "Welcome": "Velkomin", + "LongWelcomeMessage": "Verið velkomin í forritið. Þetta er startup verkefni sem byggir á ABP. Nánari upplýsingar er að finna á abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/it.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/it.json new file mode 100644 index 0000000..8a50b61 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/it.json @@ -0,0 +1,9 @@ +{ + "culture": "it", + "texts": { + "AppName": "Admin", + "Menu:Home": "Home", + "Welcome": "Benvenuto", + "LongWelcomeMessage": "Benvenuto nell'applicazione. Questo è un progetto di avvio basato sul framework ABP. Per ulteriori informazioni, visita abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/nl.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/nl.json new file mode 100644 index 0000000..edfe06d --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/nl.json @@ -0,0 +1,9 @@ +{ + "culture": "nl", + "texts": { + "AppName": "Admin", + "Menu:Home": "Home", + "Welcome": "Welkom", + "LongWelcomeMessage": "Welkom bij de applicatie. Dit is een startup-project gebaseerd op het ABP-framework. Bezoek abp.io voor meer informatie." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/pl-PL.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/pl-PL.json new file mode 100644 index 0000000..c286219 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/pl-PL.json @@ -0,0 +1,9 @@ +{ + "culture": "pl-PL", + "texts": { + "AppName": "Admin", + "Menu:Home": "Home", + "Welcome": "Witaj", + "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/pt-BR.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/pt-BR.json new file mode 100644 index 0000000..017edcc --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/pt-BR.json @@ -0,0 +1,9 @@ +{ + "culture": "pt-BR", + "texts": { + "AppName": "Admin", + "Menu:Home": "Principal", + "Welcome": "Seja bem-vindo!", + "LongWelcomeMessage": "Bem-vindo a esta aplicação. Este é um projeto inicial baseado no ABP framework. Para mais informações, visite abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/ro-RO.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/ro-RO.json new file mode 100644 index 0000000..c137216 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/ro-RO.json @@ -0,0 +1,9 @@ +{ + "culture": "ro-RO", + "texts": { + "AppName": "Admin", + "Menu:Home": "Acasă", + "Welcome": "Bun venit", + "LongWelcomeMessage": "Bun venit la aplicaţie. Acesta este un proiect de pornire bazat pe framework-ul ABP. Pentru mai multe informaţii, vizitaţi, visit abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/ru.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/ru.json new file mode 100644 index 0000000..d359d4c --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/ru.json @@ -0,0 +1,9 @@ +{ + "culture": "ru", + "texts": { + "AppName": "Admin", + "Menu:Home": "Главная", + "Welcome": "Добро пожаловать", + "LongWelcomeMessage": "Добро пожаловать в приложение. Этот запущенный проект основан на фреймворке ABP. Для получения дополнительной информации посетите сайт abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/sk.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/sk.json new file mode 100644 index 0000000..5f5bf75 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/sk.json @@ -0,0 +1,9 @@ +{ + "culture": "sk", + "texts": { + "AppName": "Admin", + "Menu:Home": "Domov", + "Welcome": "Vitajte", + "LongWelcomeMessage": "Vitajte v aplikácii. Toto je štartovací projekt založený na ABP frameworku. Viac informácií nájdete na stránke abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/sl.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/sl.json new file mode 100644 index 0000000..c877729 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/sl.json @@ -0,0 +1,9 @@ +{ + "culture": "sl", + "texts": { + "AppName": "Admin", + "Menu:Home": "Domov", + "Welcome": "Dobrodošli", + "LongWelcomeMessage": "Dobrodošli v aplikaciji. To je začetni projekt na osnovi okolja ABP. Za več informacij obiščite abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/sv.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/sv.json new file mode 100644 index 0000000..bd1eae4 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/sv.json @@ -0,0 +1,9 @@ +{ + "culture": "sv", + "texts": { + "AppName": "MittProjektNamn", + "Menu:Home": "Hem", + "Welcome": "Välkommen", + "LongWelcomeMessage": "Välkommen till applikationen. Detta är ett startup-projekt baserat på ABP-ramverket. För mer information, besök abp.io." + } +} \ No newline at end of file diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/tr.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/tr.json new file mode 100644 index 0000000..12598cc --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/tr.json @@ -0,0 +1,9 @@ +{ + "culture": "tr", + "texts": { + "AppName": "Admin", + "Menu:Home": "Ana sayfa", + "Welcome": "Hoşgeldiniz", + "LongWelcomeMessage": "Uygulamaya hoşgeldiniz. Bu, ABP framework'ü üzerine bina edilmiş bir başlangıç projesidir. Daha fazla bilgi için abp.io adresini ziyaret edebilirsiniz." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/vi.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/vi.json new file mode 100644 index 0000000..0519f02 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/vi.json @@ -0,0 +1,9 @@ +{ + "culture": "vi", + "texts": { + "AppName": "Admin", + "Menu:Home": "Trang chủ", + "Welcome": "Chào mừng bạn", + "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án khởi nghiệp dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io." + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/zh-Hans.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/zh-Hans.json new file mode 100644 index 0000000..4e50081 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/zh-Hans.json @@ -0,0 +1,9 @@ +{ + "culture": "zh-Hans", + "texts": { + "AppName": "Admin", + "Menu:Home": "首页", + "Welcome": "欢迎", + "LongWelcomeMessage": "欢迎使用本应用程序。这是一个基于 ABP 框架的启动项目。更多信息,请访问 abp.io。" + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/zh-Hant.json b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/zh-Hant.json new file mode 100644 index 0000000..a45a089 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/Admin/zh-Hant.json @@ -0,0 +1,9 @@ +{ + "culture": "zh-Hant", + "texts": { + "AppName": "Admin", + "Menu:Home": "首頁", + "Welcome": "歡迎", + "LongWelcomeMessage": "歡迎來到此應用程式. 這是一個基於ABP框架的起始專案. 有關更多訊息, 請瀏覽 abp.io." + } + } diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/AdminResource.cs b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/AdminResource.cs new file mode 100644 index 0000000..71f6d84 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/Localization/AdminResource.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Localization; + +namespace KonSoft.Admin.Localization; + +[LocalizationResourceName("Admin")] +public class AdminResource +{ + +} diff --git a/modules/admin/src/KonSoft.Admin.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs b/modules/admin/src/KonSoft.Admin.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs new file mode 100644 index 0000000..1dbf8b3 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs @@ -0,0 +1,10 @@ +namespace KonSoft.Admin.MultiTenancy; + +public static class MultiTenancyConsts +{ + /* Enable/disable multi-tenancy easily in a single point. + * If you will never need to multi-tenancy, you can remove + * related modules and code parts, including this file. + */ + public const bool IsEnabled = true; +} diff --git a/modules/admin/src/KonSoft.Admin.Domain/AdminConsts.cs b/modules/admin/src/KonSoft.Admin.Domain/AdminConsts.cs new file mode 100644 index 0000000..976eacc --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain/AdminConsts.cs @@ -0,0 +1,8 @@ +namespace KonSoft.Admin; + +public static class AdminConsts +{ + public const string DbTablePrefix = "App"; + + public const string DbSchema = null; +} diff --git a/modules/admin/src/KonSoft.Admin.Domain/AdminDomainModule.cs b/modules/admin/src/KonSoft.Admin.Domain/AdminDomainModule.cs new file mode 100644 index 0000000..b6bbdb5 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain/AdminDomainModule.cs @@ -0,0 +1,68 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using KonSoft.Admin.MultiTenancy; +using Volo.Abp.AuditLogging; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Emailing; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.OpenIddict; +using Volo.Abp.PermissionManagement.Identity; +using Volo.Abp.PermissionManagement.OpenIddict; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Admin; + +[DependsOn( + typeof(AdminDomainSharedModule), + typeof(AbpAuditLoggingDomainModule), + typeof(AbpBackgroundJobsDomainModule), + typeof(AbpFeatureManagementDomainModule), + typeof(AbpIdentityDomainModule), + typeof(AbpOpenIddictDomainModule), + typeof(AbpPermissionManagementDomainOpenIddictModule), + typeof(AbpPermissionManagementDomainIdentityModule), + typeof(AbpSettingManagementDomainModule), + typeof(AbpTenantManagementDomainModule), + typeof(AbpEmailingModule) +)] +public class AdminDomainModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)")); + options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar")); + options.Languages.Add(new LanguageInfo("hr", "hr", "Croatian")); + options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish")); + options.Languages.Add(new LanguageInfo("fr", "fr", "Français")); + options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi")); + options.Languages.Add(new LanguageInfo("it", "it", "Italiano")); + options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); + options.Languages.Add(new LanguageInfo("ru", "ru", "Русский")); + options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak")); + options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); + options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch")); + options.Languages.Add(new LanguageInfo("es", "es", "Español")); + }); + + Configure(options => + { + options.IsEnabled = MultiTenancyConsts.IsEnabled; + }); + +#if DEBUG + context.Services.Replace(ServiceDescriptor.Singleton()); +#endif + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain/Data/AdminDbMigrationService.cs b/modules/admin/src/KonSoft.Admin.Domain/Data/AdminDbMigrationService.cs new file mode 100644 index 0000000..4b5626c --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain/Data/AdminDbMigrationService.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Admin.Data; + +public class AdminDbMigrationService : ITransientDependency +{ + public ILogger Logger { get; set; } + + private readonly IDataSeeder _dataSeeder; + private readonly IEnumerable _dbSchemaMigrators; + private readonly ITenantRepository _tenantRepository; + private readonly ICurrentTenant _currentTenant; + + public AdminDbMigrationService( + IDataSeeder dataSeeder, + IEnumerable dbSchemaMigrators, + ITenantRepository tenantRepository, + ICurrentTenant currentTenant) + { + _dataSeeder = dataSeeder; + _dbSchemaMigrators = dbSchemaMigrators; + _tenantRepository = tenantRepository; + _currentTenant = currentTenant; + + Logger = NullLogger.Instance; + } + + public async Task MigrateAsync() + { + var initialMigrationAdded = AddInitialMigrationIfNotExist(); + + if (initialMigrationAdded) + { + return; + } + + Logger.LogInformation("Started database migrations..."); + + await MigrateDatabaseSchemaAsync(); + await SeedDataAsync(); + + Logger.LogInformation($"Successfully completed host database migrations."); + + var tenants = await _tenantRepository.GetListAsync(includeDetails: true); + + var migratedDatabaseSchemas = new HashSet(); + foreach (var tenant in tenants) + { + using (_currentTenant.Change(tenant.Id)) + { + if (tenant.ConnectionStrings.Any()) + { + var tenantConnectionStrings = tenant.ConnectionStrings + .Select(x => x.Value) + .ToList(); + + if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings)) + { + await MigrateDatabaseSchemaAsync(tenant); + + migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings); + } + } + + await SeedDataAsync(tenant); + } + + Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations."); + } + + Logger.LogInformation("Successfully completed all database migrations."); + Logger.LogInformation("You can safely end this process..."); + } + + private async Task MigrateDatabaseSchemaAsync(Tenant? tenant = null) + { + Logger.LogInformation( + $"Migrating schema for {(tenant == null ? "host" : tenant.Name + " tenant")} database..."); + + foreach (var migrator in _dbSchemaMigrators) + { + await migrator.MigrateAsync(); + } + } + + private async Task SeedDataAsync(Tenant? tenant = null) + { + Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed..."); + + await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id) + .WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, IdentityDataSeedContributor.AdminEmailDefaultValue) + .WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, IdentityDataSeedContributor.AdminPasswordDefaultValue) + ); + } + + private bool AddInitialMigrationIfNotExist() + { + try + { + if (!DbMigrationsProjectExists()) + { + return false; + } + } + catch (Exception) + { + return false; + } + + try + { + if (!MigrationsFolderExists()) + { + AddInitialMigration(); + return true; + } + else + { + return false; + } + } + catch (Exception e) + { + Logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message); + return false; + } + } + + private bool DbMigrationsProjectExists() + { + var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath(); + + return dbMigrationsProjectFolder != null; + } + + private bool MigrationsFolderExists() + { + var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath(); + return dbMigrationsProjectFolder != null && Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations")); + } + + private void AddInitialMigration() + { + Logger.LogInformation("Creating initial migration..."); + + string argumentPrefix; + string fileName; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + argumentPrefix = "-c"; + fileName = "/bin/bash"; + } + else + { + argumentPrefix = "/C"; + fileName = "cmd.exe"; + } + + var procStartInfo = new ProcessStartInfo(fileName, + $"{argumentPrefix} \"abp create-migration-and-run-migrator \"{GetEntityFrameworkCoreProjectFolderPath()}\"\"" + ); + + try + { + Process.Start(procStartInfo); + } + catch (Exception) + { + throw new Exception("Couldn't run ABP CLI..."); + } + } + + private string? GetEntityFrameworkCoreProjectFolderPath() + { + var slnDirectoryPath = GetSolutionDirectoryPath(); + + if (slnDirectoryPath == null) + { + throw new Exception("Solution folder not found!"); + } + + var srcDirectoryPath = Path.Combine(slnDirectoryPath, "src"); + + return Directory.GetDirectories(srcDirectoryPath) + .FirstOrDefault(d => d.EndsWith(".EntityFrameworkCore")); + } + + private string? GetSolutionDirectoryPath() + { + var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory()); + + while (currentDirectory != null && Directory.GetParent(currentDirectory.FullName) != null) + { + currentDirectory = Directory.GetParent(currentDirectory.FullName); + + if (currentDirectory != null && Directory.GetFiles(currentDirectory.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null) + { + return currentDirectory.FullName; + } + } + + return null; + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain/Data/IAdminDbSchemaMigrator.cs b/modules/admin/src/KonSoft.Admin.Domain/Data/IAdminDbSchemaMigrator.cs new file mode 100644 index 0000000..d182021 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain/Data/IAdminDbSchemaMigrator.cs @@ -0,0 +1,8 @@ +using System.Threading.Tasks; + +namespace KonSoft.Admin.Data; + +public interface IAdminDbSchemaMigrator +{ + Task MigrateAsync(); +} diff --git a/modules/admin/src/KonSoft.Admin.Domain/Data/NullAdminDbSchemaMigrator.cs b/modules/admin/src/KonSoft.Admin.Domain/Data/NullAdminDbSchemaMigrator.cs new file mode 100644 index 0000000..0d1c758 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain/Data/NullAdminDbSchemaMigrator.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Admin.Data; + +/* This is used if database provider does't define + * IAdminDbSchemaMigrator implementation. + */ +public class NullAdminDbSchemaMigrator : IAdminDbSchemaMigrator, ITransientDependency +{ + public Task MigrateAsync() + { + return Task.CompletedTask; + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain/KonSoft.Admin.Domain.csproj b/modules/admin/src/KonSoft.Admin.Domain/KonSoft.Admin.Domain.csproj new file mode 100644 index 0000000..831a3a2 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain/KonSoft.Admin.Domain.csproj @@ -0,0 +1,28 @@ + + + + + + net8.0 + enable + KonSoft.Admin + + + + + + + + + + + + + + + + + + + + diff --git a/modules/admin/src/KonSoft.Admin.Domain/OpenIddict/OpenIddictDataSeedContributor.cs b/modules/admin/src/KonSoft.Admin.Domain/OpenIddict/OpenIddictDataSeedContributor.cs new file mode 100644 index 0000000..1e4c9a1 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain/OpenIddict/OpenIddictDataSeedContributor.cs @@ -0,0 +1,327 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Localization; +using OpenIddict.Abstractions; +using Volo.Abp; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.OpenIddict.Applications; +using Volo.Abp.OpenIddict.Scopes; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Uow; + +namespace KonSoft.Admin.OpenIddict; + +/* Creates initial data that is needed to property run the application + * and make client-to-server communication possible. + */ +public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDependency +{ + private readonly IConfiguration _configuration; + private readonly IOpenIddictApplicationRepository _openIddictApplicationRepository; + private readonly IAbpApplicationManager _applicationManager; + private readonly IOpenIddictScopeRepository _openIddictScopeRepository; + private readonly IOpenIddictScopeManager _scopeManager; + private readonly IPermissionDataSeeder _permissionDataSeeder; + private readonly IStringLocalizer L; + + public OpenIddictDataSeedContributor( + IConfiguration configuration, + IOpenIddictApplicationRepository openIddictApplicationRepository, + IAbpApplicationManager applicationManager, + IOpenIddictScopeRepository openIddictScopeRepository, + IOpenIddictScopeManager scopeManager, + IPermissionDataSeeder permissionDataSeeder, + IStringLocalizer l ) + { + _configuration = configuration; + _openIddictApplicationRepository = openIddictApplicationRepository; + _applicationManager = applicationManager; + _openIddictScopeRepository = openIddictScopeRepository; + _scopeManager = scopeManager; + _permissionDataSeeder = permissionDataSeeder; + L = l; + } + + [UnitOfWork] + public virtual async Task SeedAsync(DataSeedContext context) + { + await CreateScopesAsync(); + await CreateApplicationsAsync(); + } + + private async Task CreateScopesAsync() + { + if (await _openIddictScopeRepository.FindByNameAsync("Admin") == null) + { + await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor { + Name = "Admin", DisplayName = "Admin API", Resources = { "Admin" } + }); + } + } + + private async Task CreateApplicationsAsync() + { + var commonScopes = new List { + OpenIddictConstants.Permissions.Scopes.Address, + OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Phone, + OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Roles, + "Admin" + }; + + var configurationSection = _configuration.GetSection("OpenIddict:Applications"); + + + + + + + // Swagger Client + var swaggerClientId = configurationSection["Admin_Swagger:ClientId"]; + if (!swaggerClientId.IsNullOrWhiteSpace()) + { + var swaggerRootUrl = configurationSection["Admin_Swagger:RootUrl"]?.TrimEnd('/'); + + await CreateApplicationAsync( + name: swaggerClientId!, + type: OpenIddictConstants.ClientTypes.Public, + consentType: OpenIddictConstants.ConsentTypes.Implicit, + displayName: "Swagger Application", + secret: null, + grantTypes: new List { OpenIddictConstants.GrantTypes.AuthorizationCode, }, + scopes: commonScopes, + redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html", + clientUri: swaggerRootUrl + ); + } + } + + private async Task CreateApplicationAsync( + [NotNull] string name, + [NotNull] string type, + [NotNull] string consentType, + string displayName, + string? secret, + List grantTypes, + List scopes, + string? clientUri = null, + string? redirectUri = null, + string? postLogoutRedirectUri = null, + List? permissions = null) + { + if (!string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Public, + StringComparison.OrdinalIgnoreCase)) + { + throw new BusinessException(L["NoClientSecretCanBeSetForPublicApplications"]); + } + + if (string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, + StringComparison.OrdinalIgnoreCase)) + { + throw new BusinessException(L["TheClientSecretIsRequiredForConfidentialApplications"]); + } + + var client = await _openIddictApplicationRepository.FindByClientIdAsync(name); + + var application = new AbpApplicationDescriptor { + ClientId = name, + ClientType = type, + ClientSecret = secret, + ConsentType = consentType, + DisplayName = displayName, + ClientUri = clientUri, + }; + + Check.NotNullOrEmpty(grantTypes, nameof(grantTypes)); + Check.NotNullOrEmpty(scopes, nameof(scopes)); + + if (new[] { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }.All( + grantTypes.Contains)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken); + + if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeToken); + } + } + + if (!redirectUri.IsNullOrWhiteSpace() || !postLogoutRedirectUri.IsNullOrWhiteSpace()) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout); + } + + var buildInGrantTypes = new[] { + OpenIddictConstants.GrantTypes.Implicit, OpenIddictConstants.GrantTypes.Password, + OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.ClientCredentials, + OpenIddictConstants.GrantTypes.DeviceCode, OpenIddictConstants.GrantTypes.RefreshToken + }; + + foreach (var grantType in grantTypes) + { + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code); + } + + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || + grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization); + } + + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || + grantType == OpenIddictConstants.GrantTypes.ClientCredentials || + grantType == OpenIddictConstants.GrantTypes.Password || + grantType == OpenIddictConstants.GrantTypes.RefreshToken || + grantType == OpenIddictConstants.GrantTypes.DeviceCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Revocation); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Introspection); + } + + if (grantType == OpenIddictConstants.GrantTypes.ClientCredentials) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials); + } + + if (grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit); + } + + if (grantType == OpenIddictConstants.GrantTypes.Password) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password); + } + + if (grantType == OpenIddictConstants.GrantTypes.RefreshToken) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken); + } + + if (grantType == OpenIddictConstants.GrantTypes.DeviceCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.DeviceCode); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Device); + } + + if (grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdToken); + if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Token); + } + } + + if (!buildInGrantTypes.Contains(grantType)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.GrantType + grantType); + } + } + + var buildInScopes = new[] { + OpenIddictConstants.Permissions.Scopes.Address, OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Phone, OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Roles + }; + + foreach (var scope in scopes) + { + if (buildInScopes.Contains(scope)) + { + application.Permissions.Add(scope); + } + else + { + application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.Scope + scope); + } + } + + if (redirectUri != null) + { + if (!redirectUri.IsNullOrEmpty()) + { + if (!Uri.TryCreate(redirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) + { + throw new BusinessException(L["InvalidRedirectUri", redirectUri]); + } + + if (application.RedirectUris.All(x => x != uri)) + { + application.RedirectUris.Add(uri); + } + } + } + + if (postLogoutRedirectUri != null) + { + if (!postLogoutRedirectUri.IsNullOrEmpty()) + { + if (!Uri.TryCreate(postLogoutRedirectUri, UriKind.Absolute, out var uri) || + !uri.IsWellFormedOriginalString()) + { + throw new BusinessException(L["InvalidPostLogoutRedirectUri", postLogoutRedirectUri]); + } + + if (application.PostLogoutRedirectUris.All(x => x != uri)) + { + application.PostLogoutRedirectUris.Add(uri); + } + } + } + + if (permissions != null) + { + await _permissionDataSeeder.SeedAsync( + ClientPermissionValueProvider.ProviderName, + name, + permissions, + null + ); + } + + if (client == null) + { + await _applicationManager.CreateAsync(application); + return; + } + + if (!HasSameRedirectUris(client, application)) + { + client.RedirectUris = JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); + client.PostLogoutRedirectUris = JsonSerializer.Serialize(application.PostLogoutRedirectUris.Select(q => q.ToString().TrimEnd('/'))); + + await _applicationManager.UpdateAsync(client.ToModel()); + } + + if (!HasSameScopes(client, application)) + { + client.Permissions = JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString())); + await _applicationManager.UpdateAsync(client.ToModel()); + } + } + + private bool HasSameRedirectUris(OpenIddictApplication existingClient, AbpApplicationDescriptor application) + { + return existingClient.RedirectUris == JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); + } + + private bool HasSameScopes(OpenIddictApplication existingClient, AbpApplicationDescriptor application) + { + return existingClient.Permissions == JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString().TrimEnd('/'))); + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain/Properties/AssemblyInfo.cs b/modules/admin/src/KonSoft.Admin.Domain/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1ed25b9 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.Admin.Domain.Tests")] +[assembly:InternalsVisibleToAttribute("KonSoft.Admin.TestBase")] diff --git a/modules/admin/src/KonSoft.Admin.Domain/Settings/AdminSettingDefinitionProvider.cs b/modules/admin/src/KonSoft.Admin.Domain/Settings/AdminSettingDefinitionProvider.cs new file mode 100644 index 0000000..0920a30 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain/Settings/AdminSettingDefinitionProvider.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Settings; + +namespace KonSoft.Admin.Settings; + +public class AdminSettingDefinitionProvider : SettingDefinitionProvider +{ + public override void Define(ISettingDefinitionContext context) + { + //Define your own settings here. Example: + //context.Add(new SettingDefinition(AdminSettings.MySetting1)); + } +} diff --git a/modules/admin/src/KonSoft.Admin.Domain/Settings/AdminSettings.cs b/modules/admin/src/KonSoft.Admin.Domain/Settings/AdminSettings.cs new file mode 100644 index 0000000..1d1d09e --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.Domain/Settings/AdminSettings.cs @@ -0,0 +1,9 @@ +namespace KonSoft.Admin.Settings; + +public static class AdminSettings +{ + private const string Prefix = "Admin"; + + //Add your own setting names here. Example: + //public const string MySetting1 = Prefix + ".MySetting1"; +} diff --git a/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminDbContext.cs b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminDbContext.cs new file mode 100644 index 0000000..f78d79f --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminDbContext.cs @@ -0,0 +1,86 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.AuditLogging.EntityFrameworkCore; +using Volo.Abp.BackgroundJobs.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Identity; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.OpenIddict.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.TenantManagement; +using Volo.Abp.TenantManagement.EntityFrameworkCore; + +namespace KonSoft.Admin.EntityFrameworkCore; + +[ReplaceDbContext(typeof(IIdentityDbContext))] +[ReplaceDbContext(typeof(ITenantManagementDbContext))] +[ConnectionStringName("Default")] +public class AdminDbContext : + AbpDbContext, + IIdentityDbContext, + ITenantManagementDbContext +{ + /* Add DbSet properties for your Aggregate Roots / Entities here. */ + + #region Entities from the modules + + /* Notice: We only implemented IIdentityDbContext and ITenantManagementDbContext + * and replaced them for this DbContext. This allows you to perform JOIN + * queries for the entities of these modules over the repositories easily. You + * typically don't need that for other modules. But, if you need, you can + * implement the DbContext interface of the needed module and use ReplaceDbContext + * attribute just like IIdentityDbContext and ITenantManagementDbContext. + * + * More info: Replacing a DbContext of a module ensures that the related module + * uses this DbContext on runtime. Otherwise, it will use its own DbContext class. + */ + + //Identity + public DbSet Users { get; set; } + public DbSet Roles { get; set; } + public DbSet ClaimTypes { get; set; } + public DbSet OrganizationUnits { get; set; } + public DbSet SecurityLogs { get; set; } + public DbSet LinkUsers { get; set; } + public DbSet UserDelegations { get; set; } + public DbSet Sessions { get; set; } + // Tenant Management + public DbSet Tenants { get; set; } + public DbSet TenantConnectionStrings { get; set; } + + #endregion + + public AdminDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + /* Include modules to your migration db context */ + + builder.ConfigurePermissionManagement(); + builder.ConfigureSettingManagement(); + builder.ConfigureBackgroundJobs(); + builder.ConfigureAuditLogging(); + builder.ConfigureIdentity(); + builder.ConfigureOpenIddict(); + builder.ConfigureFeatureManagement(); + builder.ConfigureTenantManagement(); + + /* Configure your own tables/entities inside here */ + + //builder.Entity(b => + //{ + // b.ToTable(AdminConsts.DbTablePrefix + "YourEntities", AdminConsts.DbSchema); + // b.ConfigureByConvention(); //auto configure for the base class props + // //... + //}); + } +} diff --git a/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminDbContextFactory.cs b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminDbContextFactory.cs new file mode 100644 index 0000000..9d63ad3 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminDbContextFactory.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; + +namespace KonSoft.Admin.EntityFrameworkCore; + +/* This class is needed for EF Core console commands + * (like Add-Migration and Update-Database commands) */ +public class AdminDbContextFactory : IDesignTimeDbContextFactory +{ + public AdminDbContext CreateDbContext(string[] args) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + + AdminEfCoreEntityExtensionMappings.Configure(); + + var configuration = BuildConfiguration(); + + var builder = new DbContextOptionsBuilder() + .UseNpgsql(configuration.GetConnectionString("Default")); + + return new AdminDbContext(builder.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../KonSoft.Admin.DbMigrator/")) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminEfCoreEntityExtensionMappings.cs b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminEfCoreEntityExtensionMappings.cs new file mode 100644 index 0000000..a41e0ac --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminEfCoreEntityExtensionMappings.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.Admin.EntityFrameworkCore; + +public static class AdminEfCoreEntityExtensionMappings +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + AdminGlobalFeatureConfigurator.Configure(); + AdminModuleExtensionConfigurator.Configure(); + + OneTimeRunner.Run(() => + { + /* You can configure extra properties for the + * entities defined in the modules used by your application. + * + * This class can be used to map these extra properties to table fields in the database. + * + * USE THIS CLASS ONLY TO CONFIGURE EF CORE RELATED MAPPING. + * USE AdminModuleExtensionConfigurator CLASS (in the Domain.Shared project) + * FOR A HIGH LEVEL API TO DEFINE EXTRA PROPERTIES TO ENTITIES OF THE USED MODULES + * + * Example: Map a property to a table field: + + ObjectExtensionManager.Instance + .MapEfCoreProperty( + "MyProperty", + (entityBuilder, propertyBuilder) => + { + propertyBuilder.HasMaxLength(128); + } + ); + + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities + */ + }); + } +} diff --git a/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminEntityFrameworkCoreModule.cs b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminEntityFrameworkCoreModule.cs new file mode 100644 index 0000000..ff52226 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/AdminEntityFrameworkCoreModule.cs @@ -0,0 +1,57 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Uow; +using Volo.Abp.AuditLogging.EntityFrameworkCore; +using Volo.Abp.BackgroundJobs.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.TenantManagement.EntityFrameworkCore; + +namespace KonSoft.Admin.EntityFrameworkCore; + +[DependsOn( + typeof(AdminDomainModule), + typeof(AbpIdentityEntityFrameworkCoreModule), + typeof(AbpOpenIddictEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpBackgroundJobsEntityFrameworkCoreModule), + typeof(AbpAuditLoggingEntityFrameworkCoreModule), + typeof(AbpTenantManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule) + )] +public class AdminEntityFrameworkCoreModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + + AdminEfCoreEntityExtensionMappings.Configure(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(options => + { + /* Remove "includeAllEntities: true" to create + * default repositories only for aggregate roots */ + options.AddDefaultRepositories(includeAllEntities: true); + }); + + Configure(options => + { + /* The main point to change your DBMS. + * See also AdminMigrationsDbContextFactory for EF Core tooling. */ + options.UseNpgsql(); + }); + + } +} diff --git a/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreAdminDbSchemaMigrator.cs b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreAdminDbSchemaMigrator.cs new file mode 100644 index 0000000..99dceb8 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreAdminDbSchemaMigrator.cs @@ -0,0 +1,34 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using KonSoft.Admin.Data; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Admin.EntityFrameworkCore; + +public class EntityFrameworkCoreAdminDbSchemaMigrator + : IAdminDbSchemaMigrator, ITransientDependency +{ + private readonly IServiceProvider _serviceProvider; + + public EntityFrameworkCoreAdminDbSchemaMigrator( + IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public async Task MigrateAsync() + { + /* We intentionally resolve the AdminDbContext + * from IServiceProvider (instead of directly injecting it) + * to properly get the connection string of the current tenant in the + * current scope. + */ + + await _serviceProvider + .GetRequiredService() + .Database + .MigrateAsync(); + } +} diff --git a/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/KonSoft.Admin.EntityFrameworkCore.csproj b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/KonSoft.Admin.EntityFrameworkCore.csproj new file mode 100644 index 0000000..ca32b8e --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/KonSoft.Admin.EntityFrameworkCore.csproj @@ -0,0 +1,31 @@ + + + + + + net8.0 + enable + KonSoft.Admin + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + diff --git a/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Migrations/20250908050617_Initial.Designer.cs b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Migrations/20250908050617_Initial.Designer.cs new file mode 100644 index 0000000..26bce1d --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Migrations/20250908050617_Initial.Designer.cs @@ -0,0 +1,2006 @@ +// +using System; +using KonSoft.Admin.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace KonSoft.Admin.Migrations +{ + [DbContext(typeof(AdminDbContext))] + [Migration("20250908050617_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("text"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("integer") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("smallint") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("uuid"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("EntityChangeId") + .HasColumnType("uuid"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsAbandoned") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("JobArgs") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)"); + + b.Property("JobName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LastTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("NextTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((byte)15); + + b.Property("TryCount") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((short)0); + + b.HasKey("Id"); + + b.HasIndex("IsAbandoned", "NextTryTime"); + + b.ToTable("AbpBackgroundJobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property("ValueType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("SourceTenantId") + .HasColumnType("uuid"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("TargetTenantId") + .HasColumnType("uuid"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique(); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("boolean") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("boolean") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("IpAddresses") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("LastAccessed") + .HasColumnType("timestamp without time zone"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("SignedIn") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("boolean"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("EndTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("StartTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("character varying(196)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("character varying(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ClientSecret") + .HasColumnType("text"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientUri") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JsonWebKeySet") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasColumnType("text"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedirectUris") + .HasColumnType("text"); + + b.Property("Requirements") + .HasColumnType("text"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Scopes") + .HasColumnType("text"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Descriptions") + .HasColumnType("text"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Resources") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AuthorizationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Payload") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("MultiTenancySide") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("boolean"); + + b.Property("IsInherited") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + + b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) + .WithMany() + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Migrations/20250908050617_Initial.cs b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Migrations/20250908050617_Initial.cs new file mode 100644 index 0000000..020c22d --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Migrations/20250908050617_Initial.cs @@ -0,0 +1,1156 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace KonSoft.Admin.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpAuditLogs", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationName = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + TenantName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ImpersonatorUserId = table.Column(type: "uuid", nullable: true), + ImpersonatorUserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ImpersonatorTenantId = table.Column(type: "uuid", nullable: true), + ImpersonatorTenantName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ExecutionTime = table.Column(type: "timestamp without time zone", nullable: false), + ExecutionDuration = table.Column(type: "integer", nullable: false), + ClientIpAddress = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + HttpMethod = table.Column(type: "character varying(16)", maxLength: 16, nullable: true), + Url = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + Exceptions = table.Column(type: "text", nullable: true), + Comments = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + HttpStatusCode = table.Column(type: "integer", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpBackgroundJobs", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + JobName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + JobArgs = table.Column(type: "character varying(1048576)", maxLength: 1048576, nullable: false), + TryCount = table.Column(type: "smallint", nullable: false, defaultValue: (short)0), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + NextTryTime = table.Column(type: "timestamp without time zone", nullable: false), + LastTryTime = table.Column(type: "timestamp without time zone", nullable: true), + IsAbandoned = table.Column(type: "boolean", nullable: false, defaultValue: false), + Priority = table.Column(type: "smallint", nullable: false, defaultValue: (byte)15), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpBackgroundJobs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpClaimTypes", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Required = table.Column(type: "boolean", nullable: false), + IsStatic = table.Column(type: "boolean", nullable: false), + Regex = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + RegexDescription = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatureGroups", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatures", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + GroupName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ParentName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + DefaultValue = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + IsVisibleToClients = table.Column(type: "boolean", nullable: false), + IsAvailableToHost = table.Column(type: "boolean", nullable: false), + AllowedProviders = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatures", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatureValues", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureValues", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpLinkUsers", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + SourceUserId = table.Column(type: "uuid", nullable: false), + SourceTenantId = table.Column(type: "uuid", nullable: true), + TargetUserId = table.Column(type: "uuid", nullable: false), + TargetTenantId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLinkUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ParentId = table.Column(type: "uuid", nullable: true), + Code = table.Column(type: "character varying(95)", maxLength: 95, nullable: false), + DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGrants", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGrants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGroups", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + GroupName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ParentName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsEnabled = table.Column(type: "boolean", nullable: false), + MultiTenancySide = table.Column(type: "smallint", nullable: false), + Providers = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + StateCheckers = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpRoles", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsDefault = table.Column(type: "boolean", nullable: false), + IsStatic = table.Column(type: "boolean", nullable: false), + IsPublic = table.Column(type: "boolean", nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSecurityLogs", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ApplicationName = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + Identity = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + Action = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + TenantName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientIpAddress = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSecurityLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSessions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + SessionId = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Device = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + DeviceInfo = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + UserId = table.Column(type: "uuid", nullable: false), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + IpAddresses = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + SignedIn = table.Column(type: "timestamp without time zone", nullable: false), + LastAccessed = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSessions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSettingDefinitions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + DefaultValue = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + IsVisibleToClients = table.Column(type: "boolean", nullable: false), + Providers = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + IsInherited = table.Column(type: "boolean", nullable: false), + IsEncrypted = table.Column(type: "boolean", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettingDefinitions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSettings", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpTenants", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUserDelegations", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + SourceUserId = table.Column(type: "uuid", nullable: false), + TargetUserId = table.Column(type: "uuid", nullable: false), + StartTime = table.Column(type: "timestamp without time zone", nullable: false), + EndTime = table.Column(type: "timestamp without time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserDelegations", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUsers", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedUserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + Surname = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + Email = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedEmail = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + EmailConfirmed = table.Column(type: "boolean", nullable: false, defaultValue: false), + PasswordHash = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + SecurityStamp = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsExternal = table.Column(type: "boolean", nullable: false, defaultValue: false), + PhoneNumber = table.Column(type: "character varying(16)", maxLength: 16, nullable: true), + PhoneNumberConfirmed = table.Column(type: "boolean", nullable: false, defaultValue: false), + IsActive = table.Column(type: "boolean", nullable: false), + TwoFactorEnabled = table.Column(type: "boolean", nullable: false, defaultValue: false), + LockoutEnd = table.Column(type: "timestamp with time zone", nullable: true), + LockoutEnabled = table.Column(type: "boolean", nullable: false, defaultValue: false), + AccessFailedCount = table.Column(type: "integer", nullable: false, defaultValue: 0), + ShouldChangePasswordOnNextLogin = table.Column(type: "boolean", nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + LastPasswordChangeTime = table.Column(type: "timestamp with time zone", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictApplications", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ClientId = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + ClientSecret = table.Column(type: "text", nullable: true), + ClientType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ConsentType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + DisplayName = table.Column(type: "text", nullable: true), + DisplayNames = table.Column(type: "text", nullable: true), + JsonWebKeySet = table.Column(type: "text", nullable: true), + Permissions = table.Column(type: "text", nullable: true), + PostLogoutRedirectUris = table.Column(type: "text", nullable: true), + Properties = table.Column(type: "text", nullable: true), + RedirectUris = table.Column(type: "text", nullable: true), + Requirements = table.Column(type: "text", nullable: true), + Settings = table.Column(type: "text", nullable: true), + ClientUri = table.Column(type: "text", nullable: true), + LogoUri = table.Column(type: "text", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictApplications", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictScopes", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Description = table.Column(type: "text", nullable: true), + Descriptions = table.Column(type: "text", nullable: true), + DisplayName = table.Column(type: "text", nullable: true), + DisplayNames = table.Column(type: "text", nullable: true), + Name = table.Column(type: "character varying(200)", maxLength: 200, nullable: true), + Properties = table.Column(type: "text", nullable: true), + Resources = table.Column(type: "text", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictScopes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpAuditLogActions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + AuditLogId = table.Column(type: "uuid", nullable: false), + ServiceName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + MethodName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Parameters = table.Column(type: "character varying(2000)", maxLength: 2000, nullable: true), + ExecutionTime = table.Column(type: "timestamp without time zone", nullable: false), + ExecutionDuration = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogActions", x => x.Id); + table.ForeignKey( + name: "FK_AbpAuditLogActions_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpEntityChanges", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + AuditLogId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ChangeTime = table.Column(type: "timestamp without time zone", nullable: false), + ChangeType = table.Column(type: "smallint", nullable: false), + EntityTenantId = table.Column(type: "uuid", nullable: true), + EntityId = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + EntityTypeFullName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityChanges_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(type: "uuid", nullable: false), + OrganizationUnitId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationU~", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpRoleClaims", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ClaimType = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpRoleClaims_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpTenantConnectionStrings", + columns: table => new + { + TenantId = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Value = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenantConnectionStrings", x => new { x.TenantId, x.Name }); + table.ForeignKey( + name: "FK_AbpTenantConnectionStrings_AbpTenants_TenantId", + column: x => x.TenantId, + principalTable: "AbpTenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserClaims", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ClaimType = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpUserClaims_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserLogins", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + LoginProvider = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ProviderKey = table.Column(type: "character varying(196)", maxLength: 196, nullable: false), + ProviderDisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserLogins", x => new { x.UserId, x.LoginProvider }); + table.ForeignKey( + name: "FK_AbpUserLogins_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + OrganizationUnitId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationU~", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserRoles", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserTokens", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + LoginProvider = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Value = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AbpUserTokens_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictAuthorizations", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationId = table.Column(type: "uuid", nullable: true), + CreationDate = table.Column(type: "timestamp without time zone", nullable: true), + Properties = table.Column(type: "text", nullable: true), + Scopes = table.Column(type: "text", nullable: true), + Status = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + Subject = table.Column(type: "character varying(400)", maxLength: 400, nullable: true), + Type = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictAuthorizations_OpenIddictApplications_Application~", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AbpEntityPropertyChanges", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + EntityChangeId = table.Column(type: "uuid", nullable: false), + NewValue = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + OriginalValue = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + PropertyName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + PropertyTypeFullName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityPropertyChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityPropertyChanges_AbpEntityChanges_EntityChangeId", + column: x => x.EntityChangeId, + principalTable: "AbpEntityChanges", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictTokens", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationId = table.Column(type: "uuid", nullable: true), + AuthorizationId = table.Column(type: "uuid", nullable: true), + CreationDate = table.Column(type: "timestamp without time zone", nullable: true), + ExpirationDate = table.Column(type: "timestamp without time zone", nullable: true), + Payload = table.Column(type: "text", nullable: true), + Properties = table.Column(type: "text", nullable: true), + RedemptionDate = table.Column(type: "timestamp without time zone", nullable: true), + ReferenceId = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + Status = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + Subject = table.Column(type: "character varying(400)", maxLength: 400, nullable: true), + Type = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictTokens", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId", + column: x => x.AuthorizationId, + principalTable: "OpenIddictAuthorizations", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_AuditLogId", + table: "AbpAuditLogActions", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_TenantId_ServiceName_MethodName_Executio~", + table: "AbpAuditLogActions", + columns: new[] { "TenantId", "ServiceName", "MethodName", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_UserId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "UserId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpBackgroundJobs_IsAbandoned_NextTryTime", + table: "AbpBackgroundJobs", + columns: new[] { "IsAbandoned", "NextTryTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_AuditLogId", + table: "AbpEntityChanges", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_TenantId_EntityTypeFullName_EntityId", + table: "AbpEntityChanges", + columns: new[] { "TenantId", "EntityTypeFullName", "EntityId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityPropertyChanges_EntityChangeId", + table: "AbpEntityPropertyChanges", + column: "EntityChangeId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureGroups_Name", + table: "AbpFeatureGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_GroupName", + table: "AbpFeatures", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_Name", + table: "AbpFeatures", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureValues_Name_ProviderName_ProviderKey", + table: "AbpFeatureValues", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpLinkUsers_SourceUserId_SourceTenantId_TargetUserId_Targe~", + table: "AbpLinkUsers", + columns: new[] { "SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGrants_TenantId_Name_ProviderName_ProviderKey", + table: "AbpPermissionGrants", + columns: new[] { "TenantId", "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGroups_Name", + table: "AbpPermissionGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_GroupName", + table: "AbpPermissions", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_Name", + table: "AbpPermissions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoleClaims_RoleId", + table: "AbpRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoles_NormalizedName", + table: "AbpRoles", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Action", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Action" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_ApplicationName", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "ApplicationName" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Identity", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Identity" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_UserId", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_Device", + table: "AbpSessions", + column: "Device"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_SessionId", + table: "AbpSessions", + column: "SessionId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_TenantId_UserId", + table: "AbpSessions", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettingDefinitions_Name", + table: "AbpSettingDefinitions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettings_Name_ProviderName_ProviderKey", + table: "AbpSettings", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_Name", + table: "AbpTenants", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserClaims_UserId", + table: "AbpUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserLogins_LoginProvider_ProviderKey", + table: "AbpUserLogins", + columns: new[] { "LoginProvider", "ProviderKey" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserRoles_RoleId_UserId", + table: "AbpUserRoles", + columns: new[] { "RoleId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_Email", + table: "AbpUsers", + column: "Email"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedEmail", + table: "AbpUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedUserName", + table: "AbpUsers", + column: "NormalizedUserName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_UserName", + table: "AbpUsers", + column: "UserName"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictApplications_ClientId", + table: "OpenIddictApplications", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictAuthorizations_ApplicationId_Status_Subject_Type", + table: "OpenIddictAuthorizations", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictScopes_Name", + table: "OpenIddictScopes", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ApplicationId_Status_Subject_Type", + table: "OpenIddictTokens", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_AuthorizationId", + table: "OpenIddictTokens", + column: "AuthorizationId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ReferenceId", + table: "OpenIddictTokens", + column: "ReferenceId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpAuditLogActions"); + + migrationBuilder.DropTable( + name: "AbpBackgroundJobs"); + + migrationBuilder.DropTable( + name: "AbpClaimTypes"); + + migrationBuilder.DropTable( + name: "AbpEntityPropertyChanges"); + + migrationBuilder.DropTable( + name: "AbpFeatureGroups"); + + migrationBuilder.DropTable( + name: "AbpFeatures"); + + migrationBuilder.DropTable( + name: "AbpFeatureValues"); + + migrationBuilder.DropTable( + name: "AbpLinkUsers"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + + migrationBuilder.DropTable( + name: "AbpPermissionGrants"); + + migrationBuilder.DropTable( + name: "AbpPermissionGroups"); + + migrationBuilder.DropTable( + name: "AbpPermissions"); + + migrationBuilder.DropTable( + name: "AbpRoleClaims"); + + migrationBuilder.DropTable( + name: "AbpSecurityLogs"); + + migrationBuilder.DropTable( + name: "AbpSessions"); + + migrationBuilder.DropTable( + name: "AbpSettingDefinitions"); + + migrationBuilder.DropTable( + name: "AbpSettings"); + + migrationBuilder.DropTable( + name: "AbpTenantConnectionStrings"); + + migrationBuilder.DropTable( + name: "AbpUserClaims"); + + migrationBuilder.DropTable( + name: "AbpUserDelegations"); + + migrationBuilder.DropTable( + name: "AbpUserLogins"); + + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpUserRoles"); + + migrationBuilder.DropTable( + name: "AbpUserTokens"); + + migrationBuilder.DropTable( + name: "OpenIddictScopes"); + + migrationBuilder.DropTable( + name: "OpenIddictTokens"); + + migrationBuilder.DropTable( + name: "AbpEntityChanges"); + + migrationBuilder.DropTable( + name: "AbpTenants"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpRoles"); + + migrationBuilder.DropTable( + name: "AbpUsers"); + + migrationBuilder.DropTable( + name: "OpenIddictAuthorizations"); + + migrationBuilder.DropTable( + name: "AbpAuditLogs"); + + migrationBuilder.DropTable( + name: "OpenIddictApplications"); + } + } +} diff --git a/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Migrations/AdminDbContextModelSnapshot.cs b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Migrations/AdminDbContextModelSnapshot.cs new file mode 100644 index 0000000..e985b81 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Migrations/AdminDbContextModelSnapshot.cs @@ -0,0 +1,2003 @@ +// +using System; +using KonSoft.Admin.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace KonSoft.Admin.Migrations +{ + [DbContext(typeof(AdminDbContext))] + partial class AdminDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("text"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("integer") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("smallint") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("uuid"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("EntityChangeId") + .HasColumnType("uuid"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsAbandoned") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("JobArgs") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)"); + + b.Property("JobName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LastTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("NextTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((byte)15); + + b.Property("TryCount") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((short)0); + + b.HasKey("Id"); + + b.HasIndex("IsAbandoned", "NextTryTime"); + + b.ToTable("AbpBackgroundJobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property("ValueType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("SourceTenantId") + .HasColumnType("uuid"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("TargetTenantId") + .HasColumnType("uuid"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique(); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("boolean") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("boolean") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("IpAddresses") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("LastAccessed") + .HasColumnType("timestamp without time zone"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("SignedIn") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("boolean"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("EndTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("StartTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("character varying(196)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("character varying(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ClientSecret") + .HasColumnType("text"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientUri") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JsonWebKeySet") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasColumnType("text"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedirectUris") + .HasColumnType("text"); + + b.Property("Requirements") + .HasColumnType("text"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Scopes") + .HasColumnType("text"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Descriptions") + .HasColumnType("text"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Resources") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AuthorizationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Payload") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("MultiTenancySide") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("boolean"); + + b.Property("IsInherited") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + + b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) + .WithMany() + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Properties/AssemblyInfo.cs b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..106acb2 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.EntityFrameworkCore/Properties/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.Admin.EntityFrameworkCore.Tests")] diff --git a/modules/admin/src/KonSoft.Admin.HttpApi.Client/AdminHttpApiClientModule.cs b/modules/admin/src/KonSoft.Admin.HttpApi.Client/AdminHttpApiClientModule.cs new file mode 100644 index 0000000..d97145c --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.HttpApi.Client/AdminHttpApiClientModule.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.TenantManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.Admin; + +[DependsOn( + typeof(AdminApplicationContractsModule), + typeof(AbpAccountHttpApiClientModule), + typeof(AbpIdentityHttpApiClientModule), + typeof(AbpPermissionManagementHttpApiClientModule), + typeof(AbpTenantManagementHttpApiClientModule), + typeof(AbpFeatureManagementHttpApiClientModule), + typeof(AbpSettingManagementHttpApiClientModule) +)] +public class AdminHttpApiClientModule : AbpModule +{ + public const string RemoteServiceName = "Default"; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddHttpClientProxies( + typeof(AdminApplicationContractsModule).Assembly, + RemoteServiceName + ); + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + } +} diff --git a/modules/admin/src/KonSoft.Admin.HttpApi.Client/KonSoft.Admin.HttpApi.Client.csproj b/modules/admin/src/KonSoft.Admin.HttpApi.Client/KonSoft.Admin.HttpApi.Client.csproj new file mode 100644 index 0000000..71bb2db --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.HttpApi.Client/KonSoft.Admin.HttpApi.Client.csproj @@ -0,0 +1,29 @@ + + + + + + net8.0 + enable + KonSoft.Admin + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/admin/src/KonSoft.Admin.HttpApi/AdminHttpApiModule.cs b/modules/admin/src/KonSoft.Admin.HttpApi/AdminHttpApiModule.cs new file mode 100644 index 0000000..c92618f --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.HttpApi/AdminHttpApiModule.cs @@ -0,0 +1,41 @@ +using Localization.Resources.AbpUi; +using KonSoft.Admin.Localization; +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.HttpApi; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Admin; + +[DependsOn( + typeof(AdminApplicationContractsModule), + typeof(AbpAccountHttpApiModule), + typeof(AbpIdentityHttpApiModule), + typeof(AbpPermissionManagementHttpApiModule), + typeof(AbpTenantManagementHttpApiModule), + typeof(AbpFeatureManagementHttpApiModule), + typeof(AbpSettingManagementHttpApiModule) + )] +public class AdminHttpApiModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + ConfigureLocalization(); + } + + private void ConfigureLocalization() + { + Configure(options => + { + options.Resources + .Get() + .AddBaseTypes( + typeof(AbpUiResource) + ); + }); + } +} diff --git a/modules/admin/src/KonSoft.Admin.HttpApi/Controllers/AdminController.cs b/modules/admin/src/KonSoft.Admin.HttpApi/Controllers/AdminController.cs new file mode 100644 index 0000000..e1fd158 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.HttpApi/Controllers/AdminController.cs @@ -0,0 +1,14 @@ +using KonSoft.Admin.Localization; +using Volo.Abp.AspNetCore.Mvc; + +namespace KonSoft.Admin.Controllers; + +/* Inherit your controllers from this class. + */ +public abstract class AdminController : AbpControllerBase +{ + protected AdminController() + { + LocalizationResource = typeof(AdminResource); + } +} diff --git a/modules/admin/src/KonSoft.Admin.HttpApi/KonSoft.Admin.HttpApi.csproj b/modules/admin/src/KonSoft.Admin.HttpApi/KonSoft.Admin.HttpApi.csproj new file mode 100644 index 0000000..cb7a804 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.HttpApi/KonSoft.Admin.HttpApi.csproj @@ -0,0 +1,24 @@ + + + + + + net8.0 + enable + KonSoft.Admin + + + + + + + + + + + + + + + + diff --git a/modules/admin/src/KonSoft.Admin.HttpApi/Models/Test/TestModel.cs b/modules/admin/src/KonSoft.Admin.HttpApi/Models/Test/TestModel.cs new file mode 100644 index 0000000..15c0908 --- /dev/null +++ b/modules/admin/src/KonSoft.Admin.HttpApi/Models/Test/TestModel.cs @@ -0,0 +1,10 @@ +using System; + +namespace KonSoft.Admin.Models.Test; + +public class TestModel +{ + public string? Name { get; set; } + + public DateTime BirthDate { get; set; } +} diff --git a/modules/admin/test/KonSoft.Admin.Application.Tests/AdminApplicationTestBase.cs b/modules/admin/test/KonSoft.Admin.Application.Tests/AdminApplicationTestBase.cs new file mode 100644 index 0000000..ea110b2 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.Application.Tests/AdminApplicationTestBase.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Admin; + +public abstract class AdminApplicationTestBase : AdminTestBase + where TStartupModule : IAbpModule +{ + +} diff --git a/modules/admin/test/KonSoft.Admin.Application.Tests/AdminApplicationTestModule.cs b/modules/admin/test/KonSoft.Admin.Application.Tests/AdminApplicationTestModule.cs new file mode 100644 index 0000000..2d1054f --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.Application.Tests/AdminApplicationTestModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Admin; + +[DependsOn( + typeof(AdminApplicationModule), + typeof(AdminDomainTestModule) +)] +public class AdminApplicationTestModule : AbpModule +{ + +} diff --git a/modules/admin/test/KonSoft.Admin.Application.Tests/KonSoft.Admin.Application.Tests.csproj b/modules/admin/test/KonSoft.Admin.Application.Tests/KonSoft.Admin.Application.Tests.csproj new file mode 100644 index 0000000..53d9673 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.Application.Tests/KonSoft.Admin.Application.Tests.csproj @@ -0,0 +1,20 @@ + + + + + + net8.0 + enable + KonSoft.Admin + + + + + + + + + + + + diff --git a/modules/admin/test/KonSoft.Admin.Application.Tests/Samples/SampleAppServiceTests.cs b/modules/admin/test/KonSoft.Admin.Application.Tests/Samples/SampleAppServiceTests.cs new file mode 100644 index 0000000..7f3e109 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.Application.Tests/Samples/SampleAppServiceTests.cs @@ -0,0 +1,34 @@ +using Shouldly; +using System.Threading.Tasks; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Xunit; + +namespace KonSoft.Admin.Samples; + +/* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IIdentityUserAppService here). + * Only test your own application services. + */ +public abstract class SampleAppServiceTests : AdminApplicationTestBase + where TStartupModule : IAbpModule +{ + private readonly IIdentityUserAppService _userAppService; + + protected SampleAppServiceTests() + { + _userAppService = GetRequiredService(); + } + + [Fact] + public async Task Initial_Data_Should_Contain_Admin_User() + { + //Act + var result = await _userAppService.GetListAsync(new GetIdentityUsersInput()); + + //Assert + result.TotalCount.ShouldBeGreaterThan(0); + result.Items.ShouldContain(u => u.UserName == "admin"); + } +} diff --git a/modules/admin/test/KonSoft.Admin.Domain.Tests/AdminDomainTestBase.cs b/modules/admin/test/KonSoft.Admin.Domain.Tests/AdminDomainTestBase.cs new file mode 100644 index 0000000..1a88fce --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.Domain.Tests/AdminDomainTestBase.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Admin; + +/* Inherit from this class for your domain layer tests. */ +public abstract class AdminDomainTestBase : AdminTestBase + where TStartupModule : IAbpModule +{ + +} diff --git a/modules/admin/test/KonSoft.Admin.Domain.Tests/AdminDomainTestModule.cs b/modules/admin/test/KonSoft.Admin.Domain.Tests/AdminDomainTestModule.cs new file mode 100644 index 0000000..35e8eb5 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.Domain.Tests/AdminDomainTestModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Admin; + +[DependsOn( + typeof(AdminDomainModule), + typeof(AdminTestBaseModule) +)] +public class AdminDomainTestModule : AbpModule +{ + +} diff --git a/modules/admin/test/KonSoft.Admin.Domain.Tests/KonSoft.Admin.Domain.Tests.csproj b/modules/admin/test/KonSoft.Admin.Domain.Tests/KonSoft.Admin.Domain.Tests.csproj new file mode 100644 index 0000000..d191c63 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.Domain.Tests/KonSoft.Admin.Domain.Tests.csproj @@ -0,0 +1,20 @@ + + + + + + net8.0 + enable + KonSoft.Admin + + + + + + + + + + + + diff --git a/modules/admin/test/KonSoft.Admin.Domain.Tests/Samples/SampleDomainTests.cs b/modules/admin/test/KonSoft.Admin.Domain.Tests/Samples/SampleDomainTests.cs new file mode 100644 index 0000000..094ffc0 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.Domain.Tests/Samples/SampleDomainTests.cs @@ -0,0 +1,46 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Xunit; + +namespace KonSoft.Admin.Samples; + +/* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IdentityUserManager here). + * Only test your own domain services. + */ +public abstract class SampleDomainTests : AdminDomainTestBase + where TStartupModule : IAbpModule +{ + private readonly IIdentityUserRepository _identityUserRepository; + private readonly IdentityUserManager _identityUserManager; + + protected SampleDomainTests() + { + _identityUserRepository = GetRequiredService(); + _identityUserManager = GetRequiredService(); + } + + [Fact] + public async Task Should_Set_Email_Of_A_User() + { + IdentityUser adminUser; + + /* Need to manually start Unit Of Work because + * FirstOrDefaultAsync should be executed while db connection / context is available. + */ + await WithUnitOfWorkAsync(async () => + { + adminUser = await _identityUserRepository + .FindByNormalizedUserNameAsync("ADMIN"); + + await _identityUserManager.SetEmailAsync(adminUser, "newemail@abp.io"); + await _identityUserRepository.UpdateAsync(adminUser); + }); + + adminUser = await _identityUserRepository.FindByNormalizedUserNameAsync("ADMIN"); + adminUser.Email.ShouldBe("newemail@abp.io"); + } +} diff --git a/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreCollection.cs b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreCollection.cs new file mode 100644 index 0000000..9f006da --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreCollection.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace KonSoft.Admin.EntityFrameworkCore; + +[CollectionDefinition(AdminTestConsts.CollectionDefinitionName)] +public class AdminEntityFrameworkCoreCollection : ICollectionFixture +{ + +} diff --git a/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreCollectionFixtureBase.cs b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreCollectionFixtureBase.cs new file mode 100644 index 0000000..5e02704 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreCollectionFixtureBase.cs @@ -0,0 +1,9 @@ +using KonSoft.Admin.EntityFrameworkCore; +using Xunit; + +namespace KonSoft.Admin.EntityFrameworkCore; + +public class AdminEntityFrameworkCoreCollectionFixtureBase : ICollectionFixture +{ + +} diff --git a/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreFixture.cs b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreFixture.cs new file mode 100644 index 0000000..920d586 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreFixture.cs @@ -0,0 +1,11 @@ +using System; + +namespace KonSoft.Admin.EntityFrameworkCore; + +public class AdminEntityFrameworkCoreFixture : IDisposable +{ + public void Dispose() + { + + } +} diff --git a/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreTestBase.cs b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreTestBase.cs new file mode 100644 index 0000000..36c1c35 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreTestBase.cs @@ -0,0 +1,8 @@ +using Volo.Abp; + +namespace KonSoft.Admin.EntityFrameworkCore; + +public abstract class AdminEntityFrameworkCoreTestBase : AdminTestBase +{ + +} diff --git a/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreTestModule.cs b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreTestModule.cs new file mode 100644 index 0000000..a98eee4 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/AdminEntityFrameworkCoreTestModule.cs @@ -0,0 +1,82 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.Sqlite; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.Uow; + +namespace KonSoft.Admin.EntityFrameworkCore; + +[DependsOn( + typeof(AdminApplicationTestModule), + typeof(AdminEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCoreSqliteModule) + )] +public class AdminEntityFrameworkCoreTestModule : AbpModule +{ + private SqliteConnection? _sqliteConnection; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.SaveStaticFeaturesToDatabase = false; + options.IsDynamicFeatureStoreEnabled = false; + }); + Configure(options => + { + options.SaveStaticPermissionsToDatabase = false; + options.IsDynamicPermissionStoreEnabled = false; + }); + Configure(options => + { + options.SaveStaticSettingsToDatabase = false; + options.IsDynamicSettingStoreEnabled = false; + }); + context.Services.AddAlwaysDisableUnitOfWorkTransaction(); + + ConfigureInMemorySqlite(context.Services); + } + + private void ConfigureInMemorySqlite(IServiceCollection services) + { + _sqliteConnection = CreateDatabaseAndGetConnection(); + + services.Configure(options => + { + options.Configure(context => + { + context.DbContextOptions.UseSqlite(_sqliteConnection); + }); + }); + } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + _sqliteConnection?.Dispose(); + } + + private static SqliteConnection CreateDatabaseAndGetConnection() + { + var connection = new AbpUnitTestSqliteConnection("Data Source=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new AdminDbContext(options)) + { + context.GetService().CreateTables(); + } + + return connection; + } +} diff --git a/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs new file mode 100644 index 0000000..10298f2 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs @@ -0,0 +1,10 @@ +using KonSoft.Admin.Samples; +using Xunit; + +namespace KonSoft.Admin.EntityFrameworkCore.Applications; + +[Collection(AdminTestConsts.CollectionDefinitionName)] +public class EfCoreSampleAppServiceTests : SampleAppServiceTests +{ + +} diff --git a/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs new file mode 100644 index 0000000..a5eb518 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs @@ -0,0 +1,10 @@ +using KonSoft.Admin.Samples; +using Xunit; + +namespace KonSoft.Admin.EntityFrameworkCore.Domains; + +[Collection(AdminTestConsts.CollectionDefinitionName)] +public class EfCoreSampleDomainTests : SampleDomainTests +{ + +} diff --git a/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs new file mode 100644 index 0000000..1d6ee8e --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Shouldly; +using System; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Identity; +using Xunit; + +namespace KonSoft.Admin.EntityFrameworkCore.Samples; + +/* This is just an example test class. + * Normally, you don't test ABP framework code + * (like default AppUser repository IRepository here). + * Only test your custom repository methods. + */ +[Collection(AdminTestConsts.CollectionDefinitionName)] +public class SampleRepositoryTests : AdminEntityFrameworkCoreTestBase +{ + private readonly IRepository _appUserRepository; + + public SampleRepositoryTests() + { + _appUserRepository = GetRequiredService>(); + } + + [Fact] + public async Task Should_Query_AppUser() + { + /* Need to manually start Unit Of Work because + * FirstOrDefaultAsync should be executed while db connection / context is available. + */ + await WithUnitOfWorkAsync(async () => + { + //Act + var adminUser = await (await _appUserRepository.GetQueryableAsync()) + .Where(u => u.UserName == "admin") + .FirstOrDefaultAsync(); + + //Assert + adminUser.ShouldNotBeNull(); + }); + } +} diff --git a/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/KonSoft.Admin.EntityFrameworkCore.Tests.csproj b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/KonSoft.Admin.EntityFrameworkCore.Tests.csproj new file mode 100644 index 0000000..719702a --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.EntityFrameworkCore.Tests/KonSoft.Admin.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,21 @@ + + + + + + net8.0 + enable + KonSoft.Admin + + + + + + + + + + + + + diff --git a/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/AdminConsoleApiClientModule.cs b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/AdminConsoleApiClientModule.cs new file mode 100644 index 0000000..7f3049c --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/AdminConsoleApiClientModule.cs @@ -0,0 +1,30 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Polly; +using Volo.Abp.Autofac; +using Volo.Abp.Http.Client; +using Volo.Abp.Http.Client.IdentityModel; +using Volo.Abp.Modularity; + +namespace KonSoft.Admin.HttpApi.Client.ConsoleTestApp; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AdminHttpApiClientModule), + typeof(AbpHttpClientIdentityModelModule) + )] +public class AdminConsoleApiClientModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(options => + { + options.ProxyClientBuildActions.Add((remoteServiceName, clientBuilder) => + { + clientBuilder.AddTransientHttpErrorPolicy( + policyBuilder => policyBuilder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i))) + ); + }); + }); + } +} diff --git a/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs new file mode 100644 index 0000000..b50730a --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs @@ -0,0 +1,25 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Account; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Admin.HttpApi.Client.ConsoleTestApp; + +public class ClientDemoService : ITransientDependency +{ + private readonly IProfileAppService _profileAppService; + + public ClientDemoService(IProfileAppService profileAppService) + { + _profileAppService = profileAppService; + } + + public async Task RunAsync() + { + var output = await _profileAppService.GetAsync(); + Console.WriteLine($"UserName : {output.UserName}"); + Console.WriteLine($"Email : {output.Email}"); + Console.WriteLine($"Name : {output.Name}"); + Console.WriteLine($"Surname : {output.Surname}"); + } +} diff --git a/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs new file mode 100644 index 0000000..2753a32 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.Hosting; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; + +namespace KonSoft.Admin.HttpApi.Client.ConsoleTestApp; + +public class ConsoleTestAppHostedService : IHostedService +{ + private readonly IConfiguration _configuration; + + public ConsoleTestAppHostedService(IConfiguration configuration) + { + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using (var application = await AbpApplicationFactory.CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + })) + { + await application.InitializeAsync(); + + var demo = application.ServiceProvider.GetRequiredService(); + await demo.RunAsync(); + + await application.ShutdownAsync(); + } + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/KonSoft.Admin.HttpApi.Client.ConsoleTestApp.csproj b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/KonSoft.Admin.HttpApi.Client.ConsoleTestApp.csproj new file mode 100644 index 0000000..ddc21a1 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/KonSoft.Admin.HttpApi.Client.ConsoleTestApp.csproj @@ -0,0 +1,33 @@ + + + + Exe + net8.0 + enable + + + + + + PreserveNewest + Always + + + + PreserveNewest + Always + + + + + + + + + + + + + + + diff --git a/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/Program.cs b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/Program.cs new file mode 100644 index 0000000..a163537 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/Program.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace KonSoft.Admin.HttpApi.Client.ConsoleTestApp; + +class Program +{ + static async Task Main(string[] args) + { + await CreateHostBuilder(args).RunConsoleAsync(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .AddAppSettingsSecretsJson() + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); +} diff --git a/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/appsettings.json b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/appsettings.json new file mode 100644 index 0000000..a0ac857 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/appsettings.json @@ -0,0 +1,17 @@ +{ + "RemoteServices": { + "Default": { + "BaseUrl": "https://localhost:44350" + } + }, + "IdentityClients": { + "Default": { + "GrantType": "password", + "ClientId": "Admin_App", + "UserName": "admin", + "UserPassword": "1q2w3E*", + "Authority": "https://localhost:44350", + "Scope": "Admin" + } + } +} diff --git a/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/modules/admin/test/KonSoft.Admin.TestBase/AdminTestBase.cs b/modules/admin/test/KonSoft.Admin.TestBase/AdminTestBase.cs new file mode 100644 index 0000000..148d2a6 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.TestBase/AdminTestBase.cs @@ -0,0 +1,60 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Modularity; +using Volo.Abp.Uow; +using Volo.Abp.Testing; + +namespace KonSoft.Admin; + +/* All test classes are derived from this class, directly or indirectly. + */ +public abstract class AdminTestBase : AbpIntegratedTest + where TStartupModule : IAbpModule +{ + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + protected virtual Task WithUnitOfWorkAsync(Func func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func action) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + await action(); + + await uow.CompleteAsync(); + } + } + } + + protected virtual Task WithUnitOfWorkAsync(Func> func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func> func) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + var result = await func(); + await uow.CompleteAsync(); + return result; + } + } + } +} diff --git a/modules/admin/test/KonSoft.Admin.TestBase/AdminTestBaseModule.cs b/modules/admin/test/KonSoft.Admin.TestBase/AdminTestBaseModule.cs new file mode 100644 index 0000000..8f3a138 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.TestBase/AdminTestBaseModule.cs @@ -0,0 +1,47 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Authorization; +using Volo.Abp.Autofac; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Abp.Threading; + +namespace KonSoft.Admin; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpTestBaseModule), + typeof(AbpAuthorizationModule), + typeof(AbpBackgroundJobsAbstractionsModule) + )] +public class AdminTestBaseModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.IsJobExecutionEnabled = false; + }); + + context.Services.AddAlwaysAllowAuthorization(); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + AsyncHelper.RunSync(async () => + { + using (var scope = context.ServiceProvider.CreateScope()) + { + await scope.ServiceProvider + .GetRequiredService() + .SeedAsync(); + } + }); + } +} diff --git a/modules/admin/test/KonSoft.Admin.TestBase/AdminTestConsts.cs b/modules/admin/test/KonSoft.Admin.TestBase/AdminTestConsts.cs new file mode 100644 index 0000000..a8cd415 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.TestBase/AdminTestConsts.cs @@ -0,0 +1,6 @@ +namespace KonSoft.Admin; + +public static class AdminTestConsts +{ + public const string CollectionDefinitionName = "Admin collection"; +} diff --git a/modules/admin/test/KonSoft.Admin.TestBase/AdminTestDataSeedContributor.cs b/modules/admin/test/KonSoft.Admin.TestBase/AdminTestDataSeedContributor.cs new file mode 100644 index 0000000..5aad1ca --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.TestBase/AdminTestDataSeedContributor.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Admin; + +public class AdminTestDataSeedContributor : IDataSeedContributor, ITransientDependency +{ + public Task SeedAsync(DataSeedContext context) + { + /* Seed additional test data... */ + + return Task.CompletedTask; + } +} diff --git a/modules/admin/test/KonSoft.Admin.TestBase/KonSoft.Admin.TestBase.csproj b/modules/admin/test/KonSoft.Admin.TestBase/KonSoft.Admin.TestBase.csproj new file mode 100644 index 0000000..7a45449 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.TestBase/KonSoft.Admin.TestBase.csproj @@ -0,0 +1,31 @@ + + + + + + net8.0 + enable + KonSoft.Admin + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + diff --git a/modules/admin/test/KonSoft.Admin.TestBase/Security/FakeCurrentPrincipalAccessor.cs b/modules/admin/test/KonSoft.Admin.TestBase/Security/FakeCurrentPrincipalAccessor.cs new file mode 100644 index 0000000..fd9de28 --- /dev/null +++ b/modules/admin/test/KonSoft.Admin.TestBase/Security/FakeCurrentPrincipalAccessor.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Security.Claims; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Claims; + +namespace KonSoft.Admin.Security; + +[Dependency(ReplaceServices = true)] +public class FakeCurrentPrincipalAccessor : ThreadCurrentPrincipalAccessor +{ + protected override ClaimsPrincipal GetClaimsPrincipal() + { + return GetPrincipal(); + } + + private ClaimsPrincipal GetPrincipal() + { + return new ClaimsPrincipal(new ClaimsIdentity(new List + { + new Claim(AbpClaimTypes.UserId, "2e701e62-0953-4dd3-910b-dc6cc93ccb0d"), + new Claim(AbpClaimTypes.UserName, "admin"), + new Claim(AbpClaimTypes.Email, "admin@abp.io") + })); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/DispatchApplicationContractsModule.cs b/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/DispatchApplicationContractsModule.cs new file mode 100644 index 0000000..4742494 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/DispatchApplicationContractsModule.cs @@ -0,0 +1,28 @@ +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Dispatch; + +[DependsOn( + typeof(DispatchDomainSharedModule), + typeof(AbpAccountApplicationContractsModule), + typeof(AbpFeatureManagementApplicationContractsModule), + typeof(AbpIdentityApplicationContractsModule), + typeof(AbpPermissionManagementApplicationContractsModule), + typeof(AbpSettingManagementApplicationContractsModule), + typeof(AbpTenantManagementApplicationContractsModule), + typeof(AbpObjectExtendingModule) +)] +public class DispatchApplicationContractsModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + DispatchDtoExtensions.Configure(); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/DispatchDtoExtensions.cs b/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/DispatchDtoExtensions.cs new file mode 100644 index 0000000..6af0031 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/DispatchDtoExtensions.cs @@ -0,0 +1,28 @@ +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.Dispatch; + +public static class DispatchDtoExtensions +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can add extension properties to DTOs + * defined in the depended modules. + * + * Example: + * + * ObjectExtensionManager.Instance + * .AddOrUpdateProperty("Title"); + * + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Object-Extensions + */ + }); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/KonSoft.Dispatch.Application.Contracts.csproj b/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/KonSoft.Dispatch.Application.Contracts.csproj new file mode 100644 index 0000000..2a4ca1e --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/KonSoft.Dispatch.Application.Contracts.csproj @@ -0,0 +1,25 @@ + + + + + + net8.0 + enable + KonSoft.Dispatch + + + + + + + + + + + + + + + + + diff --git a/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/Permissions/DispatchPermissionDefinitionProvider.cs b/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/Permissions/DispatchPermissionDefinitionProvider.cs new file mode 100644 index 0000000..bd90841 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/Permissions/DispatchPermissionDefinitionProvider.cs @@ -0,0 +1,20 @@ +using KonSoft.Dispatch.Localization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; + +namespace KonSoft.Dispatch.Permissions; + +public class DispatchPermissionDefinitionProvider : PermissionDefinitionProvider +{ + public override void Define(IPermissionDefinitionContext context) + { + var myGroup = context.AddGroup(DispatchPermissions.GroupName); + //Define your own permissions here. Example: + //myGroup.AddPermission(DispatchPermissions.MyPermission1, L("Permission:MyPermission1")); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/Permissions/DispatchPermissions.cs b/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/Permissions/DispatchPermissions.cs new file mode 100644 index 0000000..95d2818 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Application.Contracts/Permissions/DispatchPermissions.cs @@ -0,0 +1,9 @@ +namespace KonSoft.Dispatch.Permissions; + +public static class DispatchPermissions +{ + public const string GroupName = "Dispatch"; + + //Add your own permission names. Example: + //public const string MyPermission1 = GroupName + ".MyPermission1"; +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Application/DispatchAppService.cs b/modules/dispatch/src/KonSoft.Dispatch.Application/DispatchAppService.cs new file mode 100644 index 0000000..b0edd14 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Application/DispatchAppService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using KonSoft.Dispatch.Localization; +using Volo.Abp.Application.Services; + +namespace KonSoft.Dispatch; + +/* Inherit your application services from this class. + */ +public abstract class DispatchAppService : ApplicationService +{ + protected DispatchAppService() + { + LocalizationResource = typeof(DispatchResource); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Application/DispatchApplicationAutoMapperProfile.cs b/modules/dispatch/src/KonSoft.Dispatch.Application/DispatchApplicationAutoMapperProfile.cs new file mode 100644 index 0000000..6b7db35 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Application/DispatchApplicationAutoMapperProfile.cs @@ -0,0 +1,13 @@ +using AutoMapper; + +namespace KonSoft.Dispatch; + +public class DispatchApplicationAutoMapperProfile : Profile +{ + public DispatchApplicationAutoMapperProfile() + { + /* You can configure your AutoMapper mapping configuration here. + * Alternatively, you can split your mapping configurations + * into multiple profile classes for a better organization. */ + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Application/DispatchApplicationModule.cs b/modules/dispatch/src/KonSoft.Dispatch.Application/DispatchApplicationModule.cs new file mode 100644 index 0000000..17607d9 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Application/DispatchApplicationModule.cs @@ -0,0 +1,31 @@ +using Volo.Abp.Account; +using Volo.Abp.AutoMapper; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Dispatch; + +[DependsOn( + typeof(DispatchDomainModule), + typeof(AbpAccountApplicationModule), + typeof(DispatchApplicationContractsModule), + typeof(AbpIdentityApplicationModule), + typeof(AbpPermissionManagementApplicationModule), + typeof(AbpTenantManagementApplicationModule), + typeof(AbpFeatureManagementApplicationModule), + typeof(AbpSettingManagementApplicationModule) + )] +public class DispatchApplicationModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.AddMaps(); + }); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Application/KonSoft.Dispatch.Application.csproj b/modules/dispatch/src/KonSoft.Dispatch.Application/KonSoft.Dispatch.Application.csproj new file mode 100644 index 0000000..e7b7c5f --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Application/KonSoft.Dispatch.Application.csproj @@ -0,0 +1,25 @@ + + + + + + net8.0 + enable + KonSoft.Dispatch + + + + + + + + + + + + + + + + + diff --git a/modules/dispatch/src/KonSoft.Dispatch.Application/Properties/AssemblyInfo.cs b/modules/dispatch/src/KonSoft.Dispatch.Application/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..3aec15b --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Application/Properties/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.Dispatch.Application.Tests")] diff --git a/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/DbMigratorHostedService.cs b/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/DbMigratorHostedService.cs new file mode 100644 index 0000000..08885c8 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/DbMigratorHostedService.cs @@ -0,0 +1,51 @@ +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using KonSoft.Dispatch.Data; +using Serilog; +using Volo.Abp; +using Volo.Abp.Data; + +namespace KonSoft.Dispatch.DbMigrator; + +public class DbMigratorHostedService : IHostedService +{ + private readonly IHostApplicationLifetime _hostApplicationLifetime; + private readonly IConfiguration _configuration; + + public DbMigratorHostedService(IHostApplicationLifetime hostApplicationLifetime, IConfiguration configuration) + { + _hostApplicationLifetime = hostApplicationLifetime; + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using (var application = await AbpApplicationFactory.CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + options.Services.AddLogging(c => c.AddSerilog()); + options.AddDataMigrationEnvironment(); + })) + { + await application.InitializeAsync(); + + await application + .ServiceProvider + .GetRequiredService() + .MigrateAsync(); + + await application.ShutdownAsync(); + + _hostApplicationLifetime.StopApplication(); + } + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/DispatchDbMigratorModule.cs b/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/DispatchDbMigratorModule.cs new file mode 100644 index 0000000..d2e473c --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/DispatchDbMigratorModule.cs @@ -0,0 +1,21 @@ +using KonSoft.Dispatch.EntityFrameworkCore; +using Volo.Abp.Autofac; +using Volo.Abp.Caching; +using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Abp.Modularity; + +namespace KonSoft.Dispatch.DbMigrator; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpCachingStackExchangeRedisModule), + typeof(DispatchEntityFrameworkCoreModule), + typeof(DispatchApplicationContractsModule) + )] +public class DispatchDbMigratorModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => { options.KeyPrefix = "Dispatch:"; }); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/KonSoft.Dispatch.DbMigrator.csproj b/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/KonSoft.Dispatch.DbMigrator.csproj new file mode 100644 index 0000000..9a9728d --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/KonSoft.Dispatch.DbMigrator.csproj @@ -0,0 +1,46 @@ + + + + + + Exe + net8.0 + enable + + + + + + PreserveNewest + Always + + + + PreserveNewest + Always + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/Program.cs b/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/Program.cs new file mode 100644 index 0000000..3aaba5b --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/Program.cs @@ -0,0 +1,41 @@ +using System.IO; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Serilog; +using Serilog.Events; + +namespace KonSoft.Dispatch.DbMigrator; + +class Program +{ + static async Task Main(string[] args) + { + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Information() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning) +#if DEBUG + .MinimumLevel.Override("KonSoft.Dispatch", LogEventLevel.Debug) +#else + .MinimumLevel.Override("KonSoft.Dispatch", LogEventLevel.Information) +#endif + .Enrich.FromLogContext() + .WriteTo.Async(c => c.File("Logs/logs.txt")) + .WriteTo.Async(c => c.Console()) + .CreateLogger(); + + await CreateHostBuilder(args).RunConsoleAsync(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .AddAppSettingsSecretsJson() + .ConfigureLogging((context, logging) => logging.ClearProviders()) + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/appsettings.json b/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/appsettings.json new file mode 100644 index 0000000..008c2fb --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/appsettings.json @@ -0,0 +1,16 @@ +{ + "ConnectionStrings": { + "Default": "Host=localhost;Port=5432;Database=Dispatch;User ID=root;Password=myPassword;" + }, + "Redis": { + "Configuration": "127.0.0.1" + }, + "OpenIddict": { + "Applications": { + "Dispatch_Swagger": { + "ClientId": "Dispatch_Swagger", + "RootUrl": "https://localhost:44321" + } + } + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/appsettings.secrets.json b/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/appsettings.secrets.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.DbMigrator/appsettings.secrets.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchDomainErrorCodes.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchDomainErrorCodes.cs new file mode 100644 index 0000000..5674d61 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchDomainErrorCodes.cs @@ -0,0 +1,6 @@ +namespace KonSoft.Dispatch; + +public static class DispatchDomainErrorCodes +{ + /* You can add your business exception error codes here, as constants */ +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchDomainSharedModule.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchDomainSharedModule.cs new file mode 100644 index 0000000..22f9225 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchDomainSharedModule.cs @@ -0,0 +1,58 @@ +using KonSoft.Dispatch.Localization; +using Volo.Abp.AuditLogging; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Localization.ExceptionHandling; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; +using Volo.Abp.Validation.Localization; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.Dispatch; + +[DependsOn( + typeof(AbpAuditLoggingDomainSharedModule), + typeof(AbpBackgroundJobsDomainSharedModule), + typeof(AbpFeatureManagementDomainSharedModule), + typeof(AbpIdentityDomainSharedModule), + typeof(AbpOpenIddictDomainSharedModule), + typeof(AbpPermissionManagementDomainSharedModule), + typeof(AbpSettingManagementDomainSharedModule), + typeof(AbpTenantManagementDomainSharedModule) + )] +public class DispatchDomainSharedModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + DispatchGlobalFeatureConfigurator.Configure(); + DispatchModuleExtensionConfigurator.Configure(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddBaseTypes(typeof(AbpValidationResource)) + .AddVirtualJson("/Localization/Dispatch"); + + options.DefaultResourceType = typeof(DispatchResource); + }); + + Configure(options => + { + options.MapCodeNamespace("Dispatch", typeof(DispatchResource)); + }); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchGlobalFeatureConfigurator.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchGlobalFeatureConfigurator.cs new file mode 100644 index 0000000..fed3907 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchGlobalFeatureConfigurator.cs @@ -0,0 +1,22 @@ +using Volo.Abp.Threading; + +namespace KonSoft.Dispatch; + +public static class DispatchGlobalFeatureConfigurator +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can configure (enable/disable) global features of the used modules here. + * + * YOU CAN SAFELY DELETE THIS CLASS AND REMOVE ITS USAGES IF YOU DON'T NEED TO IT! + * + * Please refer to the documentation to lear more about the Global Features System: + * https://docs.abp.io/en/abp/latest/Global-Features + */ + }); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchModuleExtensionConfigurator.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchModuleExtensionConfigurator.cs new file mode 100644 index 0000000..7dc6572 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/DispatchModuleExtensionConfigurator.cs @@ -0,0 +1,73 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.Dispatch; + +public static class DispatchModuleExtensionConfigurator +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + ConfigureExistingProperties(); + ConfigureExtraProperties(); + }); + } + + private static void ConfigureExistingProperties() + { + /* You can change max lengths for properties of the + * entities defined in the modules used by your application. + * + * Example: Change user and role name max lengths + + AbpUserConsts.MaxNameLength = 99; + IdentityRoleConsts.MaxNameLength = 99; + + * Notice: It is not suggested to change property lengths + * unless you really need it. Go with the standard values wherever possible. + * + * If you are using EF Core, you will need to run the add-migration command after your changes. + */ + } + + private static void ConfigureExtraProperties() + { + /* You can configure extra properties for the + * entities defined in the modules used by your application. + * + * This class can be used to define these extra properties + * with a high level, easy to use API. + * + * Example: Add a new property to the user entity of the identity module + + ObjectExtensionManager.Instance.Modules() + .ConfigureIdentity(identity => + { + identity.ConfigureUser(user => + { + user.AddOrUpdateProperty( //property type: string + "SocialSecurityNumber", //property name + property => + { + //validation rules + property.Attributes.Add(new RequiredAttribute()); + property.Attributes.Add(new StringLengthAttribute(64) {MinimumLength = 4}); + + property.Configuration[IdentityModuleExtensionConsts.ConfigurationNames.AllowUserToEdit] = true; + + //...other configurations for this property + } + ); + }); + }); + + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Module-Entity-Extensions + */ + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/KonSoft.Dispatch.Domain.Shared.csproj b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/KonSoft.Dispatch.Domain.Shared.csproj new file mode 100644 index 0000000..b529317 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/KonSoft.Dispatch.Domain.Shared.csproj @@ -0,0 +1,32 @@ + + + + + + net8.0 + enable + KonSoft.Dispatch + true + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/ar.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/ar.json new file mode 100644 index 0000000..ab9a761 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/ar.json @@ -0,0 +1,9 @@ +{ + "culture": "ar", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "الصفحة الرئيسية", + "Welcome": "مرحباً", + "LongWelcomeMessage": "مرحبا بكم في التطبيق. هذا مشروع بدء تشغيل يعتمد على إطار عمل ABP. لمزيد من المعلومات ، يرجى زيارة abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/cs.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/cs.json new file mode 100644 index 0000000..831b3db --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/cs.json @@ -0,0 +1,9 @@ +{ + "culture": "cs", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Úvod", + "Welcome": "Vítejte", + "LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/de.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/de.json new file mode 100644 index 0000000..61e6ef6 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/de.json @@ -0,0 +1,9 @@ +{ + "culture": "de", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Home", + "Welcome": "Willkommen", + "LongWelcomeMessage": "Willkommen bei der Anwendung. Dies ist ein Startup-Projekt, das auf dem ABP-Framework basiert. Weitere Informationen finden Sie unter abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/en-GB.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/en-GB.json new file mode 100644 index 0000000..70a6a63 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/en-GB.json @@ -0,0 +1,9 @@ +{ + "culture": "en-GB", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Home", + "Welcome": "Welcome", + "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/en.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/en.json new file mode 100644 index 0000000..82f9dad --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/en.json @@ -0,0 +1,9 @@ +{ + "culture": "en", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Home", + "Welcome": "Welcome", + "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/es.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/es.json new file mode 100644 index 0000000..f0d27e9 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/es.json @@ -0,0 +1,9 @@ +{ + "culture": "es", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Inicio", + "Welcome": "Bienvenido", + "LongWelcomeMessage": "Bienvenido a la aplicación, este es un proyecto base basado en el framework ABP. Para más información, visita abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/fi.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/fi.json new file mode 100644 index 0000000..c93ee65 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/fi.json @@ -0,0 +1,9 @@ +{ + "culture": "fi", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Koti", + "Welcome": "Tervetuloa", + "LongWelcomeMessage": "Tervetuloa sovellukseen. Tämä on ABP-kehykseen perustuva käynnistysprojekti. Lisätietoja on osoitteessa abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/fr.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/fr.json new file mode 100644 index 0000000..3165e49 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/fr.json @@ -0,0 +1,9 @@ +{ + "culture": "fr", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Accueil", + "Welcome": "Bienvenue", + "LongWelcomeMessage": "Bienvenue dans l'application. Il s'agit d'un projet de démarrage basé sur le framework ABP. Pour plus d'informations, visitez abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/hi.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/hi.json new file mode 100644 index 0000000..cc071ac --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/hi.json @@ -0,0 +1,9 @@ +{ + "culture": "hi", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "घर", + "Welcome": "स्वागत हे", + "LongWelcomeMessage": "आवेदन करने के लिए आपका स्वागत है। यह एबीपी ढांचे पर आधारित एक स्टार्टअप परियोजना है। अधिक जानकारी के लिए, abp.io पर जाएं।" + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/hr.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/hr.json new file mode 100644 index 0000000..f32e630 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/hr.json @@ -0,0 +1,9 @@ +{ + "culture": "hr", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Početna", + "Welcome": "Dobrodošli", + "LongWelcomeMessage": "Dobrodošli u aplikaciju. Ovo je startup projekt temeljen na ABP framework-u. Za više informacija posjetite abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/hu.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/hu.json new file mode 100644 index 0000000..826efd3 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/hu.json @@ -0,0 +1,9 @@ +{ + "culture": "hu", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Kezdőlap", + "Welcome": "Üdvözlöm", + "LongWelcomeMessage": "Üdvözöljük az alkalmazásban. Ez egy ABP keretrendszeren alapuló startup projekt. További információkért látogasson el az abp.io oldalra." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/is.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/is.json new file mode 100644 index 0000000..9b078c4 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/is.json @@ -0,0 +1,9 @@ +{ + "culture": "is", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Heim", + "Welcome": "Velkomin", + "LongWelcomeMessage": "Verið velkomin í forritið. Þetta er startup verkefni sem byggir á ABP. Nánari upplýsingar er að finna á abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/it.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/it.json new file mode 100644 index 0000000..6c6a3c1 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/it.json @@ -0,0 +1,9 @@ +{ + "culture": "it", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Home", + "Welcome": "Benvenuto", + "LongWelcomeMessage": "Benvenuto nell'applicazione. Questo è un progetto di avvio basato sul framework ABP. Per ulteriori informazioni, visita abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/nl.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/nl.json new file mode 100644 index 0000000..6b3c5f5 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/nl.json @@ -0,0 +1,9 @@ +{ + "culture": "nl", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Home", + "Welcome": "Welkom", + "LongWelcomeMessage": "Welkom bij de applicatie. Dit is een startup-project gebaseerd op het ABP-framework. Bezoek abp.io voor meer informatie." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/pl-PL.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/pl-PL.json new file mode 100644 index 0000000..a984f63 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/pl-PL.json @@ -0,0 +1,9 @@ +{ + "culture": "pl-PL", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Home", + "Welcome": "Witaj", + "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/pt-BR.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/pt-BR.json new file mode 100644 index 0000000..154abbc --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/pt-BR.json @@ -0,0 +1,9 @@ +{ + "culture": "pt-BR", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Principal", + "Welcome": "Seja bem-vindo!", + "LongWelcomeMessage": "Bem-vindo a esta aplicação. Este é um projeto inicial baseado no ABP framework. Para mais informações, visite abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/ro-RO.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/ro-RO.json new file mode 100644 index 0000000..7bff132 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/ro-RO.json @@ -0,0 +1,9 @@ +{ + "culture": "ro-RO", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Acasă", + "Welcome": "Bun venit", + "LongWelcomeMessage": "Bun venit la aplicaţie. Acesta este un proiect de pornire bazat pe framework-ul ABP. Pentru mai multe informaţii, vizitaţi, visit abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/ru.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/ru.json new file mode 100644 index 0000000..839d60f --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/ru.json @@ -0,0 +1,9 @@ +{ + "culture": "ru", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Главная", + "Welcome": "Добро пожаловать", + "LongWelcomeMessage": "Добро пожаловать в приложение. Этот запущенный проект основан на фреймворке ABP. Для получения дополнительной информации посетите сайт abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/sk.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/sk.json new file mode 100644 index 0000000..f9a124c --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/sk.json @@ -0,0 +1,9 @@ +{ + "culture": "sk", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Domov", + "Welcome": "Vitajte", + "LongWelcomeMessage": "Vitajte v aplikácii. Toto je štartovací projekt založený na ABP frameworku. Viac informácií nájdete na stránke abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/sl.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/sl.json new file mode 100644 index 0000000..20acbb4 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/sl.json @@ -0,0 +1,9 @@ +{ + "culture": "sl", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Domov", + "Welcome": "Dobrodošli", + "LongWelcomeMessage": "Dobrodošli v aplikaciji. To je začetni projekt na osnovi okolja ABP. Za več informacij obiščite abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/sv.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/sv.json new file mode 100644 index 0000000..bd1eae4 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/sv.json @@ -0,0 +1,9 @@ +{ + "culture": "sv", + "texts": { + "AppName": "MittProjektNamn", + "Menu:Home": "Hem", + "Welcome": "Välkommen", + "LongWelcomeMessage": "Välkommen till applikationen. Detta är ett startup-projekt baserat på ABP-ramverket. För mer information, besök abp.io." + } +} \ No newline at end of file diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/tr.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/tr.json new file mode 100644 index 0000000..6adeb66 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/tr.json @@ -0,0 +1,9 @@ +{ + "culture": "tr", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Ana sayfa", + "Welcome": "Hoşgeldiniz", + "LongWelcomeMessage": "Uygulamaya hoşgeldiniz. Bu, ABP framework'ü üzerine bina edilmiş bir başlangıç projesidir. Daha fazla bilgi için abp.io adresini ziyaret edebilirsiniz." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/vi.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/vi.json new file mode 100644 index 0000000..6c861c8 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/vi.json @@ -0,0 +1,9 @@ +{ + "culture": "vi", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "Trang chủ", + "Welcome": "Chào mừng bạn", + "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án khởi nghiệp dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io." + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/zh-Hans.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/zh-Hans.json new file mode 100644 index 0000000..0f10121 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/zh-Hans.json @@ -0,0 +1,9 @@ +{ + "culture": "zh-Hans", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "首页", + "Welcome": "欢迎", + "LongWelcomeMessage": "欢迎使用本应用程序。这是一个基于 ABP 框架的启动项目。更多信息,请访问 abp.io。" + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/zh-Hant.json b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/zh-Hant.json new file mode 100644 index 0000000..a8bd0de --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/Dispatch/zh-Hant.json @@ -0,0 +1,9 @@ +{ + "culture": "zh-Hant", + "texts": { + "AppName": "Dispatch", + "Menu:Home": "首頁", + "Welcome": "歡迎", + "LongWelcomeMessage": "歡迎來到此應用程式. 這是一個基於ABP框架的起始專案. 有關更多訊息, 請瀏覽 abp.io." + } + } diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/DispatchResource.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/DispatchResource.cs new file mode 100644 index 0000000..fc03359 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/Localization/DispatchResource.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Localization; + +namespace KonSoft.Dispatch.Localization; + +[LocalizationResourceName("Dispatch")] +public class DispatchResource +{ + +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs new file mode 100644 index 0000000..7fb6333 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs @@ -0,0 +1,10 @@ +namespace KonSoft.Dispatch.MultiTenancy; + +public static class MultiTenancyConsts +{ + /* Enable/disable multi-tenancy easily in a single point. + * If you will never need to multi-tenancy, you can remove + * related modules and code parts, including this file. + */ + public const bool IsEnabled = true; +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain/Data/DispatchDbMigrationService.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain/Data/DispatchDbMigrationService.cs new file mode 100644 index 0000000..11680bc --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain/Data/DispatchDbMigrationService.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Dispatch.Data; + +public class DispatchDbMigrationService : ITransientDependency +{ + public ILogger Logger { get; set; } + + private readonly IDataSeeder _dataSeeder; + private readonly IEnumerable _dbSchemaMigrators; + private readonly ITenantRepository _tenantRepository; + private readonly ICurrentTenant _currentTenant; + + public DispatchDbMigrationService( + IDataSeeder dataSeeder, + IEnumerable dbSchemaMigrators, + ITenantRepository tenantRepository, + ICurrentTenant currentTenant) + { + _dataSeeder = dataSeeder; + _dbSchemaMigrators = dbSchemaMigrators; + _tenantRepository = tenantRepository; + _currentTenant = currentTenant; + + Logger = NullLogger.Instance; + } + + public async Task MigrateAsync() + { + var initialMigrationAdded = AddInitialMigrationIfNotExist(); + + if (initialMigrationAdded) + { + return; + } + + Logger.LogInformation("Started database migrations..."); + + await MigrateDatabaseSchemaAsync(); + await SeedDataAsync(); + + Logger.LogInformation($"Successfully completed host database migrations."); + + var tenants = await _tenantRepository.GetListAsync(includeDetails: true); + + var migratedDatabaseSchemas = new HashSet(); + foreach (var tenant in tenants) + { + using (_currentTenant.Change(tenant.Id)) + { + if (tenant.ConnectionStrings.Any()) + { + var tenantConnectionStrings = tenant.ConnectionStrings + .Select(x => x.Value) + .ToList(); + + if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings)) + { + await MigrateDatabaseSchemaAsync(tenant); + + migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings); + } + } + + await SeedDataAsync(tenant); + } + + Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations."); + } + + Logger.LogInformation("Successfully completed all database migrations."); + Logger.LogInformation("You can safely end this process..."); + } + + private async Task MigrateDatabaseSchemaAsync(Tenant? tenant = null) + { + Logger.LogInformation( + $"Migrating schema for {(tenant == null ? "host" : tenant.Name + " tenant")} database..."); + + foreach (var migrator in _dbSchemaMigrators) + { + await migrator.MigrateAsync(); + } + } + + private async Task SeedDataAsync(Tenant? tenant = null) + { + Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed..."); + + await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id) + .WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, IdentityDataSeedContributor.AdminEmailDefaultValue) + .WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, IdentityDataSeedContributor.AdminPasswordDefaultValue) + ); + } + + private bool AddInitialMigrationIfNotExist() + { + try + { + if (!DbMigrationsProjectExists()) + { + return false; + } + } + catch (Exception) + { + return false; + } + + try + { + if (!MigrationsFolderExists()) + { + AddInitialMigration(); + return true; + } + else + { + return false; + } + } + catch (Exception e) + { + Logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message); + return false; + } + } + + private bool DbMigrationsProjectExists() + { + var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath(); + + return dbMigrationsProjectFolder != null; + } + + private bool MigrationsFolderExists() + { + var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath(); + return dbMigrationsProjectFolder != null && Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations")); + } + + private void AddInitialMigration() + { + Logger.LogInformation("Creating initial migration..."); + + string argumentPrefix; + string fileName; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + argumentPrefix = "-c"; + fileName = "/bin/bash"; + } + else + { + argumentPrefix = "/C"; + fileName = "cmd.exe"; + } + + var procStartInfo = new ProcessStartInfo(fileName, + $"{argumentPrefix} \"abp create-migration-and-run-migrator \"{GetEntityFrameworkCoreProjectFolderPath()}\"\"" + ); + + try + { + Process.Start(procStartInfo); + } + catch (Exception) + { + throw new Exception("Couldn't run ABP CLI..."); + } + } + + private string? GetEntityFrameworkCoreProjectFolderPath() + { + var slnDirectoryPath = GetSolutionDirectoryPath(); + + if (slnDirectoryPath == null) + { + throw new Exception("Solution folder not found!"); + } + + var srcDirectoryPath = Path.Combine(slnDirectoryPath, "src"); + + return Directory.GetDirectories(srcDirectoryPath) + .FirstOrDefault(d => d.EndsWith(".EntityFrameworkCore")); + } + + private string? GetSolutionDirectoryPath() + { + var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory()); + + while (currentDirectory != null && Directory.GetParent(currentDirectory.FullName) != null) + { + currentDirectory = Directory.GetParent(currentDirectory.FullName); + + if (currentDirectory != null && Directory.GetFiles(currentDirectory.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null) + { + return currentDirectory.FullName; + } + } + + return null; + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain/Data/IDispatchDbSchemaMigrator.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain/Data/IDispatchDbSchemaMigrator.cs new file mode 100644 index 0000000..e161870 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain/Data/IDispatchDbSchemaMigrator.cs @@ -0,0 +1,8 @@ +using System.Threading.Tasks; + +namespace KonSoft.Dispatch.Data; + +public interface IDispatchDbSchemaMigrator +{ + Task MigrateAsync(); +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain/Data/NullDispatchDbSchemaMigrator.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain/Data/NullDispatchDbSchemaMigrator.cs new file mode 100644 index 0000000..cd2f4c2 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain/Data/NullDispatchDbSchemaMigrator.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Dispatch.Data; + +/* This is used if database provider does't define + * IDispatchDbSchemaMigrator implementation. + */ +public class NullDispatchDbSchemaMigrator : IDispatchDbSchemaMigrator, ITransientDependency +{ + public Task MigrateAsync() + { + return Task.CompletedTask; + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain/DispatchConsts.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain/DispatchConsts.cs new file mode 100644 index 0000000..e886226 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain/DispatchConsts.cs @@ -0,0 +1,8 @@ +namespace KonSoft.Dispatch; + +public static class DispatchConsts +{ + public const string DbTablePrefix = "App"; + + public const string DbSchema = null; +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain/DispatchDomainModule.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain/DispatchDomainModule.cs new file mode 100644 index 0000000..edd9075 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain/DispatchDomainModule.cs @@ -0,0 +1,68 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using KonSoft.Dispatch.MultiTenancy; +using Volo.Abp.AuditLogging; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Emailing; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.OpenIddict; +using Volo.Abp.PermissionManagement.Identity; +using Volo.Abp.PermissionManagement.OpenIddict; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Dispatch; + +[DependsOn( + typeof(DispatchDomainSharedModule), + typeof(AbpAuditLoggingDomainModule), + typeof(AbpBackgroundJobsDomainModule), + typeof(AbpFeatureManagementDomainModule), + typeof(AbpIdentityDomainModule), + typeof(AbpOpenIddictDomainModule), + typeof(AbpPermissionManagementDomainOpenIddictModule), + typeof(AbpPermissionManagementDomainIdentityModule), + typeof(AbpSettingManagementDomainModule), + typeof(AbpTenantManagementDomainModule), + typeof(AbpEmailingModule) +)] +public class DispatchDomainModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)")); + options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar")); + options.Languages.Add(new LanguageInfo("hr", "hr", "Croatian")); + options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish")); + options.Languages.Add(new LanguageInfo("fr", "fr", "Français")); + options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi")); + options.Languages.Add(new LanguageInfo("it", "it", "Italiano")); + options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); + options.Languages.Add(new LanguageInfo("ru", "ru", "Русский")); + options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak")); + options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); + options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch")); + options.Languages.Add(new LanguageInfo("es", "es", "Español")); + }); + + Configure(options => + { + options.IsEnabled = MultiTenancyConsts.IsEnabled; + }); + +#if DEBUG + context.Services.Replace(ServiceDescriptor.Singleton()); +#endif + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain/KonSoft.Dispatch.Domain.csproj b/modules/dispatch/src/KonSoft.Dispatch.Domain/KonSoft.Dispatch.Domain.csproj new file mode 100644 index 0000000..a2e6370 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain/KonSoft.Dispatch.Domain.csproj @@ -0,0 +1,28 @@ + + + + + + net8.0 + enable + KonSoft.Dispatch + + + + + + + + + + + + + + + + + + + + diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain/OpenIddict/OpenIddictDataSeedContributor.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain/OpenIddict/OpenIddictDataSeedContributor.cs new file mode 100644 index 0000000..6e766f2 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain/OpenIddict/OpenIddictDataSeedContributor.cs @@ -0,0 +1,327 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Localization; +using OpenIddict.Abstractions; +using Volo.Abp; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.OpenIddict.Applications; +using Volo.Abp.OpenIddict.Scopes; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Uow; + +namespace KonSoft.Dispatch.OpenIddict; + +/* Creates initial data that is needed to property run the application + * and make client-to-server communication possible. + */ +public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDependency +{ + private readonly IConfiguration _configuration; + private readonly IOpenIddictApplicationRepository _openIddictApplicationRepository; + private readonly IAbpApplicationManager _applicationManager; + private readonly IOpenIddictScopeRepository _openIddictScopeRepository; + private readonly IOpenIddictScopeManager _scopeManager; + private readonly IPermissionDataSeeder _permissionDataSeeder; + private readonly IStringLocalizer L; + + public OpenIddictDataSeedContributor( + IConfiguration configuration, + IOpenIddictApplicationRepository openIddictApplicationRepository, + IAbpApplicationManager applicationManager, + IOpenIddictScopeRepository openIddictScopeRepository, + IOpenIddictScopeManager scopeManager, + IPermissionDataSeeder permissionDataSeeder, + IStringLocalizer l ) + { + _configuration = configuration; + _openIddictApplicationRepository = openIddictApplicationRepository; + _applicationManager = applicationManager; + _openIddictScopeRepository = openIddictScopeRepository; + _scopeManager = scopeManager; + _permissionDataSeeder = permissionDataSeeder; + L = l; + } + + [UnitOfWork] + public virtual async Task SeedAsync(DataSeedContext context) + { + await CreateScopesAsync(); + await CreateApplicationsAsync(); + } + + private async Task CreateScopesAsync() + { + if (await _openIddictScopeRepository.FindByNameAsync("Dispatch") == null) + { + await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor { + Name = "Dispatch", DisplayName = "Dispatch API", Resources = { "Dispatch" } + }); + } + } + + private async Task CreateApplicationsAsync() + { + var commonScopes = new List { + OpenIddictConstants.Permissions.Scopes.Address, + OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Phone, + OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Roles, + "Dispatch" + }; + + var configurationSection = _configuration.GetSection("OpenIddict:Applications"); + + + + + + + // Swagger Client + var swaggerClientId = configurationSection["Dispatch_Swagger:ClientId"]; + if (!swaggerClientId.IsNullOrWhiteSpace()) + { + var swaggerRootUrl = configurationSection["Dispatch_Swagger:RootUrl"]?.TrimEnd('/'); + + await CreateApplicationAsync( + name: swaggerClientId!, + type: OpenIddictConstants.ClientTypes.Public, + consentType: OpenIddictConstants.ConsentTypes.Implicit, + displayName: "Swagger Application", + secret: null, + grantTypes: new List { OpenIddictConstants.GrantTypes.AuthorizationCode, }, + scopes: commonScopes, + redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html", + clientUri: swaggerRootUrl + ); + } + } + + private async Task CreateApplicationAsync( + [NotNull] string name, + [NotNull] string type, + [NotNull] string consentType, + string displayName, + string? secret, + List grantTypes, + List scopes, + string? clientUri = null, + string? redirectUri = null, + string? postLogoutRedirectUri = null, + List? permissions = null) + { + if (!string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Public, + StringComparison.OrdinalIgnoreCase)) + { + throw new BusinessException(L["NoClientSecretCanBeSetForPublicApplications"]); + } + + if (string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, + StringComparison.OrdinalIgnoreCase)) + { + throw new BusinessException(L["TheClientSecretIsRequiredForConfidentialApplications"]); + } + + var client = await _openIddictApplicationRepository.FindByClientIdAsync(name); + + var application = new AbpApplicationDescriptor { + ClientId = name, + ClientType = type, + ClientSecret = secret, + ConsentType = consentType, + DisplayName = displayName, + ClientUri = clientUri, + }; + + Check.NotNullOrEmpty(grantTypes, nameof(grantTypes)); + Check.NotNullOrEmpty(scopes, nameof(scopes)); + + if (new[] { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }.All( + grantTypes.Contains)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken); + + if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeToken); + } + } + + if (!redirectUri.IsNullOrWhiteSpace() || !postLogoutRedirectUri.IsNullOrWhiteSpace()) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout); + } + + var buildInGrantTypes = new[] { + OpenIddictConstants.GrantTypes.Implicit, OpenIddictConstants.GrantTypes.Password, + OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.ClientCredentials, + OpenIddictConstants.GrantTypes.DeviceCode, OpenIddictConstants.GrantTypes.RefreshToken + }; + + foreach (var grantType in grantTypes) + { + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code); + } + + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || + grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization); + } + + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || + grantType == OpenIddictConstants.GrantTypes.ClientCredentials || + grantType == OpenIddictConstants.GrantTypes.Password || + grantType == OpenIddictConstants.GrantTypes.RefreshToken || + grantType == OpenIddictConstants.GrantTypes.DeviceCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Revocation); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Introspection); + } + + if (grantType == OpenIddictConstants.GrantTypes.ClientCredentials) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials); + } + + if (grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit); + } + + if (grantType == OpenIddictConstants.GrantTypes.Password) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password); + } + + if (grantType == OpenIddictConstants.GrantTypes.RefreshToken) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken); + } + + if (grantType == OpenIddictConstants.GrantTypes.DeviceCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.DeviceCode); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Device); + } + + if (grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdToken); + if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Token); + } + } + + if (!buildInGrantTypes.Contains(grantType)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.GrantType + grantType); + } + } + + var buildInScopes = new[] { + OpenIddictConstants.Permissions.Scopes.Address, OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Phone, OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Roles + }; + + foreach (var scope in scopes) + { + if (buildInScopes.Contains(scope)) + { + application.Permissions.Add(scope); + } + else + { + application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.Scope + scope); + } + } + + if (redirectUri != null) + { + if (!redirectUri.IsNullOrEmpty()) + { + if (!Uri.TryCreate(redirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) + { + throw new BusinessException(L["InvalidRedirectUri", redirectUri]); + } + + if (application.RedirectUris.All(x => x != uri)) + { + application.RedirectUris.Add(uri); + } + } + } + + if (postLogoutRedirectUri != null) + { + if (!postLogoutRedirectUri.IsNullOrEmpty()) + { + if (!Uri.TryCreate(postLogoutRedirectUri, UriKind.Absolute, out var uri) || + !uri.IsWellFormedOriginalString()) + { + throw new BusinessException(L["InvalidPostLogoutRedirectUri", postLogoutRedirectUri]); + } + + if (application.PostLogoutRedirectUris.All(x => x != uri)) + { + application.PostLogoutRedirectUris.Add(uri); + } + } + } + + if (permissions != null) + { + await _permissionDataSeeder.SeedAsync( + ClientPermissionValueProvider.ProviderName, + name, + permissions, + null + ); + } + + if (client == null) + { + await _applicationManager.CreateAsync(application); + return; + } + + if (!HasSameRedirectUris(client, application)) + { + client.RedirectUris = JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); + client.PostLogoutRedirectUris = JsonSerializer.Serialize(application.PostLogoutRedirectUris.Select(q => q.ToString().TrimEnd('/'))); + + await _applicationManager.UpdateAsync(client.ToModel()); + } + + if (!HasSameScopes(client, application)) + { + client.Permissions = JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString())); + await _applicationManager.UpdateAsync(client.ToModel()); + } + } + + private bool HasSameRedirectUris(OpenIddictApplication existingClient, AbpApplicationDescriptor application) + { + return existingClient.RedirectUris == JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); + } + + private bool HasSameScopes(OpenIddictApplication existingClient, AbpApplicationDescriptor application) + { + return existingClient.Permissions == JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString().TrimEnd('/'))); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain/Properties/AssemblyInfo.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..62d174d --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.Dispatch.Domain.Tests")] +[assembly:InternalsVisibleToAttribute("KonSoft.Dispatch.TestBase")] diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain/Settings/DispatchSettingDefinitionProvider.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain/Settings/DispatchSettingDefinitionProvider.cs new file mode 100644 index 0000000..a90d428 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain/Settings/DispatchSettingDefinitionProvider.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Settings; + +namespace KonSoft.Dispatch.Settings; + +public class DispatchSettingDefinitionProvider : SettingDefinitionProvider +{ + public override void Define(ISettingDefinitionContext context) + { + //Define your own settings here. Example: + //context.Add(new SettingDefinition(DispatchSettings.MySetting1)); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.Domain/Settings/DispatchSettings.cs b/modules/dispatch/src/KonSoft.Dispatch.Domain/Settings/DispatchSettings.cs new file mode 100644 index 0000000..606a2b9 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.Domain/Settings/DispatchSettings.cs @@ -0,0 +1,9 @@ +namespace KonSoft.Dispatch.Settings; + +public static class DispatchSettings +{ + private const string Prefix = "Dispatch"; + + //Add your own setting names here. Example: + //public const string MySetting1 = Prefix + ".MySetting1"; +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchDbContext.cs b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchDbContext.cs new file mode 100644 index 0000000..857a29c --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchDbContext.cs @@ -0,0 +1,86 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.AuditLogging.EntityFrameworkCore; +using Volo.Abp.BackgroundJobs.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Identity; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.OpenIddict.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.TenantManagement; +using Volo.Abp.TenantManagement.EntityFrameworkCore; + +namespace KonSoft.Dispatch.EntityFrameworkCore; + +[ReplaceDbContext(typeof(IIdentityDbContext))] +[ReplaceDbContext(typeof(ITenantManagementDbContext))] +[ConnectionStringName("Default")] +public class DispatchDbContext : + AbpDbContext, + IIdentityDbContext, + ITenantManagementDbContext +{ + /* Add DbSet properties for your Aggregate Roots / Entities here. */ + + #region Entities from the modules + + /* Notice: We only implemented IIdentityDbContext and ITenantManagementDbContext + * and replaced them for this DbContext. This allows you to perform JOIN + * queries for the entities of these modules over the repositories easily. You + * typically don't need that for other modules. But, if you need, you can + * implement the DbContext interface of the needed module and use ReplaceDbContext + * attribute just like IIdentityDbContext and ITenantManagementDbContext. + * + * More info: Replacing a DbContext of a module ensures that the related module + * uses this DbContext on runtime. Otherwise, it will use its own DbContext class. + */ + + //Identity + public DbSet Users { get; set; } + public DbSet Roles { get; set; } + public DbSet ClaimTypes { get; set; } + public DbSet OrganizationUnits { get; set; } + public DbSet SecurityLogs { get; set; } + public DbSet LinkUsers { get; set; } + public DbSet UserDelegations { get; set; } + public DbSet Sessions { get; set; } + // Tenant Management + public DbSet Tenants { get; set; } + public DbSet TenantConnectionStrings { get; set; } + + #endregion + + public DispatchDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + /* Include modules to your migration db context */ + + builder.ConfigurePermissionManagement(); + builder.ConfigureSettingManagement(); + builder.ConfigureBackgroundJobs(); + builder.ConfigureAuditLogging(); + builder.ConfigureIdentity(); + builder.ConfigureOpenIddict(); + builder.ConfigureFeatureManagement(); + builder.ConfigureTenantManagement(); + + /* Configure your own tables/entities inside here */ + + //builder.Entity(b => + //{ + // b.ToTable(DispatchConsts.DbTablePrefix + "YourEntities", DispatchConsts.DbSchema); + // b.ConfigureByConvention(); //auto configure for the base class props + // //... + //}); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchDbContextFactory.cs b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchDbContextFactory.cs new file mode 100644 index 0000000..83440e2 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchDbContextFactory.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; + +namespace KonSoft.Dispatch.EntityFrameworkCore; + +/* This class is needed for EF Core console commands + * (like Add-Migration and Update-Database commands) */ +public class DispatchDbContextFactory : IDesignTimeDbContextFactory +{ + public DispatchDbContext CreateDbContext(string[] args) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + + DispatchEfCoreEntityExtensionMappings.Configure(); + + var configuration = BuildConfiguration(); + + var builder = new DbContextOptionsBuilder() + .UseNpgsql(configuration.GetConnectionString("Default")); + + return new DispatchDbContext(builder.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../KonSoft.Dispatch.DbMigrator/")) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchEfCoreEntityExtensionMappings.cs b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchEfCoreEntityExtensionMappings.cs new file mode 100644 index 0000000..61f016e --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchEfCoreEntityExtensionMappings.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.Dispatch.EntityFrameworkCore; + +public static class DispatchEfCoreEntityExtensionMappings +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + DispatchGlobalFeatureConfigurator.Configure(); + DispatchModuleExtensionConfigurator.Configure(); + + OneTimeRunner.Run(() => + { + /* You can configure extra properties for the + * entities defined in the modules used by your application. + * + * This class can be used to map these extra properties to table fields in the database. + * + * USE THIS CLASS ONLY TO CONFIGURE EF CORE RELATED MAPPING. + * USE DispatchModuleExtensionConfigurator CLASS (in the Domain.Shared project) + * FOR A HIGH LEVEL API TO DEFINE EXTRA PROPERTIES TO ENTITIES OF THE USED MODULES + * + * Example: Map a property to a table field: + + ObjectExtensionManager.Instance + .MapEfCoreProperty( + "MyProperty", + (entityBuilder, propertyBuilder) => + { + propertyBuilder.HasMaxLength(128); + } + ); + + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities + */ + }); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchEntityFrameworkCoreModule.cs b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchEntityFrameworkCoreModule.cs new file mode 100644 index 0000000..788dca1 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/DispatchEntityFrameworkCoreModule.cs @@ -0,0 +1,57 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Uow; +using Volo.Abp.AuditLogging.EntityFrameworkCore; +using Volo.Abp.BackgroundJobs.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.TenantManagement.EntityFrameworkCore; + +namespace KonSoft.Dispatch.EntityFrameworkCore; + +[DependsOn( + typeof(DispatchDomainModule), + typeof(AbpIdentityEntityFrameworkCoreModule), + typeof(AbpOpenIddictEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpBackgroundJobsEntityFrameworkCoreModule), + typeof(AbpAuditLoggingEntityFrameworkCoreModule), + typeof(AbpTenantManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule) + )] +public class DispatchEntityFrameworkCoreModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + + DispatchEfCoreEntityExtensionMappings.Configure(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(options => + { + /* Remove "includeAllEntities: true" to create + * default repositories only for aggregate roots */ + options.AddDefaultRepositories(includeAllEntities: true); + }); + + Configure(options => + { + /* The main point to change your DBMS. + * See also DispatchMigrationsDbContextFactory for EF Core tooling. */ + options.UseNpgsql(); + }); + + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreDispatchDbSchemaMigrator.cs b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreDispatchDbSchemaMigrator.cs new file mode 100644 index 0000000..6475cdb --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreDispatchDbSchemaMigrator.cs @@ -0,0 +1,34 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using KonSoft.Dispatch.Data; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Dispatch.EntityFrameworkCore; + +public class EntityFrameworkCoreDispatchDbSchemaMigrator + : IDispatchDbSchemaMigrator, ITransientDependency +{ + private readonly IServiceProvider _serviceProvider; + + public EntityFrameworkCoreDispatchDbSchemaMigrator( + IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public async Task MigrateAsync() + { + /* We intentionally resolve the DispatchDbContext + * from IServiceProvider (instead of directly injecting it) + * to properly get the connection string of the current tenant in the + * current scope. + */ + + await _serviceProvider + .GetRequiredService() + .Database + .MigrateAsync(); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/KonSoft.Dispatch.EntityFrameworkCore.csproj b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/KonSoft.Dispatch.EntityFrameworkCore.csproj new file mode 100644 index 0000000..4c1c6f1 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/KonSoft.Dispatch.EntityFrameworkCore.csproj @@ -0,0 +1,31 @@ + + + + + + net8.0 + enable + KonSoft.Dispatch + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + diff --git a/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Migrations/20250908052345_Initial.Designer.cs b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Migrations/20250908052345_Initial.Designer.cs new file mode 100644 index 0000000..6135d0a --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Migrations/20250908052345_Initial.Designer.cs @@ -0,0 +1,2006 @@ +// +using System; +using KonSoft.Dispatch.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace KonSoft.Dispatch.Migrations +{ + [DbContext(typeof(DispatchDbContext))] + [Migration("20250908052345_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("text"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("integer") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("smallint") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("uuid"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("EntityChangeId") + .HasColumnType("uuid"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsAbandoned") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("JobArgs") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)"); + + b.Property("JobName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LastTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("NextTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((byte)15); + + b.Property("TryCount") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((short)0); + + b.HasKey("Id"); + + b.HasIndex("IsAbandoned", "NextTryTime"); + + b.ToTable("AbpBackgroundJobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property("ValueType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("SourceTenantId") + .HasColumnType("uuid"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("TargetTenantId") + .HasColumnType("uuid"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique(); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("boolean") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("boolean") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("IpAddresses") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("LastAccessed") + .HasColumnType("timestamp without time zone"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("SignedIn") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("boolean"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("EndTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("StartTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("character varying(196)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("character varying(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ClientSecret") + .HasColumnType("text"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientUri") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JsonWebKeySet") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasColumnType("text"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedirectUris") + .HasColumnType("text"); + + b.Property("Requirements") + .HasColumnType("text"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Scopes") + .HasColumnType("text"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Descriptions") + .HasColumnType("text"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Resources") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AuthorizationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Payload") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("MultiTenancySide") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("boolean"); + + b.Property("IsInherited") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + + b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) + .WithMany() + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Migrations/20250908052345_Initial.cs b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Migrations/20250908052345_Initial.cs new file mode 100644 index 0000000..8d71e00 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Migrations/20250908052345_Initial.cs @@ -0,0 +1,1156 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace KonSoft.Dispatch.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpAuditLogs", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationName = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + TenantName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ImpersonatorUserId = table.Column(type: "uuid", nullable: true), + ImpersonatorUserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ImpersonatorTenantId = table.Column(type: "uuid", nullable: true), + ImpersonatorTenantName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ExecutionTime = table.Column(type: "timestamp without time zone", nullable: false), + ExecutionDuration = table.Column(type: "integer", nullable: false), + ClientIpAddress = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + HttpMethod = table.Column(type: "character varying(16)", maxLength: 16, nullable: true), + Url = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + Exceptions = table.Column(type: "text", nullable: true), + Comments = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + HttpStatusCode = table.Column(type: "integer", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpBackgroundJobs", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + JobName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + JobArgs = table.Column(type: "character varying(1048576)", maxLength: 1048576, nullable: false), + TryCount = table.Column(type: "smallint", nullable: false, defaultValue: (short)0), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + NextTryTime = table.Column(type: "timestamp without time zone", nullable: false), + LastTryTime = table.Column(type: "timestamp without time zone", nullable: true), + IsAbandoned = table.Column(type: "boolean", nullable: false, defaultValue: false), + Priority = table.Column(type: "smallint", nullable: false, defaultValue: (byte)15), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpBackgroundJobs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpClaimTypes", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Required = table.Column(type: "boolean", nullable: false), + IsStatic = table.Column(type: "boolean", nullable: false), + Regex = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + RegexDescription = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatureGroups", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatures", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + GroupName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ParentName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + DefaultValue = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + IsVisibleToClients = table.Column(type: "boolean", nullable: false), + IsAvailableToHost = table.Column(type: "boolean", nullable: false), + AllowedProviders = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatures", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatureValues", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureValues", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpLinkUsers", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + SourceUserId = table.Column(type: "uuid", nullable: false), + SourceTenantId = table.Column(type: "uuid", nullable: true), + TargetUserId = table.Column(type: "uuid", nullable: false), + TargetTenantId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLinkUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ParentId = table.Column(type: "uuid", nullable: true), + Code = table.Column(type: "character varying(95)", maxLength: 95, nullable: false), + DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGrants", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGrants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGroups", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + GroupName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ParentName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsEnabled = table.Column(type: "boolean", nullable: false), + MultiTenancySide = table.Column(type: "smallint", nullable: false), + Providers = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + StateCheckers = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpRoles", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsDefault = table.Column(type: "boolean", nullable: false), + IsStatic = table.Column(type: "boolean", nullable: false), + IsPublic = table.Column(type: "boolean", nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSecurityLogs", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ApplicationName = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + Identity = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + Action = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + TenantName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientIpAddress = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSecurityLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSessions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + SessionId = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Device = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + DeviceInfo = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + UserId = table.Column(type: "uuid", nullable: false), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + IpAddresses = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + SignedIn = table.Column(type: "timestamp without time zone", nullable: false), + LastAccessed = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSessions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSettingDefinitions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + DefaultValue = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + IsVisibleToClients = table.Column(type: "boolean", nullable: false), + Providers = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + IsInherited = table.Column(type: "boolean", nullable: false), + IsEncrypted = table.Column(type: "boolean", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettingDefinitions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSettings", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpTenants", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUserDelegations", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + SourceUserId = table.Column(type: "uuid", nullable: false), + TargetUserId = table.Column(type: "uuid", nullable: false), + StartTime = table.Column(type: "timestamp without time zone", nullable: false), + EndTime = table.Column(type: "timestamp without time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserDelegations", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUsers", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedUserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + Surname = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + Email = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedEmail = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + EmailConfirmed = table.Column(type: "boolean", nullable: false, defaultValue: false), + PasswordHash = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + SecurityStamp = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsExternal = table.Column(type: "boolean", nullable: false, defaultValue: false), + PhoneNumber = table.Column(type: "character varying(16)", maxLength: 16, nullable: true), + PhoneNumberConfirmed = table.Column(type: "boolean", nullable: false, defaultValue: false), + IsActive = table.Column(type: "boolean", nullable: false), + TwoFactorEnabled = table.Column(type: "boolean", nullable: false, defaultValue: false), + LockoutEnd = table.Column(type: "timestamp with time zone", nullable: true), + LockoutEnabled = table.Column(type: "boolean", nullable: false, defaultValue: false), + AccessFailedCount = table.Column(type: "integer", nullable: false, defaultValue: 0), + ShouldChangePasswordOnNextLogin = table.Column(type: "boolean", nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + LastPasswordChangeTime = table.Column(type: "timestamp with time zone", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictApplications", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ClientId = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + ClientSecret = table.Column(type: "text", nullable: true), + ClientType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ConsentType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + DisplayName = table.Column(type: "text", nullable: true), + DisplayNames = table.Column(type: "text", nullable: true), + JsonWebKeySet = table.Column(type: "text", nullable: true), + Permissions = table.Column(type: "text", nullable: true), + PostLogoutRedirectUris = table.Column(type: "text", nullable: true), + Properties = table.Column(type: "text", nullable: true), + RedirectUris = table.Column(type: "text", nullable: true), + Requirements = table.Column(type: "text", nullable: true), + Settings = table.Column(type: "text", nullable: true), + ClientUri = table.Column(type: "text", nullable: true), + LogoUri = table.Column(type: "text", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictApplications", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictScopes", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Description = table.Column(type: "text", nullable: true), + Descriptions = table.Column(type: "text", nullable: true), + DisplayName = table.Column(type: "text", nullable: true), + DisplayNames = table.Column(type: "text", nullable: true), + Name = table.Column(type: "character varying(200)", maxLength: 200, nullable: true), + Properties = table.Column(type: "text", nullable: true), + Resources = table.Column(type: "text", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictScopes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpAuditLogActions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + AuditLogId = table.Column(type: "uuid", nullable: false), + ServiceName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + MethodName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Parameters = table.Column(type: "character varying(2000)", maxLength: 2000, nullable: true), + ExecutionTime = table.Column(type: "timestamp without time zone", nullable: false), + ExecutionDuration = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogActions", x => x.Id); + table.ForeignKey( + name: "FK_AbpAuditLogActions_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpEntityChanges", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + AuditLogId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ChangeTime = table.Column(type: "timestamp without time zone", nullable: false), + ChangeType = table.Column(type: "smallint", nullable: false), + EntityTenantId = table.Column(type: "uuid", nullable: true), + EntityId = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + EntityTypeFullName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityChanges_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(type: "uuid", nullable: false), + OrganizationUnitId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationU~", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpRoleClaims", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ClaimType = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpRoleClaims_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpTenantConnectionStrings", + columns: table => new + { + TenantId = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Value = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenantConnectionStrings", x => new { x.TenantId, x.Name }); + table.ForeignKey( + name: "FK_AbpTenantConnectionStrings_AbpTenants_TenantId", + column: x => x.TenantId, + principalTable: "AbpTenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserClaims", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ClaimType = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpUserClaims_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserLogins", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + LoginProvider = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ProviderKey = table.Column(type: "character varying(196)", maxLength: 196, nullable: false), + ProviderDisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserLogins", x => new { x.UserId, x.LoginProvider }); + table.ForeignKey( + name: "FK_AbpUserLogins_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + OrganizationUnitId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationU~", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserRoles", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserTokens", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + LoginProvider = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Value = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AbpUserTokens_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictAuthorizations", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationId = table.Column(type: "uuid", nullable: true), + CreationDate = table.Column(type: "timestamp without time zone", nullable: true), + Properties = table.Column(type: "text", nullable: true), + Scopes = table.Column(type: "text", nullable: true), + Status = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + Subject = table.Column(type: "character varying(400)", maxLength: 400, nullable: true), + Type = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictAuthorizations_OpenIddictApplications_Application~", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AbpEntityPropertyChanges", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + EntityChangeId = table.Column(type: "uuid", nullable: false), + NewValue = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + OriginalValue = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + PropertyName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + PropertyTypeFullName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityPropertyChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityPropertyChanges_AbpEntityChanges_EntityChangeId", + column: x => x.EntityChangeId, + principalTable: "AbpEntityChanges", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictTokens", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationId = table.Column(type: "uuid", nullable: true), + AuthorizationId = table.Column(type: "uuid", nullable: true), + CreationDate = table.Column(type: "timestamp without time zone", nullable: true), + ExpirationDate = table.Column(type: "timestamp without time zone", nullable: true), + Payload = table.Column(type: "text", nullable: true), + Properties = table.Column(type: "text", nullable: true), + RedemptionDate = table.Column(type: "timestamp without time zone", nullable: true), + ReferenceId = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + Status = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + Subject = table.Column(type: "character varying(400)", maxLength: 400, nullable: true), + Type = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictTokens", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId", + column: x => x.AuthorizationId, + principalTable: "OpenIddictAuthorizations", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_AuditLogId", + table: "AbpAuditLogActions", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_TenantId_ServiceName_MethodName_Executio~", + table: "AbpAuditLogActions", + columns: new[] { "TenantId", "ServiceName", "MethodName", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_UserId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "UserId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpBackgroundJobs_IsAbandoned_NextTryTime", + table: "AbpBackgroundJobs", + columns: new[] { "IsAbandoned", "NextTryTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_AuditLogId", + table: "AbpEntityChanges", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_TenantId_EntityTypeFullName_EntityId", + table: "AbpEntityChanges", + columns: new[] { "TenantId", "EntityTypeFullName", "EntityId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityPropertyChanges_EntityChangeId", + table: "AbpEntityPropertyChanges", + column: "EntityChangeId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureGroups_Name", + table: "AbpFeatureGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_GroupName", + table: "AbpFeatures", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_Name", + table: "AbpFeatures", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureValues_Name_ProviderName_ProviderKey", + table: "AbpFeatureValues", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpLinkUsers_SourceUserId_SourceTenantId_TargetUserId_Targe~", + table: "AbpLinkUsers", + columns: new[] { "SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGrants_TenantId_Name_ProviderName_ProviderKey", + table: "AbpPermissionGrants", + columns: new[] { "TenantId", "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGroups_Name", + table: "AbpPermissionGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_GroupName", + table: "AbpPermissions", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_Name", + table: "AbpPermissions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoleClaims_RoleId", + table: "AbpRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoles_NormalizedName", + table: "AbpRoles", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Action", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Action" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_ApplicationName", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "ApplicationName" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Identity", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Identity" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_UserId", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_Device", + table: "AbpSessions", + column: "Device"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_SessionId", + table: "AbpSessions", + column: "SessionId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_TenantId_UserId", + table: "AbpSessions", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettingDefinitions_Name", + table: "AbpSettingDefinitions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettings_Name_ProviderName_ProviderKey", + table: "AbpSettings", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_Name", + table: "AbpTenants", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserClaims_UserId", + table: "AbpUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserLogins_LoginProvider_ProviderKey", + table: "AbpUserLogins", + columns: new[] { "LoginProvider", "ProviderKey" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserRoles_RoleId_UserId", + table: "AbpUserRoles", + columns: new[] { "RoleId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_Email", + table: "AbpUsers", + column: "Email"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedEmail", + table: "AbpUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedUserName", + table: "AbpUsers", + column: "NormalizedUserName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_UserName", + table: "AbpUsers", + column: "UserName"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictApplications_ClientId", + table: "OpenIddictApplications", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictAuthorizations_ApplicationId_Status_Subject_Type", + table: "OpenIddictAuthorizations", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictScopes_Name", + table: "OpenIddictScopes", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ApplicationId_Status_Subject_Type", + table: "OpenIddictTokens", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_AuthorizationId", + table: "OpenIddictTokens", + column: "AuthorizationId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ReferenceId", + table: "OpenIddictTokens", + column: "ReferenceId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpAuditLogActions"); + + migrationBuilder.DropTable( + name: "AbpBackgroundJobs"); + + migrationBuilder.DropTable( + name: "AbpClaimTypes"); + + migrationBuilder.DropTable( + name: "AbpEntityPropertyChanges"); + + migrationBuilder.DropTable( + name: "AbpFeatureGroups"); + + migrationBuilder.DropTable( + name: "AbpFeatures"); + + migrationBuilder.DropTable( + name: "AbpFeatureValues"); + + migrationBuilder.DropTable( + name: "AbpLinkUsers"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + + migrationBuilder.DropTable( + name: "AbpPermissionGrants"); + + migrationBuilder.DropTable( + name: "AbpPermissionGroups"); + + migrationBuilder.DropTable( + name: "AbpPermissions"); + + migrationBuilder.DropTable( + name: "AbpRoleClaims"); + + migrationBuilder.DropTable( + name: "AbpSecurityLogs"); + + migrationBuilder.DropTable( + name: "AbpSessions"); + + migrationBuilder.DropTable( + name: "AbpSettingDefinitions"); + + migrationBuilder.DropTable( + name: "AbpSettings"); + + migrationBuilder.DropTable( + name: "AbpTenantConnectionStrings"); + + migrationBuilder.DropTable( + name: "AbpUserClaims"); + + migrationBuilder.DropTable( + name: "AbpUserDelegations"); + + migrationBuilder.DropTable( + name: "AbpUserLogins"); + + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpUserRoles"); + + migrationBuilder.DropTable( + name: "AbpUserTokens"); + + migrationBuilder.DropTable( + name: "OpenIddictScopes"); + + migrationBuilder.DropTable( + name: "OpenIddictTokens"); + + migrationBuilder.DropTable( + name: "AbpEntityChanges"); + + migrationBuilder.DropTable( + name: "AbpTenants"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpRoles"); + + migrationBuilder.DropTable( + name: "AbpUsers"); + + migrationBuilder.DropTable( + name: "OpenIddictAuthorizations"); + + migrationBuilder.DropTable( + name: "AbpAuditLogs"); + + migrationBuilder.DropTable( + name: "OpenIddictApplications"); + } + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Migrations/DispatchDbContextModelSnapshot.cs b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Migrations/DispatchDbContextModelSnapshot.cs new file mode 100644 index 0000000..c679511 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Migrations/DispatchDbContextModelSnapshot.cs @@ -0,0 +1,2003 @@ +// +using System; +using KonSoft.Dispatch.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace KonSoft.Dispatch.Migrations +{ + [DbContext(typeof(DispatchDbContext))] + partial class DispatchDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("text"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("integer") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("smallint") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("uuid"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("EntityChangeId") + .HasColumnType("uuid"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsAbandoned") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("JobArgs") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)"); + + b.Property("JobName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LastTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("NextTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((byte)15); + + b.Property("TryCount") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((short)0); + + b.HasKey("Id"); + + b.HasIndex("IsAbandoned", "NextTryTime"); + + b.ToTable("AbpBackgroundJobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property("ValueType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("SourceTenantId") + .HasColumnType("uuid"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("TargetTenantId") + .HasColumnType("uuid"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique(); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("boolean") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("boolean") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("IpAddresses") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("LastAccessed") + .HasColumnType("timestamp without time zone"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("SignedIn") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("boolean"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("EndTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("StartTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("character varying(196)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("character varying(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ClientSecret") + .HasColumnType("text"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientUri") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JsonWebKeySet") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasColumnType("text"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedirectUris") + .HasColumnType("text"); + + b.Property("Requirements") + .HasColumnType("text"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Scopes") + .HasColumnType("text"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Descriptions") + .HasColumnType("text"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Resources") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AuthorizationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Payload") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("MultiTenancySide") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("boolean"); + + b.Property("IsInherited") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + + b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) + .WithMany() + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Properties/AssemblyInfo.cs b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b9f7b48 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.EntityFrameworkCore/Properties/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.Dispatch.EntityFrameworkCore.Tests")] diff --git a/modules/dispatch/src/KonSoft.Dispatch.HttpApi.Client/DispatchHttpApiClientModule.cs b/modules/dispatch/src/KonSoft.Dispatch.HttpApi.Client/DispatchHttpApiClientModule.cs new file mode 100644 index 0000000..f91692b --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.HttpApi.Client/DispatchHttpApiClientModule.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.TenantManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.Dispatch; + +[DependsOn( + typeof(DispatchApplicationContractsModule), + typeof(AbpAccountHttpApiClientModule), + typeof(AbpIdentityHttpApiClientModule), + typeof(AbpPermissionManagementHttpApiClientModule), + typeof(AbpTenantManagementHttpApiClientModule), + typeof(AbpFeatureManagementHttpApiClientModule), + typeof(AbpSettingManagementHttpApiClientModule) +)] +public class DispatchHttpApiClientModule : AbpModule +{ + public const string RemoteServiceName = "Default"; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddHttpClientProxies( + typeof(DispatchApplicationContractsModule).Assembly, + RemoteServiceName + ); + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.HttpApi.Client/KonSoft.Dispatch.HttpApi.Client.csproj b/modules/dispatch/src/KonSoft.Dispatch.HttpApi.Client/KonSoft.Dispatch.HttpApi.Client.csproj new file mode 100644 index 0000000..08a8461 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.HttpApi.Client/KonSoft.Dispatch.HttpApi.Client.csproj @@ -0,0 +1,29 @@ + + + + + + net8.0 + enable + KonSoft.Dispatch + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/dispatch/src/KonSoft.Dispatch.HttpApi/Controllers/DispatchController.cs b/modules/dispatch/src/KonSoft.Dispatch.HttpApi/Controllers/DispatchController.cs new file mode 100644 index 0000000..a1cea3d --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.HttpApi/Controllers/DispatchController.cs @@ -0,0 +1,14 @@ +using KonSoft.Dispatch.Localization; +using Volo.Abp.AspNetCore.Mvc; + +namespace KonSoft.Dispatch.Controllers; + +/* Inherit your controllers from this class. + */ +public abstract class DispatchController : AbpControllerBase +{ + protected DispatchController() + { + LocalizationResource = typeof(DispatchResource); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.HttpApi/DispatchHttpApiModule.cs b/modules/dispatch/src/KonSoft.Dispatch.HttpApi/DispatchHttpApiModule.cs new file mode 100644 index 0000000..c5bf83b --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.HttpApi/DispatchHttpApiModule.cs @@ -0,0 +1,41 @@ +using Localization.Resources.AbpUi; +using KonSoft.Dispatch.Localization; +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.HttpApi; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Dispatch; + +[DependsOn( + typeof(DispatchApplicationContractsModule), + typeof(AbpAccountHttpApiModule), + typeof(AbpIdentityHttpApiModule), + typeof(AbpPermissionManagementHttpApiModule), + typeof(AbpTenantManagementHttpApiModule), + typeof(AbpFeatureManagementHttpApiModule), + typeof(AbpSettingManagementHttpApiModule) + )] +public class DispatchHttpApiModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + ConfigureLocalization(); + } + + private void ConfigureLocalization() + { + Configure(options => + { + options.Resources + .Get() + .AddBaseTypes( + typeof(AbpUiResource) + ); + }); + } +} diff --git a/modules/dispatch/src/KonSoft.Dispatch.HttpApi/KonSoft.Dispatch.HttpApi.csproj b/modules/dispatch/src/KonSoft.Dispatch.HttpApi/KonSoft.Dispatch.HttpApi.csproj new file mode 100644 index 0000000..0d821e0 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.HttpApi/KonSoft.Dispatch.HttpApi.csproj @@ -0,0 +1,24 @@ + + + + + + net8.0 + enable + KonSoft.Dispatch + + + + + + + + + + + + + + + + diff --git a/modules/dispatch/src/KonSoft.Dispatch.HttpApi/Models/Test/TestModel.cs b/modules/dispatch/src/KonSoft.Dispatch.HttpApi/Models/Test/TestModel.cs new file mode 100644 index 0000000..7da0622 --- /dev/null +++ b/modules/dispatch/src/KonSoft.Dispatch.HttpApi/Models/Test/TestModel.cs @@ -0,0 +1,10 @@ +using System; + +namespace KonSoft.Dispatch.Models.Test; + +public class TestModel +{ + public string? Name { get; set; } + + public DateTime BirthDate { get; set; } +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.Application.Tests/DispatchApplicationTestBase.cs b/modules/dispatch/test/KonSoft.Dispatch.Application.Tests/DispatchApplicationTestBase.cs new file mode 100644 index 0000000..3638395 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.Application.Tests/DispatchApplicationTestBase.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Dispatch; + +public abstract class DispatchApplicationTestBase : DispatchTestBase + where TStartupModule : IAbpModule +{ + +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.Application.Tests/DispatchApplicationTestModule.cs b/modules/dispatch/test/KonSoft.Dispatch.Application.Tests/DispatchApplicationTestModule.cs new file mode 100644 index 0000000..a2e8f91 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.Application.Tests/DispatchApplicationTestModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Dispatch; + +[DependsOn( + typeof(DispatchApplicationModule), + typeof(DispatchDomainTestModule) +)] +public class DispatchApplicationTestModule : AbpModule +{ + +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.Application.Tests/KonSoft.Dispatch.Application.Tests.csproj b/modules/dispatch/test/KonSoft.Dispatch.Application.Tests/KonSoft.Dispatch.Application.Tests.csproj new file mode 100644 index 0000000..6218618 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.Application.Tests/KonSoft.Dispatch.Application.Tests.csproj @@ -0,0 +1,20 @@ + + + + + + net8.0 + enable + KonSoft.Dispatch + + + + + + + + + + + + diff --git a/modules/dispatch/test/KonSoft.Dispatch.Application.Tests/Samples/SampleAppServiceTests.cs b/modules/dispatch/test/KonSoft.Dispatch.Application.Tests/Samples/SampleAppServiceTests.cs new file mode 100644 index 0000000..51703b8 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.Application.Tests/Samples/SampleAppServiceTests.cs @@ -0,0 +1,34 @@ +using Shouldly; +using System.Threading.Tasks; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Xunit; + +namespace KonSoft.Dispatch.Samples; + +/* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IIdentityUserAppService here). + * Only test your own application services. + */ +public abstract class SampleAppServiceTests : DispatchApplicationTestBase + where TStartupModule : IAbpModule +{ + private readonly IIdentityUserAppService _userAppService; + + protected SampleAppServiceTests() + { + _userAppService = GetRequiredService(); + } + + [Fact] + public async Task Initial_Data_Should_Contain_Admin_User() + { + //Act + var result = await _userAppService.GetListAsync(new GetIdentityUsersInput()); + + //Assert + result.TotalCount.ShouldBeGreaterThan(0); + result.Items.ShouldContain(u => u.UserName == "admin"); + } +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/DispatchDomainTestBase.cs b/modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/DispatchDomainTestBase.cs new file mode 100644 index 0000000..c0e94f5 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/DispatchDomainTestBase.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Dispatch; + +/* Inherit from this class for your domain layer tests. */ +public abstract class DispatchDomainTestBase : DispatchTestBase + where TStartupModule : IAbpModule +{ + +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/DispatchDomainTestModule.cs b/modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/DispatchDomainTestModule.cs new file mode 100644 index 0000000..c28f7b8 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/DispatchDomainTestModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Dispatch; + +[DependsOn( + typeof(DispatchDomainModule), + typeof(DispatchTestBaseModule) +)] +public class DispatchDomainTestModule : AbpModule +{ + +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/KonSoft.Dispatch.Domain.Tests.csproj b/modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/KonSoft.Dispatch.Domain.Tests.csproj new file mode 100644 index 0000000..2df7195 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/KonSoft.Dispatch.Domain.Tests.csproj @@ -0,0 +1,20 @@ + + + + + + net8.0 + enable + KonSoft.Dispatch + + + + + + + + + + + + diff --git a/modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/Samples/SampleDomainTests.cs b/modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/Samples/SampleDomainTests.cs new file mode 100644 index 0000000..a56788e --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.Domain.Tests/Samples/SampleDomainTests.cs @@ -0,0 +1,46 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Xunit; + +namespace KonSoft.Dispatch.Samples; + +/* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IdentityUserManager here). + * Only test your own domain services. + */ +public abstract class SampleDomainTests : DispatchDomainTestBase + where TStartupModule : IAbpModule +{ + private readonly IIdentityUserRepository _identityUserRepository; + private readonly IdentityUserManager _identityUserManager; + + protected SampleDomainTests() + { + _identityUserRepository = GetRequiredService(); + _identityUserManager = GetRequiredService(); + } + + [Fact] + public async Task Should_Set_Email_Of_A_User() + { + IdentityUser adminUser; + + /* Need to manually start Unit Of Work because + * FirstOrDefaultAsync should be executed while db connection / context is available. + */ + await WithUnitOfWorkAsync(async () => + { + adminUser = await _identityUserRepository + .FindByNormalizedUserNameAsync("ADMIN"); + + await _identityUserManager.SetEmailAsync(adminUser, "newemail@abp.io"); + await _identityUserRepository.UpdateAsync(adminUser); + }); + + adminUser = await _identityUserRepository.FindByNormalizedUserNameAsync("ADMIN"); + adminUser.Email.ShouldBe("newemail@abp.io"); + } +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs new file mode 100644 index 0000000..1b831fc --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs @@ -0,0 +1,10 @@ +using KonSoft.Dispatch.Samples; +using Xunit; + +namespace KonSoft.Dispatch.EntityFrameworkCore.Applications; + +[Collection(DispatchTestConsts.CollectionDefinitionName)] +public class EfCoreSampleAppServiceTests : SampleAppServiceTests +{ + +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreCollection.cs b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreCollection.cs new file mode 100644 index 0000000..a2578dd --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreCollection.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace KonSoft.Dispatch.EntityFrameworkCore; + +[CollectionDefinition(DispatchTestConsts.CollectionDefinitionName)] +public class DispatchEntityFrameworkCoreCollection : ICollectionFixture +{ + +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreCollectionFixtureBase.cs b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreCollectionFixtureBase.cs new file mode 100644 index 0000000..0d37668 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreCollectionFixtureBase.cs @@ -0,0 +1,9 @@ +using KonSoft.Dispatch.EntityFrameworkCore; +using Xunit; + +namespace KonSoft.Dispatch.EntityFrameworkCore; + +public class DispatchEntityFrameworkCoreCollectionFixtureBase : ICollectionFixture +{ + +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreFixture.cs b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreFixture.cs new file mode 100644 index 0000000..086b344 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreFixture.cs @@ -0,0 +1,11 @@ +using System; + +namespace KonSoft.Dispatch.EntityFrameworkCore; + +public class DispatchEntityFrameworkCoreFixture : IDisposable +{ + public void Dispose() + { + + } +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreTestBase.cs b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreTestBase.cs new file mode 100644 index 0000000..989b941 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreTestBase.cs @@ -0,0 +1,8 @@ +using Volo.Abp; + +namespace KonSoft.Dispatch.EntityFrameworkCore; + +public abstract class DispatchEntityFrameworkCoreTestBase : DispatchTestBase +{ + +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreTestModule.cs b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreTestModule.cs new file mode 100644 index 0000000..f6517d9 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/DispatchEntityFrameworkCoreTestModule.cs @@ -0,0 +1,82 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.Sqlite; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.Uow; + +namespace KonSoft.Dispatch.EntityFrameworkCore; + +[DependsOn( + typeof(DispatchApplicationTestModule), + typeof(DispatchEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCoreSqliteModule) + )] +public class DispatchEntityFrameworkCoreTestModule : AbpModule +{ + private SqliteConnection? _sqliteConnection; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.SaveStaticFeaturesToDatabase = false; + options.IsDynamicFeatureStoreEnabled = false; + }); + Configure(options => + { + options.SaveStaticPermissionsToDatabase = false; + options.IsDynamicPermissionStoreEnabled = false; + }); + Configure(options => + { + options.SaveStaticSettingsToDatabase = false; + options.IsDynamicSettingStoreEnabled = false; + }); + context.Services.AddAlwaysDisableUnitOfWorkTransaction(); + + ConfigureInMemorySqlite(context.Services); + } + + private void ConfigureInMemorySqlite(IServiceCollection services) + { + _sqliteConnection = CreateDatabaseAndGetConnection(); + + services.Configure(options => + { + options.Configure(context => + { + context.DbContextOptions.UseSqlite(_sqliteConnection); + }); + }); + } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + _sqliteConnection?.Dispose(); + } + + private static SqliteConnection CreateDatabaseAndGetConnection() + { + var connection = new AbpUnitTestSqliteConnection("Data Source=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new DispatchDbContext(options)) + { + context.GetService().CreateTables(); + } + + return connection; + } +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs new file mode 100644 index 0000000..3bad6ef --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs @@ -0,0 +1,10 @@ +using KonSoft.Dispatch.Samples; +using Xunit; + +namespace KonSoft.Dispatch.EntityFrameworkCore.Domains; + +[Collection(DispatchTestConsts.CollectionDefinitionName)] +public class EfCoreSampleDomainTests : SampleDomainTests +{ + +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs new file mode 100644 index 0000000..234cc69 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Shouldly; +using System; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Identity; +using Xunit; + +namespace KonSoft.Dispatch.EntityFrameworkCore.Samples; + +/* This is just an example test class. + * Normally, you don't test ABP framework code + * (like default AppUser repository IRepository here). + * Only test your custom repository methods. + */ +[Collection(DispatchTestConsts.CollectionDefinitionName)] +public class SampleRepositoryTests : DispatchEntityFrameworkCoreTestBase +{ + private readonly IRepository _appUserRepository; + + public SampleRepositoryTests() + { + _appUserRepository = GetRequiredService>(); + } + + [Fact] + public async Task Should_Query_AppUser() + { + /* Need to manually start Unit Of Work because + * FirstOrDefaultAsync should be executed while db connection / context is available. + */ + await WithUnitOfWorkAsync(async () => + { + //Act + var adminUser = await (await _appUserRepository.GetQueryableAsync()) + .Where(u => u.UserName == "admin") + .FirstOrDefaultAsync(); + + //Assert + adminUser.ShouldNotBeNull(); + }); + } +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/KonSoft.Dispatch.EntityFrameworkCore.Tests.csproj b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/KonSoft.Dispatch.EntityFrameworkCore.Tests.csproj new file mode 100644 index 0000000..7fac87a --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.EntityFrameworkCore.Tests/KonSoft.Dispatch.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,21 @@ + + + + + + net8.0 + enable + KonSoft.Dispatch + + + + + + + + + + + + + diff --git a/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs new file mode 100644 index 0000000..636311e --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs @@ -0,0 +1,25 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Account; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp; + +public class ClientDemoService : ITransientDependency +{ + private readonly IProfileAppService _profileAppService; + + public ClientDemoService(IProfileAppService profileAppService) + { + _profileAppService = profileAppService; + } + + public async Task RunAsync() + { + var output = await _profileAppService.GetAsync(); + Console.WriteLine($"UserName : {output.UserName}"); + Console.WriteLine($"Email : {output.Email}"); + Console.WriteLine($"Name : {output.Name}"); + Console.WriteLine($"Surname : {output.Surname}"); + } +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs new file mode 100644 index 0000000..6e81f80 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.Hosting; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; + +namespace KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp; + +public class ConsoleTestAppHostedService : IHostedService +{ + private readonly IConfiguration _configuration; + + public ConsoleTestAppHostedService(IConfiguration configuration) + { + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using (var application = await AbpApplicationFactory.CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + })) + { + await application.InitializeAsync(); + + var demo = application.ServiceProvider.GetRequiredService(); + await demo.RunAsync(); + + await application.ShutdownAsync(); + } + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/DispatchConsoleApiClientModule.cs b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/DispatchConsoleApiClientModule.cs new file mode 100644 index 0000000..be6deb9 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/DispatchConsoleApiClientModule.cs @@ -0,0 +1,30 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Polly; +using Volo.Abp.Autofac; +using Volo.Abp.Http.Client; +using Volo.Abp.Http.Client.IdentityModel; +using Volo.Abp.Modularity; + +namespace KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(DispatchHttpApiClientModule), + typeof(AbpHttpClientIdentityModelModule) + )] +public class DispatchConsoleApiClientModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(options => + { + options.ProxyClientBuildActions.Add((remoteServiceName, clientBuilder) => + { + clientBuilder.AddTransientHttpErrorPolicy( + policyBuilder => policyBuilder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i))) + ); + }); + }); + } +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp.csproj b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp.csproj new file mode 100644 index 0000000..2182f74 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp.csproj @@ -0,0 +1,33 @@ + + + + Exe + net8.0 + enable + + + + + + PreserveNewest + Always + + + + PreserveNewest + Always + + + + + + + + + + + + + + + diff --git a/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/Program.cs b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/Program.cs new file mode 100644 index 0000000..2c0b50a --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/Program.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp; + +class Program +{ + static async Task Main(string[] args) + { + await CreateHostBuilder(args).RunConsoleAsync(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .AddAppSettingsSecretsJson() + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/appsettings.json b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/appsettings.json new file mode 100644 index 0000000..e85919d --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/appsettings.json @@ -0,0 +1,17 @@ +{ + "RemoteServices": { + "Default": { + "BaseUrl": "https://localhost:44321" + } + }, + "IdentityClients": { + "Default": { + "GrantType": "password", + "ClientId": "Dispatch_App", + "UserName": "admin", + "UserPassword": "1q2w3E*", + "Authority": "https://localhost:44321", + "Scope": "Dispatch" + } + } +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestBase.cs b/modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestBase.cs new file mode 100644 index 0000000..db3f3f2 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestBase.cs @@ -0,0 +1,60 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Modularity; +using Volo.Abp.Uow; +using Volo.Abp.Testing; + +namespace KonSoft.Dispatch; + +/* All test classes are derived from this class, directly or indirectly. + */ +public abstract class DispatchTestBase : AbpIntegratedTest + where TStartupModule : IAbpModule +{ + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + protected virtual Task WithUnitOfWorkAsync(Func func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func action) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + await action(); + + await uow.CompleteAsync(); + } + } + } + + protected virtual Task WithUnitOfWorkAsync(Func> func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func> func) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + var result = await func(); + await uow.CompleteAsync(); + return result; + } + } + } +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestBaseModule.cs b/modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestBaseModule.cs new file mode 100644 index 0000000..87e2202 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestBaseModule.cs @@ -0,0 +1,47 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Authorization; +using Volo.Abp.Autofac; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Abp.Threading; + +namespace KonSoft.Dispatch; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpTestBaseModule), + typeof(AbpAuthorizationModule), + typeof(AbpBackgroundJobsAbstractionsModule) + )] +public class DispatchTestBaseModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.IsJobExecutionEnabled = false; + }); + + context.Services.AddAlwaysAllowAuthorization(); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + AsyncHelper.RunSync(async () => + { + using (var scope = context.ServiceProvider.CreateScope()) + { + await scope.ServiceProvider + .GetRequiredService() + .SeedAsync(); + } + }); + } +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestConsts.cs b/modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestConsts.cs new file mode 100644 index 0000000..394b858 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestConsts.cs @@ -0,0 +1,6 @@ +namespace KonSoft.Dispatch; + +public static class DispatchTestConsts +{ + public const string CollectionDefinitionName = "Dispatch collection"; +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestDataSeedContributor.cs b/modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestDataSeedContributor.cs new file mode 100644 index 0000000..cdf13ef --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.TestBase/DispatchTestDataSeedContributor.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Dispatch; + +public class DispatchTestDataSeedContributor : IDataSeedContributor, ITransientDependency +{ + public Task SeedAsync(DataSeedContext context) + { + /* Seed additional test data... */ + + return Task.CompletedTask; + } +} diff --git a/modules/dispatch/test/KonSoft.Dispatch.TestBase/KonSoft.Dispatch.TestBase.csproj b/modules/dispatch/test/KonSoft.Dispatch.TestBase/KonSoft.Dispatch.TestBase.csproj new file mode 100644 index 0000000..7e34e0a --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.TestBase/KonSoft.Dispatch.TestBase.csproj @@ -0,0 +1,31 @@ + + + + + + net8.0 + enable + KonSoft.Dispatch + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + diff --git a/modules/dispatch/test/KonSoft.Dispatch.TestBase/Security/FakeCurrentPrincipalAccessor.cs b/modules/dispatch/test/KonSoft.Dispatch.TestBase/Security/FakeCurrentPrincipalAccessor.cs new file mode 100644 index 0000000..1f8fe62 --- /dev/null +++ b/modules/dispatch/test/KonSoft.Dispatch.TestBase/Security/FakeCurrentPrincipalAccessor.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Security.Claims; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Claims; + +namespace KonSoft.Dispatch.Security; + +[Dependency(ReplaceServices = true)] +public class FakeCurrentPrincipalAccessor : ThreadCurrentPrincipalAccessor +{ + protected override ClaimsPrincipal GetClaimsPrincipal() + { + return GetPrincipal(); + } + + private ClaimsPrincipal GetPrincipal() + { + return new ClaimsPrincipal(new ClaimsIdentity(new List + { + new Claim(AbpClaimTypes.UserId, "2e701e62-0953-4dd3-910b-dc6cc93ccb0d"), + new Claim(AbpClaimTypes.UserName, "admin"), + new Claim(AbpClaimTypes.Email, "admin@abp.io") + })); + } +} diff --git a/modules/payment/src/KonSoft.Payment.Application.Contracts/KonSoft.Payment.Application.Contracts.csproj b/modules/payment/src/KonSoft.Payment.Application.Contracts/KonSoft.Payment.Application.Contracts.csproj new file mode 100644 index 0000000..dcc8a92 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Application.Contracts/KonSoft.Payment.Application.Contracts.csproj @@ -0,0 +1,25 @@ + + + + + + net8.0 + enable + KonSoft.Payment + + + + + + + + + + + + + + + + + diff --git a/modules/payment/src/KonSoft.Payment.Application.Contracts/PaymentApplicationContractsModule.cs b/modules/payment/src/KonSoft.Payment.Application.Contracts/PaymentApplicationContractsModule.cs new file mode 100644 index 0000000..779660b --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Application.Contracts/PaymentApplicationContractsModule.cs @@ -0,0 +1,28 @@ +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Payment; + +[DependsOn( + typeof(PaymentDomainSharedModule), + typeof(AbpAccountApplicationContractsModule), + typeof(AbpFeatureManagementApplicationContractsModule), + typeof(AbpIdentityApplicationContractsModule), + typeof(AbpPermissionManagementApplicationContractsModule), + typeof(AbpSettingManagementApplicationContractsModule), + typeof(AbpTenantManagementApplicationContractsModule), + typeof(AbpObjectExtendingModule) +)] +public class PaymentApplicationContractsModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PaymentDtoExtensions.Configure(); + } +} diff --git a/modules/payment/src/KonSoft.Payment.Application.Contracts/PaymentDtoExtensions.cs b/modules/payment/src/KonSoft.Payment.Application.Contracts/PaymentDtoExtensions.cs new file mode 100644 index 0000000..d9e8eed --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Application.Contracts/PaymentDtoExtensions.cs @@ -0,0 +1,28 @@ +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.Payment; + +public static class PaymentDtoExtensions +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can add extension properties to DTOs + * defined in the depended modules. + * + * Example: + * + * ObjectExtensionManager.Instance + * .AddOrUpdateProperty("Title"); + * + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Object-Extensions + */ + }); + } +} diff --git a/modules/payment/src/KonSoft.Payment.Application.Contracts/Permissions/PaymentPermissionDefinitionProvider.cs b/modules/payment/src/KonSoft.Payment.Application.Contracts/Permissions/PaymentPermissionDefinitionProvider.cs new file mode 100644 index 0000000..e0a83de --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Application.Contracts/Permissions/PaymentPermissionDefinitionProvider.cs @@ -0,0 +1,20 @@ +using KonSoft.Payment.Localization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; + +namespace KonSoft.Payment.Permissions; + +public class PaymentPermissionDefinitionProvider : PermissionDefinitionProvider +{ + public override void Define(IPermissionDefinitionContext context) + { + var myGroup = context.AddGroup(PaymentPermissions.GroupName); + //Define your own permissions here. Example: + //myGroup.AddPermission(PaymentPermissions.MyPermission1, L("Permission:MyPermission1")); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/modules/payment/src/KonSoft.Payment.Application.Contracts/Permissions/PaymentPermissions.cs b/modules/payment/src/KonSoft.Payment.Application.Contracts/Permissions/PaymentPermissions.cs new file mode 100644 index 0000000..2c9a28b --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Application.Contracts/Permissions/PaymentPermissions.cs @@ -0,0 +1,9 @@ +namespace KonSoft.Payment.Permissions; + +public static class PaymentPermissions +{ + public const string GroupName = "Payment"; + + //Add your own permission names. Example: + //public const string MyPermission1 = GroupName + ".MyPermission1"; +} diff --git a/modules/payment/src/KonSoft.Payment.Application/KonSoft.Payment.Application.csproj b/modules/payment/src/KonSoft.Payment.Application/KonSoft.Payment.Application.csproj new file mode 100644 index 0000000..4f2eb85 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Application/KonSoft.Payment.Application.csproj @@ -0,0 +1,25 @@ + + + + + + net8.0 + enable + KonSoft.Payment + + + + + + + + + + + + + + + + + diff --git a/modules/payment/src/KonSoft.Payment.Application/PaymentAppService.cs b/modules/payment/src/KonSoft.Payment.Application/PaymentAppService.cs new file mode 100644 index 0000000..3e3e04a --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Application/PaymentAppService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using KonSoft.Payment.Localization; +using Volo.Abp.Application.Services; + +namespace KonSoft.Payment; + +/* Inherit your application services from this class. + */ +public abstract class PaymentAppService : ApplicationService +{ + protected PaymentAppService() + { + LocalizationResource = typeof(PaymentResource); + } +} diff --git a/modules/payment/src/KonSoft.Payment.Application/PaymentApplicationAutoMapperProfile.cs b/modules/payment/src/KonSoft.Payment.Application/PaymentApplicationAutoMapperProfile.cs new file mode 100644 index 0000000..cd57e6f --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Application/PaymentApplicationAutoMapperProfile.cs @@ -0,0 +1,13 @@ +using AutoMapper; + +namespace KonSoft.Payment; + +public class PaymentApplicationAutoMapperProfile : Profile +{ + public PaymentApplicationAutoMapperProfile() + { + /* You can configure your AutoMapper mapping configuration here. + * Alternatively, you can split your mapping configurations + * into multiple profile classes for a better organization. */ + } +} diff --git a/modules/payment/src/KonSoft.Payment.Application/PaymentApplicationModule.cs b/modules/payment/src/KonSoft.Payment.Application/PaymentApplicationModule.cs new file mode 100644 index 0000000..827aee4 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Application/PaymentApplicationModule.cs @@ -0,0 +1,31 @@ +using Volo.Abp.Account; +using Volo.Abp.AutoMapper; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Payment; + +[DependsOn( + typeof(PaymentDomainModule), + typeof(AbpAccountApplicationModule), + typeof(PaymentApplicationContractsModule), + typeof(AbpIdentityApplicationModule), + typeof(AbpPermissionManagementApplicationModule), + typeof(AbpTenantManagementApplicationModule), + typeof(AbpFeatureManagementApplicationModule), + typeof(AbpSettingManagementApplicationModule) + )] +public class PaymentApplicationModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.AddMaps(); + }); + } +} diff --git a/modules/payment/src/KonSoft.Payment.Application/Properties/AssemblyInfo.cs b/modules/payment/src/KonSoft.Payment.Application/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..2626411 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Application/Properties/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.Payment.Application.Tests")] diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/KonSoft.Payment.Domain.Shared.csproj b/modules/payment/src/KonSoft.Payment.Domain.Shared/KonSoft.Payment.Domain.Shared.csproj new file mode 100644 index 0000000..ef9d680 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/KonSoft.Payment.Domain.Shared.csproj @@ -0,0 +1,32 @@ + + + + + + net8.0 + enable + KonSoft.Payment + true + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/ar.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/ar.json new file mode 100644 index 0000000..6c6546a --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/ar.json @@ -0,0 +1,9 @@ +{ + "culture": "ar", + "texts": { + "AppName": "Payment", + "Menu:Home": "الصفحة الرئيسية", + "Welcome": "مرحباً", + "LongWelcomeMessage": "مرحبا بكم في التطبيق. هذا مشروع بدء تشغيل يعتمد على إطار عمل ABP. لمزيد من المعلومات ، يرجى زيارة abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/cs.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/cs.json new file mode 100644 index 0000000..06f07d8 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/cs.json @@ -0,0 +1,9 @@ +{ + "culture": "cs", + "texts": { + "AppName": "Payment", + "Menu:Home": "Úvod", + "Welcome": "Vítejte", + "LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/de.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/de.json new file mode 100644 index 0000000..937a03d --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/de.json @@ -0,0 +1,9 @@ +{ + "culture": "de", + "texts": { + "AppName": "Payment", + "Menu:Home": "Home", + "Welcome": "Willkommen", + "LongWelcomeMessage": "Willkommen bei der Anwendung. Dies ist ein Startup-Projekt, das auf dem ABP-Framework basiert. Weitere Informationen finden Sie unter abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/en-GB.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/en-GB.json new file mode 100644 index 0000000..954746e --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/en-GB.json @@ -0,0 +1,9 @@ +{ + "culture": "en-GB", + "texts": { + "AppName": "Payment", + "Menu:Home": "Home", + "Welcome": "Welcome", + "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/en.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/en.json new file mode 100644 index 0000000..3aaad49 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/en.json @@ -0,0 +1,9 @@ +{ + "culture": "en", + "texts": { + "AppName": "Payment", + "Menu:Home": "Home", + "Welcome": "Welcome", + "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/es.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/es.json new file mode 100644 index 0000000..e133058 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/es.json @@ -0,0 +1,9 @@ +{ + "culture": "es", + "texts": { + "AppName": "Payment", + "Menu:Home": "Inicio", + "Welcome": "Bienvenido", + "LongWelcomeMessage": "Bienvenido a la aplicación, este es un proyecto base basado en el framework ABP. Para más información, visita abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/fi.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/fi.json new file mode 100644 index 0000000..74ee99d --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/fi.json @@ -0,0 +1,9 @@ +{ + "culture": "fi", + "texts": { + "AppName": "Payment", + "Menu:Home": "Koti", + "Welcome": "Tervetuloa", + "LongWelcomeMessage": "Tervetuloa sovellukseen. Tämä on ABP-kehykseen perustuva käynnistysprojekti. Lisätietoja on osoitteessa abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/fr.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/fr.json new file mode 100644 index 0000000..20fcbee --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/fr.json @@ -0,0 +1,9 @@ +{ + "culture": "fr", + "texts": { + "AppName": "Payment", + "Menu:Home": "Accueil", + "Welcome": "Bienvenue", + "LongWelcomeMessage": "Bienvenue dans l'application. Il s'agit d'un projet de démarrage basé sur le framework ABP. Pour plus d'informations, visitez abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/hi.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/hi.json new file mode 100644 index 0000000..c39bdee --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/hi.json @@ -0,0 +1,9 @@ +{ + "culture": "hi", + "texts": { + "AppName": "Payment", + "Menu:Home": "घर", + "Welcome": "स्वागत हे", + "LongWelcomeMessage": "आवेदन करने के लिए आपका स्वागत है। यह एबीपी ढांचे पर आधारित एक स्टार्टअप परियोजना है। अधिक जानकारी के लिए, abp.io पर जाएं।" + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/hr.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/hr.json new file mode 100644 index 0000000..230051f --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/hr.json @@ -0,0 +1,9 @@ +{ + "culture": "hr", + "texts": { + "AppName": "Payment", + "Menu:Home": "Početna", + "Welcome": "Dobrodošli", + "LongWelcomeMessage": "Dobrodošli u aplikaciju. Ovo je startup projekt temeljen na ABP framework-u. Za više informacija posjetite abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/hu.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/hu.json new file mode 100644 index 0000000..d9c1f20 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/hu.json @@ -0,0 +1,9 @@ +{ + "culture": "hu", + "texts": { + "AppName": "Payment", + "Menu:Home": "Kezdőlap", + "Welcome": "Üdvözlöm", + "LongWelcomeMessage": "Üdvözöljük az alkalmazásban. Ez egy ABP keretrendszeren alapuló startup projekt. További információkért látogasson el az abp.io oldalra." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/is.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/is.json new file mode 100644 index 0000000..a72f98a --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/is.json @@ -0,0 +1,9 @@ +{ + "culture": "is", + "texts": { + "AppName": "Payment", + "Menu:Home": "Heim", + "Welcome": "Velkomin", + "LongWelcomeMessage": "Verið velkomin í forritið. Þetta er startup verkefni sem byggir á ABP. Nánari upplýsingar er að finna á abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/it.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/it.json new file mode 100644 index 0000000..cebc29d --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/it.json @@ -0,0 +1,9 @@ +{ + "culture": "it", + "texts": { + "AppName": "Payment", + "Menu:Home": "Home", + "Welcome": "Benvenuto", + "LongWelcomeMessage": "Benvenuto nell'applicazione. Questo è un progetto di avvio basato sul framework ABP. Per ulteriori informazioni, visita abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/nl.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/nl.json new file mode 100644 index 0000000..d333745 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/nl.json @@ -0,0 +1,9 @@ +{ + "culture": "nl", + "texts": { + "AppName": "Payment", + "Menu:Home": "Home", + "Welcome": "Welkom", + "LongWelcomeMessage": "Welkom bij de applicatie. Dit is een startup-project gebaseerd op het ABP-framework. Bezoek abp.io voor meer informatie." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/pl-PL.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/pl-PL.json new file mode 100644 index 0000000..16f09f7 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/pl-PL.json @@ -0,0 +1,9 @@ +{ + "culture": "pl-PL", + "texts": { + "AppName": "Payment", + "Menu:Home": "Home", + "Welcome": "Witaj", + "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/pt-BR.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/pt-BR.json new file mode 100644 index 0000000..32b4fc7 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/pt-BR.json @@ -0,0 +1,9 @@ +{ + "culture": "pt-BR", + "texts": { + "AppName": "Payment", + "Menu:Home": "Principal", + "Welcome": "Seja bem-vindo!", + "LongWelcomeMessage": "Bem-vindo a esta aplicação. Este é um projeto inicial baseado no ABP framework. Para mais informações, visite abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/ro-RO.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/ro-RO.json new file mode 100644 index 0000000..2c89655 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/ro-RO.json @@ -0,0 +1,9 @@ +{ + "culture": "ro-RO", + "texts": { + "AppName": "Payment", + "Menu:Home": "Acasă", + "Welcome": "Bun venit", + "LongWelcomeMessage": "Bun venit la aplicaţie. Acesta este un proiect de pornire bazat pe framework-ul ABP. Pentru mai multe informaţii, vizitaţi, visit abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/ru.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/ru.json new file mode 100644 index 0000000..6c1469b --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/ru.json @@ -0,0 +1,9 @@ +{ + "culture": "ru", + "texts": { + "AppName": "Payment", + "Menu:Home": "Главная", + "Welcome": "Добро пожаловать", + "LongWelcomeMessage": "Добро пожаловать в приложение. Этот запущенный проект основан на фреймворке ABP. Для получения дополнительной информации посетите сайт abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/sk.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/sk.json new file mode 100644 index 0000000..2a6b160 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/sk.json @@ -0,0 +1,9 @@ +{ + "culture": "sk", + "texts": { + "AppName": "Payment", + "Menu:Home": "Domov", + "Welcome": "Vitajte", + "LongWelcomeMessage": "Vitajte v aplikácii. Toto je štartovací projekt založený na ABP frameworku. Viac informácií nájdete na stránke abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/sl.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/sl.json new file mode 100644 index 0000000..a7b06d8 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/sl.json @@ -0,0 +1,9 @@ +{ + "culture": "sl", + "texts": { + "AppName": "Payment", + "Menu:Home": "Domov", + "Welcome": "Dobrodošli", + "LongWelcomeMessage": "Dobrodošli v aplikaciji. To je začetni projekt na osnovi okolja ABP. Za več informacij obiščite abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/sv.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/sv.json new file mode 100644 index 0000000..bd1eae4 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/sv.json @@ -0,0 +1,9 @@ +{ + "culture": "sv", + "texts": { + "AppName": "MittProjektNamn", + "Menu:Home": "Hem", + "Welcome": "Välkommen", + "LongWelcomeMessage": "Välkommen till applikationen. Detta är ett startup-projekt baserat på ABP-ramverket. För mer information, besök abp.io." + } +} \ No newline at end of file diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/tr.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/tr.json new file mode 100644 index 0000000..c59e7a8 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/tr.json @@ -0,0 +1,9 @@ +{ + "culture": "tr", + "texts": { + "AppName": "Payment", + "Menu:Home": "Ana sayfa", + "Welcome": "Hoşgeldiniz", + "LongWelcomeMessage": "Uygulamaya hoşgeldiniz. Bu, ABP framework'ü üzerine bina edilmiş bir başlangıç projesidir. Daha fazla bilgi için abp.io adresini ziyaret edebilirsiniz." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/vi.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/vi.json new file mode 100644 index 0000000..333e831 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/vi.json @@ -0,0 +1,9 @@ +{ + "culture": "vi", + "texts": { + "AppName": "Payment", + "Menu:Home": "Trang chủ", + "Welcome": "Chào mừng bạn", + "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án khởi nghiệp dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io." + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/zh-Hans.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/zh-Hans.json new file mode 100644 index 0000000..01dbeac --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/zh-Hans.json @@ -0,0 +1,9 @@ +{ + "culture": "zh-Hans", + "texts": { + "AppName": "Payment", + "Menu:Home": "首页", + "Welcome": "欢迎", + "LongWelcomeMessage": "欢迎使用本应用程序。这是一个基于 ABP 框架的启动项目。更多信息,请访问 abp.io。" + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/zh-Hant.json b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/zh-Hant.json new file mode 100644 index 0000000..2ceb93b --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/Payment/zh-Hant.json @@ -0,0 +1,9 @@ +{ + "culture": "zh-Hant", + "texts": { + "AppName": "Payment", + "Menu:Home": "首頁", + "Welcome": "歡迎", + "LongWelcomeMessage": "歡迎來到此應用程式. 這是一個基於ABP框架的起始專案. 有關更多訊息, 請瀏覽 abp.io." + } + } diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/PaymentResource.cs b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/PaymentResource.cs new file mode 100644 index 0000000..fcf7fb7 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/Localization/PaymentResource.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Localization; + +namespace KonSoft.Payment.Localization; + +[LocalizationResourceName("Payment")] +public class PaymentResource +{ + +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs b/modules/payment/src/KonSoft.Payment.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs new file mode 100644 index 0000000..c3155c1 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs @@ -0,0 +1,10 @@ +namespace KonSoft.Payment.MultiTenancy; + +public static class MultiTenancyConsts +{ + /* Enable/disable multi-tenancy easily in a single point. + * If you will never need to multi-tenancy, you can remove + * related modules and code parts, including this file. + */ + public const bool IsEnabled = true; +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentDomainErrorCodes.cs b/modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentDomainErrorCodes.cs new file mode 100644 index 0000000..85cf719 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentDomainErrorCodes.cs @@ -0,0 +1,6 @@ +namespace KonSoft.Payment; + +public static class PaymentDomainErrorCodes +{ + /* You can add your business exception error codes here, as constants */ +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentDomainSharedModule.cs b/modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentDomainSharedModule.cs new file mode 100644 index 0000000..8da6490 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentDomainSharedModule.cs @@ -0,0 +1,58 @@ +using KonSoft.Payment.Localization; +using Volo.Abp.AuditLogging; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Localization.ExceptionHandling; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; +using Volo.Abp.Validation.Localization; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.Payment; + +[DependsOn( + typeof(AbpAuditLoggingDomainSharedModule), + typeof(AbpBackgroundJobsDomainSharedModule), + typeof(AbpFeatureManagementDomainSharedModule), + typeof(AbpIdentityDomainSharedModule), + typeof(AbpOpenIddictDomainSharedModule), + typeof(AbpPermissionManagementDomainSharedModule), + typeof(AbpSettingManagementDomainSharedModule), + typeof(AbpTenantManagementDomainSharedModule) + )] +public class PaymentDomainSharedModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PaymentGlobalFeatureConfigurator.Configure(); + PaymentModuleExtensionConfigurator.Configure(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddBaseTypes(typeof(AbpValidationResource)) + .AddVirtualJson("/Localization/Payment"); + + options.DefaultResourceType = typeof(PaymentResource); + }); + + Configure(options => + { + options.MapCodeNamespace("Payment", typeof(PaymentResource)); + }); + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentGlobalFeatureConfigurator.cs b/modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentGlobalFeatureConfigurator.cs new file mode 100644 index 0000000..c1b4b07 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentGlobalFeatureConfigurator.cs @@ -0,0 +1,22 @@ +using Volo.Abp.Threading; + +namespace KonSoft.Payment; + +public static class PaymentGlobalFeatureConfigurator +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can configure (enable/disable) global features of the used modules here. + * + * YOU CAN SAFELY DELETE THIS CLASS AND REMOVE ITS USAGES IF YOU DON'T NEED TO IT! + * + * Please refer to the documentation to lear more about the Global Features System: + * https://docs.abp.io/en/abp/latest/Global-Features + */ + }); + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentModuleExtensionConfigurator.cs b/modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentModuleExtensionConfigurator.cs new file mode 100644 index 0000000..a26ebbc --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain.Shared/PaymentModuleExtensionConfigurator.cs @@ -0,0 +1,73 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.Payment; + +public static class PaymentModuleExtensionConfigurator +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + ConfigureExistingProperties(); + ConfigureExtraProperties(); + }); + } + + private static void ConfigureExistingProperties() + { + /* You can change max lengths for properties of the + * entities defined in the modules used by your application. + * + * Example: Change user and role name max lengths + + AbpUserConsts.MaxNameLength = 99; + IdentityRoleConsts.MaxNameLength = 99; + + * Notice: It is not suggested to change property lengths + * unless you really need it. Go with the standard values wherever possible. + * + * If you are using EF Core, you will need to run the add-migration command after your changes. + */ + } + + private static void ConfigureExtraProperties() + { + /* You can configure extra properties for the + * entities defined in the modules used by your application. + * + * This class can be used to define these extra properties + * with a high level, easy to use API. + * + * Example: Add a new property to the user entity of the identity module + + ObjectExtensionManager.Instance.Modules() + .ConfigureIdentity(identity => + { + identity.ConfigureUser(user => + { + user.AddOrUpdateProperty( //property type: string + "SocialSecurityNumber", //property name + property => + { + //validation rules + property.Attributes.Add(new RequiredAttribute()); + property.Attributes.Add(new StringLengthAttribute(64) {MinimumLength = 4}); + + property.Configuration[IdentityModuleExtensionConsts.ConfigurationNames.AllowUserToEdit] = true; + + //...other configurations for this property + } + ); + }); + }); + + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Module-Entity-Extensions + */ + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain/Data/IPaymentDbSchemaMigrator.cs b/modules/payment/src/KonSoft.Payment.Domain/Data/IPaymentDbSchemaMigrator.cs new file mode 100644 index 0000000..78d1e4f --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain/Data/IPaymentDbSchemaMigrator.cs @@ -0,0 +1,8 @@ +using System.Threading.Tasks; + +namespace KonSoft.Payment.Data; + +public interface IPaymentDbSchemaMigrator +{ + Task MigrateAsync(); +} diff --git a/modules/payment/src/KonSoft.Payment.Domain/Data/NullPaymentDbSchemaMigrator.cs b/modules/payment/src/KonSoft.Payment.Domain/Data/NullPaymentDbSchemaMigrator.cs new file mode 100644 index 0000000..15b687d --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain/Data/NullPaymentDbSchemaMigrator.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Payment.Data; + +/* This is used if database provider does't define + * IPaymentDbSchemaMigrator implementation. + */ +public class NullPaymentDbSchemaMigrator : IPaymentDbSchemaMigrator, ITransientDependency +{ + public Task MigrateAsync() + { + return Task.CompletedTask; + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain/Data/PaymentDbMigrationService.cs b/modules/payment/src/KonSoft.Payment.Domain/Data/PaymentDbMigrationService.cs new file mode 100644 index 0000000..32e6382 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain/Data/PaymentDbMigrationService.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Payment.Data; + +public class PaymentDbMigrationService : ITransientDependency +{ + public ILogger Logger { get; set; } + + private readonly IDataSeeder _dataSeeder; + private readonly IEnumerable _dbSchemaMigrators; + private readonly ITenantRepository _tenantRepository; + private readonly ICurrentTenant _currentTenant; + + public PaymentDbMigrationService( + IDataSeeder dataSeeder, + IEnumerable dbSchemaMigrators, + ITenantRepository tenantRepository, + ICurrentTenant currentTenant) + { + _dataSeeder = dataSeeder; + _dbSchemaMigrators = dbSchemaMigrators; + _tenantRepository = tenantRepository; + _currentTenant = currentTenant; + + Logger = NullLogger.Instance; + } + + public async Task MigrateAsync() + { + var initialMigrationAdded = AddInitialMigrationIfNotExist(); + + if (initialMigrationAdded) + { + return; + } + + Logger.LogInformation("Started database migrations..."); + + await MigrateDatabaseSchemaAsync(); + await SeedDataAsync(); + + Logger.LogInformation($"Successfully completed host database migrations."); + + var tenants = await _tenantRepository.GetListAsync(includeDetails: true); + + var migratedDatabaseSchemas = new HashSet(); + foreach (var tenant in tenants) + { + using (_currentTenant.Change(tenant.Id)) + { + if (tenant.ConnectionStrings.Any()) + { + var tenantConnectionStrings = tenant.ConnectionStrings + .Select(x => x.Value) + .ToList(); + + if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings)) + { + await MigrateDatabaseSchemaAsync(tenant); + + migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings); + } + } + + await SeedDataAsync(tenant); + } + + Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations."); + } + + Logger.LogInformation("Successfully completed all database migrations."); + Logger.LogInformation("You can safely end this process..."); + } + + private async Task MigrateDatabaseSchemaAsync(Tenant? tenant = null) + { + Logger.LogInformation( + $"Migrating schema for {(tenant == null ? "host" : tenant.Name + " tenant")} database..."); + + foreach (var migrator in _dbSchemaMigrators) + { + await migrator.MigrateAsync(); + } + } + + private async Task SeedDataAsync(Tenant? tenant = null) + { + Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed..."); + + await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id) + .WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, IdentityDataSeedContributor.AdminEmailDefaultValue) + .WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, IdentityDataSeedContributor.AdminPasswordDefaultValue) + ); + } + + private bool AddInitialMigrationIfNotExist() + { + try + { + if (!DbMigrationsProjectExists()) + { + return false; + } + } + catch (Exception) + { + return false; + } + + try + { + if (!MigrationsFolderExists()) + { + AddInitialMigration(); + return true; + } + else + { + return false; + } + } + catch (Exception e) + { + Logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message); + return false; + } + } + + private bool DbMigrationsProjectExists() + { + var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath(); + + return dbMigrationsProjectFolder != null; + } + + private bool MigrationsFolderExists() + { + var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath(); + return dbMigrationsProjectFolder != null && Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations")); + } + + private void AddInitialMigration() + { + Logger.LogInformation("Creating initial migration..."); + + string argumentPrefix; + string fileName; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + argumentPrefix = "-c"; + fileName = "/bin/bash"; + } + else + { + argumentPrefix = "/C"; + fileName = "cmd.exe"; + } + + var procStartInfo = new ProcessStartInfo(fileName, + $"{argumentPrefix} \"abp create-migration-and-run-migrator \"{GetEntityFrameworkCoreProjectFolderPath()}\"\"" + ); + + try + { + Process.Start(procStartInfo); + } + catch (Exception) + { + throw new Exception("Couldn't run ABP CLI..."); + } + } + + private string? GetEntityFrameworkCoreProjectFolderPath() + { + var slnDirectoryPath = GetSolutionDirectoryPath(); + + if (slnDirectoryPath == null) + { + throw new Exception("Solution folder not found!"); + } + + var srcDirectoryPath = Path.Combine(slnDirectoryPath, "src"); + + return Directory.GetDirectories(srcDirectoryPath) + .FirstOrDefault(d => d.EndsWith(".EntityFrameworkCore")); + } + + private string? GetSolutionDirectoryPath() + { + var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory()); + + while (currentDirectory != null && Directory.GetParent(currentDirectory.FullName) != null) + { + currentDirectory = Directory.GetParent(currentDirectory.FullName); + + if (currentDirectory != null && Directory.GetFiles(currentDirectory.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null) + { + return currentDirectory.FullName; + } + } + + return null; + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain/KonSoft.Payment.Domain.csproj b/modules/payment/src/KonSoft.Payment.Domain/KonSoft.Payment.Domain.csproj new file mode 100644 index 0000000..fdccac0 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain/KonSoft.Payment.Domain.csproj @@ -0,0 +1,28 @@ + + + + + + net8.0 + enable + KonSoft.Payment + + + + + + + + + + + + + + + + + + + + diff --git a/modules/payment/src/KonSoft.Payment.Domain/OpenIddict/OpenIddictDataSeedContributor.cs b/modules/payment/src/KonSoft.Payment.Domain/OpenIddict/OpenIddictDataSeedContributor.cs new file mode 100644 index 0000000..2487dd9 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain/OpenIddict/OpenIddictDataSeedContributor.cs @@ -0,0 +1,327 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Localization; +using OpenIddict.Abstractions; +using Volo.Abp; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.OpenIddict.Applications; +using Volo.Abp.OpenIddict.Scopes; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Uow; + +namespace KonSoft.Payment.OpenIddict; + +/* Creates initial data that is needed to property run the application + * and make client-to-server communication possible. + */ +public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDependency +{ + private readonly IConfiguration _configuration; + private readonly IOpenIddictApplicationRepository _openIddictApplicationRepository; + private readonly IAbpApplicationManager _applicationManager; + private readonly IOpenIddictScopeRepository _openIddictScopeRepository; + private readonly IOpenIddictScopeManager _scopeManager; + private readonly IPermissionDataSeeder _permissionDataSeeder; + private readonly IStringLocalizer L; + + public OpenIddictDataSeedContributor( + IConfiguration configuration, + IOpenIddictApplicationRepository openIddictApplicationRepository, + IAbpApplicationManager applicationManager, + IOpenIddictScopeRepository openIddictScopeRepository, + IOpenIddictScopeManager scopeManager, + IPermissionDataSeeder permissionDataSeeder, + IStringLocalizer l ) + { + _configuration = configuration; + _openIddictApplicationRepository = openIddictApplicationRepository; + _applicationManager = applicationManager; + _openIddictScopeRepository = openIddictScopeRepository; + _scopeManager = scopeManager; + _permissionDataSeeder = permissionDataSeeder; + L = l; + } + + [UnitOfWork] + public virtual async Task SeedAsync(DataSeedContext context) + { + await CreateScopesAsync(); + await CreateApplicationsAsync(); + } + + private async Task CreateScopesAsync() + { + if (await _openIddictScopeRepository.FindByNameAsync("Payment") == null) + { + await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor { + Name = "Payment", DisplayName = "Payment API", Resources = { "Payment" } + }); + } + } + + private async Task CreateApplicationsAsync() + { + var commonScopes = new List { + OpenIddictConstants.Permissions.Scopes.Address, + OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Phone, + OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Roles, + "Payment" + }; + + var configurationSection = _configuration.GetSection("OpenIddict:Applications"); + + + + + + + // Swagger Client + var swaggerClientId = configurationSection["Payment_Swagger:ClientId"]; + if (!swaggerClientId.IsNullOrWhiteSpace()) + { + var swaggerRootUrl = configurationSection["Payment_Swagger:RootUrl"]?.TrimEnd('/'); + + await CreateApplicationAsync( + name: swaggerClientId!, + type: OpenIddictConstants.ClientTypes.Public, + consentType: OpenIddictConstants.ConsentTypes.Implicit, + displayName: "Swagger Application", + secret: null, + grantTypes: new List { OpenIddictConstants.GrantTypes.AuthorizationCode, }, + scopes: commonScopes, + redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html", + clientUri: swaggerRootUrl + ); + } + } + + private async Task CreateApplicationAsync( + [NotNull] string name, + [NotNull] string type, + [NotNull] string consentType, + string displayName, + string? secret, + List grantTypes, + List scopes, + string? clientUri = null, + string? redirectUri = null, + string? postLogoutRedirectUri = null, + List? permissions = null) + { + if (!string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Public, + StringComparison.OrdinalIgnoreCase)) + { + throw new BusinessException(L["NoClientSecretCanBeSetForPublicApplications"]); + } + + if (string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, + StringComparison.OrdinalIgnoreCase)) + { + throw new BusinessException(L["TheClientSecretIsRequiredForConfidentialApplications"]); + } + + var client = await _openIddictApplicationRepository.FindByClientIdAsync(name); + + var application = new AbpApplicationDescriptor { + ClientId = name, + ClientType = type, + ClientSecret = secret, + ConsentType = consentType, + DisplayName = displayName, + ClientUri = clientUri, + }; + + Check.NotNullOrEmpty(grantTypes, nameof(grantTypes)); + Check.NotNullOrEmpty(scopes, nameof(scopes)); + + if (new[] { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }.All( + grantTypes.Contains)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken); + + if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeToken); + } + } + + if (!redirectUri.IsNullOrWhiteSpace() || !postLogoutRedirectUri.IsNullOrWhiteSpace()) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout); + } + + var buildInGrantTypes = new[] { + OpenIddictConstants.GrantTypes.Implicit, OpenIddictConstants.GrantTypes.Password, + OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.ClientCredentials, + OpenIddictConstants.GrantTypes.DeviceCode, OpenIddictConstants.GrantTypes.RefreshToken + }; + + foreach (var grantType in grantTypes) + { + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code); + } + + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || + grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization); + } + + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || + grantType == OpenIddictConstants.GrantTypes.ClientCredentials || + grantType == OpenIddictConstants.GrantTypes.Password || + grantType == OpenIddictConstants.GrantTypes.RefreshToken || + grantType == OpenIddictConstants.GrantTypes.DeviceCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Revocation); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Introspection); + } + + if (grantType == OpenIddictConstants.GrantTypes.ClientCredentials) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials); + } + + if (grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit); + } + + if (grantType == OpenIddictConstants.GrantTypes.Password) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password); + } + + if (grantType == OpenIddictConstants.GrantTypes.RefreshToken) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken); + } + + if (grantType == OpenIddictConstants.GrantTypes.DeviceCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.DeviceCode); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Device); + } + + if (grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdToken); + if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Token); + } + } + + if (!buildInGrantTypes.Contains(grantType)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.GrantType + grantType); + } + } + + var buildInScopes = new[] { + OpenIddictConstants.Permissions.Scopes.Address, OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Phone, OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Roles + }; + + foreach (var scope in scopes) + { + if (buildInScopes.Contains(scope)) + { + application.Permissions.Add(scope); + } + else + { + application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.Scope + scope); + } + } + + if (redirectUri != null) + { + if (!redirectUri.IsNullOrEmpty()) + { + if (!Uri.TryCreate(redirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) + { + throw new BusinessException(L["InvalidRedirectUri", redirectUri]); + } + + if (application.RedirectUris.All(x => x != uri)) + { + application.RedirectUris.Add(uri); + } + } + } + + if (postLogoutRedirectUri != null) + { + if (!postLogoutRedirectUri.IsNullOrEmpty()) + { + if (!Uri.TryCreate(postLogoutRedirectUri, UriKind.Absolute, out var uri) || + !uri.IsWellFormedOriginalString()) + { + throw new BusinessException(L["InvalidPostLogoutRedirectUri", postLogoutRedirectUri]); + } + + if (application.PostLogoutRedirectUris.All(x => x != uri)) + { + application.PostLogoutRedirectUris.Add(uri); + } + } + } + + if (permissions != null) + { + await _permissionDataSeeder.SeedAsync( + ClientPermissionValueProvider.ProviderName, + name, + permissions, + null + ); + } + + if (client == null) + { + await _applicationManager.CreateAsync(application); + return; + } + + if (!HasSameRedirectUris(client, application)) + { + client.RedirectUris = JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); + client.PostLogoutRedirectUris = JsonSerializer.Serialize(application.PostLogoutRedirectUris.Select(q => q.ToString().TrimEnd('/'))); + + await _applicationManager.UpdateAsync(client.ToModel()); + } + + if (!HasSameScopes(client, application)) + { + client.Permissions = JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString())); + await _applicationManager.UpdateAsync(client.ToModel()); + } + } + + private bool HasSameRedirectUris(OpenIddictApplication existingClient, AbpApplicationDescriptor application) + { + return existingClient.RedirectUris == JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); + } + + private bool HasSameScopes(OpenIddictApplication existingClient, AbpApplicationDescriptor application) + { + return existingClient.Permissions == JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString().TrimEnd('/'))); + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain/PaymentConsts.cs b/modules/payment/src/KonSoft.Payment.Domain/PaymentConsts.cs new file mode 100644 index 0000000..9938471 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain/PaymentConsts.cs @@ -0,0 +1,8 @@ +namespace KonSoft.Payment; + +public static class PaymentConsts +{ + public const string DbTablePrefix = "App"; + + public const string DbSchema = null; +} diff --git a/modules/payment/src/KonSoft.Payment.Domain/PaymentDomainModule.cs b/modules/payment/src/KonSoft.Payment.Domain/PaymentDomainModule.cs new file mode 100644 index 0000000..c8b9650 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain/PaymentDomainModule.cs @@ -0,0 +1,68 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using KonSoft.Payment.MultiTenancy; +using Volo.Abp.AuditLogging; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Emailing; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.OpenIddict; +using Volo.Abp.PermissionManagement.Identity; +using Volo.Abp.PermissionManagement.OpenIddict; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Payment; + +[DependsOn( + typeof(PaymentDomainSharedModule), + typeof(AbpAuditLoggingDomainModule), + typeof(AbpBackgroundJobsDomainModule), + typeof(AbpFeatureManagementDomainModule), + typeof(AbpIdentityDomainModule), + typeof(AbpOpenIddictDomainModule), + typeof(AbpPermissionManagementDomainOpenIddictModule), + typeof(AbpPermissionManagementDomainIdentityModule), + typeof(AbpSettingManagementDomainModule), + typeof(AbpTenantManagementDomainModule), + typeof(AbpEmailingModule) +)] +public class PaymentDomainModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)")); + options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar")); + options.Languages.Add(new LanguageInfo("hr", "hr", "Croatian")); + options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish")); + options.Languages.Add(new LanguageInfo("fr", "fr", "Français")); + options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi")); + options.Languages.Add(new LanguageInfo("it", "it", "Italiano")); + options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); + options.Languages.Add(new LanguageInfo("ru", "ru", "Русский")); + options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak")); + options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); + options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch")); + options.Languages.Add(new LanguageInfo("es", "es", "Español")); + }); + + Configure(options => + { + options.IsEnabled = MultiTenancyConsts.IsEnabled; + }); + +#if DEBUG + context.Services.Replace(ServiceDescriptor.Singleton()); +#endif + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain/Properties/AssemblyInfo.cs b/modules/payment/src/KonSoft.Payment.Domain/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..2c6594d --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.Payment.Domain.Tests")] +[assembly:InternalsVisibleToAttribute("KonSoft.Payment.TestBase")] diff --git a/modules/payment/src/KonSoft.Payment.Domain/Settings/PaymentSettingDefinitionProvider.cs b/modules/payment/src/KonSoft.Payment.Domain/Settings/PaymentSettingDefinitionProvider.cs new file mode 100644 index 0000000..59b8e51 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain/Settings/PaymentSettingDefinitionProvider.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Settings; + +namespace KonSoft.Payment.Settings; + +public class PaymentSettingDefinitionProvider : SettingDefinitionProvider +{ + public override void Define(ISettingDefinitionContext context) + { + //Define your own settings here. Example: + //context.Add(new SettingDefinition(PaymentSettings.MySetting1)); + } +} diff --git a/modules/payment/src/KonSoft.Payment.Domain/Settings/PaymentSettings.cs b/modules/payment/src/KonSoft.Payment.Domain/Settings/PaymentSettings.cs new file mode 100644 index 0000000..07b3d18 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.Domain/Settings/PaymentSettings.cs @@ -0,0 +1,9 @@ +namespace KonSoft.Payment.Settings; + +public static class PaymentSettings +{ + private const string Prefix = "Payment"; + + //Add your own setting names here. Example: + //public const string MySetting1 = Prefix + ".MySetting1"; +} diff --git a/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCorePaymentDbSchemaMigrator.cs b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCorePaymentDbSchemaMigrator.cs new file mode 100644 index 0000000..d96b923 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCorePaymentDbSchemaMigrator.cs @@ -0,0 +1,34 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using KonSoft.Payment.Data; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Payment.EntityFrameworkCore; + +public class EntityFrameworkCorePaymentDbSchemaMigrator + : IPaymentDbSchemaMigrator, ITransientDependency +{ + private readonly IServiceProvider _serviceProvider; + + public EntityFrameworkCorePaymentDbSchemaMigrator( + IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public async Task MigrateAsync() + { + /* We intentionally resolve the PaymentDbContext + * from IServiceProvider (instead of directly injecting it) + * to properly get the connection string of the current tenant in the + * current scope. + */ + + await _serviceProvider + .GetRequiredService() + .Database + .MigrateAsync(); + } +} diff --git a/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentDbContext.cs b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentDbContext.cs new file mode 100644 index 0000000..9aecc99 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentDbContext.cs @@ -0,0 +1,86 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.AuditLogging.EntityFrameworkCore; +using Volo.Abp.BackgroundJobs.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Identity; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.OpenIddict.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.TenantManagement; +using Volo.Abp.TenantManagement.EntityFrameworkCore; + +namespace KonSoft.Payment.EntityFrameworkCore; + +[ReplaceDbContext(typeof(IIdentityDbContext))] +[ReplaceDbContext(typeof(ITenantManagementDbContext))] +[ConnectionStringName("Default")] +public class PaymentDbContext : + AbpDbContext, + IIdentityDbContext, + ITenantManagementDbContext +{ + /* Add DbSet properties for your Aggregate Roots / Entities here. */ + + #region Entities from the modules + + /* Notice: We only implemented IIdentityDbContext and ITenantManagementDbContext + * and replaced them for this DbContext. This allows you to perform JOIN + * queries for the entities of these modules over the repositories easily. You + * typically don't need that for other modules. But, if you need, you can + * implement the DbContext interface of the needed module and use ReplaceDbContext + * attribute just like IIdentityDbContext and ITenantManagementDbContext. + * + * More info: Replacing a DbContext of a module ensures that the related module + * uses this DbContext on runtime. Otherwise, it will use its own DbContext class. + */ + + //Identity + public DbSet Users { get; set; } + public DbSet Roles { get; set; } + public DbSet ClaimTypes { get; set; } + public DbSet OrganizationUnits { get; set; } + public DbSet SecurityLogs { get; set; } + public DbSet LinkUsers { get; set; } + public DbSet UserDelegations { get; set; } + public DbSet Sessions { get; set; } + // Tenant Management + public DbSet Tenants { get; set; } + public DbSet TenantConnectionStrings { get; set; } + + #endregion + + public PaymentDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + /* Include modules to your migration db context */ + + builder.ConfigurePermissionManagement(); + builder.ConfigureSettingManagement(); + builder.ConfigureBackgroundJobs(); + builder.ConfigureAuditLogging(); + builder.ConfigureIdentity(); + builder.ConfigureOpenIddict(); + builder.ConfigureFeatureManagement(); + builder.ConfigureTenantManagement(); + + /* Configure your own tables/entities inside here */ + + //builder.Entity(b => + //{ + // b.ToTable(PaymentConsts.DbTablePrefix + "YourEntities", PaymentConsts.DbSchema); + // b.ConfigureByConvention(); //auto configure for the base class props + // //... + //}); + } +} diff --git a/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentDbContextFactory.cs b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentDbContextFactory.cs new file mode 100644 index 0000000..fc21917 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentDbContextFactory.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; + +namespace KonSoft.Payment.EntityFrameworkCore; + +/* This class is needed for EF Core console commands + * (like Add-Migration and Update-Database commands) */ +public class PaymentDbContextFactory : IDesignTimeDbContextFactory +{ + public PaymentDbContext CreateDbContext(string[] args) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + + PaymentEfCoreEntityExtensionMappings.Configure(); + + var configuration = BuildConfiguration(); + + var builder = new DbContextOptionsBuilder() + .UseNpgsql(configuration.GetConnectionString("Default")); + + return new PaymentDbContext(builder.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../KonSoft.Payment.DbMigrator/")) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentEfCoreEntityExtensionMappings.cs b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentEfCoreEntityExtensionMappings.cs new file mode 100644 index 0000000..9c70801 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentEfCoreEntityExtensionMappings.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.Payment.EntityFrameworkCore; + +public static class PaymentEfCoreEntityExtensionMappings +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + PaymentGlobalFeatureConfigurator.Configure(); + PaymentModuleExtensionConfigurator.Configure(); + + OneTimeRunner.Run(() => + { + /* You can configure extra properties for the + * entities defined in the modules used by your application. + * + * This class can be used to map these extra properties to table fields in the database. + * + * USE THIS CLASS ONLY TO CONFIGURE EF CORE RELATED MAPPING. + * USE PaymentModuleExtensionConfigurator CLASS (in the Domain.Shared project) + * FOR A HIGH LEVEL API TO DEFINE EXTRA PROPERTIES TO ENTITIES OF THE USED MODULES + * + * Example: Map a property to a table field: + + ObjectExtensionManager.Instance + .MapEfCoreProperty( + "MyProperty", + (entityBuilder, propertyBuilder) => + { + propertyBuilder.HasMaxLength(128); + } + ); + + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities + */ + }); + } +} diff --git a/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentEntityFrameworkCoreModule.cs b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentEntityFrameworkCoreModule.cs new file mode 100644 index 0000000..6b196a8 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/EntityFrameworkCore/PaymentEntityFrameworkCoreModule.cs @@ -0,0 +1,57 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Uow; +using Volo.Abp.AuditLogging.EntityFrameworkCore; +using Volo.Abp.BackgroundJobs.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.TenantManagement.EntityFrameworkCore; + +namespace KonSoft.Payment.EntityFrameworkCore; + +[DependsOn( + typeof(PaymentDomainModule), + typeof(AbpIdentityEntityFrameworkCoreModule), + typeof(AbpOpenIddictEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpBackgroundJobsEntityFrameworkCoreModule), + typeof(AbpAuditLoggingEntityFrameworkCoreModule), + typeof(AbpTenantManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule) + )] +public class PaymentEntityFrameworkCoreModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + + PaymentEfCoreEntityExtensionMappings.Configure(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(options => + { + /* Remove "includeAllEntities: true" to create + * default repositories only for aggregate roots */ + options.AddDefaultRepositories(includeAllEntities: true); + }); + + Configure(options => + { + /* The main point to change your DBMS. + * See also PaymentMigrationsDbContextFactory for EF Core tooling. */ + options.UseNpgsql(); + }); + + } +} diff --git a/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/KonSoft.Payment.EntityFrameworkCore.csproj b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/KonSoft.Payment.EntityFrameworkCore.csproj new file mode 100644 index 0000000..b1ec0b7 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/KonSoft.Payment.EntityFrameworkCore.csproj @@ -0,0 +1,31 @@ + + + + + + net8.0 + enable + KonSoft.Payment + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + diff --git a/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Migrations/20250908052440_Initial.Designer.cs b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Migrations/20250908052440_Initial.Designer.cs new file mode 100644 index 0000000..0eefc2a --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Migrations/20250908052440_Initial.Designer.cs @@ -0,0 +1,2006 @@ +// +using System; +using KonSoft.Payment.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace KonSoft.Payment.Migrations +{ + [DbContext(typeof(PaymentDbContext))] + [Migration("20250908052440_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("text"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("integer") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("smallint") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("uuid"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("EntityChangeId") + .HasColumnType("uuid"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsAbandoned") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("JobArgs") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)"); + + b.Property("JobName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LastTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("NextTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((byte)15); + + b.Property("TryCount") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((short)0); + + b.HasKey("Id"); + + b.HasIndex("IsAbandoned", "NextTryTime"); + + b.ToTable("AbpBackgroundJobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property("ValueType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("SourceTenantId") + .HasColumnType("uuid"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("TargetTenantId") + .HasColumnType("uuid"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique(); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("boolean") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("boolean") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("IpAddresses") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("LastAccessed") + .HasColumnType("timestamp without time zone"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("SignedIn") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("boolean"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("EndTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("StartTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("character varying(196)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("character varying(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ClientSecret") + .HasColumnType("text"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientUri") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JsonWebKeySet") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasColumnType("text"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedirectUris") + .HasColumnType("text"); + + b.Property("Requirements") + .HasColumnType("text"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Scopes") + .HasColumnType("text"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Descriptions") + .HasColumnType("text"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Resources") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AuthorizationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Payload") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("MultiTenancySide") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("boolean"); + + b.Property("IsInherited") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + + b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) + .WithMany() + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Migrations/20250908052440_Initial.cs b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Migrations/20250908052440_Initial.cs new file mode 100644 index 0000000..00846bf --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Migrations/20250908052440_Initial.cs @@ -0,0 +1,1156 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace KonSoft.Payment.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpAuditLogs", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationName = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + TenantName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ImpersonatorUserId = table.Column(type: "uuid", nullable: true), + ImpersonatorUserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ImpersonatorTenantId = table.Column(type: "uuid", nullable: true), + ImpersonatorTenantName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ExecutionTime = table.Column(type: "timestamp without time zone", nullable: false), + ExecutionDuration = table.Column(type: "integer", nullable: false), + ClientIpAddress = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + HttpMethod = table.Column(type: "character varying(16)", maxLength: 16, nullable: true), + Url = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + Exceptions = table.Column(type: "text", nullable: true), + Comments = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + HttpStatusCode = table.Column(type: "integer", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpBackgroundJobs", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + JobName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + JobArgs = table.Column(type: "character varying(1048576)", maxLength: 1048576, nullable: false), + TryCount = table.Column(type: "smallint", nullable: false, defaultValue: (short)0), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + NextTryTime = table.Column(type: "timestamp without time zone", nullable: false), + LastTryTime = table.Column(type: "timestamp without time zone", nullable: true), + IsAbandoned = table.Column(type: "boolean", nullable: false, defaultValue: false), + Priority = table.Column(type: "smallint", nullable: false, defaultValue: (byte)15), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpBackgroundJobs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpClaimTypes", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Required = table.Column(type: "boolean", nullable: false), + IsStatic = table.Column(type: "boolean", nullable: false), + Regex = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + RegexDescription = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatureGroups", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatures", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + GroupName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ParentName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + DefaultValue = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + IsVisibleToClients = table.Column(type: "boolean", nullable: false), + IsAvailableToHost = table.Column(type: "boolean", nullable: false), + AllowedProviders = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatures", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatureValues", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureValues", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpLinkUsers", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + SourceUserId = table.Column(type: "uuid", nullable: false), + SourceTenantId = table.Column(type: "uuid", nullable: true), + TargetUserId = table.Column(type: "uuid", nullable: false), + TargetTenantId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLinkUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ParentId = table.Column(type: "uuid", nullable: true), + Code = table.Column(type: "character varying(95)", maxLength: 95, nullable: false), + DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGrants", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGrants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGroups", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + GroupName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ParentName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsEnabled = table.Column(type: "boolean", nullable: false), + MultiTenancySide = table.Column(type: "smallint", nullable: false), + Providers = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + StateCheckers = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpRoles", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsDefault = table.Column(type: "boolean", nullable: false), + IsStatic = table.Column(type: "boolean", nullable: false), + IsPublic = table.Column(type: "boolean", nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSecurityLogs", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ApplicationName = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + Identity = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + Action = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + TenantName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientIpAddress = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSecurityLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSessions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + SessionId = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Device = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + DeviceInfo = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + UserId = table.Column(type: "uuid", nullable: false), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + IpAddresses = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + SignedIn = table.Column(type: "timestamp without time zone", nullable: false), + LastAccessed = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSessions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSettingDefinitions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + DefaultValue = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + IsVisibleToClients = table.Column(type: "boolean", nullable: false), + Providers = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + IsInherited = table.Column(type: "boolean", nullable: false), + IsEncrypted = table.Column(type: "boolean", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettingDefinitions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSettings", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpTenants", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUserDelegations", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + SourceUserId = table.Column(type: "uuid", nullable: false), + TargetUserId = table.Column(type: "uuid", nullable: false), + StartTime = table.Column(type: "timestamp without time zone", nullable: false), + EndTime = table.Column(type: "timestamp without time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserDelegations", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUsers", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedUserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + Surname = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + Email = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedEmail = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + EmailConfirmed = table.Column(type: "boolean", nullable: false, defaultValue: false), + PasswordHash = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + SecurityStamp = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsExternal = table.Column(type: "boolean", nullable: false, defaultValue: false), + PhoneNumber = table.Column(type: "character varying(16)", maxLength: 16, nullable: true), + PhoneNumberConfirmed = table.Column(type: "boolean", nullable: false, defaultValue: false), + IsActive = table.Column(type: "boolean", nullable: false), + TwoFactorEnabled = table.Column(type: "boolean", nullable: false, defaultValue: false), + LockoutEnd = table.Column(type: "timestamp with time zone", nullable: true), + LockoutEnabled = table.Column(type: "boolean", nullable: false, defaultValue: false), + AccessFailedCount = table.Column(type: "integer", nullable: false, defaultValue: 0), + ShouldChangePasswordOnNextLogin = table.Column(type: "boolean", nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + LastPasswordChangeTime = table.Column(type: "timestamp with time zone", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictApplications", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ClientId = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + ClientSecret = table.Column(type: "text", nullable: true), + ClientType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ConsentType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + DisplayName = table.Column(type: "text", nullable: true), + DisplayNames = table.Column(type: "text", nullable: true), + JsonWebKeySet = table.Column(type: "text", nullable: true), + Permissions = table.Column(type: "text", nullable: true), + PostLogoutRedirectUris = table.Column(type: "text", nullable: true), + Properties = table.Column(type: "text", nullable: true), + RedirectUris = table.Column(type: "text", nullable: true), + Requirements = table.Column(type: "text", nullable: true), + Settings = table.Column(type: "text", nullable: true), + ClientUri = table.Column(type: "text", nullable: true), + LogoUri = table.Column(type: "text", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictApplications", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictScopes", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Description = table.Column(type: "text", nullable: true), + Descriptions = table.Column(type: "text", nullable: true), + DisplayName = table.Column(type: "text", nullable: true), + DisplayNames = table.Column(type: "text", nullable: true), + Name = table.Column(type: "character varying(200)", maxLength: 200, nullable: true), + Properties = table.Column(type: "text", nullable: true), + Resources = table.Column(type: "text", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictScopes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpAuditLogActions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + AuditLogId = table.Column(type: "uuid", nullable: false), + ServiceName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + MethodName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Parameters = table.Column(type: "character varying(2000)", maxLength: 2000, nullable: true), + ExecutionTime = table.Column(type: "timestamp without time zone", nullable: false), + ExecutionDuration = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogActions", x => x.Id); + table.ForeignKey( + name: "FK_AbpAuditLogActions_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpEntityChanges", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + AuditLogId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ChangeTime = table.Column(type: "timestamp without time zone", nullable: false), + ChangeType = table.Column(type: "smallint", nullable: false), + EntityTenantId = table.Column(type: "uuid", nullable: true), + EntityId = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + EntityTypeFullName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityChanges_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(type: "uuid", nullable: false), + OrganizationUnitId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationU~", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpRoleClaims", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ClaimType = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpRoleClaims_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpTenantConnectionStrings", + columns: table => new + { + TenantId = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Value = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenantConnectionStrings", x => new { x.TenantId, x.Name }); + table.ForeignKey( + name: "FK_AbpTenantConnectionStrings_AbpTenants_TenantId", + column: x => x.TenantId, + principalTable: "AbpTenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserClaims", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ClaimType = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpUserClaims_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserLogins", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + LoginProvider = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ProviderKey = table.Column(type: "character varying(196)", maxLength: 196, nullable: false), + ProviderDisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserLogins", x => new { x.UserId, x.LoginProvider }); + table.ForeignKey( + name: "FK_AbpUserLogins_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + OrganizationUnitId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationU~", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserRoles", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserTokens", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + LoginProvider = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Value = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AbpUserTokens_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictAuthorizations", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationId = table.Column(type: "uuid", nullable: true), + CreationDate = table.Column(type: "timestamp without time zone", nullable: true), + Properties = table.Column(type: "text", nullable: true), + Scopes = table.Column(type: "text", nullable: true), + Status = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + Subject = table.Column(type: "character varying(400)", maxLength: 400, nullable: true), + Type = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictAuthorizations_OpenIddictApplications_Application~", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AbpEntityPropertyChanges", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + EntityChangeId = table.Column(type: "uuid", nullable: false), + NewValue = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + OriginalValue = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + PropertyName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + PropertyTypeFullName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityPropertyChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityPropertyChanges_AbpEntityChanges_EntityChangeId", + column: x => x.EntityChangeId, + principalTable: "AbpEntityChanges", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictTokens", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationId = table.Column(type: "uuid", nullable: true), + AuthorizationId = table.Column(type: "uuid", nullable: true), + CreationDate = table.Column(type: "timestamp without time zone", nullable: true), + ExpirationDate = table.Column(type: "timestamp without time zone", nullable: true), + Payload = table.Column(type: "text", nullable: true), + Properties = table.Column(type: "text", nullable: true), + RedemptionDate = table.Column(type: "timestamp without time zone", nullable: true), + ReferenceId = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + Status = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + Subject = table.Column(type: "character varying(400)", maxLength: 400, nullable: true), + Type = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictTokens", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId", + column: x => x.AuthorizationId, + principalTable: "OpenIddictAuthorizations", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_AuditLogId", + table: "AbpAuditLogActions", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_TenantId_ServiceName_MethodName_Executio~", + table: "AbpAuditLogActions", + columns: new[] { "TenantId", "ServiceName", "MethodName", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_UserId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "UserId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpBackgroundJobs_IsAbandoned_NextTryTime", + table: "AbpBackgroundJobs", + columns: new[] { "IsAbandoned", "NextTryTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_AuditLogId", + table: "AbpEntityChanges", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_TenantId_EntityTypeFullName_EntityId", + table: "AbpEntityChanges", + columns: new[] { "TenantId", "EntityTypeFullName", "EntityId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityPropertyChanges_EntityChangeId", + table: "AbpEntityPropertyChanges", + column: "EntityChangeId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureGroups_Name", + table: "AbpFeatureGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_GroupName", + table: "AbpFeatures", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_Name", + table: "AbpFeatures", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureValues_Name_ProviderName_ProviderKey", + table: "AbpFeatureValues", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpLinkUsers_SourceUserId_SourceTenantId_TargetUserId_Targe~", + table: "AbpLinkUsers", + columns: new[] { "SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGrants_TenantId_Name_ProviderName_ProviderKey", + table: "AbpPermissionGrants", + columns: new[] { "TenantId", "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGroups_Name", + table: "AbpPermissionGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_GroupName", + table: "AbpPermissions", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_Name", + table: "AbpPermissions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoleClaims_RoleId", + table: "AbpRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoles_NormalizedName", + table: "AbpRoles", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Action", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Action" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_ApplicationName", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "ApplicationName" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Identity", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Identity" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_UserId", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_Device", + table: "AbpSessions", + column: "Device"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_SessionId", + table: "AbpSessions", + column: "SessionId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_TenantId_UserId", + table: "AbpSessions", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettingDefinitions_Name", + table: "AbpSettingDefinitions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettings_Name_ProviderName_ProviderKey", + table: "AbpSettings", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_Name", + table: "AbpTenants", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserClaims_UserId", + table: "AbpUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserLogins_LoginProvider_ProviderKey", + table: "AbpUserLogins", + columns: new[] { "LoginProvider", "ProviderKey" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserRoles_RoleId_UserId", + table: "AbpUserRoles", + columns: new[] { "RoleId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_Email", + table: "AbpUsers", + column: "Email"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedEmail", + table: "AbpUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedUserName", + table: "AbpUsers", + column: "NormalizedUserName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_UserName", + table: "AbpUsers", + column: "UserName"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictApplications_ClientId", + table: "OpenIddictApplications", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictAuthorizations_ApplicationId_Status_Subject_Type", + table: "OpenIddictAuthorizations", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictScopes_Name", + table: "OpenIddictScopes", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ApplicationId_Status_Subject_Type", + table: "OpenIddictTokens", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_AuthorizationId", + table: "OpenIddictTokens", + column: "AuthorizationId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ReferenceId", + table: "OpenIddictTokens", + column: "ReferenceId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpAuditLogActions"); + + migrationBuilder.DropTable( + name: "AbpBackgroundJobs"); + + migrationBuilder.DropTable( + name: "AbpClaimTypes"); + + migrationBuilder.DropTable( + name: "AbpEntityPropertyChanges"); + + migrationBuilder.DropTable( + name: "AbpFeatureGroups"); + + migrationBuilder.DropTable( + name: "AbpFeatures"); + + migrationBuilder.DropTable( + name: "AbpFeatureValues"); + + migrationBuilder.DropTable( + name: "AbpLinkUsers"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + + migrationBuilder.DropTable( + name: "AbpPermissionGrants"); + + migrationBuilder.DropTable( + name: "AbpPermissionGroups"); + + migrationBuilder.DropTable( + name: "AbpPermissions"); + + migrationBuilder.DropTable( + name: "AbpRoleClaims"); + + migrationBuilder.DropTable( + name: "AbpSecurityLogs"); + + migrationBuilder.DropTable( + name: "AbpSessions"); + + migrationBuilder.DropTable( + name: "AbpSettingDefinitions"); + + migrationBuilder.DropTable( + name: "AbpSettings"); + + migrationBuilder.DropTable( + name: "AbpTenantConnectionStrings"); + + migrationBuilder.DropTable( + name: "AbpUserClaims"); + + migrationBuilder.DropTable( + name: "AbpUserDelegations"); + + migrationBuilder.DropTable( + name: "AbpUserLogins"); + + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpUserRoles"); + + migrationBuilder.DropTable( + name: "AbpUserTokens"); + + migrationBuilder.DropTable( + name: "OpenIddictScopes"); + + migrationBuilder.DropTable( + name: "OpenIddictTokens"); + + migrationBuilder.DropTable( + name: "AbpEntityChanges"); + + migrationBuilder.DropTable( + name: "AbpTenants"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpRoles"); + + migrationBuilder.DropTable( + name: "AbpUsers"); + + migrationBuilder.DropTable( + name: "OpenIddictAuthorizations"); + + migrationBuilder.DropTable( + name: "AbpAuditLogs"); + + migrationBuilder.DropTable( + name: "OpenIddictApplications"); + } + } +} diff --git a/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Migrations/PaymentDbContextModelSnapshot.cs b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Migrations/PaymentDbContextModelSnapshot.cs new file mode 100644 index 0000000..e65c7ae --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Migrations/PaymentDbContextModelSnapshot.cs @@ -0,0 +1,2003 @@ +// +using System; +using KonSoft.Payment.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace KonSoft.Payment.Migrations +{ + [DbContext(typeof(PaymentDbContext))] + partial class PaymentDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("text"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("integer") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("smallint") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("uuid"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("EntityChangeId") + .HasColumnType("uuid"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsAbandoned") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("JobArgs") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)"); + + b.Property("JobName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LastTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("NextTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((byte)15); + + b.Property("TryCount") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((short)0); + + b.HasKey("Id"); + + b.HasIndex("IsAbandoned", "NextTryTime"); + + b.ToTable("AbpBackgroundJobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property("ValueType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("SourceTenantId") + .HasColumnType("uuid"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("TargetTenantId") + .HasColumnType("uuid"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique(); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("boolean") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("boolean") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("IpAddresses") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("LastAccessed") + .HasColumnType("timestamp without time zone"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("SignedIn") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("boolean"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("EndTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("StartTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("character varying(196)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("character varying(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ClientSecret") + .HasColumnType("text"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientUri") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JsonWebKeySet") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasColumnType("text"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedirectUris") + .HasColumnType("text"); + + b.Property("Requirements") + .HasColumnType("text"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Scopes") + .HasColumnType("text"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Descriptions") + .HasColumnType("text"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Resources") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AuthorizationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Payload") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("MultiTenancySide") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("boolean"); + + b.Property("IsInherited") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + + b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) + .WithMany() + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Properties/AssemblyInfo.cs b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..cf32d3b --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.EntityFrameworkCore/Properties/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.Payment.EntityFrameworkCore.Tests")] diff --git a/modules/payment/src/KonSoft.Payment.HttpApi.Client/KonSoft.Payment.HttpApi.Client.csproj b/modules/payment/src/KonSoft.Payment.HttpApi.Client/KonSoft.Payment.HttpApi.Client.csproj new file mode 100644 index 0000000..59ef0ab --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.HttpApi.Client/KonSoft.Payment.HttpApi.Client.csproj @@ -0,0 +1,29 @@ + + + + + + net8.0 + enable + KonSoft.Payment + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/payment/src/KonSoft.Payment.HttpApi.Client/PaymentHttpApiClientModule.cs b/modules/payment/src/KonSoft.Payment.HttpApi.Client/PaymentHttpApiClientModule.cs new file mode 100644 index 0000000..bbdeb31 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.HttpApi.Client/PaymentHttpApiClientModule.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.TenantManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.Payment; + +[DependsOn( + typeof(PaymentApplicationContractsModule), + typeof(AbpAccountHttpApiClientModule), + typeof(AbpIdentityHttpApiClientModule), + typeof(AbpPermissionManagementHttpApiClientModule), + typeof(AbpTenantManagementHttpApiClientModule), + typeof(AbpFeatureManagementHttpApiClientModule), + typeof(AbpSettingManagementHttpApiClientModule) +)] +public class PaymentHttpApiClientModule : AbpModule +{ + public const string RemoteServiceName = "Default"; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddHttpClientProxies( + typeof(PaymentApplicationContractsModule).Assembly, + RemoteServiceName + ); + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + } +} diff --git a/modules/payment/src/KonSoft.Payment.HttpApi/Controllers/PaymentController.cs b/modules/payment/src/KonSoft.Payment.HttpApi/Controllers/PaymentController.cs new file mode 100644 index 0000000..4120fb4 --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.HttpApi/Controllers/PaymentController.cs @@ -0,0 +1,14 @@ +using KonSoft.Payment.Localization; +using Volo.Abp.AspNetCore.Mvc; + +namespace KonSoft.Payment.Controllers; + +/* Inherit your controllers from this class. + */ +public abstract class PaymentController : AbpControllerBase +{ + protected PaymentController() + { + LocalizationResource = typeof(PaymentResource); + } +} diff --git a/modules/payment/src/KonSoft.Payment.HttpApi/KonSoft.Payment.HttpApi.csproj b/modules/payment/src/KonSoft.Payment.HttpApi/KonSoft.Payment.HttpApi.csproj new file mode 100644 index 0000000..ba7550c --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.HttpApi/KonSoft.Payment.HttpApi.csproj @@ -0,0 +1,24 @@ + + + + + + net8.0 + enable + KonSoft.Payment + + + + + + + + + + + + + + + + diff --git a/modules/payment/src/KonSoft.Payment.HttpApi/Models/Test/TestModel.cs b/modules/payment/src/KonSoft.Payment.HttpApi/Models/Test/TestModel.cs new file mode 100644 index 0000000..0f9671c --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.HttpApi/Models/Test/TestModel.cs @@ -0,0 +1,10 @@ +using System; + +namespace KonSoft.Payment.Models.Test; + +public class TestModel +{ + public string? Name { get; set; } + + public DateTime BirthDate { get; set; } +} diff --git a/modules/payment/src/KonSoft.Payment.HttpApi/PaymentHttpApiModule.cs b/modules/payment/src/KonSoft.Payment.HttpApi/PaymentHttpApiModule.cs new file mode 100644 index 0000000..ae7ce3a --- /dev/null +++ b/modules/payment/src/KonSoft.Payment.HttpApi/PaymentHttpApiModule.cs @@ -0,0 +1,41 @@ +using Localization.Resources.AbpUi; +using KonSoft.Payment.Localization; +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.HttpApi; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Payment; + +[DependsOn( + typeof(PaymentApplicationContractsModule), + typeof(AbpAccountHttpApiModule), + typeof(AbpIdentityHttpApiModule), + typeof(AbpPermissionManagementHttpApiModule), + typeof(AbpTenantManagementHttpApiModule), + typeof(AbpFeatureManagementHttpApiModule), + typeof(AbpSettingManagementHttpApiModule) + )] +public class PaymentHttpApiModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + ConfigureLocalization(); + } + + private void ConfigureLocalization() + { + Configure(options => + { + options.Resources + .Get() + .AddBaseTypes( + typeof(AbpUiResource) + ); + }); + } +} diff --git a/modules/payment/test/KonSoft.Payment.Application.Tests/KonSoft.Payment.Application.Tests.csproj b/modules/payment/test/KonSoft.Payment.Application.Tests/KonSoft.Payment.Application.Tests.csproj new file mode 100644 index 0000000..8745827 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.Application.Tests/KonSoft.Payment.Application.Tests.csproj @@ -0,0 +1,20 @@ + + + + + + net8.0 + enable + KonSoft.Payment + + + + + + + + + + + + diff --git a/modules/payment/test/KonSoft.Payment.Application.Tests/PaymentApplicationTestBase.cs b/modules/payment/test/KonSoft.Payment.Application.Tests/PaymentApplicationTestBase.cs new file mode 100644 index 0000000..9478300 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.Application.Tests/PaymentApplicationTestBase.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Payment; + +public abstract class PaymentApplicationTestBase : PaymentTestBase + where TStartupModule : IAbpModule +{ + +} diff --git a/modules/payment/test/KonSoft.Payment.Application.Tests/PaymentApplicationTestModule.cs b/modules/payment/test/KonSoft.Payment.Application.Tests/PaymentApplicationTestModule.cs new file mode 100644 index 0000000..19d15d8 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.Application.Tests/PaymentApplicationTestModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Payment; + +[DependsOn( + typeof(PaymentApplicationModule), + typeof(PaymentDomainTestModule) +)] +public class PaymentApplicationTestModule : AbpModule +{ + +} diff --git a/modules/payment/test/KonSoft.Payment.Application.Tests/Samples/SampleAppServiceTests.cs b/modules/payment/test/KonSoft.Payment.Application.Tests/Samples/SampleAppServiceTests.cs new file mode 100644 index 0000000..058c005 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.Application.Tests/Samples/SampleAppServiceTests.cs @@ -0,0 +1,34 @@ +using Shouldly; +using System.Threading.Tasks; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Xunit; + +namespace KonSoft.Payment.Samples; + +/* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IIdentityUserAppService here). + * Only test your own application services. + */ +public abstract class SampleAppServiceTests : PaymentApplicationTestBase + where TStartupModule : IAbpModule +{ + private readonly IIdentityUserAppService _userAppService; + + protected SampleAppServiceTests() + { + _userAppService = GetRequiredService(); + } + + [Fact] + public async Task Initial_Data_Should_Contain_Admin_User() + { + //Act + var result = await _userAppService.GetListAsync(new GetIdentityUsersInput()); + + //Assert + result.TotalCount.ShouldBeGreaterThan(0); + result.Items.ShouldContain(u => u.UserName == "admin"); + } +} diff --git a/modules/payment/test/KonSoft.Payment.Domain.Tests/KonSoft.Payment.Domain.Tests.csproj b/modules/payment/test/KonSoft.Payment.Domain.Tests/KonSoft.Payment.Domain.Tests.csproj new file mode 100644 index 0000000..34891a2 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.Domain.Tests/KonSoft.Payment.Domain.Tests.csproj @@ -0,0 +1,20 @@ + + + + + + net8.0 + enable + KonSoft.Payment + + + + + + + + + + + + diff --git a/modules/payment/test/KonSoft.Payment.Domain.Tests/PaymentDomainTestBase.cs b/modules/payment/test/KonSoft.Payment.Domain.Tests/PaymentDomainTestBase.cs new file mode 100644 index 0000000..919c54d --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.Domain.Tests/PaymentDomainTestBase.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Payment; + +/* Inherit from this class for your domain layer tests. */ +public abstract class PaymentDomainTestBase : PaymentTestBase + where TStartupModule : IAbpModule +{ + +} diff --git a/modules/payment/test/KonSoft.Payment.Domain.Tests/PaymentDomainTestModule.cs b/modules/payment/test/KonSoft.Payment.Domain.Tests/PaymentDomainTestModule.cs new file mode 100644 index 0000000..9a6dca8 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.Domain.Tests/PaymentDomainTestModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Payment; + +[DependsOn( + typeof(PaymentDomainModule), + typeof(PaymentTestBaseModule) +)] +public class PaymentDomainTestModule : AbpModule +{ + +} diff --git a/modules/payment/test/KonSoft.Payment.Domain.Tests/Samples/SampleDomainTests.cs b/modules/payment/test/KonSoft.Payment.Domain.Tests/Samples/SampleDomainTests.cs new file mode 100644 index 0000000..8994eaf --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.Domain.Tests/Samples/SampleDomainTests.cs @@ -0,0 +1,46 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Xunit; + +namespace KonSoft.Payment.Samples; + +/* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IdentityUserManager here). + * Only test your own domain services. + */ +public abstract class SampleDomainTests : PaymentDomainTestBase + where TStartupModule : IAbpModule +{ + private readonly IIdentityUserRepository _identityUserRepository; + private readonly IdentityUserManager _identityUserManager; + + protected SampleDomainTests() + { + _identityUserRepository = GetRequiredService(); + _identityUserManager = GetRequiredService(); + } + + [Fact] + public async Task Should_Set_Email_Of_A_User() + { + IdentityUser adminUser; + + /* Need to manually start Unit Of Work because + * FirstOrDefaultAsync should be executed while db connection / context is available. + */ + await WithUnitOfWorkAsync(async () => + { + adminUser = await _identityUserRepository + .FindByNormalizedUserNameAsync("ADMIN"); + + await _identityUserManager.SetEmailAsync(adminUser, "newemail@abp.io"); + await _identityUserRepository.UpdateAsync(adminUser); + }); + + adminUser = await _identityUserRepository.FindByNormalizedUserNameAsync("ADMIN"); + adminUser.Email.ShouldBe("newemail@abp.io"); + } +} diff --git a/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs new file mode 100644 index 0000000..cc8ecc3 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs @@ -0,0 +1,10 @@ +using KonSoft.Payment.Samples; +using Xunit; + +namespace KonSoft.Payment.EntityFrameworkCore.Applications; + +[Collection(PaymentTestConsts.CollectionDefinitionName)] +public class EfCoreSampleAppServiceTests : SampleAppServiceTests +{ + +} diff --git a/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs new file mode 100644 index 0000000..e90b9fa --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs @@ -0,0 +1,10 @@ +using KonSoft.Payment.Samples; +using Xunit; + +namespace KonSoft.Payment.EntityFrameworkCore.Domains; + +[Collection(PaymentTestConsts.CollectionDefinitionName)] +public class EfCoreSampleDomainTests : SampleDomainTests +{ + +} diff --git a/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreCollection.cs b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreCollection.cs new file mode 100644 index 0000000..f2ddf4d --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreCollection.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace KonSoft.Payment.EntityFrameworkCore; + +[CollectionDefinition(PaymentTestConsts.CollectionDefinitionName)] +public class PaymentEntityFrameworkCoreCollection : ICollectionFixture +{ + +} diff --git a/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreCollectionFixtureBase.cs b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreCollectionFixtureBase.cs new file mode 100644 index 0000000..d29e066 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreCollectionFixtureBase.cs @@ -0,0 +1,9 @@ +using KonSoft.Payment.EntityFrameworkCore; +using Xunit; + +namespace KonSoft.Payment.EntityFrameworkCore; + +public class PaymentEntityFrameworkCoreCollectionFixtureBase : ICollectionFixture +{ + +} diff --git a/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreFixture.cs b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreFixture.cs new file mode 100644 index 0000000..54424f9 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreFixture.cs @@ -0,0 +1,11 @@ +using System; + +namespace KonSoft.Payment.EntityFrameworkCore; + +public class PaymentEntityFrameworkCoreFixture : IDisposable +{ + public void Dispose() + { + + } +} diff --git a/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreTestBase.cs b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreTestBase.cs new file mode 100644 index 0000000..ac885da --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreTestBase.cs @@ -0,0 +1,8 @@ +using Volo.Abp; + +namespace KonSoft.Payment.EntityFrameworkCore; + +public abstract class PaymentEntityFrameworkCoreTestBase : PaymentTestBase +{ + +} diff --git a/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreTestModule.cs b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreTestModule.cs new file mode 100644 index 0000000..d431bc1 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/PaymentEntityFrameworkCoreTestModule.cs @@ -0,0 +1,82 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.Sqlite; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.Uow; + +namespace KonSoft.Payment.EntityFrameworkCore; + +[DependsOn( + typeof(PaymentApplicationTestModule), + typeof(PaymentEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCoreSqliteModule) + )] +public class PaymentEntityFrameworkCoreTestModule : AbpModule +{ + private SqliteConnection? _sqliteConnection; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.SaveStaticFeaturesToDatabase = false; + options.IsDynamicFeatureStoreEnabled = false; + }); + Configure(options => + { + options.SaveStaticPermissionsToDatabase = false; + options.IsDynamicPermissionStoreEnabled = false; + }); + Configure(options => + { + options.SaveStaticSettingsToDatabase = false; + options.IsDynamicSettingStoreEnabled = false; + }); + context.Services.AddAlwaysDisableUnitOfWorkTransaction(); + + ConfigureInMemorySqlite(context.Services); + } + + private void ConfigureInMemorySqlite(IServiceCollection services) + { + _sqliteConnection = CreateDatabaseAndGetConnection(); + + services.Configure(options => + { + options.Configure(context => + { + context.DbContextOptions.UseSqlite(_sqliteConnection); + }); + }); + } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + _sqliteConnection?.Dispose(); + } + + private static SqliteConnection CreateDatabaseAndGetConnection() + { + var connection = new AbpUnitTestSqliteConnection("Data Source=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new PaymentDbContext(options)) + { + context.GetService().CreateTables(); + } + + return connection; + } +} diff --git a/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs new file mode 100644 index 0000000..0dcfeff --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Shouldly; +using System; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Identity; +using Xunit; + +namespace KonSoft.Payment.EntityFrameworkCore.Samples; + +/* This is just an example test class. + * Normally, you don't test ABP framework code + * (like default AppUser repository IRepository here). + * Only test your custom repository methods. + */ +[Collection(PaymentTestConsts.CollectionDefinitionName)] +public class SampleRepositoryTests : PaymentEntityFrameworkCoreTestBase +{ + private readonly IRepository _appUserRepository; + + public SampleRepositoryTests() + { + _appUserRepository = GetRequiredService>(); + } + + [Fact] + public async Task Should_Query_AppUser() + { + /* Need to manually start Unit Of Work because + * FirstOrDefaultAsync should be executed while db connection / context is available. + */ + await WithUnitOfWorkAsync(async () => + { + //Act + var adminUser = await (await _appUserRepository.GetQueryableAsync()) + .Where(u => u.UserName == "admin") + .FirstOrDefaultAsync(); + + //Assert + adminUser.ShouldNotBeNull(); + }); + } +} diff --git a/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/KonSoft.Payment.EntityFrameworkCore.Tests.csproj b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/KonSoft.Payment.EntityFrameworkCore.Tests.csproj new file mode 100644 index 0000000..5fbb4a3 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.EntityFrameworkCore.Tests/KonSoft.Payment.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,21 @@ + + + + + + net8.0 + enable + KonSoft.Payment + + + + + + + + + + + + + diff --git a/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs new file mode 100644 index 0000000..3b69ac0 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs @@ -0,0 +1,25 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Account; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Payment.HttpApi.Client.ConsoleTestApp; + +public class ClientDemoService : ITransientDependency +{ + private readonly IProfileAppService _profileAppService; + + public ClientDemoService(IProfileAppService profileAppService) + { + _profileAppService = profileAppService; + } + + public async Task RunAsync() + { + var output = await _profileAppService.GetAsync(); + Console.WriteLine($"UserName : {output.UserName}"); + Console.WriteLine($"Email : {output.Email}"); + Console.WriteLine($"Name : {output.Name}"); + Console.WriteLine($"Surname : {output.Surname}"); + } +} diff --git a/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs new file mode 100644 index 0000000..ee68c9a --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.Hosting; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; + +namespace KonSoft.Payment.HttpApi.Client.ConsoleTestApp; + +public class ConsoleTestAppHostedService : IHostedService +{ + private readonly IConfiguration _configuration; + + public ConsoleTestAppHostedService(IConfiguration configuration) + { + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using (var application = await AbpApplicationFactory.CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + })) + { + await application.InitializeAsync(); + + var demo = application.ServiceProvider.GetRequiredService(); + await demo.RunAsync(); + + await application.ShutdownAsync(); + } + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/KonSoft.Payment.HttpApi.Client.ConsoleTestApp.csproj b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/KonSoft.Payment.HttpApi.Client.ConsoleTestApp.csproj new file mode 100644 index 0000000..0ec131f --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/KonSoft.Payment.HttpApi.Client.ConsoleTestApp.csproj @@ -0,0 +1,33 @@ + + + + Exe + net8.0 + enable + + + + + + PreserveNewest + Always + + + + PreserveNewest + Always + + + + + + + + + + + + + + + diff --git a/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/PaymentConsoleApiClientModule.cs b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/PaymentConsoleApiClientModule.cs new file mode 100644 index 0000000..1ff17ab --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/PaymentConsoleApiClientModule.cs @@ -0,0 +1,30 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Polly; +using Volo.Abp.Autofac; +using Volo.Abp.Http.Client; +using Volo.Abp.Http.Client.IdentityModel; +using Volo.Abp.Modularity; + +namespace KonSoft.Payment.HttpApi.Client.ConsoleTestApp; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(PaymentHttpApiClientModule), + typeof(AbpHttpClientIdentityModelModule) + )] +public class PaymentConsoleApiClientModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(options => + { + options.ProxyClientBuildActions.Add((remoteServiceName, clientBuilder) => + { + clientBuilder.AddTransientHttpErrorPolicy( + policyBuilder => policyBuilder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i))) + ); + }); + }); + } +} diff --git a/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/Program.cs b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/Program.cs new file mode 100644 index 0000000..8654dd1 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/Program.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace KonSoft.Payment.HttpApi.Client.ConsoleTestApp; + +class Program +{ + static async Task Main(string[] args) + { + await CreateHostBuilder(args).RunConsoleAsync(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .AddAppSettingsSecretsJson() + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); +} diff --git a/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/appsettings.json b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/appsettings.json new file mode 100644 index 0000000..fcddc86 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/appsettings.json @@ -0,0 +1,17 @@ +{ + "RemoteServices": { + "Default": { + "BaseUrl": "https://localhost:44355" + } + }, + "IdentityClients": { + "Default": { + "GrantType": "password", + "ClientId": "Payment_App", + "UserName": "admin", + "UserPassword": "1q2w3E*", + "Authority": "https://localhost:44355", + "Scope": "Payment" + } + } +} diff --git a/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/modules/payment/test/KonSoft.Payment.TestBase/KonSoft.Payment.TestBase.csproj b/modules/payment/test/KonSoft.Payment.TestBase/KonSoft.Payment.TestBase.csproj new file mode 100644 index 0000000..9272bcd --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.TestBase/KonSoft.Payment.TestBase.csproj @@ -0,0 +1,31 @@ + + + + + + net8.0 + enable + KonSoft.Payment + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + diff --git a/modules/payment/test/KonSoft.Payment.TestBase/PaymentTestBase.cs b/modules/payment/test/KonSoft.Payment.TestBase/PaymentTestBase.cs new file mode 100644 index 0000000..3331157 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.TestBase/PaymentTestBase.cs @@ -0,0 +1,60 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Modularity; +using Volo.Abp.Uow; +using Volo.Abp.Testing; + +namespace KonSoft.Payment; + +/* All test classes are derived from this class, directly or indirectly. + */ +public abstract class PaymentTestBase : AbpIntegratedTest + where TStartupModule : IAbpModule +{ + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + protected virtual Task WithUnitOfWorkAsync(Func func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func action) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + await action(); + + await uow.CompleteAsync(); + } + } + } + + protected virtual Task WithUnitOfWorkAsync(Func> func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func> func) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + var result = await func(); + await uow.CompleteAsync(); + return result; + } + } + } +} diff --git a/modules/payment/test/KonSoft.Payment.TestBase/PaymentTestBaseModule.cs b/modules/payment/test/KonSoft.Payment.TestBase/PaymentTestBaseModule.cs new file mode 100644 index 0000000..d9c1ff6 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.TestBase/PaymentTestBaseModule.cs @@ -0,0 +1,47 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Authorization; +using Volo.Abp.Autofac; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Abp.Threading; + +namespace KonSoft.Payment; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpTestBaseModule), + typeof(AbpAuthorizationModule), + typeof(AbpBackgroundJobsAbstractionsModule) + )] +public class PaymentTestBaseModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.IsJobExecutionEnabled = false; + }); + + context.Services.AddAlwaysAllowAuthorization(); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + AsyncHelper.RunSync(async () => + { + using (var scope = context.ServiceProvider.CreateScope()) + { + await scope.ServiceProvider + .GetRequiredService() + .SeedAsync(); + } + }); + } +} diff --git a/modules/payment/test/KonSoft.Payment.TestBase/PaymentTestConsts.cs b/modules/payment/test/KonSoft.Payment.TestBase/PaymentTestConsts.cs new file mode 100644 index 0000000..64b3623 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.TestBase/PaymentTestConsts.cs @@ -0,0 +1,6 @@ +namespace KonSoft.Payment; + +public static class PaymentTestConsts +{ + public const string CollectionDefinitionName = "Payment collection"; +} diff --git a/modules/payment/test/KonSoft.Payment.TestBase/PaymentTestDataSeedContributor.cs b/modules/payment/test/KonSoft.Payment.TestBase/PaymentTestDataSeedContributor.cs new file mode 100644 index 0000000..eb4eaff --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.TestBase/PaymentTestDataSeedContributor.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Payment; + +public class PaymentTestDataSeedContributor : IDataSeedContributor, ITransientDependency +{ + public Task SeedAsync(DataSeedContext context) + { + /* Seed additional test data... */ + + return Task.CompletedTask; + } +} diff --git a/modules/payment/test/KonSoft.Payment.TestBase/Security/FakeCurrentPrincipalAccessor.cs b/modules/payment/test/KonSoft.Payment.TestBase/Security/FakeCurrentPrincipalAccessor.cs new file mode 100644 index 0000000..10983b2 --- /dev/null +++ b/modules/payment/test/KonSoft.Payment.TestBase/Security/FakeCurrentPrincipalAccessor.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Security.Claims; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Claims; + +namespace KonSoft.Payment.Security; + +[Dependency(ReplaceServices = true)] +public class FakeCurrentPrincipalAccessor : ThreadCurrentPrincipalAccessor +{ + protected override ClaimsPrincipal GetClaimsPrincipal() + { + return GetPrincipal(); + } + + private ClaimsPrincipal GetPrincipal() + { + return new ClaimsPrincipal(new ClaimsIdentity(new List + { + new Claim(AbpClaimTypes.UserId, "2e701e62-0953-4dd3-910b-dc6cc93ccb0d"), + new Claim(AbpClaimTypes.UserName, "admin"), + new Claim(AbpClaimTypes.Email, "admin@abp.io") + })); + } +} diff --git a/modules/report/src/KonSoft.Report.Application.Contracts/KonSoft.Report.Application.Contracts.csproj b/modules/report/src/KonSoft.Report.Application.Contracts/KonSoft.Report.Application.Contracts.csproj new file mode 100644 index 0000000..cc23daa --- /dev/null +++ b/modules/report/src/KonSoft.Report.Application.Contracts/KonSoft.Report.Application.Contracts.csproj @@ -0,0 +1,25 @@ + + + + + + net8.0 + enable + KonSoft.Report + + + + + + + + + + + + + + + + + diff --git a/modules/report/src/KonSoft.Report.Application.Contracts/Permissions/ReportPermissionDefinitionProvider.cs b/modules/report/src/KonSoft.Report.Application.Contracts/Permissions/ReportPermissionDefinitionProvider.cs new file mode 100644 index 0000000..b99e6bd --- /dev/null +++ b/modules/report/src/KonSoft.Report.Application.Contracts/Permissions/ReportPermissionDefinitionProvider.cs @@ -0,0 +1,20 @@ +using KonSoft.Report.Localization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; + +namespace KonSoft.Report.Permissions; + +public class ReportPermissionDefinitionProvider : PermissionDefinitionProvider +{ + public override void Define(IPermissionDefinitionContext context) + { + var myGroup = context.AddGroup(ReportPermissions.GroupName); + //Define your own permissions here. Example: + //myGroup.AddPermission(ReportPermissions.MyPermission1, L("Permission:MyPermission1")); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/modules/report/src/KonSoft.Report.Application.Contracts/Permissions/ReportPermissions.cs b/modules/report/src/KonSoft.Report.Application.Contracts/Permissions/ReportPermissions.cs new file mode 100644 index 0000000..4b65916 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Application.Contracts/Permissions/ReportPermissions.cs @@ -0,0 +1,9 @@ +namespace KonSoft.Report.Permissions; + +public static class ReportPermissions +{ + public const string GroupName = "Report"; + + //Add your own permission names. Example: + //public const string MyPermission1 = GroupName + ".MyPermission1"; +} diff --git a/modules/report/src/KonSoft.Report.Application.Contracts/ReportApplicationContractsModule.cs b/modules/report/src/KonSoft.Report.Application.Contracts/ReportApplicationContractsModule.cs new file mode 100644 index 0000000..e8b9e7d --- /dev/null +++ b/modules/report/src/KonSoft.Report.Application.Contracts/ReportApplicationContractsModule.cs @@ -0,0 +1,28 @@ +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Report; + +[DependsOn( + typeof(ReportDomainSharedModule), + typeof(AbpAccountApplicationContractsModule), + typeof(AbpFeatureManagementApplicationContractsModule), + typeof(AbpIdentityApplicationContractsModule), + typeof(AbpPermissionManagementApplicationContractsModule), + typeof(AbpSettingManagementApplicationContractsModule), + typeof(AbpTenantManagementApplicationContractsModule), + typeof(AbpObjectExtendingModule) +)] +public class ReportApplicationContractsModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + ReportDtoExtensions.Configure(); + } +} diff --git a/modules/report/src/KonSoft.Report.Application.Contracts/ReportDtoExtensions.cs b/modules/report/src/KonSoft.Report.Application.Contracts/ReportDtoExtensions.cs new file mode 100644 index 0000000..4541f59 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Application.Contracts/ReportDtoExtensions.cs @@ -0,0 +1,28 @@ +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.Report; + +public static class ReportDtoExtensions +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can add extension properties to DTOs + * defined in the depended modules. + * + * Example: + * + * ObjectExtensionManager.Instance + * .AddOrUpdateProperty("Title"); + * + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Object-Extensions + */ + }); + } +} diff --git a/modules/report/src/KonSoft.Report.Application/KonSoft.Report.Application.csproj b/modules/report/src/KonSoft.Report.Application/KonSoft.Report.Application.csproj new file mode 100644 index 0000000..e39e71e --- /dev/null +++ b/modules/report/src/KonSoft.Report.Application/KonSoft.Report.Application.csproj @@ -0,0 +1,25 @@ + + + + + + net8.0 + enable + KonSoft.Report + + + + + + + + + + + + + + + + + diff --git a/modules/report/src/KonSoft.Report.Application/Properties/AssemblyInfo.cs b/modules/report/src/KonSoft.Report.Application/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..62f1528 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Application/Properties/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.Report.Application.Tests")] diff --git a/modules/report/src/KonSoft.Report.Application/ReportAppService.cs b/modules/report/src/KonSoft.Report.Application/ReportAppService.cs new file mode 100644 index 0000000..4d50cce --- /dev/null +++ b/modules/report/src/KonSoft.Report.Application/ReportAppService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using KonSoft.Report.Localization; +using Volo.Abp.Application.Services; + +namespace KonSoft.Report; + +/* Inherit your application services from this class. + */ +public abstract class ReportAppService : ApplicationService +{ + protected ReportAppService() + { + LocalizationResource = typeof(ReportResource); + } +} diff --git a/modules/report/src/KonSoft.Report.Application/ReportApplicationAutoMapperProfile.cs b/modules/report/src/KonSoft.Report.Application/ReportApplicationAutoMapperProfile.cs new file mode 100644 index 0000000..a7d2748 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Application/ReportApplicationAutoMapperProfile.cs @@ -0,0 +1,13 @@ +using AutoMapper; + +namespace KonSoft.Report; + +public class ReportApplicationAutoMapperProfile : Profile +{ + public ReportApplicationAutoMapperProfile() + { + /* You can configure your AutoMapper mapping configuration here. + * Alternatively, you can split your mapping configurations + * into multiple profile classes for a better organization. */ + } +} diff --git a/modules/report/src/KonSoft.Report.Application/ReportApplicationModule.cs b/modules/report/src/KonSoft.Report.Application/ReportApplicationModule.cs new file mode 100644 index 0000000..a010131 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Application/ReportApplicationModule.cs @@ -0,0 +1,31 @@ +using Volo.Abp.Account; +using Volo.Abp.AutoMapper; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Report; + +[DependsOn( + typeof(ReportDomainModule), + typeof(AbpAccountApplicationModule), + typeof(ReportApplicationContractsModule), + typeof(AbpIdentityApplicationModule), + typeof(AbpPermissionManagementApplicationModule), + typeof(AbpTenantManagementApplicationModule), + typeof(AbpFeatureManagementApplicationModule), + typeof(AbpSettingManagementApplicationModule) + )] +public class ReportApplicationModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.AddMaps(); + }); + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/KonSoft.Report.Domain.Shared.csproj b/modules/report/src/KonSoft.Report.Domain.Shared/KonSoft.Report.Domain.Shared.csproj new file mode 100644 index 0000000..80b1023 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/KonSoft.Report.Domain.Shared.csproj @@ -0,0 +1,32 @@ + + + + + + net8.0 + enable + KonSoft.Report + true + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/ar.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/ar.json new file mode 100644 index 0000000..c27a209 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/ar.json @@ -0,0 +1,9 @@ +{ + "culture": "ar", + "texts": { + "AppName": "Report", + "Menu:Home": "الصفحة الرئيسية", + "Welcome": "مرحباً", + "LongWelcomeMessage": "مرحبا بكم في التطبيق. هذا مشروع بدء تشغيل يعتمد على إطار عمل ABP. لمزيد من المعلومات ، يرجى زيارة abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/cs.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/cs.json new file mode 100644 index 0000000..e1914eb --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/cs.json @@ -0,0 +1,9 @@ +{ + "culture": "cs", + "texts": { + "AppName": "Report", + "Menu:Home": "Úvod", + "Welcome": "Vítejte", + "LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/de.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/de.json new file mode 100644 index 0000000..e0d1ee6 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/de.json @@ -0,0 +1,9 @@ +{ + "culture": "de", + "texts": { + "AppName": "Report", + "Menu:Home": "Home", + "Welcome": "Willkommen", + "LongWelcomeMessage": "Willkommen bei der Anwendung. Dies ist ein Startup-Projekt, das auf dem ABP-Framework basiert. Weitere Informationen finden Sie unter abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/en-GB.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/en-GB.json new file mode 100644 index 0000000..d808639 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/en-GB.json @@ -0,0 +1,9 @@ +{ + "culture": "en-GB", + "texts": { + "AppName": "Report", + "Menu:Home": "Home", + "Welcome": "Welcome", + "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/en.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/en.json new file mode 100644 index 0000000..6be22e3 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/en.json @@ -0,0 +1,9 @@ +{ + "culture": "en", + "texts": { + "AppName": "Report", + "Menu:Home": "Home", + "Welcome": "Welcome", + "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/es.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/es.json new file mode 100644 index 0000000..05f168d --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/es.json @@ -0,0 +1,9 @@ +{ + "culture": "es", + "texts": { + "AppName": "Report", + "Menu:Home": "Inicio", + "Welcome": "Bienvenido", + "LongWelcomeMessage": "Bienvenido a la aplicación, este es un proyecto base basado en el framework ABP. Para más información, visita abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/fi.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/fi.json new file mode 100644 index 0000000..dc45858 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/fi.json @@ -0,0 +1,9 @@ +{ + "culture": "fi", + "texts": { + "AppName": "Report", + "Menu:Home": "Koti", + "Welcome": "Tervetuloa", + "LongWelcomeMessage": "Tervetuloa sovellukseen. Tämä on ABP-kehykseen perustuva käynnistysprojekti. Lisätietoja on osoitteessa abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/fr.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/fr.json new file mode 100644 index 0000000..99e4e97 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/fr.json @@ -0,0 +1,9 @@ +{ + "culture": "fr", + "texts": { + "AppName": "Report", + "Menu:Home": "Accueil", + "Welcome": "Bienvenue", + "LongWelcomeMessage": "Bienvenue dans l'application. Il s'agit d'un projet de démarrage basé sur le framework ABP. Pour plus d'informations, visitez abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/hi.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/hi.json new file mode 100644 index 0000000..2659892 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/hi.json @@ -0,0 +1,9 @@ +{ + "culture": "hi", + "texts": { + "AppName": "Report", + "Menu:Home": "घर", + "Welcome": "स्वागत हे", + "LongWelcomeMessage": "आवेदन करने के लिए आपका स्वागत है। यह एबीपी ढांचे पर आधारित एक स्टार्टअप परियोजना है। अधिक जानकारी के लिए, abp.io पर जाएं।" + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/hr.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/hr.json new file mode 100644 index 0000000..c6af8b3 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/hr.json @@ -0,0 +1,9 @@ +{ + "culture": "hr", + "texts": { + "AppName": "Report", + "Menu:Home": "Početna", + "Welcome": "Dobrodošli", + "LongWelcomeMessage": "Dobrodošli u aplikaciju. Ovo je startup projekt temeljen na ABP framework-u. Za više informacija posjetite abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/hu.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/hu.json new file mode 100644 index 0000000..4a687e5 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/hu.json @@ -0,0 +1,9 @@ +{ + "culture": "hu", + "texts": { + "AppName": "Report", + "Menu:Home": "Kezdőlap", + "Welcome": "Üdvözlöm", + "LongWelcomeMessage": "Üdvözöljük az alkalmazásban. Ez egy ABP keretrendszeren alapuló startup projekt. További információkért látogasson el az abp.io oldalra." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/is.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/is.json new file mode 100644 index 0000000..3e89ddb --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/is.json @@ -0,0 +1,9 @@ +{ + "culture": "is", + "texts": { + "AppName": "Report", + "Menu:Home": "Heim", + "Welcome": "Velkomin", + "LongWelcomeMessage": "Verið velkomin í forritið. Þetta er startup verkefni sem byggir á ABP. Nánari upplýsingar er að finna á abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/it.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/it.json new file mode 100644 index 0000000..4666506 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/it.json @@ -0,0 +1,9 @@ +{ + "culture": "it", + "texts": { + "AppName": "Report", + "Menu:Home": "Home", + "Welcome": "Benvenuto", + "LongWelcomeMessage": "Benvenuto nell'applicazione. Questo è un progetto di avvio basato sul framework ABP. Per ulteriori informazioni, visita abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/nl.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/nl.json new file mode 100644 index 0000000..779c1d5 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/nl.json @@ -0,0 +1,9 @@ +{ + "culture": "nl", + "texts": { + "AppName": "Report", + "Menu:Home": "Home", + "Welcome": "Welkom", + "LongWelcomeMessage": "Welkom bij de applicatie. Dit is een startup-project gebaseerd op het ABP-framework. Bezoek abp.io voor meer informatie." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/pl-PL.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/pl-PL.json new file mode 100644 index 0000000..2f134f0 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/pl-PL.json @@ -0,0 +1,9 @@ +{ + "culture": "pl-PL", + "texts": { + "AppName": "Report", + "Menu:Home": "Home", + "Welcome": "Witaj", + "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/pt-BR.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/pt-BR.json new file mode 100644 index 0000000..804c2da --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/pt-BR.json @@ -0,0 +1,9 @@ +{ + "culture": "pt-BR", + "texts": { + "AppName": "Report", + "Menu:Home": "Principal", + "Welcome": "Seja bem-vindo!", + "LongWelcomeMessage": "Bem-vindo a esta aplicação. Este é um projeto inicial baseado no ABP framework. Para mais informações, visite abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/ro-RO.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/ro-RO.json new file mode 100644 index 0000000..7b9e67d --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/ro-RO.json @@ -0,0 +1,9 @@ +{ + "culture": "ro-RO", + "texts": { + "AppName": "Report", + "Menu:Home": "Acasă", + "Welcome": "Bun venit", + "LongWelcomeMessage": "Bun venit la aplicaţie. Acesta este un proiect de pornire bazat pe framework-ul ABP. Pentru mai multe informaţii, vizitaţi, visit abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/ru.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/ru.json new file mode 100644 index 0000000..854bc96 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/ru.json @@ -0,0 +1,9 @@ +{ + "culture": "ru", + "texts": { + "AppName": "Report", + "Menu:Home": "Главная", + "Welcome": "Добро пожаловать", + "LongWelcomeMessage": "Добро пожаловать в приложение. Этот запущенный проект основан на фреймворке ABP. Для получения дополнительной информации посетите сайт abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/sk.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/sk.json new file mode 100644 index 0000000..e520fe2 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/sk.json @@ -0,0 +1,9 @@ +{ + "culture": "sk", + "texts": { + "AppName": "Report", + "Menu:Home": "Domov", + "Welcome": "Vitajte", + "LongWelcomeMessage": "Vitajte v aplikácii. Toto je štartovací projekt založený na ABP frameworku. Viac informácií nájdete na stránke abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/sl.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/sl.json new file mode 100644 index 0000000..08dbb08 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/sl.json @@ -0,0 +1,9 @@ +{ + "culture": "sl", + "texts": { + "AppName": "Report", + "Menu:Home": "Domov", + "Welcome": "Dobrodošli", + "LongWelcomeMessage": "Dobrodošli v aplikaciji. To je začetni projekt na osnovi okolja ABP. Za več informacij obiščite abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/sv.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/sv.json new file mode 100644 index 0000000..bd1eae4 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/sv.json @@ -0,0 +1,9 @@ +{ + "culture": "sv", + "texts": { + "AppName": "MittProjektNamn", + "Menu:Home": "Hem", + "Welcome": "Välkommen", + "LongWelcomeMessage": "Välkommen till applikationen. Detta är ett startup-projekt baserat på ABP-ramverket. För mer information, besök abp.io." + } +} \ No newline at end of file diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/tr.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/tr.json new file mode 100644 index 0000000..fb949e4 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/tr.json @@ -0,0 +1,9 @@ +{ + "culture": "tr", + "texts": { + "AppName": "Report", + "Menu:Home": "Ana sayfa", + "Welcome": "Hoşgeldiniz", + "LongWelcomeMessage": "Uygulamaya hoşgeldiniz. Bu, ABP framework'ü üzerine bina edilmiş bir başlangıç projesidir. Daha fazla bilgi için abp.io adresini ziyaret edebilirsiniz." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/vi.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/vi.json new file mode 100644 index 0000000..cbf9a01 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/vi.json @@ -0,0 +1,9 @@ +{ + "culture": "vi", + "texts": { + "AppName": "Report", + "Menu:Home": "Trang chủ", + "Welcome": "Chào mừng bạn", + "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án khởi nghiệp dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io." + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/zh-Hans.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/zh-Hans.json new file mode 100644 index 0000000..9ebba61 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/zh-Hans.json @@ -0,0 +1,9 @@ +{ + "culture": "zh-Hans", + "texts": { + "AppName": "Report", + "Menu:Home": "首页", + "Welcome": "欢迎", + "LongWelcomeMessage": "欢迎使用本应用程序。这是一个基于 ABP 框架的启动项目。更多信息,请访问 abp.io。" + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/zh-Hant.json b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/zh-Hant.json new file mode 100644 index 0000000..a292114 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/Report/zh-Hant.json @@ -0,0 +1,9 @@ +{ + "culture": "zh-Hant", + "texts": { + "AppName": "Report", + "Menu:Home": "首頁", + "Welcome": "歡迎", + "LongWelcomeMessage": "歡迎來到此應用程式. 這是一個基於ABP框架的起始專案. 有關更多訊息, 請瀏覽 abp.io." + } + } diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/Localization/ReportResource.cs b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/ReportResource.cs new file mode 100644 index 0000000..bdab1be --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/Localization/ReportResource.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Localization; + +namespace KonSoft.Report.Localization; + +[LocalizationResourceName("Report")] +public class ReportResource +{ + +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs b/modules/report/src/KonSoft.Report.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs new file mode 100644 index 0000000..40a27a4 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs @@ -0,0 +1,10 @@ +namespace KonSoft.Report.MultiTenancy; + +public static class MultiTenancyConsts +{ + /* Enable/disable multi-tenancy easily in a single point. + * If you will never need to multi-tenancy, you can remove + * related modules and code parts, including this file. + */ + public const bool IsEnabled = true; +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/ReportDomainErrorCodes.cs b/modules/report/src/KonSoft.Report.Domain.Shared/ReportDomainErrorCodes.cs new file mode 100644 index 0000000..3f91211 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/ReportDomainErrorCodes.cs @@ -0,0 +1,6 @@ +namespace KonSoft.Report; + +public static class ReportDomainErrorCodes +{ + /* You can add your business exception error codes here, as constants */ +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/ReportDomainSharedModule.cs b/modules/report/src/KonSoft.Report.Domain.Shared/ReportDomainSharedModule.cs new file mode 100644 index 0000000..e49c6eb --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/ReportDomainSharedModule.cs @@ -0,0 +1,58 @@ +using KonSoft.Report.Localization; +using Volo.Abp.AuditLogging; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Localization.ExceptionHandling; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; +using Volo.Abp.Validation.Localization; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.Report; + +[DependsOn( + typeof(AbpAuditLoggingDomainSharedModule), + typeof(AbpBackgroundJobsDomainSharedModule), + typeof(AbpFeatureManagementDomainSharedModule), + typeof(AbpIdentityDomainSharedModule), + typeof(AbpOpenIddictDomainSharedModule), + typeof(AbpPermissionManagementDomainSharedModule), + typeof(AbpSettingManagementDomainSharedModule), + typeof(AbpTenantManagementDomainSharedModule) + )] +public class ReportDomainSharedModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + ReportGlobalFeatureConfigurator.Configure(); + ReportModuleExtensionConfigurator.Configure(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddBaseTypes(typeof(AbpValidationResource)) + .AddVirtualJson("/Localization/Report"); + + options.DefaultResourceType = typeof(ReportResource); + }); + + Configure(options => + { + options.MapCodeNamespace("Report", typeof(ReportResource)); + }); + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/ReportGlobalFeatureConfigurator.cs b/modules/report/src/KonSoft.Report.Domain.Shared/ReportGlobalFeatureConfigurator.cs new file mode 100644 index 0000000..5ce692d --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/ReportGlobalFeatureConfigurator.cs @@ -0,0 +1,22 @@ +using Volo.Abp.Threading; + +namespace KonSoft.Report; + +public static class ReportGlobalFeatureConfigurator +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can configure (enable/disable) global features of the used modules here. + * + * YOU CAN SAFELY DELETE THIS CLASS AND REMOVE ITS USAGES IF YOU DON'T NEED TO IT! + * + * Please refer to the documentation to lear more about the Global Features System: + * https://docs.abp.io/en/abp/latest/Global-Features + */ + }); + } +} diff --git a/modules/report/src/KonSoft.Report.Domain.Shared/ReportModuleExtensionConfigurator.cs b/modules/report/src/KonSoft.Report.Domain.Shared/ReportModuleExtensionConfigurator.cs new file mode 100644 index 0000000..3a1ae57 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain.Shared/ReportModuleExtensionConfigurator.cs @@ -0,0 +1,73 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.Report; + +public static class ReportModuleExtensionConfigurator +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + ConfigureExistingProperties(); + ConfigureExtraProperties(); + }); + } + + private static void ConfigureExistingProperties() + { + /* You can change max lengths for properties of the + * entities defined in the modules used by your application. + * + * Example: Change user and role name max lengths + + AbpUserConsts.MaxNameLength = 99; + IdentityRoleConsts.MaxNameLength = 99; + + * Notice: It is not suggested to change property lengths + * unless you really need it. Go with the standard values wherever possible. + * + * If you are using EF Core, you will need to run the add-migration command after your changes. + */ + } + + private static void ConfigureExtraProperties() + { + /* You can configure extra properties for the + * entities defined in the modules used by your application. + * + * This class can be used to define these extra properties + * with a high level, easy to use API. + * + * Example: Add a new property to the user entity of the identity module + + ObjectExtensionManager.Instance.Modules() + .ConfigureIdentity(identity => + { + identity.ConfigureUser(user => + { + user.AddOrUpdateProperty( //property type: string + "SocialSecurityNumber", //property name + property => + { + //validation rules + property.Attributes.Add(new RequiredAttribute()); + property.Attributes.Add(new StringLengthAttribute(64) {MinimumLength = 4}); + + property.Configuration[IdentityModuleExtensionConsts.ConfigurationNames.AllowUserToEdit] = true; + + //...other configurations for this property + } + ); + }); + }); + + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Module-Entity-Extensions + */ + } +} diff --git a/modules/report/src/KonSoft.Report.Domain/Data/IReportDbSchemaMigrator.cs b/modules/report/src/KonSoft.Report.Domain/Data/IReportDbSchemaMigrator.cs new file mode 100644 index 0000000..eda5adb --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain/Data/IReportDbSchemaMigrator.cs @@ -0,0 +1,8 @@ +using System.Threading.Tasks; + +namespace KonSoft.Report.Data; + +public interface IReportDbSchemaMigrator +{ + Task MigrateAsync(); +} diff --git a/modules/report/src/KonSoft.Report.Domain/Data/NullReportDbSchemaMigrator.cs b/modules/report/src/KonSoft.Report.Domain/Data/NullReportDbSchemaMigrator.cs new file mode 100644 index 0000000..4133e60 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain/Data/NullReportDbSchemaMigrator.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Report.Data; + +/* This is used if database provider does't define + * IReportDbSchemaMigrator implementation. + */ +public class NullReportDbSchemaMigrator : IReportDbSchemaMigrator, ITransientDependency +{ + public Task MigrateAsync() + { + return Task.CompletedTask; + } +} diff --git a/modules/report/src/KonSoft.Report.Domain/Data/ReportDbMigrationService.cs b/modules/report/src/KonSoft.Report.Domain/Data/ReportDbMigrationService.cs new file mode 100644 index 0000000..f53ae54 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain/Data/ReportDbMigrationService.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Report.Data; + +public class ReportDbMigrationService : ITransientDependency +{ + public ILogger Logger { get; set; } + + private readonly IDataSeeder _dataSeeder; + private readonly IEnumerable _dbSchemaMigrators; + private readonly ITenantRepository _tenantRepository; + private readonly ICurrentTenant _currentTenant; + + public ReportDbMigrationService( + IDataSeeder dataSeeder, + IEnumerable dbSchemaMigrators, + ITenantRepository tenantRepository, + ICurrentTenant currentTenant) + { + _dataSeeder = dataSeeder; + _dbSchemaMigrators = dbSchemaMigrators; + _tenantRepository = tenantRepository; + _currentTenant = currentTenant; + + Logger = NullLogger.Instance; + } + + public async Task MigrateAsync() + { + var initialMigrationAdded = AddInitialMigrationIfNotExist(); + + if (initialMigrationAdded) + { + return; + } + + Logger.LogInformation("Started database migrations..."); + + await MigrateDatabaseSchemaAsync(); + await SeedDataAsync(); + + Logger.LogInformation($"Successfully completed host database migrations."); + + var tenants = await _tenantRepository.GetListAsync(includeDetails: true); + + var migratedDatabaseSchemas = new HashSet(); + foreach (var tenant in tenants) + { + using (_currentTenant.Change(tenant.Id)) + { + if (tenant.ConnectionStrings.Any()) + { + var tenantConnectionStrings = tenant.ConnectionStrings + .Select(x => x.Value) + .ToList(); + + if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings)) + { + await MigrateDatabaseSchemaAsync(tenant); + + migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings); + } + } + + await SeedDataAsync(tenant); + } + + Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations."); + } + + Logger.LogInformation("Successfully completed all database migrations."); + Logger.LogInformation("You can safely end this process..."); + } + + private async Task MigrateDatabaseSchemaAsync(Tenant? tenant = null) + { + Logger.LogInformation( + $"Migrating schema for {(tenant == null ? "host" : tenant.Name + " tenant")} database..."); + + foreach (var migrator in _dbSchemaMigrators) + { + await migrator.MigrateAsync(); + } + } + + private async Task SeedDataAsync(Tenant? tenant = null) + { + Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed..."); + + await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id) + .WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, IdentityDataSeedContributor.AdminEmailDefaultValue) + .WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, IdentityDataSeedContributor.AdminPasswordDefaultValue) + ); + } + + private bool AddInitialMigrationIfNotExist() + { + try + { + if (!DbMigrationsProjectExists()) + { + return false; + } + } + catch (Exception) + { + return false; + } + + try + { + if (!MigrationsFolderExists()) + { + AddInitialMigration(); + return true; + } + else + { + return false; + } + } + catch (Exception e) + { + Logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message); + return false; + } + } + + private bool DbMigrationsProjectExists() + { + var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath(); + + return dbMigrationsProjectFolder != null; + } + + private bool MigrationsFolderExists() + { + var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath(); + return dbMigrationsProjectFolder != null && Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations")); + } + + private void AddInitialMigration() + { + Logger.LogInformation("Creating initial migration..."); + + string argumentPrefix; + string fileName; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + argumentPrefix = "-c"; + fileName = "/bin/bash"; + } + else + { + argumentPrefix = "/C"; + fileName = "cmd.exe"; + } + + var procStartInfo = new ProcessStartInfo(fileName, + $"{argumentPrefix} \"abp create-migration-and-run-migrator \"{GetEntityFrameworkCoreProjectFolderPath()}\"\"" + ); + + try + { + Process.Start(procStartInfo); + } + catch (Exception) + { + throw new Exception("Couldn't run ABP CLI..."); + } + } + + private string? GetEntityFrameworkCoreProjectFolderPath() + { + var slnDirectoryPath = GetSolutionDirectoryPath(); + + if (slnDirectoryPath == null) + { + throw new Exception("Solution folder not found!"); + } + + var srcDirectoryPath = Path.Combine(slnDirectoryPath, "src"); + + return Directory.GetDirectories(srcDirectoryPath) + .FirstOrDefault(d => d.EndsWith(".EntityFrameworkCore")); + } + + private string? GetSolutionDirectoryPath() + { + var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory()); + + while (currentDirectory != null && Directory.GetParent(currentDirectory.FullName) != null) + { + currentDirectory = Directory.GetParent(currentDirectory.FullName); + + if (currentDirectory != null && Directory.GetFiles(currentDirectory.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null) + { + return currentDirectory.FullName; + } + } + + return null; + } +} diff --git a/modules/report/src/KonSoft.Report.Domain/KonSoft.Report.Domain.csproj b/modules/report/src/KonSoft.Report.Domain/KonSoft.Report.Domain.csproj new file mode 100644 index 0000000..3ca0779 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain/KonSoft.Report.Domain.csproj @@ -0,0 +1,28 @@ + + + + + + net8.0 + enable + KonSoft.Report + + + + + + + + + + + + + + + + + + + + diff --git a/modules/report/src/KonSoft.Report.Domain/OpenIddict/OpenIddictDataSeedContributor.cs b/modules/report/src/KonSoft.Report.Domain/OpenIddict/OpenIddictDataSeedContributor.cs new file mode 100644 index 0000000..e2b734f --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain/OpenIddict/OpenIddictDataSeedContributor.cs @@ -0,0 +1,327 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Localization; +using OpenIddict.Abstractions; +using Volo.Abp; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.OpenIddict.Applications; +using Volo.Abp.OpenIddict.Scopes; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Uow; + +namespace KonSoft.Report.OpenIddict; + +/* Creates initial data that is needed to property run the application + * and make client-to-server communication possible. + */ +public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDependency +{ + private readonly IConfiguration _configuration; + private readonly IOpenIddictApplicationRepository _openIddictApplicationRepository; + private readonly IAbpApplicationManager _applicationManager; + private readonly IOpenIddictScopeRepository _openIddictScopeRepository; + private readonly IOpenIddictScopeManager _scopeManager; + private readonly IPermissionDataSeeder _permissionDataSeeder; + private readonly IStringLocalizer L; + + public OpenIddictDataSeedContributor( + IConfiguration configuration, + IOpenIddictApplicationRepository openIddictApplicationRepository, + IAbpApplicationManager applicationManager, + IOpenIddictScopeRepository openIddictScopeRepository, + IOpenIddictScopeManager scopeManager, + IPermissionDataSeeder permissionDataSeeder, + IStringLocalizer l ) + { + _configuration = configuration; + _openIddictApplicationRepository = openIddictApplicationRepository; + _applicationManager = applicationManager; + _openIddictScopeRepository = openIddictScopeRepository; + _scopeManager = scopeManager; + _permissionDataSeeder = permissionDataSeeder; + L = l; + } + + [UnitOfWork] + public virtual async Task SeedAsync(DataSeedContext context) + { + await CreateScopesAsync(); + await CreateApplicationsAsync(); + } + + private async Task CreateScopesAsync() + { + if (await _openIddictScopeRepository.FindByNameAsync("Report") == null) + { + await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor { + Name = "Report", DisplayName = "Report API", Resources = { "Report" } + }); + } + } + + private async Task CreateApplicationsAsync() + { + var commonScopes = new List { + OpenIddictConstants.Permissions.Scopes.Address, + OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Phone, + OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Roles, + "Report" + }; + + var configurationSection = _configuration.GetSection("OpenIddict:Applications"); + + + + + + + // Swagger Client + var swaggerClientId = configurationSection["Report_Swagger:ClientId"]; + if (!swaggerClientId.IsNullOrWhiteSpace()) + { + var swaggerRootUrl = configurationSection["Report_Swagger:RootUrl"]?.TrimEnd('/'); + + await CreateApplicationAsync( + name: swaggerClientId!, + type: OpenIddictConstants.ClientTypes.Public, + consentType: OpenIddictConstants.ConsentTypes.Implicit, + displayName: "Swagger Application", + secret: null, + grantTypes: new List { OpenIddictConstants.GrantTypes.AuthorizationCode, }, + scopes: commonScopes, + redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html", + clientUri: swaggerRootUrl + ); + } + } + + private async Task CreateApplicationAsync( + [NotNull] string name, + [NotNull] string type, + [NotNull] string consentType, + string displayName, + string? secret, + List grantTypes, + List scopes, + string? clientUri = null, + string? redirectUri = null, + string? postLogoutRedirectUri = null, + List? permissions = null) + { + if (!string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Public, + StringComparison.OrdinalIgnoreCase)) + { + throw new BusinessException(L["NoClientSecretCanBeSetForPublicApplications"]); + } + + if (string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, + StringComparison.OrdinalIgnoreCase)) + { + throw new BusinessException(L["TheClientSecretIsRequiredForConfidentialApplications"]); + } + + var client = await _openIddictApplicationRepository.FindByClientIdAsync(name); + + var application = new AbpApplicationDescriptor { + ClientId = name, + ClientType = type, + ClientSecret = secret, + ConsentType = consentType, + DisplayName = displayName, + ClientUri = clientUri, + }; + + Check.NotNullOrEmpty(grantTypes, nameof(grantTypes)); + Check.NotNullOrEmpty(scopes, nameof(scopes)); + + if (new[] { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }.All( + grantTypes.Contains)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken); + + if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeToken); + } + } + + if (!redirectUri.IsNullOrWhiteSpace() || !postLogoutRedirectUri.IsNullOrWhiteSpace()) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout); + } + + var buildInGrantTypes = new[] { + OpenIddictConstants.GrantTypes.Implicit, OpenIddictConstants.GrantTypes.Password, + OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.ClientCredentials, + OpenIddictConstants.GrantTypes.DeviceCode, OpenIddictConstants.GrantTypes.RefreshToken + }; + + foreach (var grantType in grantTypes) + { + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code); + } + + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || + grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization); + } + + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || + grantType == OpenIddictConstants.GrantTypes.ClientCredentials || + grantType == OpenIddictConstants.GrantTypes.Password || + grantType == OpenIddictConstants.GrantTypes.RefreshToken || + grantType == OpenIddictConstants.GrantTypes.DeviceCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Revocation); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Introspection); + } + + if (grantType == OpenIddictConstants.GrantTypes.ClientCredentials) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials); + } + + if (grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit); + } + + if (grantType == OpenIddictConstants.GrantTypes.Password) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password); + } + + if (grantType == OpenIddictConstants.GrantTypes.RefreshToken) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken); + } + + if (grantType == OpenIddictConstants.GrantTypes.DeviceCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.DeviceCode); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Device); + } + + if (grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdToken); + if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Token); + } + } + + if (!buildInGrantTypes.Contains(grantType)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.GrantType + grantType); + } + } + + var buildInScopes = new[] { + OpenIddictConstants.Permissions.Scopes.Address, OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Phone, OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Roles + }; + + foreach (var scope in scopes) + { + if (buildInScopes.Contains(scope)) + { + application.Permissions.Add(scope); + } + else + { + application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.Scope + scope); + } + } + + if (redirectUri != null) + { + if (!redirectUri.IsNullOrEmpty()) + { + if (!Uri.TryCreate(redirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) + { + throw new BusinessException(L["InvalidRedirectUri", redirectUri]); + } + + if (application.RedirectUris.All(x => x != uri)) + { + application.RedirectUris.Add(uri); + } + } + } + + if (postLogoutRedirectUri != null) + { + if (!postLogoutRedirectUri.IsNullOrEmpty()) + { + if (!Uri.TryCreate(postLogoutRedirectUri, UriKind.Absolute, out var uri) || + !uri.IsWellFormedOriginalString()) + { + throw new BusinessException(L["InvalidPostLogoutRedirectUri", postLogoutRedirectUri]); + } + + if (application.PostLogoutRedirectUris.All(x => x != uri)) + { + application.PostLogoutRedirectUris.Add(uri); + } + } + } + + if (permissions != null) + { + await _permissionDataSeeder.SeedAsync( + ClientPermissionValueProvider.ProviderName, + name, + permissions, + null + ); + } + + if (client == null) + { + await _applicationManager.CreateAsync(application); + return; + } + + if (!HasSameRedirectUris(client, application)) + { + client.RedirectUris = JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); + client.PostLogoutRedirectUris = JsonSerializer.Serialize(application.PostLogoutRedirectUris.Select(q => q.ToString().TrimEnd('/'))); + + await _applicationManager.UpdateAsync(client.ToModel()); + } + + if (!HasSameScopes(client, application)) + { + client.Permissions = JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString())); + await _applicationManager.UpdateAsync(client.ToModel()); + } + } + + private bool HasSameRedirectUris(OpenIddictApplication existingClient, AbpApplicationDescriptor application) + { + return existingClient.RedirectUris == JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); + } + + private bool HasSameScopes(OpenIddictApplication existingClient, AbpApplicationDescriptor application) + { + return existingClient.Permissions == JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString().TrimEnd('/'))); + } +} diff --git a/modules/report/src/KonSoft.Report.Domain/Properties/AssemblyInfo.cs b/modules/report/src/KonSoft.Report.Domain/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d9b7131 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.Report.Domain.Tests")] +[assembly:InternalsVisibleToAttribute("KonSoft.Report.TestBase")] diff --git a/modules/report/src/KonSoft.Report.Domain/ReportConsts.cs b/modules/report/src/KonSoft.Report.Domain/ReportConsts.cs new file mode 100644 index 0000000..705ae6a --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain/ReportConsts.cs @@ -0,0 +1,8 @@ +namespace KonSoft.Report; + +public static class ReportConsts +{ + public const string DbTablePrefix = "App"; + + public const string DbSchema = null; +} diff --git a/modules/report/src/KonSoft.Report.Domain/ReportDomainModule.cs b/modules/report/src/KonSoft.Report.Domain/ReportDomainModule.cs new file mode 100644 index 0000000..ad4c0de --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain/ReportDomainModule.cs @@ -0,0 +1,68 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using KonSoft.Report.MultiTenancy; +using Volo.Abp.AuditLogging; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Emailing; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.OpenIddict; +using Volo.Abp.PermissionManagement.Identity; +using Volo.Abp.PermissionManagement.OpenIddict; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Report; + +[DependsOn( + typeof(ReportDomainSharedModule), + typeof(AbpAuditLoggingDomainModule), + typeof(AbpBackgroundJobsDomainModule), + typeof(AbpFeatureManagementDomainModule), + typeof(AbpIdentityDomainModule), + typeof(AbpOpenIddictDomainModule), + typeof(AbpPermissionManagementDomainOpenIddictModule), + typeof(AbpPermissionManagementDomainIdentityModule), + typeof(AbpSettingManagementDomainModule), + typeof(AbpTenantManagementDomainModule), + typeof(AbpEmailingModule) +)] +public class ReportDomainModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)")); + options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar")); + options.Languages.Add(new LanguageInfo("hr", "hr", "Croatian")); + options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish")); + options.Languages.Add(new LanguageInfo("fr", "fr", "Français")); + options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi")); + options.Languages.Add(new LanguageInfo("it", "it", "Italiano")); + options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); + options.Languages.Add(new LanguageInfo("ru", "ru", "Русский")); + options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak")); + options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); + options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch")); + options.Languages.Add(new LanguageInfo("es", "es", "Español")); + }); + + Configure(options => + { + options.IsEnabled = MultiTenancyConsts.IsEnabled; + }); + +#if DEBUG + context.Services.Replace(ServiceDescriptor.Singleton()); +#endif + } +} diff --git a/modules/report/src/KonSoft.Report.Domain/Settings/ReportSettingDefinitionProvider.cs b/modules/report/src/KonSoft.Report.Domain/Settings/ReportSettingDefinitionProvider.cs new file mode 100644 index 0000000..844e270 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain/Settings/ReportSettingDefinitionProvider.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Settings; + +namespace KonSoft.Report.Settings; + +public class ReportSettingDefinitionProvider : SettingDefinitionProvider +{ + public override void Define(ISettingDefinitionContext context) + { + //Define your own settings here. Example: + //context.Add(new SettingDefinition(ReportSettings.MySetting1)); + } +} diff --git a/modules/report/src/KonSoft.Report.Domain/Settings/ReportSettings.cs b/modules/report/src/KonSoft.Report.Domain/Settings/ReportSettings.cs new file mode 100644 index 0000000..48d4c45 --- /dev/null +++ b/modules/report/src/KonSoft.Report.Domain/Settings/ReportSettings.cs @@ -0,0 +1,9 @@ +namespace KonSoft.Report.Settings; + +public static class ReportSettings +{ + private const string Prefix = "Report"; + + //Add your own setting names here. Example: + //public const string MySetting1 = Prefix + ".MySetting1"; +} diff --git a/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreReportDbSchemaMigrator.cs b/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreReportDbSchemaMigrator.cs new file mode 100644 index 0000000..40bff4e --- /dev/null +++ b/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreReportDbSchemaMigrator.cs @@ -0,0 +1,34 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using KonSoft.Report.Data; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Report.EntityFrameworkCore; + +public class EntityFrameworkCoreReportDbSchemaMigrator + : IReportDbSchemaMigrator, ITransientDependency +{ + private readonly IServiceProvider _serviceProvider; + + public EntityFrameworkCoreReportDbSchemaMigrator( + IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public async Task MigrateAsync() + { + /* We intentionally resolve the ReportDbContext + * from IServiceProvider (instead of directly injecting it) + * to properly get the connection string of the current tenant in the + * current scope. + */ + + await _serviceProvider + .GetRequiredService() + .Database + .MigrateAsync(); + } +} diff --git a/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportDbContext.cs b/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportDbContext.cs new file mode 100644 index 0000000..10edbfb --- /dev/null +++ b/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportDbContext.cs @@ -0,0 +1,86 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.AuditLogging.EntityFrameworkCore; +using Volo.Abp.BackgroundJobs.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Identity; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.OpenIddict.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.TenantManagement; +using Volo.Abp.TenantManagement.EntityFrameworkCore; + +namespace KonSoft.Report.EntityFrameworkCore; + +[ReplaceDbContext(typeof(IIdentityDbContext))] +[ReplaceDbContext(typeof(ITenantManagementDbContext))] +[ConnectionStringName("Default")] +public class ReportDbContext : + AbpDbContext, + IIdentityDbContext, + ITenantManagementDbContext +{ + /* Add DbSet properties for your Aggregate Roots / Entities here. */ + + #region Entities from the modules + + /* Notice: We only implemented IIdentityDbContext and ITenantManagementDbContext + * and replaced them for this DbContext. This allows you to perform JOIN + * queries for the entities of these modules over the repositories easily. You + * typically don't need that for other modules. But, if you need, you can + * implement the DbContext interface of the needed module and use ReplaceDbContext + * attribute just like IIdentityDbContext and ITenantManagementDbContext. + * + * More info: Replacing a DbContext of a module ensures that the related module + * uses this DbContext on runtime. Otherwise, it will use its own DbContext class. + */ + + //Identity + public DbSet Users { get; set; } + public DbSet Roles { get; set; } + public DbSet ClaimTypes { get; set; } + public DbSet OrganizationUnits { get; set; } + public DbSet SecurityLogs { get; set; } + public DbSet LinkUsers { get; set; } + public DbSet UserDelegations { get; set; } + public DbSet Sessions { get; set; } + // Tenant Management + public DbSet Tenants { get; set; } + public DbSet TenantConnectionStrings { get; set; } + + #endregion + + public ReportDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + /* Include modules to your migration db context */ + + builder.ConfigurePermissionManagement(); + builder.ConfigureSettingManagement(); + builder.ConfigureBackgroundJobs(); + builder.ConfigureAuditLogging(); + builder.ConfigureIdentity(); + builder.ConfigureOpenIddict(); + builder.ConfigureFeatureManagement(); + builder.ConfigureTenantManagement(); + + /* Configure your own tables/entities inside here */ + + //builder.Entity(b => + //{ + // b.ToTable(ReportConsts.DbTablePrefix + "YourEntities", ReportConsts.DbSchema); + // b.ConfigureByConvention(); //auto configure for the base class props + // //... + //}); + } +} diff --git a/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportDbContextFactory.cs b/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportDbContextFactory.cs new file mode 100644 index 0000000..d394ab6 --- /dev/null +++ b/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportDbContextFactory.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; + +namespace KonSoft.Report.EntityFrameworkCore; + +/* This class is needed for EF Core console commands + * (like Add-Migration and Update-Database commands) */ +public class ReportDbContextFactory : IDesignTimeDbContextFactory +{ + public ReportDbContext CreateDbContext(string[] args) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + + ReportEfCoreEntityExtensionMappings.Configure(); + + var configuration = BuildConfiguration(); + + var builder = new DbContextOptionsBuilder() + .UseNpgsql(configuration.GetConnectionString("Default")); + + return new ReportDbContext(builder.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../KonSoft.Report.DbMigrator/")) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportEfCoreEntityExtensionMappings.cs b/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportEfCoreEntityExtensionMappings.cs new file mode 100644 index 0000000..ca2ce19 --- /dev/null +++ b/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportEfCoreEntityExtensionMappings.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.Report.EntityFrameworkCore; + +public static class ReportEfCoreEntityExtensionMappings +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + ReportGlobalFeatureConfigurator.Configure(); + ReportModuleExtensionConfigurator.Configure(); + + OneTimeRunner.Run(() => + { + /* You can configure extra properties for the + * entities defined in the modules used by your application. + * + * This class can be used to map these extra properties to table fields in the database. + * + * USE THIS CLASS ONLY TO CONFIGURE EF CORE RELATED MAPPING. + * USE ReportModuleExtensionConfigurator CLASS (in the Domain.Shared project) + * FOR A HIGH LEVEL API TO DEFINE EXTRA PROPERTIES TO ENTITIES OF THE USED MODULES + * + * Example: Map a property to a table field: + + ObjectExtensionManager.Instance + .MapEfCoreProperty( + "MyProperty", + (entityBuilder, propertyBuilder) => + { + propertyBuilder.HasMaxLength(128); + } + ); + + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities + */ + }); + } +} diff --git a/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportEntityFrameworkCoreModule.cs b/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportEntityFrameworkCoreModule.cs new file mode 100644 index 0000000..cabe4ec --- /dev/null +++ b/modules/report/src/KonSoft.Report.EntityFrameworkCore/EntityFrameworkCore/ReportEntityFrameworkCoreModule.cs @@ -0,0 +1,57 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Uow; +using Volo.Abp.AuditLogging.EntityFrameworkCore; +using Volo.Abp.BackgroundJobs.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.TenantManagement.EntityFrameworkCore; + +namespace KonSoft.Report.EntityFrameworkCore; + +[DependsOn( + typeof(ReportDomainModule), + typeof(AbpIdentityEntityFrameworkCoreModule), + typeof(AbpOpenIddictEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpBackgroundJobsEntityFrameworkCoreModule), + typeof(AbpAuditLoggingEntityFrameworkCoreModule), + typeof(AbpTenantManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule) + )] +public class ReportEntityFrameworkCoreModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + + ReportEfCoreEntityExtensionMappings.Configure(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(options => + { + /* Remove "includeAllEntities: true" to create + * default repositories only for aggregate roots */ + options.AddDefaultRepositories(includeAllEntities: true); + }); + + Configure(options => + { + /* The main point to change your DBMS. + * See also ReportMigrationsDbContextFactory for EF Core tooling. */ + options.UseNpgsql(); + }); + + } +} diff --git a/modules/report/src/KonSoft.Report.EntityFrameworkCore/KonSoft.Report.EntityFrameworkCore.csproj b/modules/report/src/KonSoft.Report.EntityFrameworkCore/KonSoft.Report.EntityFrameworkCore.csproj new file mode 100644 index 0000000..d31cb9c --- /dev/null +++ b/modules/report/src/KonSoft.Report.EntityFrameworkCore/KonSoft.Report.EntityFrameworkCore.csproj @@ -0,0 +1,31 @@ + + + + + + net8.0 + enable + KonSoft.Report + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + diff --git a/modules/report/src/KonSoft.Report.EntityFrameworkCore/Properties/AssemblyInfo.cs b/modules/report/src/KonSoft.Report.EntityFrameworkCore/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b45c97b --- /dev/null +++ b/modules/report/src/KonSoft.Report.EntityFrameworkCore/Properties/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.Report.EntityFrameworkCore.Tests")] diff --git a/modules/report/src/KonSoft.Report.HttpApi.Client/KonSoft.Report.HttpApi.Client.csproj b/modules/report/src/KonSoft.Report.HttpApi.Client/KonSoft.Report.HttpApi.Client.csproj new file mode 100644 index 0000000..85a166a --- /dev/null +++ b/modules/report/src/KonSoft.Report.HttpApi.Client/KonSoft.Report.HttpApi.Client.csproj @@ -0,0 +1,29 @@ + + + + + + net8.0 + enable + KonSoft.Report + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/report/src/KonSoft.Report.HttpApi.Client/ReportHttpApiClientModule.cs b/modules/report/src/KonSoft.Report.HttpApi.Client/ReportHttpApiClientModule.cs new file mode 100644 index 0000000..0ec52d7 --- /dev/null +++ b/modules/report/src/KonSoft.Report.HttpApi.Client/ReportHttpApiClientModule.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.TenantManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.Report; + +[DependsOn( + typeof(ReportApplicationContractsModule), + typeof(AbpAccountHttpApiClientModule), + typeof(AbpIdentityHttpApiClientModule), + typeof(AbpPermissionManagementHttpApiClientModule), + typeof(AbpTenantManagementHttpApiClientModule), + typeof(AbpFeatureManagementHttpApiClientModule), + typeof(AbpSettingManagementHttpApiClientModule) +)] +public class ReportHttpApiClientModule : AbpModule +{ + public const string RemoteServiceName = "Default"; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddHttpClientProxies( + typeof(ReportApplicationContractsModule).Assembly, + RemoteServiceName + ); + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + } +} diff --git a/modules/report/src/KonSoft.Report.HttpApi/Controllers/ReportController.cs b/modules/report/src/KonSoft.Report.HttpApi/Controllers/ReportController.cs new file mode 100644 index 0000000..e2843e2 --- /dev/null +++ b/modules/report/src/KonSoft.Report.HttpApi/Controllers/ReportController.cs @@ -0,0 +1,14 @@ +using KonSoft.Report.Localization; +using Volo.Abp.AspNetCore.Mvc; + +namespace KonSoft.Report.Controllers; + +/* Inherit your controllers from this class. + */ +public abstract class ReportController : AbpControllerBase +{ + protected ReportController() + { + LocalizationResource = typeof(ReportResource); + } +} diff --git a/modules/report/src/KonSoft.Report.HttpApi/KonSoft.Report.HttpApi.csproj b/modules/report/src/KonSoft.Report.HttpApi/KonSoft.Report.HttpApi.csproj new file mode 100644 index 0000000..acf82b7 --- /dev/null +++ b/modules/report/src/KonSoft.Report.HttpApi/KonSoft.Report.HttpApi.csproj @@ -0,0 +1,24 @@ + + + + + + net8.0 + enable + KonSoft.Report + + + + + + + + + + + + + + + + diff --git a/modules/report/src/KonSoft.Report.HttpApi/Models/Test/TestModel.cs b/modules/report/src/KonSoft.Report.HttpApi/Models/Test/TestModel.cs new file mode 100644 index 0000000..0673740 --- /dev/null +++ b/modules/report/src/KonSoft.Report.HttpApi/Models/Test/TestModel.cs @@ -0,0 +1,10 @@ +using System; + +namespace KonSoft.Report.Models.Test; + +public class TestModel +{ + public string? Name { get; set; } + + public DateTime BirthDate { get; set; } +} diff --git a/modules/report/src/KonSoft.Report.HttpApi/ReportHttpApiModule.cs b/modules/report/src/KonSoft.Report.HttpApi/ReportHttpApiModule.cs new file mode 100644 index 0000000..ee189b5 --- /dev/null +++ b/modules/report/src/KonSoft.Report.HttpApi/ReportHttpApiModule.cs @@ -0,0 +1,41 @@ +using Localization.Resources.AbpUi; +using KonSoft.Report.Localization; +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.HttpApi; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.Report; + +[DependsOn( + typeof(ReportApplicationContractsModule), + typeof(AbpAccountHttpApiModule), + typeof(AbpIdentityHttpApiModule), + typeof(AbpPermissionManagementHttpApiModule), + typeof(AbpTenantManagementHttpApiModule), + typeof(AbpFeatureManagementHttpApiModule), + typeof(AbpSettingManagementHttpApiModule) + )] +public class ReportHttpApiModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + ConfigureLocalization(); + } + + private void ConfigureLocalization() + { + Configure(options => + { + options.Resources + .Get() + .AddBaseTypes( + typeof(AbpUiResource) + ); + }); + } +} diff --git a/modules/report/test/KonSoft.Report.Application.Tests/KonSoft.Report.Application.Tests.csproj b/modules/report/test/KonSoft.Report.Application.Tests/KonSoft.Report.Application.Tests.csproj new file mode 100644 index 0000000..c5374fb --- /dev/null +++ b/modules/report/test/KonSoft.Report.Application.Tests/KonSoft.Report.Application.Tests.csproj @@ -0,0 +1,20 @@ + + + + + + net8.0 + enable + KonSoft.Report + + + + + + + + + + + + diff --git a/modules/report/test/KonSoft.Report.Application.Tests/ReportApplicationTestBase.cs b/modules/report/test/KonSoft.Report.Application.Tests/ReportApplicationTestBase.cs new file mode 100644 index 0000000..634c92a --- /dev/null +++ b/modules/report/test/KonSoft.Report.Application.Tests/ReportApplicationTestBase.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Report; + +public abstract class ReportApplicationTestBase : ReportTestBase + where TStartupModule : IAbpModule +{ + +} diff --git a/modules/report/test/KonSoft.Report.Application.Tests/ReportApplicationTestModule.cs b/modules/report/test/KonSoft.Report.Application.Tests/ReportApplicationTestModule.cs new file mode 100644 index 0000000..b612b5f --- /dev/null +++ b/modules/report/test/KonSoft.Report.Application.Tests/ReportApplicationTestModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Report; + +[DependsOn( + typeof(ReportApplicationModule), + typeof(ReportDomainTestModule) +)] +public class ReportApplicationTestModule : AbpModule +{ + +} diff --git a/modules/report/test/KonSoft.Report.Application.Tests/Samples/SampleAppServiceTests.cs b/modules/report/test/KonSoft.Report.Application.Tests/Samples/SampleAppServiceTests.cs new file mode 100644 index 0000000..b597da9 --- /dev/null +++ b/modules/report/test/KonSoft.Report.Application.Tests/Samples/SampleAppServiceTests.cs @@ -0,0 +1,34 @@ +using Shouldly; +using System.Threading.Tasks; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Xunit; + +namespace KonSoft.Report.Samples; + +/* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IIdentityUserAppService here). + * Only test your own application services. + */ +public abstract class SampleAppServiceTests : ReportApplicationTestBase + where TStartupModule : IAbpModule +{ + private readonly IIdentityUserAppService _userAppService; + + protected SampleAppServiceTests() + { + _userAppService = GetRequiredService(); + } + + [Fact] + public async Task Initial_Data_Should_Contain_Admin_User() + { + //Act + var result = await _userAppService.GetListAsync(new GetIdentityUsersInput()); + + //Assert + result.TotalCount.ShouldBeGreaterThan(0); + result.Items.ShouldContain(u => u.UserName == "admin"); + } +} diff --git a/modules/report/test/KonSoft.Report.Domain.Tests/KonSoft.Report.Domain.Tests.csproj b/modules/report/test/KonSoft.Report.Domain.Tests/KonSoft.Report.Domain.Tests.csproj new file mode 100644 index 0000000..f294473 --- /dev/null +++ b/modules/report/test/KonSoft.Report.Domain.Tests/KonSoft.Report.Domain.Tests.csproj @@ -0,0 +1,20 @@ + + + + + + net8.0 + enable + KonSoft.Report + + + + + + + + + + + + diff --git a/modules/report/test/KonSoft.Report.Domain.Tests/ReportDomainTestBase.cs b/modules/report/test/KonSoft.Report.Domain.Tests/ReportDomainTestBase.cs new file mode 100644 index 0000000..1840a70 --- /dev/null +++ b/modules/report/test/KonSoft.Report.Domain.Tests/ReportDomainTestBase.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Report; + +/* Inherit from this class for your domain layer tests. */ +public abstract class ReportDomainTestBase : ReportTestBase + where TStartupModule : IAbpModule +{ + +} diff --git a/modules/report/test/KonSoft.Report.Domain.Tests/ReportDomainTestModule.cs b/modules/report/test/KonSoft.Report.Domain.Tests/ReportDomainTestModule.cs new file mode 100644 index 0000000..59edb92 --- /dev/null +++ b/modules/report/test/KonSoft.Report.Domain.Tests/ReportDomainTestModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.Report; + +[DependsOn( + typeof(ReportDomainModule), + typeof(ReportTestBaseModule) +)] +public class ReportDomainTestModule : AbpModule +{ + +} diff --git a/modules/report/test/KonSoft.Report.Domain.Tests/Samples/SampleDomainTests.cs b/modules/report/test/KonSoft.Report.Domain.Tests/Samples/SampleDomainTests.cs new file mode 100644 index 0000000..4b4729f --- /dev/null +++ b/modules/report/test/KonSoft.Report.Domain.Tests/Samples/SampleDomainTests.cs @@ -0,0 +1,46 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Xunit; + +namespace KonSoft.Report.Samples; + +/* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IdentityUserManager here). + * Only test your own domain services. + */ +public abstract class SampleDomainTests : ReportDomainTestBase + where TStartupModule : IAbpModule +{ + private readonly IIdentityUserRepository _identityUserRepository; + private readonly IdentityUserManager _identityUserManager; + + protected SampleDomainTests() + { + _identityUserRepository = GetRequiredService(); + _identityUserManager = GetRequiredService(); + } + + [Fact] + public async Task Should_Set_Email_Of_A_User() + { + IdentityUser adminUser; + + /* Need to manually start Unit Of Work because + * FirstOrDefaultAsync should be executed while db connection / context is available. + */ + await WithUnitOfWorkAsync(async () => + { + adminUser = await _identityUserRepository + .FindByNormalizedUserNameAsync("ADMIN"); + + await _identityUserManager.SetEmailAsync(adminUser, "newemail@abp.io"); + await _identityUserRepository.UpdateAsync(adminUser); + }); + + adminUser = await _identityUserRepository.FindByNormalizedUserNameAsync("ADMIN"); + adminUser.Email.ShouldBe("newemail@abp.io"); + } +} diff --git a/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs new file mode 100644 index 0000000..4ef5eed --- /dev/null +++ b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs @@ -0,0 +1,10 @@ +using KonSoft.Report.Samples; +using Xunit; + +namespace KonSoft.Report.EntityFrameworkCore.Applications; + +[Collection(ReportTestConsts.CollectionDefinitionName)] +public class EfCoreSampleAppServiceTests : SampleAppServiceTests +{ + +} diff --git a/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs new file mode 100644 index 0000000..4019f10 --- /dev/null +++ b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs @@ -0,0 +1,10 @@ +using KonSoft.Report.Samples; +using Xunit; + +namespace KonSoft.Report.EntityFrameworkCore.Domains; + +[Collection(ReportTestConsts.CollectionDefinitionName)] +public class EfCoreSampleDomainTests : SampleDomainTests +{ + +} diff --git a/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreCollection.cs b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreCollection.cs new file mode 100644 index 0000000..beeedd5 --- /dev/null +++ b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreCollection.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace KonSoft.Report.EntityFrameworkCore; + +[CollectionDefinition(ReportTestConsts.CollectionDefinitionName)] +public class ReportEntityFrameworkCoreCollection : ICollectionFixture +{ + +} diff --git a/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreCollectionFixtureBase.cs b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreCollectionFixtureBase.cs new file mode 100644 index 0000000..1fd8ecb --- /dev/null +++ b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreCollectionFixtureBase.cs @@ -0,0 +1,9 @@ +using KonSoft.Report.EntityFrameworkCore; +using Xunit; + +namespace KonSoft.Report.EntityFrameworkCore; + +public class ReportEntityFrameworkCoreCollectionFixtureBase : ICollectionFixture +{ + +} diff --git a/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreFixture.cs b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreFixture.cs new file mode 100644 index 0000000..62ce6b1 --- /dev/null +++ b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreFixture.cs @@ -0,0 +1,11 @@ +using System; + +namespace KonSoft.Report.EntityFrameworkCore; + +public class ReportEntityFrameworkCoreFixture : IDisposable +{ + public void Dispose() + { + + } +} diff --git a/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreTestBase.cs b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreTestBase.cs new file mode 100644 index 0000000..13022d1 --- /dev/null +++ b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreTestBase.cs @@ -0,0 +1,8 @@ +using Volo.Abp; + +namespace KonSoft.Report.EntityFrameworkCore; + +public abstract class ReportEntityFrameworkCoreTestBase : ReportTestBase +{ + +} diff --git a/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreTestModule.cs b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreTestModule.cs new file mode 100644 index 0000000..ef01433 --- /dev/null +++ b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/ReportEntityFrameworkCoreTestModule.cs @@ -0,0 +1,82 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.Sqlite; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.Uow; + +namespace KonSoft.Report.EntityFrameworkCore; + +[DependsOn( + typeof(ReportApplicationTestModule), + typeof(ReportEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCoreSqliteModule) + )] +public class ReportEntityFrameworkCoreTestModule : AbpModule +{ + private SqliteConnection? _sqliteConnection; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.SaveStaticFeaturesToDatabase = false; + options.IsDynamicFeatureStoreEnabled = false; + }); + Configure(options => + { + options.SaveStaticPermissionsToDatabase = false; + options.IsDynamicPermissionStoreEnabled = false; + }); + Configure(options => + { + options.SaveStaticSettingsToDatabase = false; + options.IsDynamicSettingStoreEnabled = false; + }); + context.Services.AddAlwaysDisableUnitOfWorkTransaction(); + + ConfigureInMemorySqlite(context.Services); + } + + private void ConfigureInMemorySqlite(IServiceCollection services) + { + _sqliteConnection = CreateDatabaseAndGetConnection(); + + services.Configure(options => + { + options.Configure(context => + { + context.DbContextOptions.UseSqlite(_sqliteConnection); + }); + }); + } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + _sqliteConnection?.Dispose(); + } + + private static SqliteConnection CreateDatabaseAndGetConnection() + { + var connection = new AbpUnitTestSqliteConnection("Data Source=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new ReportDbContext(options)) + { + context.GetService().CreateTables(); + } + + return connection; + } +} diff --git a/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs new file mode 100644 index 0000000..c1dd450 --- /dev/null +++ b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Shouldly; +using System; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Identity; +using Xunit; + +namespace KonSoft.Report.EntityFrameworkCore.Samples; + +/* This is just an example test class. + * Normally, you don't test ABP framework code + * (like default AppUser repository IRepository here). + * Only test your custom repository methods. + */ +[Collection(ReportTestConsts.CollectionDefinitionName)] +public class SampleRepositoryTests : ReportEntityFrameworkCoreTestBase +{ + private readonly IRepository _appUserRepository; + + public SampleRepositoryTests() + { + _appUserRepository = GetRequiredService>(); + } + + [Fact] + public async Task Should_Query_AppUser() + { + /* Need to manually start Unit Of Work because + * FirstOrDefaultAsync should be executed while db connection / context is available. + */ + await WithUnitOfWorkAsync(async () => + { + //Act + var adminUser = await (await _appUserRepository.GetQueryableAsync()) + .Where(u => u.UserName == "admin") + .FirstOrDefaultAsync(); + + //Assert + adminUser.ShouldNotBeNull(); + }); + } +} diff --git a/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/KonSoft.Report.EntityFrameworkCore.Tests.csproj b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/KonSoft.Report.EntityFrameworkCore.Tests.csproj new file mode 100644 index 0000000..fbb99dc --- /dev/null +++ b/modules/report/test/KonSoft.Report.EntityFrameworkCore.Tests/KonSoft.Report.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,21 @@ + + + + + + net8.0 + enable + KonSoft.Report + + + + + + + + + + + + + diff --git a/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs new file mode 100644 index 0000000..8b4d7a3 --- /dev/null +++ b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs @@ -0,0 +1,25 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Account; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Report.HttpApi.Client.ConsoleTestApp; + +public class ClientDemoService : ITransientDependency +{ + private readonly IProfileAppService _profileAppService; + + public ClientDemoService(IProfileAppService profileAppService) + { + _profileAppService = profileAppService; + } + + public async Task RunAsync() + { + var output = await _profileAppService.GetAsync(); + Console.WriteLine($"UserName : {output.UserName}"); + Console.WriteLine($"Email : {output.Email}"); + Console.WriteLine($"Name : {output.Name}"); + Console.WriteLine($"Surname : {output.Surname}"); + } +} diff --git a/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs new file mode 100644 index 0000000..125fa85 --- /dev/null +++ b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.Hosting; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; + +namespace KonSoft.Report.HttpApi.Client.ConsoleTestApp; + +public class ConsoleTestAppHostedService : IHostedService +{ + private readonly IConfiguration _configuration; + + public ConsoleTestAppHostedService(IConfiguration configuration) + { + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using (var application = await AbpApplicationFactory.CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + })) + { + await application.InitializeAsync(); + + var demo = application.ServiceProvider.GetRequiredService(); + await demo.RunAsync(); + + await application.ShutdownAsync(); + } + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/KonSoft.Report.HttpApi.Client.ConsoleTestApp.csproj b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/KonSoft.Report.HttpApi.Client.ConsoleTestApp.csproj new file mode 100644 index 0000000..357a6d6 --- /dev/null +++ b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/KonSoft.Report.HttpApi.Client.ConsoleTestApp.csproj @@ -0,0 +1,33 @@ + + + + Exe + net8.0 + enable + + + + + + PreserveNewest + Always + + + + PreserveNewest + Always + + + + + + + + + + + + + + + diff --git a/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/Program.cs b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/Program.cs new file mode 100644 index 0000000..288c22a --- /dev/null +++ b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/Program.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace KonSoft.Report.HttpApi.Client.ConsoleTestApp; + +class Program +{ + static async Task Main(string[] args) + { + await CreateHostBuilder(args).RunConsoleAsync(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .AddAppSettingsSecretsJson() + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); +} diff --git a/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/ReportConsoleApiClientModule.cs b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/ReportConsoleApiClientModule.cs new file mode 100644 index 0000000..08ba7f7 --- /dev/null +++ b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/ReportConsoleApiClientModule.cs @@ -0,0 +1,30 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Polly; +using Volo.Abp.Autofac; +using Volo.Abp.Http.Client; +using Volo.Abp.Http.Client.IdentityModel; +using Volo.Abp.Modularity; + +namespace KonSoft.Report.HttpApi.Client.ConsoleTestApp; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(ReportHttpApiClientModule), + typeof(AbpHttpClientIdentityModelModule) + )] +public class ReportConsoleApiClientModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(options => + { + options.ProxyClientBuildActions.Add((remoteServiceName, clientBuilder) => + { + clientBuilder.AddTransientHttpErrorPolicy( + policyBuilder => policyBuilder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i))) + ); + }); + }); + } +} diff --git a/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/appsettings.json b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/appsettings.json new file mode 100644 index 0000000..a47a418 --- /dev/null +++ b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/appsettings.json @@ -0,0 +1,17 @@ +{ + "RemoteServices": { + "Default": { + "BaseUrl": "https://localhost:44340" + } + }, + "IdentityClients": { + "Default": { + "GrantType": "password", + "ClientId": "Report_App", + "UserName": "admin", + "UserPassword": "1q2w3E*", + "Authority": "https://localhost:44340", + "Scope": "Report" + } + } +} diff --git a/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/modules/report/test/KonSoft.Report.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/modules/report/test/KonSoft.Report.TestBase/KonSoft.Report.TestBase.csproj b/modules/report/test/KonSoft.Report.TestBase/KonSoft.Report.TestBase.csproj new file mode 100644 index 0000000..e162884 --- /dev/null +++ b/modules/report/test/KonSoft.Report.TestBase/KonSoft.Report.TestBase.csproj @@ -0,0 +1,31 @@ + + + + + + net8.0 + enable + KonSoft.Report + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + diff --git a/modules/report/test/KonSoft.Report.TestBase/ReportTestBase.cs b/modules/report/test/KonSoft.Report.TestBase/ReportTestBase.cs new file mode 100644 index 0000000..70f614d --- /dev/null +++ b/modules/report/test/KonSoft.Report.TestBase/ReportTestBase.cs @@ -0,0 +1,60 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Modularity; +using Volo.Abp.Uow; +using Volo.Abp.Testing; + +namespace KonSoft.Report; + +/* All test classes are derived from this class, directly or indirectly. + */ +public abstract class ReportTestBase : AbpIntegratedTest + where TStartupModule : IAbpModule +{ + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + protected virtual Task WithUnitOfWorkAsync(Func func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func action) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + await action(); + + await uow.CompleteAsync(); + } + } + } + + protected virtual Task WithUnitOfWorkAsync(Func> func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func> func) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + var result = await func(); + await uow.CompleteAsync(); + return result; + } + } + } +} diff --git a/modules/report/test/KonSoft.Report.TestBase/ReportTestBaseModule.cs b/modules/report/test/KonSoft.Report.TestBase/ReportTestBaseModule.cs new file mode 100644 index 0000000..a3c53db --- /dev/null +++ b/modules/report/test/KonSoft.Report.TestBase/ReportTestBaseModule.cs @@ -0,0 +1,47 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Authorization; +using Volo.Abp.Autofac; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Abp.Threading; + +namespace KonSoft.Report; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpTestBaseModule), + typeof(AbpAuthorizationModule), + typeof(AbpBackgroundJobsAbstractionsModule) + )] +public class ReportTestBaseModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.IsJobExecutionEnabled = false; + }); + + context.Services.AddAlwaysAllowAuthorization(); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + AsyncHelper.RunSync(async () => + { + using (var scope = context.ServiceProvider.CreateScope()) + { + await scope.ServiceProvider + .GetRequiredService() + .SeedAsync(); + } + }); + } +} diff --git a/modules/report/test/KonSoft.Report.TestBase/ReportTestConsts.cs b/modules/report/test/KonSoft.Report.TestBase/ReportTestConsts.cs new file mode 100644 index 0000000..552b154 --- /dev/null +++ b/modules/report/test/KonSoft.Report.TestBase/ReportTestConsts.cs @@ -0,0 +1,6 @@ +namespace KonSoft.Report; + +public static class ReportTestConsts +{ + public const string CollectionDefinitionName = "Report collection"; +} diff --git a/modules/report/test/KonSoft.Report.TestBase/ReportTestDataSeedContributor.cs b/modules/report/test/KonSoft.Report.TestBase/ReportTestDataSeedContributor.cs new file mode 100644 index 0000000..2931d7e --- /dev/null +++ b/modules/report/test/KonSoft.Report.TestBase/ReportTestDataSeedContributor.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.Report; + +public class ReportTestDataSeedContributor : IDataSeedContributor, ITransientDependency +{ + public Task SeedAsync(DataSeedContext context) + { + /* Seed additional test data... */ + + return Task.CompletedTask; + } +} diff --git a/modules/report/test/KonSoft.Report.TestBase/Security/FakeCurrentPrincipalAccessor.cs b/modules/report/test/KonSoft.Report.TestBase/Security/FakeCurrentPrincipalAccessor.cs new file mode 100644 index 0000000..184f07f --- /dev/null +++ b/modules/report/test/KonSoft.Report.TestBase/Security/FakeCurrentPrincipalAccessor.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Security.Claims; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Claims; + +namespace KonSoft.Report.Security; + +[Dependency(ReplaceServices = true)] +public class FakeCurrentPrincipalAccessor : ThreadCurrentPrincipalAccessor +{ + protected override ClaimsPrincipal GetClaimsPrincipal() + { + return GetPrincipal(); + } + + private ClaimsPrincipal GetPrincipal() + { + return new ClaimsPrincipal(new ClaimsIdentity(new List + { + new Claim(AbpClaimTypes.UserId, "2e701e62-0953-4dd3-910b-dc6cc93ccb0d"), + new Claim(AbpClaimTypes.UserName, "admin"), + new Claim(AbpClaimTypes.Email, "admin@abp.io") + })); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/KonSoft.TenantManagement.Application.Contracts.csproj b/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/KonSoft.TenantManagement.Application.Contracts.csproj new file mode 100644 index 0000000..254eea6 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/KonSoft.TenantManagement.Application.Contracts.csproj @@ -0,0 +1,25 @@ + + + + + + net8.0 + enable + KonSoft.TenantManagement + + + + + + + + + + + + + + + + + diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/Permissions/TenantManagementPermissionDefinitionProvider.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/Permissions/TenantManagementPermissionDefinitionProvider.cs new file mode 100644 index 0000000..1bf7394 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/Permissions/TenantManagementPermissionDefinitionProvider.cs @@ -0,0 +1,20 @@ +using KonSoft.TenantManagement.Localization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; + +namespace KonSoft.TenantManagement.Permissions; + +public class TenantManagementPermissionDefinitionProvider : PermissionDefinitionProvider +{ + public override void Define(IPermissionDefinitionContext context) + { + var myGroup = context.AddGroup(TenantManagementPermissions.GroupName); + //Define your own permissions here. Example: + //myGroup.AddPermission(TenantManagementPermissions.MyPermission1, L("Permission:MyPermission1")); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/Permissions/TenantManagementPermissions.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/Permissions/TenantManagementPermissions.cs new file mode 100644 index 0000000..b18cbdd --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/Permissions/TenantManagementPermissions.cs @@ -0,0 +1,9 @@ +namespace KonSoft.TenantManagement.Permissions; + +public static class TenantManagementPermissions +{ + public const string GroupName = "TenantManagement"; + + //Add your own permission names. Example: + //public const string MyPermission1 = GroupName + ".MyPermission1"; +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/TenantManagementApplicationContractsModule.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/TenantManagementApplicationContractsModule.cs new file mode 100644 index 0000000..cb1dc8c --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/TenantManagementApplicationContractsModule.cs @@ -0,0 +1,28 @@ +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.TenantManagement; + +[DependsOn( + typeof(TenantManagementDomainSharedModule), + typeof(AbpAccountApplicationContractsModule), + typeof(AbpFeatureManagementApplicationContractsModule), + typeof(AbpIdentityApplicationContractsModule), + typeof(AbpPermissionManagementApplicationContractsModule), + typeof(AbpSettingManagementApplicationContractsModule), + typeof(AbpTenantManagementApplicationContractsModule), + typeof(AbpObjectExtendingModule) +)] +public class TenantManagementApplicationContractsModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + TenantManagementDtoExtensions.Configure(); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/TenantManagementDtoExtensions.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/TenantManagementDtoExtensions.cs new file mode 100644 index 0000000..8f59d3e --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Application.Contracts/TenantManagementDtoExtensions.cs @@ -0,0 +1,28 @@ +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.TenantManagement; + +public static class TenantManagementDtoExtensions +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can add extension properties to DTOs + * defined in the depended modules. + * + * Example: + * + * ObjectExtensionManager.Instance + * .AddOrUpdateProperty("Title"); + * + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Object-Extensions + */ + }); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Application/KonSoft.TenantManagement.Application.csproj b/modules/tenant-management/src/KonSoft.TenantManagement.Application/KonSoft.TenantManagement.Application.csproj new file mode 100644 index 0000000..6c2e177 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Application/KonSoft.TenantManagement.Application.csproj @@ -0,0 +1,25 @@ + + + + + + net8.0 + enable + KonSoft.TenantManagement + + + + + + + + + + + + + + + + + diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Application/Properties/AssemblyInfo.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Application/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..532c436 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Application/Properties/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.TenantManagement.Application.Tests")] diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Application/TenantManagementAppService.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Application/TenantManagementAppService.cs new file mode 100644 index 0000000..73aab41 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Application/TenantManagementAppService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using KonSoft.TenantManagement.Localization; +using Volo.Abp.Application.Services; + +namespace KonSoft.TenantManagement; + +/* Inherit your application services from this class. + */ +public abstract class TenantManagementAppService : ApplicationService +{ + protected TenantManagementAppService() + { + LocalizationResource = typeof(TenantManagementResource); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Application/TenantManagementApplicationAutoMapperProfile.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Application/TenantManagementApplicationAutoMapperProfile.cs new file mode 100644 index 0000000..cd54bf0 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Application/TenantManagementApplicationAutoMapperProfile.cs @@ -0,0 +1,13 @@ +using AutoMapper; + +namespace KonSoft.TenantManagement; + +public class TenantManagementApplicationAutoMapperProfile : Profile +{ + public TenantManagementApplicationAutoMapperProfile() + { + /* You can configure your AutoMapper mapping configuration here. + * Alternatively, you can split your mapping configurations + * into multiple profile classes for a better organization. */ + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Application/TenantManagementApplicationModule.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Application/TenantManagementApplicationModule.cs new file mode 100644 index 0000000..abcec47 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Application/TenantManagementApplicationModule.cs @@ -0,0 +1,31 @@ +using Volo.Abp.Account; +using Volo.Abp.AutoMapper; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.TenantManagement; + +[DependsOn( + typeof(TenantManagementDomainModule), + typeof(AbpAccountApplicationModule), + typeof(TenantManagementApplicationContractsModule), + typeof(AbpIdentityApplicationModule), + typeof(AbpPermissionManagementApplicationModule), + typeof(AbpTenantManagementApplicationModule), + typeof(AbpFeatureManagementApplicationModule), + typeof(AbpSettingManagementApplicationModule) + )] +public class TenantManagementApplicationModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.AddMaps(); + }); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/KonSoft.TenantManagement.Domain.Shared.csproj b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/KonSoft.TenantManagement.Domain.Shared.csproj new file mode 100644 index 0000000..bdf9f4d --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/KonSoft.TenantManagement.Domain.Shared.csproj @@ -0,0 +1,32 @@ + + + + + + net8.0 + enable + KonSoft.TenantManagement + true + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/ar.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/ar.json new file mode 100644 index 0000000..1549fba --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/ar.json @@ -0,0 +1,9 @@ +{ + "culture": "ar", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "الصفحة الرئيسية", + "Welcome": "مرحباً", + "LongWelcomeMessage": "مرحبا بكم في التطبيق. هذا مشروع بدء تشغيل يعتمد على إطار عمل ABP. لمزيد من المعلومات ، يرجى زيارة abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/cs.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/cs.json new file mode 100644 index 0000000..fb1838f --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/cs.json @@ -0,0 +1,9 @@ +{ + "culture": "cs", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Úvod", + "Welcome": "Vítejte", + "LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/de.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/de.json new file mode 100644 index 0000000..10aa9f0 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/de.json @@ -0,0 +1,9 @@ +{ + "culture": "de", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Home", + "Welcome": "Willkommen", + "LongWelcomeMessage": "Willkommen bei der Anwendung. Dies ist ein Startup-Projekt, das auf dem ABP-Framework basiert. Weitere Informationen finden Sie unter abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/en-GB.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/en-GB.json new file mode 100644 index 0000000..2d474a0 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/en-GB.json @@ -0,0 +1,9 @@ +{ + "culture": "en-GB", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Home", + "Welcome": "Welcome", + "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/en.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/en.json new file mode 100644 index 0000000..e5372ca --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/en.json @@ -0,0 +1,9 @@ +{ + "culture": "en", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Home", + "Welcome": "Welcome", + "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/es.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/es.json new file mode 100644 index 0000000..ca7d341 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/es.json @@ -0,0 +1,9 @@ +{ + "culture": "es", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Inicio", + "Welcome": "Bienvenido", + "LongWelcomeMessage": "Bienvenido a la aplicación, este es un proyecto base basado en el framework ABP. Para más información, visita abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/fi.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/fi.json new file mode 100644 index 0000000..c70a458 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/fi.json @@ -0,0 +1,9 @@ +{ + "culture": "fi", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Koti", + "Welcome": "Tervetuloa", + "LongWelcomeMessage": "Tervetuloa sovellukseen. Tämä on ABP-kehykseen perustuva käynnistysprojekti. Lisätietoja on osoitteessa abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/fr.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/fr.json new file mode 100644 index 0000000..04f34e0 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/fr.json @@ -0,0 +1,9 @@ +{ + "culture": "fr", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Accueil", + "Welcome": "Bienvenue", + "LongWelcomeMessage": "Bienvenue dans l'application. Il s'agit d'un projet de démarrage basé sur le framework ABP. Pour plus d'informations, visitez abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/hi.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/hi.json new file mode 100644 index 0000000..25b0b0f --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/hi.json @@ -0,0 +1,9 @@ +{ + "culture": "hi", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "घर", + "Welcome": "स्वागत हे", + "LongWelcomeMessage": "आवेदन करने के लिए आपका स्वागत है। यह एबीपी ढांचे पर आधारित एक स्टार्टअप परियोजना है। अधिक जानकारी के लिए, abp.io पर जाएं।" + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/hr.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/hr.json new file mode 100644 index 0000000..ff8836c --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/hr.json @@ -0,0 +1,9 @@ +{ + "culture": "hr", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Početna", + "Welcome": "Dobrodošli", + "LongWelcomeMessage": "Dobrodošli u aplikaciju. Ovo je startup projekt temeljen na ABP framework-u. Za više informacija posjetite abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/hu.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/hu.json new file mode 100644 index 0000000..de7c728 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/hu.json @@ -0,0 +1,9 @@ +{ + "culture": "hu", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Kezdőlap", + "Welcome": "Üdvözlöm", + "LongWelcomeMessage": "Üdvözöljük az alkalmazásban. Ez egy ABP keretrendszeren alapuló startup projekt. További információkért látogasson el az abp.io oldalra." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/is.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/is.json new file mode 100644 index 0000000..a08c37d --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/is.json @@ -0,0 +1,9 @@ +{ + "culture": "is", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Heim", + "Welcome": "Velkomin", + "LongWelcomeMessage": "Verið velkomin í forritið. Þetta er startup verkefni sem byggir á ABP. Nánari upplýsingar er að finna á abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/it.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/it.json new file mode 100644 index 0000000..58682d2 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/it.json @@ -0,0 +1,9 @@ +{ + "culture": "it", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Home", + "Welcome": "Benvenuto", + "LongWelcomeMessage": "Benvenuto nell'applicazione. Questo è un progetto di avvio basato sul framework ABP. Per ulteriori informazioni, visita abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/nl.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/nl.json new file mode 100644 index 0000000..0298ab9 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/nl.json @@ -0,0 +1,9 @@ +{ + "culture": "nl", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Home", + "Welcome": "Welkom", + "LongWelcomeMessage": "Welkom bij de applicatie. Dit is een startup-project gebaseerd op het ABP-framework. Bezoek abp.io voor meer informatie." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/pl-PL.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/pl-PL.json new file mode 100644 index 0000000..f57b395 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/pl-PL.json @@ -0,0 +1,9 @@ +{ + "culture": "pl-PL", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Home", + "Welcome": "Witaj", + "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/pt-BR.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/pt-BR.json new file mode 100644 index 0000000..392fd64 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/pt-BR.json @@ -0,0 +1,9 @@ +{ + "culture": "pt-BR", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Principal", + "Welcome": "Seja bem-vindo!", + "LongWelcomeMessage": "Bem-vindo a esta aplicação. Este é um projeto inicial baseado no ABP framework. Para mais informações, visite abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/ro-RO.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/ro-RO.json new file mode 100644 index 0000000..ce67c79 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/ro-RO.json @@ -0,0 +1,9 @@ +{ + "culture": "ro-RO", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Acasă", + "Welcome": "Bun venit", + "LongWelcomeMessage": "Bun venit la aplicaţie. Acesta este un proiect de pornire bazat pe framework-ul ABP. Pentru mai multe informaţii, vizitaţi, visit abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/ru.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/ru.json new file mode 100644 index 0000000..e1442c6 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/ru.json @@ -0,0 +1,9 @@ +{ + "culture": "ru", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Главная", + "Welcome": "Добро пожаловать", + "LongWelcomeMessage": "Добро пожаловать в приложение. Этот запущенный проект основан на фреймворке ABP. Для получения дополнительной информации посетите сайт abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/sk.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/sk.json new file mode 100644 index 0000000..d866a32 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/sk.json @@ -0,0 +1,9 @@ +{ + "culture": "sk", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Domov", + "Welcome": "Vitajte", + "LongWelcomeMessage": "Vitajte v aplikácii. Toto je štartovací projekt založený na ABP frameworku. Viac informácií nájdete na stránke abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/sl.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/sl.json new file mode 100644 index 0000000..dec2120 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/sl.json @@ -0,0 +1,9 @@ +{ + "culture": "sl", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Domov", + "Welcome": "Dobrodošli", + "LongWelcomeMessage": "Dobrodošli v aplikaciji. To je začetni projekt na osnovi okolja ABP. Za več informacij obiščite abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/sv.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/sv.json new file mode 100644 index 0000000..bd1eae4 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/sv.json @@ -0,0 +1,9 @@ +{ + "culture": "sv", + "texts": { + "AppName": "MittProjektNamn", + "Menu:Home": "Hem", + "Welcome": "Välkommen", + "LongWelcomeMessage": "Välkommen till applikationen. Detta är ett startup-projekt baserat på ABP-ramverket. För mer information, besök abp.io." + } +} \ No newline at end of file diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/tr.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/tr.json new file mode 100644 index 0000000..d134626 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/tr.json @@ -0,0 +1,9 @@ +{ + "culture": "tr", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Ana sayfa", + "Welcome": "Hoşgeldiniz", + "LongWelcomeMessage": "Uygulamaya hoşgeldiniz. Bu, ABP framework'ü üzerine bina edilmiş bir başlangıç projesidir. Daha fazla bilgi için abp.io adresini ziyaret edebilirsiniz." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/vi.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/vi.json new file mode 100644 index 0000000..cea053f --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/vi.json @@ -0,0 +1,9 @@ +{ + "culture": "vi", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "Trang chủ", + "Welcome": "Chào mừng bạn", + "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án khởi nghiệp dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io." + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/zh-Hans.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/zh-Hans.json new file mode 100644 index 0000000..70f3be7 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/zh-Hans.json @@ -0,0 +1,9 @@ +{ + "culture": "zh-Hans", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "首页", + "Welcome": "欢迎", + "LongWelcomeMessage": "欢迎使用本应用程序。这是一个基于 ABP 框架的启动项目。更多信息,请访问 abp.io。" + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/zh-Hant.json b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/zh-Hant.json new file mode 100644 index 0000000..01a16d1 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagement/zh-Hant.json @@ -0,0 +1,9 @@ +{ + "culture": "zh-Hant", + "texts": { + "AppName": "TenantManagement", + "Menu:Home": "首頁", + "Welcome": "歡迎", + "LongWelcomeMessage": "歡迎來到此應用程式. 這是一個基於ABP框架的起始專案. 有關更多訊息, 請瀏覽 abp.io." + } + } diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagementResource.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagementResource.cs new file mode 100644 index 0000000..63c87f1 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/Localization/TenantManagementResource.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Localization; + +namespace KonSoft.TenantManagement.Localization; + +[LocalizationResourceName("TenantManagement")] +public class TenantManagementResource +{ + +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs new file mode 100644 index 0000000..16fc670 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs @@ -0,0 +1,10 @@ +namespace KonSoft.TenantManagement.MultiTenancy; + +public static class MultiTenancyConsts +{ + /* Enable/disable multi-tenancy easily in a single point. + * If you will never need to multi-tenancy, you can remove + * related modules and code parts, including this file. + */ + public const bool IsEnabled = true; +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementDomainErrorCodes.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementDomainErrorCodes.cs new file mode 100644 index 0000000..5c8ea27 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementDomainErrorCodes.cs @@ -0,0 +1,6 @@ +namespace KonSoft.TenantManagement; + +public static class TenantManagementDomainErrorCodes +{ + /* You can add your business exception error codes here, as constants */ +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementDomainSharedModule.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementDomainSharedModule.cs new file mode 100644 index 0000000..70a3f90 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementDomainSharedModule.cs @@ -0,0 +1,58 @@ +using KonSoft.TenantManagement.Localization; +using Volo.Abp.AuditLogging; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Localization.ExceptionHandling; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; +using Volo.Abp.Validation.Localization; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.TenantManagement; + +[DependsOn( + typeof(AbpAuditLoggingDomainSharedModule), + typeof(AbpBackgroundJobsDomainSharedModule), + typeof(AbpFeatureManagementDomainSharedModule), + typeof(AbpIdentityDomainSharedModule), + typeof(AbpOpenIddictDomainSharedModule), + typeof(AbpPermissionManagementDomainSharedModule), + typeof(AbpSettingManagementDomainSharedModule), + typeof(AbpTenantManagementDomainSharedModule) + )] +public class TenantManagementDomainSharedModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + TenantManagementGlobalFeatureConfigurator.Configure(); + TenantManagementModuleExtensionConfigurator.Configure(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddBaseTypes(typeof(AbpValidationResource)) + .AddVirtualJson("/Localization/TenantManagement"); + + options.DefaultResourceType = typeof(TenantManagementResource); + }); + + Configure(options => + { + options.MapCodeNamespace("TenantManagement", typeof(TenantManagementResource)); + }); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementGlobalFeatureConfigurator.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementGlobalFeatureConfigurator.cs new file mode 100644 index 0000000..a26c94b --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementGlobalFeatureConfigurator.cs @@ -0,0 +1,22 @@ +using Volo.Abp.Threading; + +namespace KonSoft.TenantManagement; + +public static class TenantManagementGlobalFeatureConfigurator +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can configure (enable/disable) global features of the used modules here. + * + * YOU CAN SAFELY DELETE THIS CLASS AND REMOVE ITS USAGES IF YOU DON'T NEED TO IT! + * + * Please refer to the documentation to lear more about the Global Features System: + * https://docs.abp.io/en/abp/latest/Global-Features + */ + }); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementModuleExtensionConfigurator.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementModuleExtensionConfigurator.cs new file mode 100644 index 0000000..c42519f --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain.Shared/TenantManagementModuleExtensionConfigurator.cs @@ -0,0 +1,73 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.TenantManagement; + +public static class TenantManagementModuleExtensionConfigurator +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + ConfigureExistingProperties(); + ConfigureExtraProperties(); + }); + } + + private static void ConfigureExistingProperties() + { + /* You can change max lengths for properties of the + * entities defined in the modules used by your application. + * + * Example: Change user and role name max lengths + + AbpUserConsts.MaxNameLength = 99; + IdentityRoleConsts.MaxNameLength = 99; + + * Notice: It is not suggested to change property lengths + * unless you really need it. Go with the standard values wherever possible. + * + * If you are using EF Core, you will need to run the add-migration command after your changes. + */ + } + + private static void ConfigureExtraProperties() + { + /* You can configure extra properties for the + * entities defined in the modules used by your application. + * + * This class can be used to define these extra properties + * with a high level, easy to use API. + * + * Example: Add a new property to the user entity of the identity module + + ObjectExtensionManager.Instance.Modules() + .ConfigureIdentity(identity => + { + identity.ConfigureUser(user => + { + user.AddOrUpdateProperty( //property type: string + "SocialSecurityNumber", //property name + property => + { + //validation rules + property.Attributes.Add(new RequiredAttribute()); + property.Attributes.Add(new StringLengthAttribute(64) {MinimumLength = 4}); + + property.Configuration[IdentityModuleExtensionConsts.ConfigurationNames.AllowUserToEdit] = true; + + //...other configurations for this property + } + ); + }); + }); + + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Module-Entity-Extensions + */ + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Data/ITenantManagementDbSchemaMigrator.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Data/ITenantManagementDbSchemaMigrator.cs new file mode 100644 index 0000000..134f8ef --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Data/ITenantManagementDbSchemaMigrator.cs @@ -0,0 +1,8 @@ +using System.Threading.Tasks; + +namespace KonSoft.TenantManagement.Data; + +public interface ITenantManagementDbSchemaMigrator +{ + Task MigrateAsync(); +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Data/NullTenantManagementDbSchemaMigrator.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Data/NullTenantManagementDbSchemaMigrator.cs new file mode 100644 index 0000000..4d10344 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Data/NullTenantManagementDbSchemaMigrator.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.TenantManagement.Data; + +/* This is used if database provider does't define + * ITenantManagementDbSchemaMigrator implementation. + */ +public class NullTenantManagementDbSchemaMigrator : ITenantManagementDbSchemaMigrator, ITransientDependency +{ + public Task MigrateAsync() + { + return Task.CompletedTask; + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Data/TenantManagementDbMigrationService.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Data/TenantManagementDbMigrationService.cs new file mode 100644 index 0000000..38df252 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Data/TenantManagementDbMigrationService.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.TenantManagement; + +namespace KonSoft.TenantManagement.Data; + +public class TenantManagementDbMigrationService : ITransientDependency +{ + public ILogger Logger { get; set; } + + private readonly IDataSeeder _dataSeeder; + private readonly IEnumerable _dbSchemaMigrators; + private readonly ITenantRepository _tenantRepository; + private readonly ICurrentTenant _currentTenant; + + public TenantManagementDbMigrationService( + IDataSeeder dataSeeder, + IEnumerable dbSchemaMigrators, + ITenantRepository tenantRepository, + ICurrentTenant currentTenant) + { + _dataSeeder = dataSeeder; + _dbSchemaMigrators = dbSchemaMigrators; + _tenantRepository = tenantRepository; + _currentTenant = currentTenant; + + Logger = NullLogger.Instance; + } + + public async Task MigrateAsync() + { + var initialMigrationAdded = AddInitialMigrationIfNotExist(); + + if (initialMigrationAdded) + { + return; + } + + Logger.LogInformation("Started database migrations..."); + + await MigrateDatabaseSchemaAsync(); + await SeedDataAsync(); + + Logger.LogInformation($"Successfully completed host database migrations."); + + var tenants = await _tenantRepository.GetListAsync(includeDetails: true); + + var migratedDatabaseSchemas = new HashSet(); + foreach (var tenant in tenants) + { + using (_currentTenant.Change(tenant.Id)) + { + if (tenant.ConnectionStrings.Any()) + { + var tenantConnectionStrings = tenant.ConnectionStrings + .Select(x => x.Value) + .ToList(); + + if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings)) + { + await MigrateDatabaseSchemaAsync(tenant); + + migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings); + } + } + + await SeedDataAsync(tenant); + } + + Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations."); + } + + Logger.LogInformation("Successfully completed all database migrations."); + Logger.LogInformation("You can safely end this process..."); + } + + private async Task MigrateDatabaseSchemaAsync(Tenant? tenant = null) + { + Logger.LogInformation( + $"Migrating schema for {(tenant == null ? "host" : tenant.Name + " tenant")} database..."); + + foreach (var migrator in _dbSchemaMigrators) + { + await migrator.MigrateAsync(); + } + } + + private async Task SeedDataAsync(Tenant? tenant = null) + { + Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed..."); + + await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id) + .WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, IdentityDataSeedContributor.AdminEmailDefaultValue) + .WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, IdentityDataSeedContributor.AdminPasswordDefaultValue) + ); + } + + private bool AddInitialMigrationIfNotExist() + { + try + { + if (!DbMigrationsProjectExists()) + { + return false; + } + } + catch (Exception) + { + return false; + } + + try + { + if (!MigrationsFolderExists()) + { + AddInitialMigration(); + return true; + } + else + { + return false; + } + } + catch (Exception e) + { + Logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message); + return false; + } + } + + private bool DbMigrationsProjectExists() + { + var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath(); + + return dbMigrationsProjectFolder != null; + } + + private bool MigrationsFolderExists() + { + var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath(); + return dbMigrationsProjectFolder != null && Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations")); + } + + private void AddInitialMigration() + { + Logger.LogInformation("Creating initial migration..."); + + string argumentPrefix; + string fileName; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + argumentPrefix = "-c"; + fileName = "/bin/bash"; + } + else + { + argumentPrefix = "/C"; + fileName = "cmd.exe"; + } + + var procStartInfo = new ProcessStartInfo(fileName, + $"{argumentPrefix} \"abp create-migration-and-run-migrator \"{GetEntityFrameworkCoreProjectFolderPath()}\"\"" + ); + + try + { + Process.Start(procStartInfo); + } + catch (Exception) + { + throw new Exception("Couldn't run ABP CLI..."); + } + } + + private string? GetEntityFrameworkCoreProjectFolderPath() + { + var slnDirectoryPath = GetSolutionDirectoryPath(); + + if (slnDirectoryPath == null) + { + throw new Exception("Solution folder not found!"); + } + + var srcDirectoryPath = Path.Combine(slnDirectoryPath, "src"); + + return Directory.GetDirectories(srcDirectoryPath) + .FirstOrDefault(d => d.EndsWith(".EntityFrameworkCore")); + } + + private string? GetSolutionDirectoryPath() + { + var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory()); + + while (currentDirectory != null && Directory.GetParent(currentDirectory.FullName) != null) + { + currentDirectory = Directory.GetParent(currentDirectory.FullName); + + if (currentDirectory != null && Directory.GetFiles(currentDirectory.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null) + { + return currentDirectory.FullName; + } + } + + return null; + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain/KonSoft.TenantManagement.Domain.csproj b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/KonSoft.TenantManagement.Domain.csproj new file mode 100644 index 0000000..80340f9 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/KonSoft.TenantManagement.Domain.csproj @@ -0,0 +1,28 @@ + + + + + + net8.0 + enable + KonSoft.TenantManagement + + + + + + + + + + + + + + + + + + + + diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain/OpenIddict/OpenIddictDataSeedContributor.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/OpenIddict/OpenIddictDataSeedContributor.cs new file mode 100644 index 0000000..595dc86 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/OpenIddict/OpenIddictDataSeedContributor.cs @@ -0,0 +1,327 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Localization; +using OpenIddict.Abstractions; +using Volo.Abp; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.OpenIddict.Applications; +using Volo.Abp.OpenIddict.Scopes; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Uow; + +namespace KonSoft.TenantManagement.OpenIddict; + +/* Creates initial data that is needed to property run the application + * and make client-to-server communication possible. + */ +public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDependency +{ + private readonly IConfiguration _configuration; + private readonly IOpenIddictApplicationRepository _openIddictApplicationRepository; + private readonly IAbpApplicationManager _applicationManager; + private readonly IOpenIddictScopeRepository _openIddictScopeRepository; + private readonly IOpenIddictScopeManager _scopeManager; + private readonly IPermissionDataSeeder _permissionDataSeeder; + private readonly IStringLocalizer L; + + public OpenIddictDataSeedContributor( + IConfiguration configuration, + IOpenIddictApplicationRepository openIddictApplicationRepository, + IAbpApplicationManager applicationManager, + IOpenIddictScopeRepository openIddictScopeRepository, + IOpenIddictScopeManager scopeManager, + IPermissionDataSeeder permissionDataSeeder, + IStringLocalizer l ) + { + _configuration = configuration; + _openIddictApplicationRepository = openIddictApplicationRepository; + _applicationManager = applicationManager; + _openIddictScopeRepository = openIddictScopeRepository; + _scopeManager = scopeManager; + _permissionDataSeeder = permissionDataSeeder; + L = l; + } + + [UnitOfWork] + public virtual async Task SeedAsync(DataSeedContext context) + { + await CreateScopesAsync(); + await CreateApplicationsAsync(); + } + + private async Task CreateScopesAsync() + { + if (await _openIddictScopeRepository.FindByNameAsync("TenantManagement") == null) + { + await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor { + Name = "TenantManagement", DisplayName = "TenantManagement API", Resources = { "TenantManagement" } + }); + } + } + + private async Task CreateApplicationsAsync() + { + var commonScopes = new List { + OpenIddictConstants.Permissions.Scopes.Address, + OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Phone, + OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Roles, + "TenantManagement" + }; + + var configurationSection = _configuration.GetSection("OpenIddict:Applications"); + + + + + + + // Swagger Client + var swaggerClientId = configurationSection["TenantManagement_Swagger:ClientId"]; + if (!swaggerClientId.IsNullOrWhiteSpace()) + { + var swaggerRootUrl = configurationSection["TenantManagement_Swagger:RootUrl"]?.TrimEnd('/'); + + await CreateApplicationAsync( + name: swaggerClientId!, + type: OpenIddictConstants.ClientTypes.Public, + consentType: OpenIddictConstants.ConsentTypes.Implicit, + displayName: "Swagger Application", + secret: null, + grantTypes: new List { OpenIddictConstants.GrantTypes.AuthorizationCode, }, + scopes: commonScopes, + redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html", + clientUri: swaggerRootUrl + ); + } + } + + private async Task CreateApplicationAsync( + [NotNull] string name, + [NotNull] string type, + [NotNull] string consentType, + string displayName, + string? secret, + List grantTypes, + List scopes, + string? clientUri = null, + string? redirectUri = null, + string? postLogoutRedirectUri = null, + List? permissions = null) + { + if (!string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Public, + StringComparison.OrdinalIgnoreCase)) + { + throw new BusinessException(L["NoClientSecretCanBeSetForPublicApplications"]); + } + + if (string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, + StringComparison.OrdinalIgnoreCase)) + { + throw new BusinessException(L["TheClientSecretIsRequiredForConfidentialApplications"]); + } + + var client = await _openIddictApplicationRepository.FindByClientIdAsync(name); + + var application = new AbpApplicationDescriptor { + ClientId = name, + ClientType = type, + ClientSecret = secret, + ConsentType = consentType, + DisplayName = displayName, + ClientUri = clientUri, + }; + + Check.NotNullOrEmpty(grantTypes, nameof(grantTypes)); + Check.NotNullOrEmpty(scopes, nameof(scopes)); + + if (new[] { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }.All( + grantTypes.Contains)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken); + + if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeToken); + } + } + + if (!redirectUri.IsNullOrWhiteSpace() || !postLogoutRedirectUri.IsNullOrWhiteSpace()) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout); + } + + var buildInGrantTypes = new[] { + OpenIddictConstants.GrantTypes.Implicit, OpenIddictConstants.GrantTypes.Password, + OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.ClientCredentials, + OpenIddictConstants.GrantTypes.DeviceCode, OpenIddictConstants.GrantTypes.RefreshToken + }; + + foreach (var grantType in grantTypes) + { + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code); + } + + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || + grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization); + } + + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || + grantType == OpenIddictConstants.GrantTypes.ClientCredentials || + grantType == OpenIddictConstants.GrantTypes.Password || + grantType == OpenIddictConstants.GrantTypes.RefreshToken || + grantType == OpenIddictConstants.GrantTypes.DeviceCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Revocation); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Introspection); + } + + if (grantType == OpenIddictConstants.GrantTypes.ClientCredentials) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials); + } + + if (grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit); + } + + if (grantType == OpenIddictConstants.GrantTypes.Password) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password); + } + + if (grantType == OpenIddictConstants.GrantTypes.RefreshToken) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken); + } + + if (grantType == OpenIddictConstants.GrantTypes.DeviceCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.DeviceCode); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Device); + } + + if (grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdToken); + if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Token); + } + } + + if (!buildInGrantTypes.Contains(grantType)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.GrantType + grantType); + } + } + + var buildInScopes = new[] { + OpenIddictConstants.Permissions.Scopes.Address, OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Phone, OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Roles + }; + + foreach (var scope in scopes) + { + if (buildInScopes.Contains(scope)) + { + application.Permissions.Add(scope); + } + else + { + application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.Scope + scope); + } + } + + if (redirectUri != null) + { + if (!redirectUri.IsNullOrEmpty()) + { + if (!Uri.TryCreate(redirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) + { + throw new BusinessException(L["InvalidRedirectUri", redirectUri]); + } + + if (application.RedirectUris.All(x => x != uri)) + { + application.RedirectUris.Add(uri); + } + } + } + + if (postLogoutRedirectUri != null) + { + if (!postLogoutRedirectUri.IsNullOrEmpty()) + { + if (!Uri.TryCreate(postLogoutRedirectUri, UriKind.Absolute, out var uri) || + !uri.IsWellFormedOriginalString()) + { + throw new BusinessException(L["InvalidPostLogoutRedirectUri", postLogoutRedirectUri]); + } + + if (application.PostLogoutRedirectUris.All(x => x != uri)) + { + application.PostLogoutRedirectUris.Add(uri); + } + } + } + + if (permissions != null) + { + await _permissionDataSeeder.SeedAsync( + ClientPermissionValueProvider.ProviderName, + name, + permissions, + null + ); + } + + if (client == null) + { + await _applicationManager.CreateAsync(application); + return; + } + + if (!HasSameRedirectUris(client, application)) + { + client.RedirectUris = JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); + client.PostLogoutRedirectUris = JsonSerializer.Serialize(application.PostLogoutRedirectUris.Select(q => q.ToString().TrimEnd('/'))); + + await _applicationManager.UpdateAsync(client.ToModel()); + } + + if (!HasSameScopes(client, application)) + { + client.Permissions = JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString())); + await _applicationManager.UpdateAsync(client.ToModel()); + } + } + + private bool HasSameRedirectUris(OpenIddictApplication existingClient, AbpApplicationDescriptor application) + { + return existingClient.RedirectUris == JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); + } + + private bool HasSameScopes(OpenIddictApplication existingClient, AbpApplicationDescriptor application) + { + return existingClient.Permissions == JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString().TrimEnd('/'))); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Properties/AssemblyInfo.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..41dfbc0 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.TenantManagement.Domain.Tests")] +[assembly:InternalsVisibleToAttribute("KonSoft.TenantManagement.TestBase")] diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Settings/TenantManagementSettingDefinitionProvider.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Settings/TenantManagementSettingDefinitionProvider.cs new file mode 100644 index 0000000..b986266 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Settings/TenantManagementSettingDefinitionProvider.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Settings; + +namespace KonSoft.TenantManagement.Settings; + +public class TenantManagementSettingDefinitionProvider : SettingDefinitionProvider +{ + public override void Define(ISettingDefinitionContext context) + { + //Define your own settings here. Example: + //context.Add(new SettingDefinition(TenantManagementSettings.MySetting1)); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Settings/TenantManagementSettings.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Settings/TenantManagementSettings.cs new file mode 100644 index 0000000..054278d --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/Settings/TenantManagementSettings.cs @@ -0,0 +1,9 @@ +namespace KonSoft.TenantManagement.Settings; + +public static class TenantManagementSettings +{ + private const string Prefix = "TenantManagement"; + + //Add your own setting names here. Example: + //public const string MySetting1 = Prefix + ".MySetting1"; +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain/TenantManagementConsts.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/TenantManagementConsts.cs new file mode 100644 index 0000000..8a46643 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/TenantManagementConsts.cs @@ -0,0 +1,8 @@ +namespace KonSoft.TenantManagement; + +public static class TenantManagementConsts +{ + public const string DbTablePrefix = "App"; + + public const string DbSchema = null; +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.Domain/TenantManagementDomainModule.cs b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/TenantManagementDomainModule.cs new file mode 100644 index 0000000..0e3b699 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.Domain/TenantManagementDomainModule.cs @@ -0,0 +1,68 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using KonSoft.TenantManagement.MultiTenancy; +using Volo.Abp.AuditLogging; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Emailing; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.OpenIddict; +using Volo.Abp.PermissionManagement.Identity; +using Volo.Abp.PermissionManagement.OpenIddict; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.TenantManagement; + +[DependsOn( + typeof(TenantManagementDomainSharedModule), + typeof(AbpAuditLoggingDomainModule), + typeof(AbpBackgroundJobsDomainModule), + typeof(AbpFeatureManagementDomainModule), + typeof(AbpIdentityDomainModule), + typeof(AbpOpenIddictDomainModule), + typeof(AbpPermissionManagementDomainOpenIddictModule), + typeof(AbpPermissionManagementDomainIdentityModule), + typeof(AbpSettingManagementDomainModule), + typeof(AbpTenantManagementDomainModule), + typeof(AbpEmailingModule) +)] +public class TenantManagementDomainModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)")); + options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar")); + options.Languages.Add(new LanguageInfo("hr", "hr", "Croatian")); + options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish")); + options.Languages.Add(new LanguageInfo("fr", "fr", "Français")); + options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi")); + options.Languages.Add(new LanguageInfo("it", "it", "Italiano")); + options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); + options.Languages.Add(new LanguageInfo("ru", "ru", "Русский")); + options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak")); + options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); + options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch")); + options.Languages.Add(new LanguageInfo("es", "es", "Español")); + }); + + Configure(options => + { + options.IsEnabled = MultiTenancyConsts.IsEnabled; + }); + +#if DEBUG + context.Services.Replace(ServiceDescriptor.Singleton()); +#endif + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreTenantManagementDbSchemaMigrator.cs b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreTenantManagementDbSchemaMigrator.cs new file mode 100644 index 0000000..ce41516 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreTenantManagementDbSchemaMigrator.cs @@ -0,0 +1,34 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using KonSoft.TenantManagement.Data; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.TenantManagement.EntityFrameworkCore; + +public class EntityFrameworkCoreTenantManagementDbSchemaMigrator + : ITenantManagementDbSchemaMigrator, ITransientDependency +{ + private readonly IServiceProvider _serviceProvider; + + public EntityFrameworkCoreTenantManagementDbSchemaMigrator( + IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public async Task MigrateAsync() + { + /* We intentionally resolve the TenantManagementDbContext + * from IServiceProvider (instead of directly injecting it) + * to properly get the connection string of the current tenant in the + * current scope. + */ + + await _serviceProvider + .GetRequiredService() + .Database + .MigrateAsync(); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementDbContext.cs b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementDbContext.cs new file mode 100644 index 0000000..42fb62f --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementDbContext.cs @@ -0,0 +1,86 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.AuditLogging.EntityFrameworkCore; +using Volo.Abp.BackgroundJobs.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Identity; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.OpenIddict.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.TenantManagement; +using Volo.Abp.TenantManagement.EntityFrameworkCore; + +namespace KonSoft.TenantManagement.EntityFrameworkCore; + +[ReplaceDbContext(typeof(IIdentityDbContext))] +[ReplaceDbContext(typeof(ITenantManagementDbContext))] +[ConnectionStringName("Default")] +public class TenantManagementDbContext : + AbpDbContext, + IIdentityDbContext, + ITenantManagementDbContext +{ + /* Add DbSet properties for your Aggregate Roots / Entities here. */ + + #region Entities from the modules + + /* Notice: We only implemented IIdentityDbContext and ITenantManagementDbContext + * and replaced them for this DbContext. This allows you to perform JOIN + * queries for the entities of these modules over the repositories easily. You + * typically don't need that for other modules. But, if you need, you can + * implement the DbContext interface of the needed module and use ReplaceDbContext + * attribute just like IIdentityDbContext and ITenantManagementDbContext. + * + * More info: Replacing a DbContext of a module ensures that the related module + * uses this DbContext on runtime. Otherwise, it will use its own DbContext class. + */ + + //Identity + public DbSet Users { get; set; } + public DbSet Roles { get; set; } + public DbSet ClaimTypes { get; set; } + public DbSet OrganizationUnits { get; set; } + public DbSet SecurityLogs { get; set; } + public DbSet LinkUsers { get; set; } + public DbSet UserDelegations { get; set; } + public DbSet Sessions { get; set; } + // Tenant Management + public DbSet Tenants { get; set; } + public DbSet TenantConnectionStrings { get; set; } + + #endregion + + public TenantManagementDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + /* Include modules to your migration db context */ + + builder.ConfigurePermissionManagement(); + builder.ConfigureSettingManagement(); + builder.ConfigureBackgroundJobs(); + builder.ConfigureAuditLogging(); + builder.ConfigureIdentity(); + builder.ConfigureOpenIddict(); + builder.ConfigureFeatureManagement(); + builder.ConfigureTenantManagement(); + + /* Configure your own tables/entities inside here */ + + //builder.Entity(b => + //{ + // b.ToTable(TenantManagementConsts.DbTablePrefix + "YourEntities", TenantManagementConsts.DbSchema); + // b.ConfigureByConvention(); //auto configure for the base class props + // //... + //}); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementDbContextFactory.cs b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementDbContextFactory.cs new file mode 100644 index 0000000..491c202 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementDbContextFactory.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; + +namespace KonSoft.TenantManagement.EntityFrameworkCore; + +/* This class is needed for EF Core console commands + * (like Add-Migration and Update-Database commands) */ +public class TenantManagementDbContextFactory : IDesignTimeDbContextFactory +{ + public TenantManagementDbContext CreateDbContext(string[] args) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + + TenantManagementEfCoreEntityExtensionMappings.Configure(); + + var configuration = BuildConfiguration(); + + var builder = new DbContextOptionsBuilder() + .UseNpgsql(configuration.GetConnectionString("Default")); + + return new TenantManagementDbContext(builder.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../KonSoft.TenantManagement.DbMigrator/")) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementEfCoreEntityExtensionMappings.cs b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementEfCoreEntityExtensionMappings.cs new file mode 100644 index 0000000..0e41151 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementEfCoreEntityExtensionMappings.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.Threading; + +namespace KonSoft.TenantManagement.EntityFrameworkCore; + +public static class TenantManagementEfCoreEntityExtensionMappings +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + TenantManagementGlobalFeatureConfigurator.Configure(); + TenantManagementModuleExtensionConfigurator.Configure(); + + OneTimeRunner.Run(() => + { + /* You can configure extra properties for the + * entities defined in the modules used by your application. + * + * This class can be used to map these extra properties to table fields in the database. + * + * USE THIS CLASS ONLY TO CONFIGURE EF CORE RELATED MAPPING. + * USE TenantManagementModuleExtensionConfigurator CLASS (in the Domain.Shared project) + * FOR A HIGH LEVEL API TO DEFINE EXTRA PROPERTIES TO ENTITIES OF THE USED MODULES + * + * Example: Map a property to a table field: + + ObjectExtensionManager.Instance + .MapEfCoreProperty( + "MyProperty", + (entityBuilder, propertyBuilder) => + { + propertyBuilder.HasMaxLength(128); + } + ); + + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities + */ + }); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementEntityFrameworkCoreModule.cs b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementEntityFrameworkCoreModule.cs new file mode 100644 index 0000000..19ad7ae --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/EntityFrameworkCore/TenantManagementEntityFrameworkCoreModule.cs @@ -0,0 +1,57 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Uow; +using Volo.Abp.AuditLogging.EntityFrameworkCore; +using Volo.Abp.BackgroundJobs.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.PostgreSql; +using Volo.Abp.FeatureManagement.EntityFrameworkCore; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.TenantManagement.EntityFrameworkCore; + +namespace KonSoft.TenantManagement.EntityFrameworkCore; + +[DependsOn( + typeof(TenantManagementDomainModule), + typeof(AbpIdentityEntityFrameworkCoreModule), + typeof(AbpOpenIddictEntityFrameworkCoreModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCorePostgreSqlModule), + typeof(AbpBackgroundJobsEntityFrameworkCoreModule), + typeof(AbpAuditLoggingEntityFrameworkCoreModule), + typeof(AbpTenantManagementEntityFrameworkCoreModule), + typeof(AbpFeatureManagementEntityFrameworkCoreModule) + )] +public class TenantManagementEntityFrameworkCoreModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + + TenantManagementEfCoreEntityExtensionMappings.Configure(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(options => + { + /* Remove "includeAllEntities: true" to create + * default repositories only for aggregate roots */ + options.AddDefaultRepositories(includeAllEntities: true); + }); + + Configure(options => + { + /* The main point to change your DBMS. + * See also TenantManagementMigrationsDbContextFactory for EF Core tooling. */ + options.UseNpgsql(); + }); + + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/KonSoft.TenantManagement.EntityFrameworkCore.csproj b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/KonSoft.TenantManagement.EntityFrameworkCore.csproj new file mode 100644 index 0000000..619558b --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/KonSoft.TenantManagement.EntityFrameworkCore.csproj @@ -0,0 +1,31 @@ + + + + + + net8.0 + enable + KonSoft.TenantManagement + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Migrations/20250908052623_Initial.Designer.cs b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Migrations/20250908052623_Initial.Designer.cs new file mode 100644 index 0000000..fbd5b65 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Migrations/20250908052623_Initial.Designer.cs @@ -0,0 +1,2006 @@ +// +using System; +using KonSoft.TenantManagement.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace KonSoft.TenantManagement.Migrations +{ + [DbContext(typeof(TenantManagementDbContext))] + [Migration("20250908052623_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("text"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("integer") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("smallint") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("uuid"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("EntityChangeId") + .HasColumnType("uuid"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsAbandoned") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("JobArgs") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)"); + + b.Property("JobName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LastTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("NextTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((byte)15); + + b.Property("TryCount") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((short)0); + + b.HasKey("Id"); + + b.HasIndex("IsAbandoned", "NextTryTime"); + + b.ToTable("AbpBackgroundJobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property("ValueType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("SourceTenantId") + .HasColumnType("uuid"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("TargetTenantId") + .HasColumnType("uuid"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique(); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("boolean") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("boolean") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("IpAddresses") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("LastAccessed") + .HasColumnType("timestamp without time zone"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("SignedIn") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("boolean"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("EndTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("StartTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("character varying(196)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("character varying(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ClientSecret") + .HasColumnType("text"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientUri") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JsonWebKeySet") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasColumnType("text"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedirectUris") + .HasColumnType("text"); + + b.Property("Requirements") + .HasColumnType("text"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Scopes") + .HasColumnType("text"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Descriptions") + .HasColumnType("text"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Resources") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AuthorizationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Payload") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("MultiTenancySide") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("boolean"); + + b.Property("IsInherited") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + + b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) + .WithMany() + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Migrations/20250908052623_Initial.cs b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Migrations/20250908052623_Initial.cs new file mode 100644 index 0000000..949d916 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Migrations/20250908052623_Initial.cs @@ -0,0 +1,1156 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace KonSoft.TenantManagement.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpAuditLogs", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationName = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + TenantName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ImpersonatorUserId = table.Column(type: "uuid", nullable: true), + ImpersonatorUserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ImpersonatorTenantId = table.Column(type: "uuid", nullable: true), + ImpersonatorTenantName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ExecutionTime = table.Column(type: "timestamp without time zone", nullable: false), + ExecutionDuration = table.Column(type: "integer", nullable: false), + ClientIpAddress = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + HttpMethod = table.Column(type: "character varying(16)", maxLength: 16, nullable: true), + Url = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + Exceptions = table.Column(type: "text", nullable: true), + Comments = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + HttpStatusCode = table.Column(type: "integer", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpBackgroundJobs", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + JobName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + JobArgs = table.Column(type: "character varying(1048576)", maxLength: 1048576, nullable: false), + TryCount = table.Column(type: "smallint", nullable: false, defaultValue: (short)0), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + NextTryTime = table.Column(type: "timestamp without time zone", nullable: false), + LastTryTime = table.Column(type: "timestamp without time zone", nullable: true), + IsAbandoned = table.Column(type: "boolean", nullable: false, defaultValue: false), + Priority = table.Column(type: "smallint", nullable: false, defaultValue: (byte)15), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpBackgroundJobs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpClaimTypes", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Required = table.Column(type: "boolean", nullable: false), + IsStatic = table.Column(type: "boolean", nullable: false), + Regex = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + RegexDescription = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatureGroups", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatures", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + GroupName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ParentName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + DefaultValue = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + IsVisibleToClients = table.Column(type: "boolean", nullable: false), + IsAvailableToHost = table.Column(type: "boolean", nullable: false), + AllowedProviders = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatures", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpFeatureValues", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureValues", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpLinkUsers", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + SourceUserId = table.Column(type: "uuid", nullable: false), + SourceTenantId = table.Column(type: "uuid", nullable: true), + TargetUserId = table.Column(type: "uuid", nullable: false), + TargetTenantId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLinkUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ParentId = table.Column(type: "uuid", nullable: true), + Code = table.Column(type: "character varying(95)", maxLength: 95, nullable: false), + DisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGrants", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGrants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGroups", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + GroupName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ParentName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsEnabled = table.Column(type: "boolean", nullable: false), + MultiTenancySide = table.Column(type: "smallint", nullable: false), + Providers = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + StateCheckers = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpRoles", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsDefault = table.Column(type: "boolean", nullable: false), + IsStatic = table.Column(type: "boolean", nullable: false), + IsPublic = table.Column(type: "boolean", nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSecurityLogs", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ApplicationName = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + Identity = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + Action = table.Column(type: "character varying(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + TenantName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ClientIpAddress = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSecurityLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSessions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + SessionId = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Device = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + DeviceInfo = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + UserId = table.Column(type: "uuid", nullable: false), + ClientId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + IpAddresses = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + SignedIn = table.Column(type: "timestamp without time zone", nullable: false), + LastAccessed = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSessions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSettingDefinitions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + DefaultValue = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + IsVisibleToClients = table.Column(type: "boolean", nullable: false), + Providers = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + IsInherited = table.Column(type: "boolean", nullable: false), + IsEncrypted = table.Column(type: "boolean", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettingDefinitions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSettings", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: false), + ProviderName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ProviderKey = table.Column(type: "character varying(64)", maxLength: 64, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpTenants", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + NormalizedName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUserDelegations", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + SourceUserId = table.Column(type: "uuid", nullable: false), + TargetUserId = table.Column(type: "uuid", nullable: false), + StartTime = table.Column(type: "timestamp without time zone", nullable: false), + EndTime = table.Column(type: "timestamp without time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserDelegations", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUsers", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedUserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + Surname = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + Email = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + NormalizedEmail = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + EmailConfirmed = table.Column(type: "boolean", nullable: false, defaultValue: false), + PasswordHash = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + SecurityStamp = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + IsExternal = table.Column(type: "boolean", nullable: false, defaultValue: false), + PhoneNumber = table.Column(type: "character varying(16)", maxLength: 16, nullable: true), + PhoneNumberConfirmed = table.Column(type: "boolean", nullable: false, defaultValue: false), + IsActive = table.Column(type: "boolean", nullable: false), + TwoFactorEnabled = table.Column(type: "boolean", nullable: false, defaultValue: false), + LockoutEnd = table.Column(type: "timestamp with time zone", nullable: true), + LockoutEnabled = table.Column(type: "boolean", nullable: false, defaultValue: false), + AccessFailedCount = table.Column(type: "integer", nullable: false, defaultValue: 0), + ShouldChangePasswordOnNextLogin = table.Column(type: "boolean", nullable: false), + EntityVersion = table.Column(type: "integer", nullable: false), + LastPasswordChangeTime = table.Column(type: "timestamp with time zone", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictApplications", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ClientId = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + ClientSecret = table.Column(type: "text", nullable: true), + ClientType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ConsentType = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + DisplayName = table.Column(type: "text", nullable: true), + DisplayNames = table.Column(type: "text", nullable: true), + JsonWebKeySet = table.Column(type: "text", nullable: true), + Permissions = table.Column(type: "text", nullable: true), + PostLogoutRedirectUris = table.Column(type: "text", nullable: true), + Properties = table.Column(type: "text", nullable: true), + RedirectUris = table.Column(type: "text", nullable: true), + Requirements = table.Column(type: "text", nullable: true), + Settings = table.Column(type: "text", nullable: true), + ClientUri = table.Column(type: "text", nullable: true), + LogoUri = table.Column(type: "text", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictApplications", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictScopes", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Description = table.Column(type: "text", nullable: true), + Descriptions = table.Column(type: "text", nullable: true), + DisplayName = table.Column(type: "text", nullable: true), + DisplayNames = table.Column(type: "text", nullable: true), + Name = table.Column(type: "character varying(200)", maxLength: 200, nullable: true), + Properties = table.Column(type: "text", nullable: true), + Resources = table.Column(type: "text", nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictScopes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpAuditLogActions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + AuditLogId = table.Column(type: "uuid", nullable: false), + ServiceName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + MethodName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + Parameters = table.Column(type: "character varying(2000)", maxLength: 2000, nullable: true), + ExecutionTime = table.Column(type: "timestamp without time zone", nullable: false), + ExecutionDuration = table.Column(type: "integer", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogActions", x => x.Id); + table.ForeignKey( + name: "FK_AbpAuditLogActions_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpEntityChanges", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + AuditLogId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ChangeTime = table.Column(type: "timestamp without time zone", nullable: false), + ChangeType = table.Column(type: "smallint", nullable: false), + EntityTenantId = table.Column(type: "uuid", nullable: true), + EntityId = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + EntityTypeFullName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + ExtraProperties = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityChanges_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(type: "uuid", nullable: false), + OrganizationUnitId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationU~", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpRoleClaims", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ClaimType = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpRoleClaims_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpTenantConnectionStrings", + columns: table => new + { + TenantId = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Value = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenantConnectionStrings", x => new { x.TenantId, x.Name }); + table.ForeignKey( + name: "FK_AbpTenantConnectionStrings_AbpTenants_TenantId", + column: x => x.TenantId, + principalTable: "AbpTenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserClaims", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ClaimType = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpUserClaims_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserLogins", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + LoginProvider = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + ProviderKey = table.Column(type: "character varying(196)", maxLength: 196, nullable: false), + ProviderDisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserLogins", x => new { x.UserId, x.LoginProvider }); + table.ForeignKey( + name: "FK_AbpUserLogins_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + OrganizationUnitId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationU~", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserRoles", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserTokens", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + LoginProvider = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + Name = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + Value = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AbpUserTokens_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictAuthorizations", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationId = table.Column(type: "uuid", nullable: true), + CreationDate = table.Column(type: "timestamp without time zone", nullable: true), + Properties = table.Column(type: "text", nullable: true), + Scopes = table.Column(type: "text", nullable: true), + Status = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + Subject = table.Column(type: "character varying(400)", maxLength: 400, nullable: true), + Type = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictAuthorizations_OpenIddictApplications_Application~", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AbpEntityPropertyChanges", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + EntityChangeId = table.Column(type: "uuid", nullable: false), + NewValue = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + OriginalValue = table.Column(type: "character varying(512)", maxLength: 512, nullable: true), + PropertyName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + PropertyTypeFullName = table.Column(type: "character varying(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityPropertyChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityPropertyChanges_AbpEntityChanges_EntityChangeId", + column: x => x.EntityChangeId, + principalTable: "AbpEntityChanges", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictTokens", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicationId = table.Column(type: "uuid", nullable: true), + AuthorizationId = table.Column(type: "uuid", nullable: true), + CreationDate = table.Column(type: "timestamp without time zone", nullable: true), + ExpirationDate = table.Column(type: "timestamp without time zone", nullable: true), + Payload = table.Column(type: "text", nullable: true), + Properties = table.Column(type: "text", nullable: true), + RedemptionDate = table.Column(type: "timestamp without time zone", nullable: true), + ReferenceId = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + Status = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + Subject = table.Column(type: "character varying(400)", maxLength: 400, nullable: true), + Type = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + IsDeleted = table.Column(type: "boolean", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uuid", nullable: true), + DeletionTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictTokens", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId", + column: x => x.AuthorizationId, + principalTable: "OpenIddictAuthorizations", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_AuditLogId", + table: "AbpAuditLogActions", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_TenantId_ServiceName_MethodName_Executio~", + table: "AbpAuditLogActions", + columns: new[] { "TenantId", "ServiceName", "MethodName", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_UserId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "UserId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpBackgroundJobs_IsAbandoned_NextTryTime", + table: "AbpBackgroundJobs", + columns: new[] { "IsAbandoned", "NextTryTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_AuditLogId", + table: "AbpEntityChanges", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_TenantId_EntityTypeFullName_EntityId", + table: "AbpEntityChanges", + columns: new[] { "TenantId", "EntityTypeFullName", "EntityId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityPropertyChanges_EntityChangeId", + table: "AbpEntityPropertyChanges", + column: "EntityChangeId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureGroups_Name", + table: "AbpFeatureGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_GroupName", + table: "AbpFeatures", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_Name", + table: "AbpFeatures", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureValues_Name_ProviderName_ProviderKey", + table: "AbpFeatureValues", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpLinkUsers_SourceUserId_SourceTenantId_TargetUserId_Targe~", + table: "AbpLinkUsers", + columns: new[] { "SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGrants_TenantId_Name_ProviderName_ProviderKey", + table: "AbpPermissionGrants", + columns: new[] { "TenantId", "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGroups_Name", + table: "AbpPermissionGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_GroupName", + table: "AbpPermissions", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_Name", + table: "AbpPermissions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoleClaims_RoleId", + table: "AbpRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoles_NormalizedName", + table: "AbpRoles", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Action", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Action" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_ApplicationName", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "ApplicationName" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Identity", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Identity" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_UserId", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_Device", + table: "AbpSessions", + column: "Device"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_SessionId", + table: "AbpSessions", + column: "SessionId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_TenantId_UserId", + table: "AbpSessions", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettingDefinitions_Name", + table: "AbpSettingDefinitions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettings_Name_ProviderName_ProviderKey", + table: "AbpSettings", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_Name", + table: "AbpTenants", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserClaims_UserId", + table: "AbpUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserLogins_LoginProvider_ProviderKey", + table: "AbpUserLogins", + columns: new[] { "LoginProvider", "ProviderKey" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserRoles_RoleId_UserId", + table: "AbpUserRoles", + columns: new[] { "RoleId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_Email", + table: "AbpUsers", + column: "Email"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedEmail", + table: "AbpUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedUserName", + table: "AbpUsers", + column: "NormalizedUserName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_UserName", + table: "AbpUsers", + column: "UserName"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictApplications_ClientId", + table: "OpenIddictApplications", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictAuthorizations_ApplicationId_Status_Subject_Type", + table: "OpenIddictAuthorizations", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictScopes_Name", + table: "OpenIddictScopes", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ApplicationId_Status_Subject_Type", + table: "OpenIddictTokens", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_AuthorizationId", + table: "OpenIddictTokens", + column: "AuthorizationId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ReferenceId", + table: "OpenIddictTokens", + column: "ReferenceId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpAuditLogActions"); + + migrationBuilder.DropTable( + name: "AbpBackgroundJobs"); + + migrationBuilder.DropTable( + name: "AbpClaimTypes"); + + migrationBuilder.DropTable( + name: "AbpEntityPropertyChanges"); + + migrationBuilder.DropTable( + name: "AbpFeatureGroups"); + + migrationBuilder.DropTable( + name: "AbpFeatures"); + + migrationBuilder.DropTable( + name: "AbpFeatureValues"); + + migrationBuilder.DropTable( + name: "AbpLinkUsers"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + + migrationBuilder.DropTable( + name: "AbpPermissionGrants"); + + migrationBuilder.DropTable( + name: "AbpPermissionGroups"); + + migrationBuilder.DropTable( + name: "AbpPermissions"); + + migrationBuilder.DropTable( + name: "AbpRoleClaims"); + + migrationBuilder.DropTable( + name: "AbpSecurityLogs"); + + migrationBuilder.DropTable( + name: "AbpSessions"); + + migrationBuilder.DropTable( + name: "AbpSettingDefinitions"); + + migrationBuilder.DropTable( + name: "AbpSettings"); + + migrationBuilder.DropTable( + name: "AbpTenantConnectionStrings"); + + migrationBuilder.DropTable( + name: "AbpUserClaims"); + + migrationBuilder.DropTable( + name: "AbpUserDelegations"); + + migrationBuilder.DropTable( + name: "AbpUserLogins"); + + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpUserRoles"); + + migrationBuilder.DropTable( + name: "AbpUserTokens"); + + migrationBuilder.DropTable( + name: "OpenIddictScopes"); + + migrationBuilder.DropTable( + name: "OpenIddictTokens"); + + migrationBuilder.DropTable( + name: "AbpEntityChanges"); + + migrationBuilder.DropTable( + name: "AbpTenants"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpRoles"); + + migrationBuilder.DropTable( + name: "AbpUsers"); + + migrationBuilder.DropTable( + name: "OpenIddictAuthorizations"); + + migrationBuilder.DropTable( + name: "AbpAuditLogs"); + + migrationBuilder.DropTable( + name: "OpenIddictApplications"); + } + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Migrations/TenantManagementDbContextModelSnapshot.cs b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Migrations/TenantManagementDbContextModelSnapshot.cs new file mode 100644 index 0000000..767b42f --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Migrations/TenantManagementDbContextModelSnapshot.cs @@ -0,0 +1,2003 @@ +// +using System; +using KonSoft.TenantManagement.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace KonSoft.TenantManagement.Migrations +{ + [DbContext(typeof(TenantManagementDbContext))] + partial class TenantManagementDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("text"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("integer") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("smallint") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("uuid"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("EntityChangeId") + .HasColumnType("uuid"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsAbandoned") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("JobArgs") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)"); + + b.Property("JobName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LastTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("NextTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((byte)15); + + b.Property("TryCount") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((short)0); + + b.HasKey("Id"); + + b.HasIndex("IsAbandoned", "NextTryTime"); + + b.ToTable("AbpBackgroundJobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property("ValueType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("SourceTenantId") + .HasColumnType("uuid"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("TargetTenantId") + .HasColumnType("uuid"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique(); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("boolean") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("boolean") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("IpAddresses") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("LastAccessed") + .HasColumnType("timestamp without time zone"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("SignedIn") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("boolean"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("EndTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("StartTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("character varying(196)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("character varying(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ClientSecret") + .HasColumnType("text"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientUri") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JsonWebKeySet") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasColumnType("text"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedirectUris") + .HasColumnType("text"); + + b.Property("Requirements") + .HasColumnType("text"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Scopes") + .HasColumnType("text"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Descriptions") + .HasColumnType("text"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Resources") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AuthorizationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Payload") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("MultiTenancySide") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("boolean"); + + b.Property("IsInherited") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + + b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) + .WithMany() + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Properties/AssemblyInfo.cs b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..135e6af --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.EntityFrameworkCore/Properties/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("KonSoft.TenantManagement.EntityFrameworkCore.Tests")] diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi.Client/KonSoft.TenantManagement.HttpApi.Client.csproj b/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi.Client/KonSoft.TenantManagement.HttpApi.Client.csproj new file mode 100644 index 0000000..f7ec709 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi.Client/KonSoft.TenantManagement.HttpApi.Client.csproj @@ -0,0 +1,29 @@ + + + + + + net8.0 + enable + KonSoft.TenantManagement + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi.Client/TenantManagementHttpApiClientModule.cs b/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi.Client/TenantManagementHttpApiClientModule.cs new file mode 100644 index 0000000..ed63970 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi.Client/TenantManagementHttpApiClientModule.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.TenantManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.VirtualFileSystem; + +namespace KonSoft.TenantManagement; + +[DependsOn( + typeof(TenantManagementApplicationContractsModule), + typeof(AbpAccountHttpApiClientModule), + typeof(AbpIdentityHttpApiClientModule), + typeof(AbpPermissionManagementHttpApiClientModule), + typeof(AbpTenantManagementHttpApiClientModule), + typeof(AbpFeatureManagementHttpApiClientModule), + typeof(AbpSettingManagementHttpApiClientModule) +)] +public class TenantManagementHttpApiClientModule : AbpModule +{ + public const string RemoteServiceName = "Default"; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddHttpClientProxies( + typeof(TenantManagementApplicationContractsModule).Assembly, + RemoteServiceName + ); + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/Controllers/TenantManagementController.cs b/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/Controllers/TenantManagementController.cs new file mode 100644 index 0000000..e4b323b --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/Controllers/TenantManagementController.cs @@ -0,0 +1,14 @@ +using KonSoft.TenantManagement.Localization; +using Volo.Abp.AspNetCore.Mvc; + +namespace KonSoft.TenantManagement.Controllers; + +/* Inherit your controllers from this class. + */ +public abstract class TenantManagementController : AbpControllerBase +{ + protected TenantManagementController() + { + LocalizationResource = typeof(TenantManagementResource); + } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/KonSoft.TenantManagement.HttpApi.csproj b/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/KonSoft.TenantManagement.HttpApi.csproj new file mode 100644 index 0000000..f81b1e6 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/KonSoft.TenantManagement.HttpApi.csproj @@ -0,0 +1,24 @@ + + + + + + net8.0 + enable + KonSoft.TenantManagement + + + + + + + + + + + + + + + + diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/Models/Test/TestModel.cs b/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/Models/Test/TestModel.cs new file mode 100644 index 0000000..e790d7b --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/Models/Test/TestModel.cs @@ -0,0 +1,10 @@ +using System; + +namespace KonSoft.TenantManagement.Models.Test; + +public class TestModel +{ + public string? Name { get; set; } + + public DateTime BirthDate { get; set; } +} diff --git a/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/TenantManagementHttpApiModule.cs b/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/TenantManagementHttpApiModule.cs new file mode 100644 index 0000000..3e5bea8 --- /dev/null +++ b/modules/tenant-management/src/KonSoft.TenantManagement.HttpApi/TenantManagementHttpApiModule.cs @@ -0,0 +1,41 @@ +using Localization.Resources.AbpUi; +using KonSoft.TenantManagement.Localization; +using Volo.Abp.Account; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Identity; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement.HttpApi; +using Volo.Abp.SettingManagement; +using Volo.Abp.TenantManagement; + +namespace KonSoft.TenantManagement; + +[DependsOn( + typeof(TenantManagementApplicationContractsModule), + typeof(AbpAccountHttpApiModule), + typeof(AbpIdentityHttpApiModule), + typeof(AbpPermissionManagementHttpApiModule), + typeof(AbpTenantManagementHttpApiModule), + typeof(AbpFeatureManagementHttpApiModule), + typeof(AbpSettingManagementHttpApiModule) + )] +public class TenantManagementHttpApiModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + ConfigureLocalization(); + } + + private void ConfigureLocalization() + { + Configure(options => + { + options.Resources + .Get() + .AddBaseTypes( + typeof(AbpUiResource) + ); + }); + } +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/KonSoft.TenantManagement.Application.Tests.csproj b/modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/KonSoft.TenantManagement.Application.Tests.csproj new file mode 100644 index 0000000..9e3bdd2 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/KonSoft.TenantManagement.Application.Tests.csproj @@ -0,0 +1,20 @@ + + + + + + net8.0 + enable + KonSoft.TenantManagement + + + + + + + + + + + + diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/Samples/SampleAppServiceTests.cs b/modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/Samples/SampleAppServiceTests.cs new file mode 100644 index 0000000..a0ce7da --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/Samples/SampleAppServiceTests.cs @@ -0,0 +1,34 @@ +using Shouldly; +using System.Threading.Tasks; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Xunit; + +namespace KonSoft.TenantManagement.Samples; + +/* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IIdentityUserAppService here). + * Only test your own application services. + */ +public abstract class SampleAppServiceTests : TenantManagementApplicationTestBase + where TStartupModule : IAbpModule +{ + private readonly IIdentityUserAppService _userAppService; + + protected SampleAppServiceTests() + { + _userAppService = GetRequiredService(); + } + + [Fact] + public async Task Initial_Data_Should_Contain_Admin_User() + { + //Act + var result = await _userAppService.GetListAsync(new GetIdentityUsersInput()); + + //Assert + result.TotalCount.ShouldBeGreaterThan(0); + result.Items.ShouldContain(u => u.UserName == "admin"); + } +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/TenantManagementApplicationTestBase.cs b/modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/TenantManagementApplicationTestBase.cs new file mode 100644 index 0000000..e6b0448 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/TenantManagementApplicationTestBase.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.TenantManagement; + +public abstract class TenantManagementApplicationTestBase : TenantManagementTestBase + where TStartupModule : IAbpModule +{ + +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/TenantManagementApplicationTestModule.cs b/modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/TenantManagementApplicationTestModule.cs new file mode 100644 index 0000000..b57a624 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.Application.Tests/TenantManagementApplicationTestModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.TenantManagement; + +[DependsOn( + typeof(TenantManagementApplicationModule), + typeof(TenantManagementDomainTestModule) +)] +public class TenantManagementApplicationTestModule : AbpModule +{ + +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/KonSoft.TenantManagement.Domain.Tests.csproj b/modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/KonSoft.TenantManagement.Domain.Tests.csproj new file mode 100644 index 0000000..16c92b5 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/KonSoft.TenantManagement.Domain.Tests.csproj @@ -0,0 +1,20 @@ + + + + + + net8.0 + enable + KonSoft.TenantManagement + + + + + + + + + + + + diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/Samples/SampleDomainTests.cs b/modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/Samples/SampleDomainTests.cs new file mode 100644 index 0000000..c7a2b7b --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/Samples/SampleDomainTests.cs @@ -0,0 +1,46 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Identity; +using Volo.Abp.Modularity; +using Xunit; + +namespace KonSoft.TenantManagement.Samples; + +/* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IdentityUserManager here). + * Only test your own domain services. + */ +public abstract class SampleDomainTests : TenantManagementDomainTestBase + where TStartupModule : IAbpModule +{ + private readonly IIdentityUserRepository _identityUserRepository; + private readonly IdentityUserManager _identityUserManager; + + protected SampleDomainTests() + { + _identityUserRepository = GetRequiredService(); + _identityUserManager = GetRequiredService(); + } + + [Fact] + public async Task Should_Set_Email_Of_A_User() + { + IdentityUser adminUser; + + /* Need to manually start Unit Of Work because + * FirstOrDefaultAsync should be executed while db connection / context is available. + */ + await WithUnitOfWorkAsync(async () => + { + adminUser = await _identityUserRepository + .FindByNormalizedUserNameAsync("ADMIN"); + + await _identityUserManager.SetEmailAsync(adminUser, "newemail@abp.io"); + await _identityUserRepository.UpdateAsync(adminUser); + }); + + adminUser = await _identityUserRepository.FindByNormalizedUserNameAsync("ADMIN"); + adminUser.Email.ShouldBe("newemail@abp.io"); + } +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/TenantManagementDomainTestBase.cs b/modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/TenantManagementDomainTestBase.cs new file mode 100644 index 0000000..c73497f --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/TenantManagementDomainTestBase.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.TenantManagement; + +/* Inherit from this class for your domain layer tests. */ +public abstract class TenantManagementDomainTestBase : TenantManagementTestBase + where TStartupModule : IAbpModule +{ + +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/TenantManagementDomainTestModule.cs b/modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/TenantManagementDomainTestModule.cs new file mode 100644 index 0000000..6847984 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.Domain.Tests/TenantManagementDomainTestModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace KonSoft.TenantManagement; + +[DependsOn( + typeof(TenantManagementDomainModule), + typeof(TenantManagementTestBaseModule) +)] +public class TenantManagementDomainTestModule : AbpModule +{ + +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs new file mode 100644 index 0000000..a6e4e59 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/Applications/EfCoreSampleAppServiceTests.cs @@ -0,0 +1,10 @@ +using KonSoft.TenantManagement.Samples; +using Xunit; + +namespace KonSoft.TenantManagement.EntityFrameworkCore.Applications; + +[Collection(TenantManagementTestConsts.CollectionDefinitionName)] +public class EfCoreSampleAppServiceTests : SampleAppServiceTests +{ + +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs new file mode 100644 index 0000000..9fddfdc --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/Domains/EfCoreSampleDomainTests.cs @@ -0,0 +1,10 @@ +using KonSoft.TenantManagement.Samples; +using Xunit; + +namespace KonSoft.TenantManagement.EntityFrameworkCore.Domains; + +[Collection(TenantManagementTestConsts.CollectionDefinitionName)] +public class EfCoreSampleDomainTests : SampleDomainTests +{ + +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs new file mode 100644 index 0000000..239ff03 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Shouldly; +using System; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Identity; +using Xunit; + +namespace KonSoft.TenantManagement.EntityFrameworkCore.Samples; + +/* This is just an example test class. + * Normally, you don't test ABP framework code + * (like default AppUser repository IRepository here). + * Only test your custom repository methods. + */ +[Collection(TenantManagementTestConsts.CollectionDefinitionName)] +public class SampleRepositoryTests : TenantManagementEntityFrameworkCoreTestBase +{ + private readonly IRepository _appUserRepository; + + public SampleRepositoryTests() + { + _appUserRepository = GetRequiredService>(); + } + + [Fact] + public async Task Should_Query_AppUser() + { + /* Need to manually start Unit Of Work because + * FirstOrDefaultAsync should be executed while db connection / context is available. + */ + await WithUnitOfWorkAsync(async () => + { + //Act + var adminUser = await (await _appUserRepository.GetQueryableAsync()) + .Where(u => u.UserName == "admin") + .FirstOrDefaultAsync(); + + //Assert + adminUser.ShouldNotBeNull(); + }); + } +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreCollection.cs b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreCollection.cs new file mode 100644 index 0000000..060cb03 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreCollection.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace KonSoft.TenantManagement.EntityFrameworkCore; + +[CollectionDefinition(TenantManagementTestConsts.CollectionDefinitionName)] +public class TenantManagementEntityFrameworkCoreCollection : ICollectionFixture +{ + +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreCollectionFixtureBase.cs b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreCollectionFixtureBase.cs new file mode 100644 index 0000000..850ce94 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreCollectionFixtureBase.cs @@ -0,0 +1,9 @@ +using KonSoft.TenantManagement.EntityFrameworkCore; +using Xunit; + +namespace KonSoft.TenantManagement.EntityFrameworkCore; + +public class TenantManagementEntityFrameworkCoreCollectionFixtureBase : ICollectionFixture +{ + +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreFixture.cs b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreFixture.cs new file mode 100644 index 0000000..f4b25a7 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreFixture.cs @@ -0,0 +1,11 @@ +using System; + +namespace KonSoft.TenantManagement.EntityFrameworkCore; + +public class TenantManagementEntityFrameworkCoreFixture : IDisposable +{ + public void Dispose() + { + + } +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreTestBase.cs b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreTestBase.cs new file mode 100644 index 0000000..89a75dd --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreTestBase.cs @@ -0,0 +1,8 @@ +using Volo.Abp; + +namespace KonSoft.TenantManagement.EntityFrameworkCore; + +public abstract class TenantManagementEntityFrameworkCoreTestBase : TenantManagementTestBase +{ + +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreTestModule.cs b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreTestModule.cs new file mode 100644 index 0000000..9a4e308 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/EntityFrameworkCore/TenantManagementEntityFrameworkCoreTestModule.cs @@ -0,0 +1,82 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.Sqlite; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.Uow; + +namespace KonSoft.TenantManagement.EntityFrameworkCore; + +[DependsOn( + typeof(TenantManagementApplicationTestModule), + typeof(TenantManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCoreSqliteModule) + )] +public class TenantManagementEntityFrameworkCoreTestModule : AbpModule +{ + private SqliteConnection? _sqliteConnection; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.SaveStaticFeaturesToDatabase = false; + options.IsDynamicFeatureStoreEnabled = false; + }); + Configure(options => + { + options.SaveStaticPermissionsToDatabase = false; + options.IsDynamicPermissionStoreEnabled = false; + }); + Configure(options => + { + options.SaveStaticSettingsToDatabase = false; + options.IsDynamicSettingStoreEnabled = false; + }); + context.Services.AddAlwaysDisableUnitOfWorkTransaction(); + + ConfigureInMemorySqlite(context.Services); + } + + private void ConfigureInMemorySqlite(IServiceCollection services) + { + _sqliteConnection = CreateDatabaseAndGetConnection(); + + services.Configure(options => + { + options.Configure(context => + { + context.DbContextOptions.UseSqlite(_sqliteConnection); + }); + }); + } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + _sqliteConnection?.Dispose(); + } + + private static SqliteConnection CreateDatabaseAndGetConnection() + { + var connection = new AbpUnitTestSqliteConnection("Data Source=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new TenantManagementDbContext(options)) + { + context.GetService().CreateTables(); + } + + return connection; + } +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/KonSoft.TenantManagement.EntityFrameworkCore.Tests.csproj b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/KonSoft.TenantManagement.EntityFrameworkCore.Tests.csproj new file mode 100644 index 0000000..f77824c --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.EntityFrameworkCore.Tests/KonSoft.TenantManagement.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,21 @@ + + + + + + net8.0 + enable + KonSoft.TenantManagement + + + + + + + + + + + + + diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs new file mode 100644 index 0000000..a388b25 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs @@ -0,0 +1,25 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Account; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp; + +public class ClientDemoService : ITransientDependency +{ + private readonly IProfileAppService _profileAppService; + + public ClientDemoService(IProfileAppService profileAppService) + { + _profileAppService = profileAppService; + } + + public async Task RunAsync() + { + var output = await _profileAppService.GetAsync(); + Console.WriteLine($"UserName : {output.UserName}"); + Console.WriteLine($"Email : {output.Email}"); + Console.WriteLine($"Name : {output.Name}"); + Console.WriteLine($"Surname : {output.Surname}"); + } +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs new file mode 100644 index 0000000..9c4f85a --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.Hosting; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; + +namespace KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp; + +public class ConsoleTestAppHostedService : IHostedService +{ + private readonly IConfiguration _configuration; + + public ConsoleTestAppHostedService(IConfiguration configuration) + { + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using (var application = await AbpApplicationFactory.CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + })) + { + await application.InitializeAsync(); + + var demo = application.ServiceProvider.GetRequiredService(); + await demo.RunAsync(); + + await application.ShutdownAsync(); + } + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp.csproj b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp.csproj new file mode 100644 index 0000000..b2b2c45 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp.csproj @@ -0,0 +1,33 @@ + + + + Exe + net8.0 + enable + + + + + + PreserveNewest + Always + + + + PreserveNewest + Always + + + + + + + + + + + + + + + diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/Program.cs b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/Program.cs new file mode 100644 index 0000000..d836b73 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/Program.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp; + +class Program +{ + static async Task Main(string[] args) + { + await CreateHostBuilder(args).RunConsoleAsync(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .AddAppSettingsSecretsJson() + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/TenantManagementConsoleApiClientModule.cs b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/TenantManagementConsoleApiClientModule.cs new file mode 100644 index 0000000..a265cfd --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/TenantManagementConsoleApiClientModule.cs @@ -0,0 +1,30 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Polly; +using Volo.Abp.Autofac; +using Volo.Abp.Http.Client; +using Volo.Abp.Http.Client.IdentityModel; +using Volo.Abp.Modularity; + +namespace KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(TenantManagementHttpApiClientModule), + typeof(AbpHttpClientIdentityModelModule) + )] +public class TenantManagementConsoleApiClientModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(options => + { + options.ProxyClientBuildActions.Add((remoteServiceName, clientBuilder) => + { + clientBuilder.AddTransientHttpErrorPolicy( + policyBuilder => policyBuilder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i))) + ); + }); + }); + } +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/appsettings.json b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/appsettings.json new file mode 100644 index 0000000..7073b87 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/appsettings.json @@ -0,0 +1,17 @@ +{ + "RemoteServices": { + "Default": { + "BaseUrl": "https://localhost:44316" + } + }, + "IdentityClients": { + "Default": { + "GrantType": "password", + "ClientId": "TenantManagement_App", + "UserName": "admin", + "UserPassword": "1q2w3E*", + "Authority": "https://localhost:44316", + "Scope": "TenantManagement" + } + } +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/KonSoft.TenantManagement.TestBase.csproj b/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/KonSoft.TenantManagement.TestBase.csproj new file mode 100644 index 0000000..d7742e1 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/KonSoft.TenantManagement.TestBase.csproj @@ -0,0 +1,31 @@ + + + + + + net8.0 + enable + KonSoft.TenantManagement + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/Security/FakeCurrentPrincipalAccessor.cs b/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/Security/FakeCurrentPrincipalAccessor.cs new file mode 100644 index 0000000..e08ed88 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/Security/FakeCurrentPrincipalAccessor.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Security.Claims; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Claims; + +namespace KonSoft.TenantManagement.Security; + +[Dependency(ReplaceServices = true)] +public class FakeCurrentPrincipalAccessor : ThreadCurrentPrincipalAccessor +{ + protected override ClaimsPrincipal GetClaimsPrincipal() + { + return GetPrincipal(); + } + + private ClaimsPrincipal GetPrincipal() + { + return new ClaimsPrincipal(new ClaimsIdentity(new List + { + new Claim(AbpClaimTypes.UserId, "2e701e62-0953-4dd3-910b-dc6cc93ccb0d"), + new Claim(AbpClaimTypes.UserName, "admin"), + new Claim(AbpClaimTypes.Email, "admin@abp.io") + })); + } +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestBase.cs b/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestBase.cs new file mode 100644 index 0000000..b5e1fbe --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestBase.cs @@ -0,0 +1,60 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Modularity; +using Volo.Abp.Uow; +using Volo.Abp.Testing; + +namespace KonSoft.TenantManagement; + +/* All test classes are derived from this class, directly or indirectly. + */ +public abstract class TenantManagementTestBase : AbpIntegratedTest + where TStartupModule : IAbpModule +{ + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + protected virtual Task WithUnitOfWorkAsync(Func func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func action) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + await action(); + + await uow.CompleteAsync(); + } + } + } + + protected virtual Task WithUnitOfWorkAsync(Func> func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func> func) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + var result = await func(); + await uow.CompleteAsync(); + return result; + } + } + } +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestBaseModule.cs b/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestBaseModule.cs new file mode 100644 index 0000000..2ed6282 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestBaseModule.cs @@ -0,0 +1,47 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Authorization; +using Volo.Abp.Autofac; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Abp.Threading; + +namespace KonSoft.TenantManagement; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpTestBaseModule), + typeof(AbpAuthorizationModule), + typeof(AbpBackgroundJobsAbstractionsModule) + )] +public class TenantManagementTestBaseModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.IsJobExecutionEnabled = false; + }); + + context.Services.AddAlwaysAllowAuthorization(); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + AsyncHelper.RunSync(async () => + { + using (var scope = context.ServiceProvider.CreateScope()) + { + await scope.ServiceProvider + .GetRequiredService() + .SeedAsync(); + } + }); + } +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestConsts.cs b/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestConsts.cs new file mode 100644 index 0000000..fbb37d2 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestConsts.cs @@ -0,0 +1,6 @@ +namespace KonSoft.TenantManagement; + +public static class TenantManagementTestConsts +{ + public const string CollectionDefinitionName = "TenantManagement collection"; +} diff --git a/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestDataSeedContributor.cs b/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestDataSeedContributor.cs new file mode 100644 index 0000000..ffc9d62 --- /dev/null +++ b/modules/tenant-management/test/KonSoft.TenantManagement.TestBase/TenantManagementTestDataSeedContributor.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; + +namespace KonSoft.TenantManagement; + +public class TenantManagementTestDataSeedContributor : IDataSeedContributor, ITransientDependency +{ + public Task SeedAsync(DataSeedContext context) + { + /* Seed additional test data... */ + + return Task.CompletedTask; + } +} diff --git a/shared/KonSoft.Shared/Class1.cs b/shared/KonSoft.Shared/Class1.cs new file mode 100644 index 0000000..3a4e8b4 --- /dev/null +++ b/shared/KonSoft.Shared/Class1.cs @@ -0,0 +1,7 @@ +namespace KonSoft.Shared +{ + public class Class1 + { + + } +} diff --git a/shared/KonSoft.Shared/KonSoft.Shared.csproj b/shared/KonSoft.Shared/KonSoft.Shared.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/shared/KonSoft.Shared/KonSoft.Shared.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + +