diff --git a/EventHub.sln b/EventHub.sln
index 9851ae4..3b8c6a4 100644
--- a/EventHub.sln
+++ b/EventHub.sln
@@ -65,6 +65,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventHub.Web.Theme", "src\E
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventHub.Admin.HttpApi.Host", "src\EventHub.Admin.HttpApi.Host\EventHub.Admin.HttpApi.Host.csproj", "{1434105B-DE2C-4AA2-A865-EBA0DBCCA5B0}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventHub.Web.Shared", "src\EventHub.Web.Shared\EventHub.Web.Shared.csproj", "{6F7DDDD3-1AC3-4304-AB2C-3BAB294F94AA}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -163,6 +165,10 @@ Global
{1434105B-DE2C-4AA2-A865-EBA0DBCCA5B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1434105B-DE2C-4AA2-A865-EBA0DBCCA5B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1434105B-DE2C-4AA2-A865-EBA0DBCCA5B0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6F7DDDD3-1AC3-4304-AB2C-3BAB294F94AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6F7DDDD3-1AC3-4304-AB2C-3BAB294F94AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6F7DDDD3-1AC3-4304-AB2C-3BAB294F94AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6F7DDDD3-1AC3-4304-AB2C-3BAB294F94AA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -197,6 +203,7 @@ Global
{69BC428E-5C49-4391-9985-0D15523D6922} = {F8CF0FE2-9F75-4940-92EC-3D021416DEBF}
{E6D5BF0E-DE92-4D82-A352-EF04B37CB11C} = {F8CF0FE2-9F75-4940-92EC-3D021416DEBF}
{1434105B-DE2C-4AA2-A865-EBA0DBCCA5B0} = {7016C0D2-D0D5-498B-9FA7-8ABA8F5C39EF}
+ {6F7DDDD3-1AC3-4304-AB2C-3BAB294F94AA} = {81F0EB50-4CF9-402D-B723-A07E95F8D7CB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6AAFA1C6-603E-13FA-45E5-7910AA9F661D}
diff --git a/src/EventHub.Admin.HttpApi.Host/EventHub.Admin.HttpApi.Host.csproj b/src/EventHub.Admin.HttpApi.Host/EventHub.Admin.HttpApi.Host.csproj
index f684632..0bde80d 100644
--- a/src/EventHub.Admin.HttpApi.Host/EventHub.Admin.HttpApi.Host.csproj
+++ b/src/EventHub.Admin.HttpApi.Host/EventHub.Admin.HttpApi.Host.csproj
@@ -26,6 +26,7 @@
+
diff --git a/src/EventHub.Admin.HttpApi.Host/EventHubAdminHttpApiHostModule.cs b/src/EventHub.Admin.HttpApi.Host/EventHubAdminHttpApiHostModule.cs
index 07c290d..5d4f910 100644
--- a/src/EventHub.Admin.HttpApi.Host/EventHubAdminHttpApiHostModule.cs
+++ b/src/EventHub.Admin.HttpApi.Host/EventHubAdminHttpApiHostModule.cs
@@ -7,6 +7,7 @@ using EventHub.Admin.Organizations;
using EventHub.Admin.Utils;
using EventHub.EntityFrameworkCore;
using EventHub.Options;
+using EventHub.Web.Shared;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
@@ -42,7 +43,8 @@ namespace EventHub.Admin
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpSwashbuckleModule),
- typeof(AbpAspNetCoreMvcUiBasicThemeModule)
+ typeof(AbpAspNetCoreMvcUiBasicThemeModule),
+ typeof(EventHubWebSharedModule)
)]
public class EventHubAdminHttpApiHostModule : AbpModule
{
@@ -65,7 +67,7 @@ namespace EventHub.Admin
ConfigureTiming();
ConfigureAutoApiControllers();
}
-
+
private void ConfigureAutoApiControllers()
{
Configure(options =>
@@ -87,7 +89,7 @@ namespace EventHub.Admin
{
Configure(options => { options.KeyPrefix = "EventHub:"; });
}
-
+
private void ConfigureTiming()
{
Configure(options => { options.Kind = DateTimeKind.Utc; });
@@ -185,7 +187,7 @@ namespace EventHub.Admin
{
context.Services.AddSameSiteCookiePolicy();
}
-
+
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
@@ -200,7 +202,7 @@ namespace EventHub.Admin
{
new CultureInfo("en")
};
-
+
app.UseAbpRequestLocalization(options =>
{
options.DefaultRequestCulture = new RequestCulture("en");
diff --git a/src/EventHub.HttpApi.Host/EventHub.HttpApi.Host.csproj b/src/EventHub.HttpApi.Host/EventHub.HttpApi.Host.csproj
index 52e2743..7ddeb0a 100644
--- a/src/EventHub.HttpApi.Host/EventHub.HttpApi.Host.csproj
+++ b/src/EventHub.HttpApi.Host/EventHub.HttpApi.Host.csproj
@@ -26,6 +26,7 @@
+
diff --git a/src/EventHub.HttpApi.Host/EventHubHttpApiHostModule.cs b/src/EventHub.HttpApi.Host/EventHubHttpApiHostModule.cs
index 9e69fa8..e2b3ced 100644
--- a/src/EventHub.HttpApi.Host/EventHubHttpApiHostModule.cs
+++ b/src/EventHub.HttpApi.Host/EventHubHttpApiHostModule.cs
@@ -9,6 +9,7 @@ using EventHub.Options;
using EventHub.Organizations;
using EventHub.Organizations.Plans;
using EventHub.Utils;
+using EventHub.Web.Shared;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
@@ -45,7 +46,8 @@ namespace EventHub
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpSwashbuckleModule),
- typeof(AbpAspNetCoreMvcUiBasicThemeModule)
+ typeof(AbpAspNetCoreMvcUiBasicThemeModule),
+ typeof(EventHubWebSharedModule)
)]
public class EventHubHttpApiHostModule : AbpModule
{
@@ -68,7 +70,7 @@ namespace EventHub
ConfigureTiming();
ConfigurePremiumPlanInfo(context, configuration);
}
-
+
private void ConfigureAutoApiControllers()
{
Configure(options =>
@@ -96,7 +98,7 @@ namespace EventHub
private void ConfigureVirtualFileSystem(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
-
+
Configure(options =>
{
options.FileSets.AddEmbedded(
@@ -189,12 +191,12 @@ namespace EventHub
{
context.Services.AddSameSiteCookiePolicy();
}
-
+
private void ConfigureTiming()
{
Configure(options => { options.Kind = DateTimeKind.Utc; });
}
-
+
private void ConfigurePremiumPlanInfo(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddOptions>()
@@ -218,7 +220,7 @@ namespace EventHub
{
app.UseDeveloperExceptionPage();
}
-
+
app.Use((context, next) =>
{
context.Request.Scheme = "https";
@@ -229,7 +231,7 @@ namespace EventHub
{
new CultureInfo("en")
};
-
+
app.UseAbpRequestLocalization(options =>
{
options.DefaultRequestCulture = new RequestCulture("en");
diff --git a/src/EventHub.IdentityServer/EventHub.IdentityServer.csproj b/src/EventHub.IdentityServer/EventHub.IdentityServer.csproj
index 0a0fdd6..43f48af 100644
--- a/src/EventHub.IdentityServer/EventHub.IdentityServer.csproj
+++ b/src/EventHub.IdentityServer/EventHub.IdentityServer.csproj
@@ -54,6 +54,7 @@
+
diff --git a/src/EventHub.IdentityServer/EventHubIdentityServerModule.cs b/src/EventHub.IdentityServer/EventHubIdentityServerModule.cs
index 9e345db..0bec194 100644
--- a/src/EventHub.IdentityServer/EventHubIdentityServerModule.cs
+++ b/src/EventHub.IdentityServer/EventHubIdentityServerModule.cs
@@ -5,6 +5,7 @@ using EventHub.Localization;
using EventHub.Options;
using EventHub.Utils;
using EventHub.Web;
+using EventHub.Web.Shared;
using EventHub.Web.Theme;
using EventHub.Web.Theme.Bundling;
using IdentityServer4.Configuration;
@@ -42,10 +43,11 @@ namespace EventHub
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpAccountWebIdentityServerModule),
typeof(AbpAccountApplicationModule),
- typeof(AbpAccountHttpApiModule),
+ typeof(AbpAccountHttpApiModule),
typeof(EventHubWebThemeModule),
typeof(EventHubEntityFrameworkCoreModule),
- typeof(AbpAspNetCoreSerilogModule)
+ typeof(AbpAspNetCoreSerilogModule),
+ typeof(EventHubWebSharedModule)
)]
public class EventHubIdentityServerModule : AbpModule
{
@@ -70,7 +72,7 @@ namespace EventHub
});
}
}
-
+
private X509Certificate2 GetSigningCertificate(IWebHostEnvironment hostingEnv, IConfiguration configuration)
{
var fileName = "account.openeventhub.pfx";
@@ -84,7 +86,7 @@ namespace EventHub
return new X509Certificate2(file, passPhrase);
}
-
+
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
@@ -180,8 +182,8 @@ namespace EventHub
.AllowCredentials();
});
});
-
- context.Services.AddSameSiteCookiePolicy();
+
+ context.Services.AddSameSiteCookiePolicy();
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
@@ -196,10 +198,10 @@ namespace EventHub
{
ctx.SetIdentityServerOrigin(EventHubUrlOptions.GetAccountConfigValue(configuration));
}
-
+
await next();
});
-
+
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
@@ -211,7 +213,7 @@ namespace EventHub
{
app.UseErrorPage();
}
-
+
app.UseCookiePolicy();
app.UseCorrelationId();
app.UseStaticFiles();
diff --git a/src/EventHub.Web.Shared/EventHub.Web.Shared.csproj b/src/EventHub.Web.Shared/EventHub.Web.Shared.csproj
new file mode 100644
index 0000000..e895206
--- /dev/null
+++ b/src/EventHub.Web.Shared/EventHub.Web.Shared.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EventHub.Web.Shared/EventHubWebSharedModule.cs b/src/EventHub.Web.Shared/EventHubWebSharedModule.cs
new file mode 100644
index 0000000..4f476ad
--- /dev/null
+++ b/src/EventHub.Web.Shared/EventHubWebSharedModule.cs
@@ -0,0 +1,15 @@
+using EventHub.EntityFrameworkCore;
+using EventHub.Web.Shared.HealthChecks;
+using Volo.Abp.AspNetCore;
+using Volo.Abp.Modularity;
+
+namespace EventHub.Web.Shared;
+
+[DependsOn(typeof(AbpAspNetCoreModule), typeof(EventHubEntityFrameworkCoreModule))]
+public class EventHubWebSharedModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddEventHubHealthChecks();
+ }
+}
diff --git a/src/EventHub.Web.Shared/HealthChecks/EventHubDatabaseCheck.cs b/src/EventHub.Web.Shared/HealthChecks/EventHubDatabaseCheck.cs
new file mode 100644
index 0000000..2e008f7
--- /dev/null
+++ b/src/EventHub.Web.Shared/HealthChecks/EventHubDatabaseCheck.cs
@@ -0,0 +1,30 @@
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Identity;
+using IdentityRole = Microsoft.AspNetCore.Identity.IdentityRole;
+
+namespace EventHub.Web.Shared.HealthChecks;
+
+public class EventHubDatabaseCheck : IHealthCheck, ITransientDependency
+{
+ protected readonly IIdentityRoleRepository IdentityRoleRepository;
+
+ public EventHubDatabaseCheck(IIdentityRoleRepository identityRoleRepository)
+ {
+ IdentityRoleRepository = identityRoleRepository;
+ }
+
+ public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
+ {
+ try
+ {
+ await IdentityRoleRepository.GetListAsync(sorting: nameof(IdentityRole.Id), maxResultCount: 1, cancellationToken: cancellationToken);
+
+ return HealthCheckResult.Healthy($"Could connect to database and get record.");
+ }
+ catch (Exception e)
+ {
+ return HealthCheckResult.Unhealthy($"Error when trying to get database record. ", e);
+ }
+ }
+}
diff --git a/src/EventHub.Web.Shared/HealthChecks/HealthChecksBuilderExtensions.cs b/src/EventHub.Web.Shared/HealthChecks/HealthChecksBuilderExtensions.cs
new file mode 100644
index 0000000..6f2546a
--- /dev/null
+++ b/src/EventHub.Web.Shared/HealthChecks/HealthChecksBuilderExtensions.cs
@@ -0,0 +1,76 @@
+using HealthChecks.UI.Client;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Diagnostics.HealthChecks;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace EventHub.Web.Shared.HealthChecks;
+
+public static class HealthChecksBuilderExtensions
+{
+ public static void AddEventHubHealthChecks(this IServiceCollection services)
+ {
+ // Add your health checks here
+ var healthChecksBuilder = services.AddHealthChecks();
+ healthChecksBuilder.AddCheck("EventHub DbContext Check", tags: new string[] { "database" });
+
+ services.ConfigureHealthCheckEndpoint("/health-status");
+
+ // If you don't want to add HealthChecksUI, remove following configurations.
+ var configuration = services.GetConfiguration();
+ var healthCheckUrl = configuration["App:HealthCheckUrl"];
+
+ if (string.IsNullOrEmpty(healthCheckUrl))
+ {
+ healthCheckUrl = "/health-status";
+ }
+
+ var healthChecksUiBuilder = services.AddHealthChecksUI(settings =>
+ {
+ settings.AddHealthCheckEndpoint("EventHub Health Status", healthCheckUrl);
+ });
+
+ // Set your HealthCheck UI Storage here
+ healthChecksUiBuilder.AddInMemoryStorage();
+
+ services.MapHealthChecksUiEndpoints(options =>
+ {
+ options.UIPath = "/health-ui";
+ options.ApiPath = "/health-api";
+ });
+ }
+
+ private static IServiceCollection ConfigureHealthCheckEndpoint(this IServiceCollection services, string path)
+ {
+ services.Configure(options =>
+ {
+ options.EndpointConfigureActions.Add(endpointContext =>
+ {
+ endpointContext.Endpoints.MapHealthChecks(
+ new PathString(path.EnsureStartsWith('/')),
+ new HealthCheckOptions
+ {
+ Predicate = _ => true,
+ ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse,
+ AllowCachingResponses = false,
+ });
+ });
+ });
+
+ return services;
+ }
+
+ private static IServiceCollection MapHealthChecksUiEndpoints(this IServiceCollection services, Action? setupOption = null)
+ {
+ services.Configure(routerOptions =>
+ {
+ routerOptions.EndpointConfigureActions.Add(endpointContext =>
+ {
+ endpointContext.Endpoints.MapHealthChecksUI(setupOption);
+ });
+ });
+
+ return services;
+ }
+}