Compare commits

...

7 Commits

26 changed files with 311 additions and 874 deletions

View File

@ -1,7 +1,6 @@
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER $APP_UID
WORKDIR /app
EXPOSE 8080
EXPOSE 8081
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
@ -9,15 +8,21 @@ ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["NuGet.Config", "."]
COPY ["applications/KonSoft.AuthServer/KonSoft.AuthServer.csproj", "applications/KonSoft.AuthServer/"]
COPY ["shared/KonSoft.Shared.Hosting.Microservices/KonSoft.Shared.Hosting.Microservices.csproj", "shared/KonSoft.Shared.Hosting.Microservices/"]
COPY ["shared/KonSoft.Shared.Hosting.AspNetCore/KonSoft.Shared.Hosting.AspNetCore.csproj", "shared/KonSoft.Shared.Hosting.AspNetCore/"]
COPY ["shared/KonSoft.Shared.Hosting/KonSoft.Shared.Hosting.csproj", "shared/KonSoft.Shared.Hosting/"]
COPY ["shared/KonSoft.Shared.Localization/KonSoft.Shared.Localization.csproj", "shared/KonSoft.Shared.Localization/"]
RUN dotnet restore "./applications/KonSoft.AuthServer/KonSoft.AuthServer.csproj"
COPY . .
WORKDIR "/src/applications/KonSoft.AuthServer"
RUN dotnet build "./KonSoft.AuthServer.csproj" -c $BUILD_CONFIGURATION -o /app/build
# 此阶段用于发布要复制到最终阶段的服务项目
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./KonSoft.AuthServer.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
# 此阶段在生产中使用,或在常规模式下从 VS 运行时使用(在不使用调试配置时为默认值)
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .

View File

@ -39,22 +39,11 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.22.1" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.4" />
<PackageReference Include="DistributedLock.Redis" Version="1.0.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.22.1" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic" Version="8.3.4" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Autofac" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="8.3.4" />
<PackageReference Include="Volo.Abp.DistributedLocking" Version="8.3.4" />
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Account.Web.OpenIddict" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Account.Application" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Account.HttpApi" Version="8.3.4" />

View File

@ -1,38 +1,13 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"KonSoft.AuthServer": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:44322"
},
"Container (Dockerfile)": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
"environmentVariables": {
"ASPNETCORE_HTTPS_PORTS": "8081",
"ASPNETCORE_HTTP_PORTS": "8080"
},
"publishAllPorts": true,
"useSSL": true
}
},
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:44322",
"sslPort": 44322
}
}
}

View File

@ -1,13 +1,5 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:4773",
"sslPort": 44380
}
},
"profiles": {
"http": {
"commandName": "Project",
@ -18,24 +10,6 @@
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7094;http://localhost:5243",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -1,13 +1,5 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:22937",
"sslPort": 44300
}
},
"profiles": {
"http": {
"commandName": "Project",
@ -18,24 +10,6 @@
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7183;http://localhost:5074",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,14 @@
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
namespace KonSoft.Admin.DbMigrations
{
public class AdminDataSeeder : IDataSeedContributor, ITransientDependency
{
public Task SeedAsync(DataSeedContext context)
{
return Task.CompletedTask;
}
}
}

View File

@ -0,0 +1,26 @@
using System;
using KonSoft.Admin.EntityFrameworkCore;
using KonSoft.Shared.Hosting.Microservices.DbMigrations.EfCore;
using Volo.Abp.DistributedLocking;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
namespace KonSoft.Admin.DbMigrations
{
public class AdminPendingEfCoreMigrationsChecker : PendingEfCoreMigrationsChecker<AdminDbContext>
{
public AdminPendingEfCoreMigrationsChecker(IUnitOfWorkManager unitOfWorkManager,
IServiceProvider serviceProvider,
ICurrentTenant currentTenant,
IDistributedEventBus distributedEventBus,
IAbpDistributedLock abpDistributedLock) : base(unitOfWorkManager,
serviceProvider,
currentTenant,
distributedEventBus,
abpDistributedLock,
"Clean")
{
}
}
}

View File

@ -2,8 +2,9 @@ FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER $APP_UID
WORKDIR /app
EXPOSE 8080
EXPOSE 8081
# 此阶段用于生成服务项目
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
@ -15,6 +16,10 @@ COPY ["modules/admin/src/KonSoft.Admin.Domain.Shared/KonSoft.Admin.Domain.Shared
COPY ["modules/admin/src/KonSoft.Admin.Application.Contracts/KonSoft.Admin.Application.Contracts.csproj", "modules/admin/src/KonSoft.Admin.Application.Contracts/"]
COPY ["modules/admin/src/KonSoft.Admin.EntityFrameworkCore/KonSoft.Admin.EntityFrameworkCore.csproj", "modules/admin/src/KonSoft.Admin.EntityFrameworkCore/"]
COPY ["modules/admin/src/KonSoft.Admin.HttpApi/KonSoft.Admin.HttpApi.csproj", "modules/admin/src/KonSoft.Admin.HttpApi/"]
COPY ["shared/KonSoft.Shared.Hosting.Microservices/KonSoft.Shared.Hosting.Microservices.csproj", "shared/KonSoft.Shared.Hosting.Microservices/"]
COPY ["shared/KonSoft.Shared.Hosting.AspNetCore/KonSoft.Shared.Hosting.AspNetCore.csproj", "shared/KonSoft.Shared.Hosting.AspNetCore/"]
COPY ["shared/KonSoft.Shared.Hosting/KonSoft.Shared.Hosting.csproj", "shared/KonSoft.Shared.Hosting/"]
COPY ["shared/KonSoft.Shared.Localization/KonSoft.Shared.Localization.csproj", "shared/KonSoft.Shared.Localization/"]
RUN dotnet restore "./microservices/KonSoft.Admin.HttpApi.Host/KonSoft.Admin.HttpApi.Host.csproj"
COPY . .
WORKDIR "/src/microservices/KonSoft.Admin.HttpApi.Host"

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>

View File

@ -1,23 +1,13 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"KonSoft.Admin.HttpApi.Host": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:44354"
},
"Container (Dockerfile)": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
"environmentVariables": {
"ASPNETCORE_HTTPS_PORTS": "8081",
"ASPNETCORE_HTTP_PORTS": "8080"
},
"publishAllPorts": true,
"useSSL": true
}
}
}

View File

@ -1,179 +1,38 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Medallion.Threading;
using Medallion.Threading.Redis;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using KonSoft.Dispatch.EntityFrameworkCore;
using KonSoft.Shared.Hosting.AspNetCore;
using KonSoft.Shared.Hosting.Microservices;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using KonSoft.Dispatch.EntityFrameworkCore;
using KonSoft.Dispatch.MultiTenancy;
using StackExchange.Redis;
using Microsoft.OpenApi.Models;
using Volo.Abp;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.Caching;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.DistributedLocking;
using Volo.Abp.Identity;
using Volo.Abp.Localization;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Swashbuckle;
using Volo.Abp.VirtualFileSystem;
namespace KonSoft.Dispatch;
[DependsOn(
typeof(DispatchHttpApiModule),
typeof(AbpAutofacModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpDistributedLockingModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(DispatchApplicationModule),
typeof(DispatchEntityFrameworkCoreModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpSwashbuckleModule)
typeof(KonSoftSharedHostingMicroservicesModule)
)]
public class DispatchHttpApiHostModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();
ConfigureConventionalControllers();
ConfigureAuthentication(context, configuration);
ConfigureCache(configuration);
ConfigureVirtualFileSystem(context);
ConfigureDataProtection(context, configuration, hostingEnvironment);
ConfigureDistributedLocking(context, configuration);
ConfigureCors(context, configuration);
ConfigureSwaggerServices(context, configuration);
}
SwaggerConfigurationHelper.ConfigureWithOidc(
context: context,
authority: configuration["AuthServer:Authority"]!,
scopes: ["DispatchService"],
discoveryEndpoint: configuration["AuthServer:MetadataAddress"],
apiTitle: "Dispatch Service API"
);
private void ConfigureCache(IConfiguration configuration)
{
Configure<AbpDistributedCacheOptions>(options => { options.KeyPrefix = "Dispatch:"; });
}
private void ConfigureVirtualFileSystem(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
if (hostingEnvironment.IsDevelopment())
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.ReplaceEmbeddedByPhysical<DispatchDomainSharedModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.Dispatch.Domain.Shared"));
options.FileSets.ReplaceEmbeddedByPhysical<DispatchDomainModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.Dispatch.Domain"));
options.FileSets.ReplaceEmbeddedByPhysical<DispatchApplicationContractsModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.Dispatch.Application.Contracts"));
options.FileSets.ReplaceEmbeddedByPhysical<DispatchApplicationModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.Dispatch.Application"));
});
}
}
private void ConfigureConventionalControllers()
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(DispatchApplicationModule).Assembly);
});
}
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddAbpJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata");
options.Audience = "Dispatch";
});
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
}
private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAbpSwaggerGenWithOAuth(
configuration["AuthServer:Authority"]!,
new Dictionary<string, string>
{
{"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 ConfigureDataProtection(
ServiceConfigurationContext context,
IConfiguration configuration,
IWebHostEnvironment hostingEnvironment)
{
var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("Dispatch");
if (!hostingEnvironment.IsDevelopment())
{
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "Dispatch-Protection-Keys");
}
}
private void ConfigureDistributedLocking(
ServiceConfigurationContext context,
IConfiguration configuration)
{
context.Services.AddSingleton<IDistributedLockProvider>(sp =>
{
var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
return new RedisDistributedSynchronizationProvider(connection.GetDatabase());
});
}
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() ?? [])
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
// ֻ<><D6BB><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>
Configure<AbpBackgroundJobOptions>(options => options.IsJobExecutionEnabled = false);
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
@ -193,7 +52,7 @@ public class DispatchHttpApiHostModule : AbpModule
app.UseCors();
app.UseAuthentication();
if (MultiTenancyConsts.IsEnabled)
if (KonSoftConsts.MultiTenancyEnabled)
{
app.UseMultiTenancy();
}

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
@ -8,21 +8,6 @@
<UserSecretsId>KonSoft.Dispatch-4681b4fd-151f-4221-84a4-929d86723e4c</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.4" />
<PackageReference Include="DistributedLock.Redis" Version="1.0.2" />
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="8.3.4" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Autofac" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="8.3.4" />
<PackageReference Include="Volo.Abp.DistributedLocking" Version="8.3.4" />
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Swashbuckle" Version="8.3.4" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Logs\**" />
<Content Remove="Logs\**" />
@ -34,6 +19,7 @@
<ProjectReference Include="..\..\modules\dispatch\src\KonSoft.Dispatch.Application\KonSoft.Dispatch.Application.csproj" />
<ProjectReference Include="..\..\modules\dispatch\src\KonSoft.Dispatch.EntityFrameworkCore\KonSoft.Dispatch.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\modules\dispatch\src\KonSoft.Dispatch.HttpApi\KonSoft.Dispatch.HttpApi.csproj" />
<ProjectReference Include="..\..\shared\KonSoft.Shared.Hosting.Microservices\KonSoft.Shared.Hosting.Microservices.csproj" />
</ItemGroup>
</Project>

View File

@ -1,27 +1,13 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:44331",
"sslPort": 44331
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"KonSoft.Dispatch.HttpApi.Host": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:44331",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"applicationUrl": "https://localhost:44331"
}
}
}

View File

@ -8,21 +8,6 @@
<UserSecretsId>KonSoft.Payment-4681b4fd-151f-4221-84a4-929d86723e4c</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.4" />
<PackageReference Include="DistributedLock.Redis" Version="1.0.2" />
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="8.3.4" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Autofac" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="8.3.4" />
<PackageReference Include="Volo.Abp.DistributedLocking" Version="8.3.4" />
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Swashbuckle" Version="8.3.4" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Logs\**" />
<Content Remove="Logs\**" />
@ -34,6 +19,7 @@
<ProjectReference Include="..\..\modules\payment\src\KonSoft.Payment.Application\KonSoft.Payment.Application.csproj" />
<ProjectReference Include="..\..\modules\payment\src\KonSoft.Payment.EntityFrameworkCore\KonSoft.Payment.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\modules\payment\src\KonSoft.Payment.HttpApi\KonSoft.Payment.HttpApi.csproj" />
<ProjectReference Include="..\..\shared\KonSoft.Shared.Hosting.Microservices\KonSoft.Shared.Hosting.Microservices.csproj" />
</ItemGroup>
</Project>

View File

@ -1,179 +1,38 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Medallion.Threading;
using Medallion.Threading.Redis;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using KonSoft.Payment.EntityFrameworkCore;
using KonSoft.Shared.Hosting.AspNetCore;
using KonSoft.Shared.Hosting.Microservices;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using KonSoft.Payment.EntityFrameworkCore;
using KonSoft.Payment.MultiTenancy;
using StackExchange.Redis;
using Microsoft.OpenApi.Models;
using Volo.Abp;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.Caching;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.DistributedLocking;
using Volo.Abp.Identity;
using Volo.Abp.Localization;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Swashbuckle;
using Volo.Abp.VirtualFileSystem;
namespace KonSoft.Payment;
[DependsOn(
typeof(PaymentHttpApiModule),
typeof(AbpAutofacModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpDistributedLockingModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(PaymentApplicationModule),
typeof(PaymentEntityFrameworkCoreModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpSwashbuckleModule)
typeof(KonSoftSharedHostingMicroservicesModule)
)]
public class PaymentHttpApiHostModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();
ConfigureConventionalControllers();
ConfigureAuthentication(context, configuration);
ConfigureCache(configuration);
ConfigureVirtualFileSystem(context);
ConfigureDataProtection(context, configuration, hostingEnvironment);
ConfigureDistributedLocking(context, configuration);
ConfigureCors(context, configuration);
ConfigureSwaggerServices(context, configuration);
}
SwaggerConfigurationHelper.ConfigureWithOidc(
context: context,
authority: configuration["AuthServer:Authority"]!,
scopes: ["PaymentService"],
discoveryEndpoint: configuration["AuthServer:MetadataAddress"],
apiTitle: "Payment Service API"
);
private void ConfigureCache(IConfiguration configuration)
{
Configure<AbpDistributedCacheOptions>(options => { options.KeyPrefix = "Payment:"; });
}
private void ConfigureVirtualFileSystem(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
if (hostingEnvironment.IsDevelopment())
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.ReplaceEmbeddedByPhysical<PaymentDomainSharedModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.Payment.Domain.Shared"));
options.FileSets.ReplaceEmbeddedByPhysical<PaymentDomainModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.Payment.Domain"));
options.FileSets.ReplaceEmbeddedByPhysical<PaymentApplicationContractsModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.Payment.Application.Contracts"));
options.FileSets.ReplaceEmbeddedByPhysical<PaymentApplicationModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.Payment.Application"));
});
}
}
private void ConfigureConventionalControllers()
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(PaymentApplicationModule).Assembly);
});
}
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddAbpJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata");
options.Audience = "Payment";
});
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
}
private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAbpSwaggerGenWithOAuth(
configuration["AuthServer:Authority"]!,
new Dictionary<string, string>
{
{"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 ConfigureDataProtection(
ServiceConfigurationContext context,
IConfiguration configuration,
IWebHostEnvironment hostingEnvironment)
{
var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("Payment");
if (!hostingEnvironment.IsDevelopment())
{
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "Payment-Protection-Keys");
}
}
private void ConfigureDistributedLocking(
ServiceConfigurationContext context,
IConfiguration configuration)
{
context.Services.AddSingleton<IDistributedLockProvider>(sp =>
{
var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
return new RedisDistributedSynchronizationProvider(connection.GetDatabase());
});
}
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() ?? [])
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
// ֻ<><D6BB><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>
Configure<AbpBackgroundJobOptions>(options => options.IsJobExecutionEnabled = false);
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
@ -193,7 +52,7 @@ public class PaymentHttpApiHostModule : AbpModule
app.UseCors();
app.UseAuthentication();
if (MultiTenancyConsts.IsEnabled)
if (KonSoftConsts.MultiTenancyEnabled)
{
app.UseMultiTenancy();
}

View File

@ -1,27 +1,13 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:44326",
"sslPort": 44326
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"KonSoft.Payment.HttpApi.Host": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:44326",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"applicationUrl": "https://localhost:44326"
}
}
}

View File

@ -8,21 +8,6 @@
<UserSecretsId>KonSoft.Report-4681b4fd-151f-4221-84a4-929d86723e4c</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.4" />
<PackageReference Include="DistributedLock.Redis" Version="1.0.2" />
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="8.3.4" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Autofac" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="8.3.4" />
<PackageReference Include="Volo.Abp.DistributedLocking" Version="8.3.4" />
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Swashbuckle" Version="8.3.4" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Logs\**" />
<Content Remove="Logs\**" />
@ -34,6 +19,7 @@
<ProjectReference Include="..\..\modules\report\src\KonSoft.Report.Application\KonSoft.Report.Application.csproj" />
<ProjectReference Include="..\..\modules\report\src\KonSoft.Report.EntityFrameworkCore\KonSoft.Report.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\modules\report\src\KonSoft.Report.HttpApi\KonSoft.Report.HttpApi.csproj" />
<ProjectReference Include="..\..\shared\KonSoft.Shared.Hosting.Microservices\KonSoft.Shared.Hosting.Microservices.csproj" />
</ItemGroup>
</Project>

View File

@ -1,27 +1,13 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:44320",
"sslPort": 44320
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"KonSoft.Report.HttpApi.Host": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:44320",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"applicationUrl": "https://localhost:44320"
}
}
}

View File

@ -1,179 +1,38 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Medallion.Threading;
using Medallion.Threading.Redis;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using KonSoft.Report.EntityFrameworkCore;
using KonSoft.Shared.Hosting.AspNetCore;
using KonSoft.Shared.Hosting.Microservices;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using KonSoft.Report.EntityFrameworkCore;
using KonSoft.Report.MultiTenancy;
using StackExchange.Redis;
using Microsoft.OpenApi.Models;
using Volo.Abp;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.Caching;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.DistributedLocking;
using Volo.Abp.Identity;
using Volo.Abp.Localization;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Swashbuckle;
using Volo.Abp.VirtualFileSystem;
namespace KonSoft.Report;
[DependsOn(
typeof(ReportHttpApiModule),
typeof(AbpAutofacModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpDistributedLockingModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(ReportApplicationModule),
typeof(ReportEntityFrameworkCoreModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpSwashbuckleModule)
typeof(KonSoftSharedHostingMicroservicesModule)
)]
public class ReportHttpApiHostModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();
ConfigureConventionalControllers();
ConfigureAuthentication(context, configuration);
ConfigureCache(configuration);
ConfigureVirtualFileSystem(context);
ConfigureDataProtection(context, configuration, hostingEnvironment);
ConfigureDistributedLocking(context, configuration);
ConfigureCors(context, configuration);
ConfigureSwaggerServices(context, configuration);
}
SwaggerConfigurationHelper.ConfigureWithOidc(
context: context,
authority: configuration["AuthServer:Authority"]!,
scopes: ["ReportService"],
discoveryEndpoint: configuration["AuthServer:MetadataAddress"],
apiTitle: "Report Service API"
);
private void ConfigureCache(IConfiguration configuration)
{
Configure<AbpDistributedCacheOptions>(options => { options.KeyPrefix = "Report:"; });
}
private void ConfigureVirtualFileSystem(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
if (hostingEnvironment.IsDevelopment())
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.ReplaceEmbeddedByPhysical<ReportDomainSharedModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.Report.Domain.Shared"));
options.FileSets.ReplaceEmbeddedByPhysical<ReportDomainModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.Report.Domain"));
options.FileSets.ReplaceEmbeddedByPhysical<ReportApplicationContractsModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.Report.Application.Contracts"));
options.FileSets.ReplaceEmbeddedByPhysical<ReportApplicationModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.Report.Application"));
});
}
}
private void ConfigureConventionalControllers()
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(ReportApplicationModule).Assembly);
});
}
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddAbpJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata");
options.Audience = "Report";
});
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
}
private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAbpSwaggerGenWithOAuth(
configuration["AuthServer:Authority"]!,
new Dictionary<string, string>
{
{"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 ConfigureDataProtection(
ServiceConfigurationContext context,
IConfiguration configuration,
IWebHostEnvironment hostingEnvironment)
{
var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("Report");
if (!hostingEnvironment.IsDevelopment())
{
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "Report-Protection-Keys");
}
}
private void ConfigureDistributedLocking(
ServiceConfigurationContext context,
IConfiguration configuration)
{
context.Services.AddSingleton<IDistributedLockProvider>(sp =>
{
var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
return new RedisDistributedSynchronizationProvider(connection.GetDatabase());
});
}
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() ?? [])
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
// ֻ<><D6BB><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>
Configure<AbpBackgroundJobOptions>(options => options.IsJobExecutionEnabled = false);
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
@ -193,7 +52,7 @@ public class ReportHttpApiHostModule : AbpModule
app.UseCors();
app.UseAuthentication();
if (MultiTenancyConsts.IsEnabled)
if (KonSoftConsts.MultiTenancyEnabled)
{
app.UseMultiTenancy();
}

View File

@ -8,21 +8,6 @@
<UserSecretsId>KonSoft.TenantManagement-4681b4fd-151f-4221-84a4-929d86723e4c</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.4" />
<PackageReference Include="DistributedLock.Redis" Version="1.0.2" />
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="8.3.4" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Autofac" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="8.3.4" />
<PackageReference Include="Volo.Abp.DistributedLocking" Version="8.3.4" />
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="8.3.4" />
<PackageReference Include="Volo.Abp.Swashbuckle" Version="8.3.4" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Logs\**" />
<Content Remove="Logs\**" />
@ -34,6 +19,7 @@
<ProjectReference Include="..\..\modules\tenant-management\src\KonSoft.TenantManagement.Application\KonSoft.TenantManagement.Application.csproj" />
<ProjectReference Include="..\..\modules\tenant-management\src\KonSoft.TenantManagement.EntityFrameworkCore\KonSoft.TenantManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\modules\tenant-management\src\KonSoft.TenantManagement.HttpApi\KonSoft.TenantManagement.HttpApi.csproj" />
<ProjectReference Include="..\..\shared\KonSoft.Shared.Hosting.Microservices\KonSoft.Shared.Hosting.Microservices.csproj" />
</ItemGroup>
</Project>

View File

@ -1,27 +1,13 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:44348",
"sslPort": 44348
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"KonSoft.TenantManagement.HttpApi.Host": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:44348",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"applicationUrl": "https://localhost:44348"
}
}
}

View File

@ -1,179 +1,38 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Medallion.Threading;
using Medallion.Threading.Redis;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using KonSoft.Shared.Hosting.AspNetCore;
using KonSoft.Shared.Hosting.Microservices;
using KonSoft.TenantManagement.EntityFrameworkCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using KonSoft.TenantManagement.EntityFrameworkCore;
using KonSoft.TenantManagement.MultiTenancy;
using StackExchange.Redis;
using Microsoft.OpenApi.Models;
using Volo.Abp;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.Caching;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.DistributedLocking;
using Volo.Abp.Identity;
using Volo.Abp.Localization;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Swashbuckle;
using Volo.Abp.VirtualFileSystem;
namespace KonSoft.TenantManagement;
[DependsOn(
typeof(TenantManagementHttpApiModule),
typeof(AbpAutofacModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpDistributedLockingModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(TenantManagementApplicationModule),
typeof(TenantManagementEntityFrameworkCoreModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpSwashbuckleModule)
typeof(KonSoftSharedHostingMicroservicesModule)
)]
public class TenantManagementHttpApiHostModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();
ConfigureConventionalControllers();
ConfigureAuthentication(context, configuration);
ConfigureCache(configuration);
ConfigureVirtualFileSystem(context);
ConfigureDataProtection(context, configuration, hostingEnvironment);
ConfigureDistributedLocking(context, configuration);
ConfigureCors(context, configuration);
ConfigureSwaggerServices(context, configuration);
}
SwaggerConfigurationHelper.ConfigureWithOidc(
context: context,
authority: configuration["AuthServer:Authority"]!,
scopes: ["TenantManagementService"],
discoveryEndpoint: configuration["AuthServer:MetadataAddress"],
apiTitle: "TenantManagement Service API"
);
private void ConfigureCache(IConfiguration configuration)
{
Configure<AbpDistributedCacheOptions>(options => { options.KeyPrefix = "TenantManagement:"; });
}
private void ConfigureVirtualFileSystem(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
if (hostingEnvironment.IsDevelopment())
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.ReplaceEmbeddedByPhysical<TenantManagementDomainSharedModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.TenantManagement.Domain.Shared"));
options.FileSets.ReplaceEmbeddedByPhysical<TenantManagementDomainModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.TenantManagement.Domain"));
options.FileSets.ReplaceEmbeddedByPhysical<TenantManagementApplicationContractsModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.TenantManagement.Application.Contracts"));
options.FileSets.ReplaceEmbeddedByPhysical<TenantManagementApplicationModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}KonSoft.TenantManagement.Application"));
});
}
}
private void ConfigureConventionalControllers()
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(TenantManagementApplicationModule).Assembly);
});
}
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddAbpJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata");
options.Audience = "TenantManagement";
});
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
}
private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAbpSwaggerGenWithOAuth(
configuration["AuthServer:Authority"]!,
new Dictionary<string, string>
{
{"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 ConfigureDataProtection(
ServiceConfigurationContext context,
IConfiguration configuration,
IWebHostEnvironment hostingEnvironment)
{
var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("TenantManagement");
if (!hostingEnvironment.IsDevelopment())
{
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "TenantManagement-Protection-Keys");
}
}
private void ConfigureDistributedLocking(
ServiceConfigurationContext context,
IConfiguration configuration)
{
context.Services.AddSingleton<IDistributedLockProvider>(sp =>
{
var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
return new RedisDistributedSynchronizationProvider(connection.GetDatabase());
});
}
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() ?? [])
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
// ֻ<><D6BB><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>
Configure<AbpBackgroundJobOptions>(options => options.IsJobExecutionEnabled = false);
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
@ -193,7 +52,7 @@ public class TenantManagementHttpApiHostModule : AbpModule
app.UseCors();
app.UseAuthentication();
if (MultiTenancyConsts.IsEnabled)
if (KonSoftConsts.MultiTenancyEnabled)
{
app.UseMultiTenancy();
}

View File

@ -7,19 +7,16 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.ObjectMapping;
namespace KonSoft.Admin.ApplicationServices
{
public class OrderAppService : ApplicationService, IOrderAppService
public class OrderAppService(IOrderRepository orderRepository) : ApplicationService, IOrderAppService
{
private readonly IOrderRepository _orderRepository;
private readonly IOrderRepository _orderRepository = orderRepository;
public OrderAppService(IOrderRepository orderRepository)
{
_orderRepository = orderRepository;
}
/// <summary>
/// 分配师傅
/// </summary>
@ -27,7 +24,7 @@ namespace KonSoft.Admin.ApplicationServices
/// <param name="workerId"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task AssignAsync(Guid orderId, Guid workerId)
public async Task AssignAsync(Guid orderId, Guid workerId)
{
var order = await _orderRepository.GetAsync(o => o.Id == orderId);
order.AssignWorker(workerId);
@ -45,6 +42,7 @@ namespace KonSoft.Admin.ApplicationServices
var order = await _orderRepository.GetAsync(o => o.Id == orderId);
order.Cancel(reason);
}
/// <summary>
/// 完成订单
/// </summary>
@ -56,6 +54,7 @@ namespace KonSoft.Admin.ApplicationServices
var order = await _orderRepository.GetAsync(o => o.Id == orderId);
order.CompleteService();
}
/// <summary>
/// 确认订单
/// </summary>
@ -67,6 +66,7 @@ namespace KonSoft.Admin.ApplicationServices
var order = await _orderRepository.GetAsync(o => o.Id == orderId);
order.ConfirmCompletion();
}
/// <summary>
/// 创建订单
/// </summary>
@ -83,6 +83,34 @@ namespace KonSoft.Admin.ApplicationServices
await _orderRepository.InsertAsync(order);
return ObjectMapper.Map<Order, OrderDto>(order);
}
/// <summary>
/// 根据订单ID删除订单
/// </summary>
/// <param name="id">订单ID</param>
public async Task DeleteAsync(Guid id)
{
// 根据ID删除订单
await _orderRepository.DeleteAsync(x => x.Id == id);
}
/// <summary>
/// 修改订单信息
/// </summary>
/// <param name="input">订单DTO对象</param>s
public async Task EditAsync(OrderDto input)
{
// 根据ID查询订单如果不存在则抛出异常【修改前端必然看到了,数据若查不到提示自定义异常信息】
var order = await _orderRepository.FindAsync(o => o.Id == input.Id) ??
throw new BusinessException("订单找不到").WithData("Id", input.Id);
// 将输入的DTO字段映射到订单实体
ObjectMapper.Map(input, order);
// 更新订单
await _orderRepository.UpdateAsync(order);
}
/// <summary>
/// 支付
/// </summary>
@ -94,6 +122,7 @@ namespace KonSoft.Admin.ApplicationServices
{
throw new NotImplementedException();
}
/// <summary>
/// 开始订单
/// </summary>
@ -106,10 +135,28 @@ namespace KonSoft.Admin.ApplicationServices
order.StartService();
}
/// <summary>
/// 根据订单ID获取单个订单
/// </summary>
public async Task<OrderDto> GetAsync(Guid id)
{
// 根据ID从数据库查询订单
var order = await _orderRepository.GetAsync(o => o.Id == id);
// 转换为OrderDto返回
return ObjectMapper.Map<Order, OrderDto>(order);
}
/// <summary>
/// 获取所有订单列表
/// </summary>
public async Task<List<OrderDto>> GetListAsync()
{
// 查询所有订单
var orders = await _orderRepository.GetListAsync();
// 转换为OrderDto列表返回
return ObjectMapper.Map<List<Order>, List<OrderDto>>(orders);
}
}
}
}

View File

@ -0,0 +1,109 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DistributedLocking;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
namespace KonSoft.Shared.Hosting.Microservices.DbMigrations.EfCore
{
public abstract class PendingEfCoreMigrationsChecker<TDbContext> : ITransientDependency
where TDbContext : DbContext
{
protected IUnitOfWorkManager UnitOfWorkManager { get; }
protected IServiceProvider ServiceProvider { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IDistributedEventBus DistributedEventBus { get; }
protected IAbpDistributedLock DistributedLockProvider { get; }
protected string DatabaseName { get; }
protected PendingEfCoreMigrationsChecker(
IUnitOfWorkManager unitOfWorkManager,
IServiceProvider serviceProvider,
ICurrentTenant currentTenant,
IDistributedEventBus distributedEventBus,
IAbpDistributedLock abpDistributedLock,
string databaseName)
{
UnitOfWorkManager = unitOfWorkManager;
ServiceProvider = serviceProvider;
CurrentTenant = currentTenant;
DistributedEventBus = distributedEventBus;
DistributedLockProvider = abpDistributedLock;
DatabaseName = databaseName;
}
public virtual async Task CheckAndApplyDatabaseMigrationsAsync()
{
await TryAsync(LockAndApplyDatabaseMigrationsAsync);
}
protected async Task TryAsync(Func<Task> task, int retryCount = 3)
{
try
{
await task();
}
catch (Exception ex)
{
retryCount--;
if (retryCount <= 0)
{
throw;
}
Log.Warning($"{ex.GetType().Name} has been thrown. The operation will be tried {retryCount} times more. Exception:\n{ex.Message}");
await Task.Delay(RandomHelper.GetRandom(5000, 15000));
await TryAsync(task, retryCount);
}
}
protected virtual async Task LockAndApplyDatabaseMigrationsAsync()
{
await using (var handle = await DistributedLockProvider.TryAcquireAsync("Migration_" + DatabaseName))
{
Log.Information($"Lock is acquired for db migration and seeding on database named: {DatabaseName}...");
if (handle is null)
{
Log.Information($"Handle is null because of the locking for : {DatabaseName}");
return;
}
using (CurrentTenant.Change(null))
{
// Create database tables if needed
using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false))
{
var dbContext = ServiceProvider.GetRequiredService<TDbContext>();
var pendingMigrations = await dbContext
.Database
.GetPendingMigrationsAsync();
if (pendingMigrations.Any())
{
await dbContext.Database.MigrateAsync();
}
await uow.CompleteAsync();
}
await ServiceProvider.GetRequiredService<IDataSeeder>()
.SeedAsync();
}
Log.Information($"Lock is released for db migration and seeding on database named: {DatabaseName}...");
}
}
}
}

View File

@ -11,7 +11,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.20" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.4" />
<PackageReference Include="DistributedLock.Redis" Version="1.1.0" />
</ItemGroup>
@ -22,6 +22,7 @@
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="8.3.4" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="8.3.4" />
<PackageReference Include="Volo.Abp.DistributedLocking" Version="8.3.4" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy" Version="8.3.4" />
</ItemGroup>
</Project>

View File

@ -2,14 +2,15 @@
using Medallion.Threading;
using Medallion.Threading.Redis;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Redis;
using System;
using System.Linq;
using Microsoft.AspNetCore.Cors;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.BackgroundJobs.RabbitMQ;
using Volo.Abp.Caching;
using Volo.Abp.Caching.StackExchangeRedis;
@ -18,6 +19,7 @@ using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EventBus.RabbitMq;
using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Swashbuckle;
namespace KonSoft.Shared.Hosting.Microservices
{
@ -28,7 +30,9 @@ namespace KonSoft.Shared.Hosting.Microservices
typeof(AbpEventBusRabbitMqModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpDistributedLockingModule),
typeof(AbpEntityFrameworkCoreModule)
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
typeof(AbpEntityFrameworkCoreModule),
typeof(AbpSwashbuckleModule)
)]
public class KonSoftSharedHostingMicroservicesModule : AbpModule
{