StartupHelpers.cs 24.1 KB
Newer Older
1
2
using System;
using System.Globalization;
janskoruba's avatar
janskoruba committed
3
using IdentityServer4.EntityFramework.Storage;
4
using Microsoft.AspNetCore.Authentication;
5
using Microsoft.AspNetCore.Builder;
6
using Microsoft.AspNetCore.HttpOverrides;
7
using Microsoft.AspNetCore.Identity;
8
using Microsoft.AspNetCore.Identity.UI.Services;
9
10
11
12
13
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
14
using Microsoft.Extensions.DependencyInjection.Extensions;
15
using Microsoft.Extensions.Options;
Michał Drzał's avatar
Michał Drzał committed
16
using SendGrid;
17
18
using Skoruba.IdentityServer4.Shared.Configuration.Email;
using Skoruba.IdentityServer4.Shared.Email;
19
using Skoruba.IdentityServer4.STS.Identity.Configuration;
20
using Skoruba.IdentityServer4.STS.Identity.Configuration.ApplicationParts;
21
using Skoruba.IdentityServer4.STS.Identity.Configuration.Constants;
Dmitrii Tarasov's avatar
Dmitrii Tarasov committed
22
using Skoruba.IdentityServer4.STS.Identity.Configuration.Interfaces;
23
using Skoruba.IdentityServer4.STS.Identity.Helpers.Localization;
24
using System.Linq;
janskoruba's avatar
janskoruba committed
25
26
27
28
29
using Skoruba.IdentityServer4.Admin.EntityFramework.Interfaces;
using Skoruba.IdentityServer4.Admin.EntityFramework.MySql.Extensions;
using Skoruba.IdentityServer4.Admin.EntityFramework.PostgreSQL.Extensions;
using Skoruba.IdentityServer4.Admin.EntityFramework.Shared.Configuration;
using Skoruba.IdentityServer4.Admin.EntityFramework.SqlServer.Extensions;
30
using Skoruba.IdentityServer4.Admin.EntityFramework.Helpers;
31
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
janskoruba's avatar
janskoruba committed
32
33
using Microsoft.AspNetCore.Http;
using Skoruba.IdentityServer4.Shared.Authentication;
34
using Skoruba.IdentityServer4.Shared.Configuration.Identity;
35
36
37
38
39

namespace Skoruba.IdentityServer4.STS.Identity.Helpers
{
    public static class StartupHelpers
    {
janskoruba's avatar
janskoruba committed
40
41
42
43
        /// <summary>
        /// Register services for MVC and localization including available languages
        /// </summary>
        /// <param name="services"></param>
Marko Matic's avatar
Marko Matic committed
44
        public static IMvcBuilder AddMvcWithLocalization<TUser, TKey>(this IServiceCollection services, IConfiguration configuration)
45
46
            where TUser : IdentityUser<TKey>
            where TKey : IEquatable<TKey>
47
48
49
        {
            services.AddLocalization(opts => { opts.ResourcesPath = ConfigurationConsts.ResourcesPath; });

50
            services.TryAddTransient(typeof(IGenericControllerLocalizer<>), typeof(GenericControllerLocalizer<>));
janskoruba's avatar
janskoruba committed
51

Marko Matic's avatar
Marko Matic committed
52
            var mvcBuilder = services.AddControllersWithViews(o =>
53
54
55
                {
                    o.Conventions.Add(new GenericControllerRouteConvention());
                })
56
57
58
                .AddViewLocalization(
                    LanguageViewLocationExpanderFormat.Suffix,
                    opts => { opts.ResourcesPath = ConfigurationConsts.ResourcesPath; })
59
60
61
62
63
                .AddDataAnnotationsLocalization()
                .ConfigureApplicationPartManager(m =>
                {
                    m.FeatureProviders.Add(new GenericTypeControllerFeatureProvider<TUser, TKey>());
                });
64

65
            var cultureConfiguration = configuration.GetSection(nameof(CultureConfiguration)).Get<CultureConfiguration>();
66
67
68
            services.Configure<RequestLocalizationOptions>(
                opts =>
                {
69
70
71
72
                    // If cultures are specified in the configuration, use them (making sure they are among the available cultures),
                    // otherwise use all the available cultures
                    var supportedCultureCodes = (cultureConfiguration?.Cultures?.Count > 0 ?
                        cultureConfiguration.Cultures.Intersect(CultureConfiguration.AvailableCultures) :
janskoruba's avatar
janskoruba committed
73
74
75
76
                        CultureConfiguration.AvailableCultures).ToArray();

                    if (!supportedCultureCodes.Any()) supportedCultureCodes = CultureConfiguration.AvailableCultures;
                    var supportedCultures = supportedCultureCodes.Select(c => new CultureInfo(c)).ToList();
77

78
                    // If the default culture is specified use it, otherwise use CultureConfiguration.DefaultRequestCulture ("en")
janskoruba's avatar
janskoruba committed
79
                    var defaultCultureCode = string.IsNullOrEmpty(cultureConfiguration?.DefaultCulture) ?
80
                        CultureConfiguration.DefaultRequestCulture : cultureConfiguration?.DefaultCulture;
janskoruba's avatar
janskoruba committed
81

82
                    // If the default culture is not among the supported cultures, use the first supported culture as default
janskoruba's avatar
janskoruba committed
83
                    if (!supportedCultureCodes.Contains(defaultCultureCode)) defaultCultureCode = supportedCultureCodes.FirstOrDefault();
84
85

                    opts.DefaultRequestCulture = new RequestCulture(defaultCultureCode);
86
87
88
                    opts.SupportedCultures = supportedCultures;
                    opts.SupportedUICultures = supportedCultures;
                });
Marko Matic's avatar
Marko Matic committed
89
90

            return mvcBuilder;
91
92
        }

janskoruba's avatar
janskoruba committed
93
94
95
96
        /// <summary>
        /// Using of Forwarded Headers and Referrer Policy
        /// </summary>
        /// <param name="app"></param>
97
98
        public static void UseSecurityHeaders(this IApplicationBuilder app)
        {
99
            var forwardingOptions = new ForwardedHeadersOptions()
100
            {
101
102
103
104
105
106
107
                ForwardedHeaders = ForwardedHeaders.All
            };

            forwardingOptions.KnownNetworks.Clear();
            forwardingOptions.KnownProxies.Clear();

            app.UseForwardedHeaders(forwardingOptions);
janskoruba's avatar
janskoruba committed
108
109

            app.UseReferrerPolicy(options => options.NoReferrer());
110
111
        }

janskoruba's avatar
janskoruba committed
112
113
114
115
116
        /// <summary>
        /// Add email senders - configuration of sendgrid, smtp senders
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
117
        public static void AddEmailSenders(this IServiceCollection services, IConfiguration configuration)
Michał Drzał's avatar
Michał Drzał committed
118
119
        {
            var smtpConfiguration = configuration.GetSection(nameof(SmtpConfiguration)).Get<SmtpConfiguration>();
120
            var sendGridConfiguration = configuration.GetSection(nameof(SendGridConfiguration)).Get<SendGridConfiguration>();
Michał Drzał's avatar
Michał Drzał committed
121

janskoruba's avatar
janskoruba committed
122
            if (sendGridConfiguration != null && !string.IsNullOrWhiteSpace(sendGridConfiguration.ApiKey))
Michał Drzał's avatar
Michał Drzał committed
123
            {
janskoruba's avatar
janskoruba committed
124
125
                services.AddSingleton<ISendGridClient>(_ => new SendGridClient(sendGridConfiguration.ApiKey));
                services.AddSingleton(sendGridConfiguration);
126
                services.AddTransient<IEmailSender, SendGridEmailSender>();
Michał Drzał's avatar
Michał Drzał committed
127
            }
128
            else if (smtpConfiguration != null && !string.IsNullOrWhiteSpace(smtpConfiguration.Host))
Michał Drzał's avatar
Michał Drzał committed
129
130
131
            {
                services.AddSingleton(smtpConfiguration);
                services.AddTransient<IEmailSender, SmtpEmailSender>();
132
133
            }
            else
Michał Drzał's avatar
Michał Drzał committed
134
            {
135
                services.AddSingleton<IEmailSender, LogEmailSender>();
Michał Drzał's avatar
Michał Drzał committed
136
137
138
            }
        }

janskoruba's avatar
janskoruba committed
139
        /// <summary>
140
        /// Register DbContexts for IdentityServer ConfigurationStore, PersistedGrants, Identity and DataProtection
janskoruba's avatar
janskoruba committed
141
142
143
144
145
146
147
        /// Configure the connection strings in AppSettings.json
        /// </summary>
        /// <typeparam name="TConfigurationDbContext"></typeparam>
        /// <typeparam name="TPersistedGrantDbContext"></typeparam>
        /// <typeparam name="TIdentityDbContext"></typeparam>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
148
        public static void RegisterDbContexts<TIdentityDbContext, TConfigurationDbContext, TPersistedGrantDbContext, TDataProtectionDbContext>(this IServiceCollection services, IConfiguration configuration)
janskoruba's avatar
janskoruba committed
149
150
151
            where TIdentityDbContext : DbContext
            where TPersistedGrantDbContext : DbContext, IAdminPersistedGrantDbContext
            where TConfigurationDbContext : DbContext, IAdminConfigurationDbContext
152
            where TDataProtectionDbContext : DbContext, IDataProtectionKeyContext
janskoruba's avatar
janskoruba committed
153
154
        {
            var databaseProvider = configuration.GetSection(nameof(DatabaseProviderConfiguration)).Get<DatabaseProviderConfiguration>();
janskoruba's avatar
janskoruba committed
155

janskoruba's avatar
janskoruba committed
156
157
158
            var identityConnectionString = configuration.GetConnectionString(ConfigurationConsts.IdentityDbConnectionStringKey);
            var configurationConnectionString = configuration.GetConnectionString(ConfigurationConsts.ConfigurationDbConnectionStringKey);
            var persistedGrantsConnectionString = configuration.GetConnectionString(ConfigurationConsts.PersistedGrantDbConnectionStringKey);
159
            var dataProtectionConnectionString = configuration.GetConnectionString(ConfigurationConsts.DataProtectionDbConnectionStringKey);
janskoruba's avatar
janskoruba committed
160

janskoruba's avatar
janskoruba committed
161
            switch (databaseProvider.ProviderType)
janskoruba's avatar
janskoruba committed
162
163
            {
                case DatabaseProviderType.SqlServer:
164
                    services.RegisterSqlServerDbContexts<TIdentityDbContext, TConfigurationDbContext, TPersistedGrantDbContext, TDataProtectionDbContext>(identityConnectionString, configurationConnectionString, persistedGrantsConnectionString, dataProtectionConnectionString);
janskoruba's avatar
janskoruba committed
165
166
                    break;
                case DatabaseProviderType.PostgreSQL:
167
                    services.RegisterNpgSqlDbContexts<TIdentityDbContext, TConfigurationDbContext, TPersistedGrantDbContext, TDataProtectionDbContext>(identityConnectionString, configurationConnectionString, persistedGrantsConnectionString, dataProtectionConnectionString);
janskoruba's avatar
janskoruba committed
168
169
                    break;
                case DatabaseProviderType.MySql:
170
                    services.RegisterMySqlDbContexts<TIdentityDbContext, TConfigurationDbContext, TPersistedGrantDbContext, TDataProtectionDbContext>(identityConnectionString, configurationConnectionString, persistedGrantsConnectionString, dataProtectionConnectionString);
janskoruba's avatar
janskoruba committed
171
172
                    break;
                default:
173
                    throw new ArgumentOutOfRangeException(nameof(databaseProvider.ProviderType), $@"The value needs to be one of {string.Join(", ", Enum.GetNames(typeof(DatabaseProviderType)))}.");
janskoruba's avatar
janskoruba committed
174
175
176
177
            }
        }

        /// <summary>
178
        /// Register InMemory DbContexts for IdentityServer ConfigurationStore, PersistedGrants, Identity and DataProtection
janskoruba's avatar
janskoruba committed
179
180
181
182
183
184
        /// Configure the connection strings in AppSettings.json
        /// </summary>
        /// <typeparam name="TConfigurationDbContext"></typeparam>
        /// <typeparam name="TPersistedGrantDbContext"></typeparam>
        /// <typeparam name="TIdentityDbContext"></typeparam>
        /// <param name="services"></param>
185
        public static void RegisterDbContextsStaging<TIdentityDbContext, TConfigurationDbContext, TPersistedGrantDbContext, TDataProtectionDbContext>(
janskoruba's avatar
janskoruba committed
186
187
188
189
            this IServiceCollection services)
            where TIdentityDbContext : DbContext
            where TPersistedGrantDbContext : DbContext, IAdminPersistedGrantDbContext
            where TConfigurationDbContext : DbContext, IAdminConfigurationDbContext
190
            where TDataProtectionDbContext : DbContext, IDataProtectionKeyContext
janskoruba's avatar
janskoruba committed
191
192
193
194
195
196
        {
            var identityDatabaseName = Guid.NewGuid().ToString();
            services.AddDbContext<TIdentityDbContext>(optionsBuilder => optionsBuilder.UseInMemoryDatabase(identityDatabaseName));

            var configurationDatabaseName = Guid.NewGuid().ToString();
            var operationalDatabaseName = Guid.NewGuid().ToString();
197
            var dataProtectionDatabaseName = Guid.NewGuid().ToString();
janskoruba's avatar
janskoruba committed
198
199
200
201
202
203
204
205
206
207

            services.AddConfigurationDbContext<TConfigurationDbContext>(options =>
            {
                options.ConfigureDbContext = b => b.UseInMemoryDatabase(configurationDatabaseName);
            });

            services.AddOperationalDbContext<TPersistedGrantDbContext>(options =>
            {
                options.ConfigureDbContext = b => b.UseInMemoryDatabase(operationalDatabaseName);
            });
208
209
210
211
212

            services.AddDbContext<TDataProtectionDbContext>(options =>
            {
                options.UseInMemoryDatabase(dataProtectionDatabaseName);
            });
janskoruba's avatar
janskoruba committed
213
214
        }

janskoruba's avatar
janskoruba committed
215
216
217
218
219
220
221
222
        /// <summary>
        /// Add services for authentication, including Identity model, IdentityServer4 and external providers
        /// </summary>
        /// <typeparam name="TIdentityDbContext">DbContext for Identity</typeparam>
        /// <typeparam name="TUserIdentity">User Identity class</typeparam>
        /// <typeparam name="TUserIdentityRole">User Identity Role class</typeparam>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
223
        public static void AddAuthenticationServices<TIdentityDbContext, TUserIdentity, TUserIdentityRole>(this IServiceCollection services, IConfiguration configuration) where TIdentityDbContext : DbContext
224
225
            where TUserIdentity : class
            where TUserIdentityRole : class
226
        {
227
            var loginConfiguration = GetLoginConfiguration(configuration);
228
            var registrationConfiguration = GetRegistrationConfiguration(configuration);
Michał Drzał's avatar
Michał Drzał committed
229
230

            services
231
                .AddSingleton(registrationConfiguration)
Michał Drzał's avatar
Michał Drzał committed
232
233
234
                .AddSingleton(loginConfiguration)
                .AddScoped<UserResolver<TUserIdentity>>()
                .AddIdentity<TUserIdentity, TUserIdentityRole>(options =>
235
                {
236
237
                    options.User.RequireUniqueEmail = loginConfiguration.RequireUniqueEmail;
                    options.SignIn.RequireConfirmedEmail = registrationConfiguration.RequireConfirmedAccount;
238
                })
janskoruba's avatar
janskoruba committed
239
                .AddEntityFrameworkStores<TIdentityDbContext>()
240
                .AddDefaultTokenProviders();
241

janskoruba's avatar
janskoruba committed
242
243
244
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
245
                options.Secure = CookieSecurePolicy.SameAsRequest;
janskoruba's avatar
janskoruba committed
246
247
248
249
250
251
                options.OnAppendCookie = cookieContext =>
                    AuthenticationHelpers.CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
                options.OnDeleteCookie = cookieContext =>
                    AuthenticationHelpers.CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
            });

252
253
254
255
256
257
            services.Configure<IISOptions>(iis =>
            {
                iis.AuthenticationDisplayName = "Windows";
                iis.AutomaticAuthentication = false;
            });

258
259
260
261
262
            var authenticationBuilder = services.AddAuthentication();

            AddExternalProviders(authenticationBuilder, configuration);
        }

263
264
265
266
267
268
269
270
        /// <summary>
        /// Get configuration for login
        /// </summary>
        /// <param name="configuration"></param>
        /// <returns></returns>
        private static LoginConfiguration GetLoginConfiguration(IConfiguration configuration)
        {
            var loginConfiguration = configuration.GetSection(nameof(LoginConfiguration)).Get<LoginConfiguration>();
271

272
273
274
275
276
277
278
279
280
            // Cannot load configuration - use default configuration values
            if (loginConfiguration == null)
            {
                return new LoginConfiguration();
            }

            return loginConfiguration;
        }

281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
        /// <summary>
        /// Get configuration for registration
        /// </summary>
        /// <param name="configuration"></param>
        /// <returns></returns>
        private static RegisterConfiguration GetRegistrationConfiguration(IConfiguration configuration)
        {
            var registerConfiguration = configuration.GetSection(nameof(RegisterConfiguration)).Get<RegisterConfiguration>();

            // Cannot load configuration - use default configuration values
            if (registerConfiguration == null)
            {
                return new RegisterConfiguration();
            }

            return registerConfiguration;
        }

janskoruba's avatar
janskoruba committed
299
300
301
302
        /// <summary>
        /// Add configuration for IdentityServer4
        /// </summary>
        /// <typeparam name="TUserIdentity"></typeparam>
303
304
        /// <typeparam name="TConfigurationDbContext"></typeparam>
        /// <typeparam name="TPersistedGrantDbContext"></typeparam>
janskoruba's avatar
janskoruba committed
305
306
        /// <param name="services"></param>
        /// <param name="configuration"></param>
307
308
        public static IIdentityServerBuilder AddIdentityServer<TConfigurationDbContext, TPersistedGrantDbContext, TUserIdentity>(
            this IServiceCollection services,
309
            IConfiguration configuration)
janskoruba's avatar
janskoruba committed
310
311
            where TPersistedGrantDbContext : DbContext, IAdminPersistedGrantDbContext
            where TConfigurationDbContext : DbContext, IAdminConfigurationDbContext
janskoruba's avatar
janskoruba committed
312
            where TUserIdentity : class
313
        {
314
315
            var advancedConfiguration = configuration.GetSection(nameof(AdvancedConfiguration)).Get<AdvancedConfiguration>();

316
            var builder = services.AddIdentityServer(options =>
317
318
319
320
321
                {
                    options.Events.RaiseErrorEvents = true;
                    options.Events.RaiseInformationEvents = true;
                    options.Events.RaiseFailureEvents = true;
                    options.Events.RaiseSuccessEvents = true;
322
323

                    if (!string.IsNullOrEmpty(advancedConfiguration.PublicOrigin))
janskoruba's avatar
janskoruba committed
324
                    {
325
                        options.PublicOrigin = advancedConfiguration.PublicOrigin;
janskoruba's avatar
janskoruba committed
326
327
328
329
330
331
                    }

                    if (!string.IsNullOrEmpty(advancedConfiguration.IssuerUri))
                    {
                        options.IssuerUri = advancedConfiguration.IssuerUri;
                    }
332
                })
janskoruba's avatar
janskoruba committed
333
334
335
                .AddConfigurationStore<TConfigurationDbContext>()
                .AddOperationalStore<TPersistedGrantDbContext>()
                .AddAspNetIdentity<TUserIdentity>();
336

337
            builder.AddCustomSigningCredential(configuration);
338
            builder.AddCustomValidationKey(configuration);
339
340

            return builder;
341
342
        }

janskoruba's avatar
janskoruba committed
343
344
345
346
347
        /// <summary>
        /// Add external providers
        /// </summary>
        /// <param name="authenticationBuilder"></param>
        /// <param name="configuration"></param>
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
        private static void AddExternalProviders(AuthenticationBuilder authenticationBuilder,
            IConfiguration configuration)
        {
            var externalProviderConfiguration = configuration.GetSection(nameof(ExternalProvidersConfiguration)).Get<ExternalProvidersConfiguration>();

            if (externalProviderConfiguration.UseGitHubProvider)
            {
                authenticationBuilder.AddGitHub(options =>
                {
                    options.ClientId = externalProviderConfiguration.GitHubClientId;
                    options.ClientSecret = externalProviderConfiguration.GitHubClientSecret;
                    options.Scope.Add("user:email");
                });
            }
        }

janskoruba's avatar
janskoruba committed
364
365
366
367
        /// <summary>
        /// Register middleware for localization
        /// </summary>
        /// <param name="app"></param>
368
369
370
371
372
        public static void UseMvcLocalizationServices(this IApplicationBuilder app)
        {
            var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
            app.UseRequestLocalization(options.Value);
        }
373

374
375
376
377
        /// <summary>
        /// Add authorization policies
        /// </summary>
        /// <param name="services"></param>
janskoruba's avatar
janskoruba committed
378
        /// <param name="rootConfiguration"></param>
379
380
        public static void AddAuthorizationPolicies(this IServiceCollection services,
                IRootConfiguration rootConfiguration)
381
382
383
384
        {
            services.AddAuthorization(options =>
            {
                options.AddPolicy(AuthorizationConsts.AdministrationPolicy,
385
                    policy => policy.RequireRole(rootConfiguration.AdminConfiguration.AdministrationRole));
386
387
            });
        }
388

389
        public static void AddIdSHealthChecks<TConfigurationDbContext, TPersistedGrantDbContext, TIdentityDbContext, TDataProtectionDbContext>(this IServiceCollection services, IConfiguration configuration)
390
391
            where TConfigurationDbContext : DbContext, IAdminConfigurationDbContext
            where TPersistedGrantDbContext : DbContext, IAdminPersistedGrantDbContext
392
            where TIdentityDbContext : DbContext
393
            where TDataProtectionDbContext : DbContext, IDataProtectionKeyContext
394
395
        {
            var configurationDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.ConfigurationDbConnectionStringKey);
janskoruba's avatar
janskoruba committed
396
            var persistedGrantsDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.PersistedGrantDbConnectionStringKey);
397
            var identityDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.IdentityDbConnectionStringKey);
398
399
            var dataProtectionDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.DataProtectionDbConnectionStringKey);

400
            var healthChecksBuilder = services.AddHealthChecks()
401
402
                .AddDbContextCheck<TConfigurationDbContext>("ConfigurationDbContext")
                .AddDbContextCheck<TPersistedGrantDbContext>("PersistedGrantsDbContext")
403
404
                .AddDbContextCheck<TIdentityDbContext>("IdentityDbContext")
                .AddDbContextCheck<TDataProtectionDbContext>("DataProtectionDbContext");
405

406
407
408
            var serviceProvider = services.BuildServiceProvider();
            var scopeFactory = serviceProvider.GetRequiredService<IServiceScopeFactory>();
            using (var scope = scopeFactory.CreateScope())
409
            {
410
411
412
                var configurationTableName = DbContextHelpers.GetEntityTable<TConfigurationDbContext>(scope.ServiceProvider);
                var persistedGrantTableName = DbContextHelpers.GetEntityTable<TPersistedGrantDbContext>(scope.ServiceProvider);
                var identityTableName = DbContextHelpers.GetEntityTable<TIdentityDbContext>(scope.ServiceProvider);
413
                var dataProtectionTableName = DbContextHelpers.GetEntityTable<TDataProtectionDbContext>(scope.ServiceProvider);
414

415
416
417
418
419
420
421
422
423
424
                var databaseProvider = configuration.GetSection(nameof(DatabaseProviderConfiguration)).Get<DatabaseProviderConfiguration>();
                switch (databaseProvider.ProviderType)
                {
                    case DatabaseProviderType.SqlServer:
                        healthChecksBuilder
                            .AddSqlServer(configurationDbConnectionString, name: "ConfigurationDb",
                                healthQuery: $"SELECT TOP 1 * FROM dbo.[{configurationTableName}]")
                            .AddSqlServer(persistedGrantsDbConnectionString, name: "PersistentGrantsDb",
                                healthQuery: $"SELECT TOP 1 * FROM dbo.[{persistedGrantTableName}]")
                            .AddSqlServer(identityDbConnectionString, name: "IdentityDb",
425
426
427
                                healthQuery: $"SELECT TOP 1 * FROM dbo.[{identityTableName}]")
                            .AddSqlServer(dataProtectionDbConnectionString, name: "DataProtectionDb",
                                healthQuery: $"SELECT TOP 1 * FROM dbo.[{dataProtectionTableName}]");
428
429
430
431
432

                        break;
                    case DatabaseProviderType.PostgreSQL:
                        healthChecksBuilder
                            .AddNpgSql(configurationDbConnectionString, name: "ConfigurationDb",
433
                                healthQuery: $"SELECT * FROM \"{configurationTableName}\" LIMIT 1")
434
                            .AddNpgSql(persistedGrantsDbConnectionString, name: "PersistentGrantsDb",
435
                                healthQuery: $"SELECT * FROM \"{persistedGrantTableName}\" LIMIT 1")
436
                            .AddNpgSql(identityDbConnectionString, name: "IdentityDb",
437
                                healthQuery: $"SELECT * FROM \"{identityTableName}\" LIMIT 1")
438
                            .AddNpgSql(dataProtectionDbConnectionString, name: "DataProtectionDb",
439
                                healthQuery: $"SELECT * FROM \"{dataProtectionTableName}\"  LIMIT 1");
440
441
442
443
444
                        break;
                    case DatabaseProviderType.MySql:
                        healthChecksBuilder
                            .AddMySql(configurationDbConnectionString, name: "ConfigurationDb")
                            .AddMySql(persistedGrantsDbConnectionString, name: "PersistentGrantsDb")
445
446
                            .AddMySql(identityDbConnectionString, name: "IdentityDb")
                            .AddMySql(dataProtectionDbConnectionString, name: "DataProtectionDb");
447
448
449
450
                        break;
                    default:
                        throw new NotImplementedException($"Health checks not defined for database provider {databaseProvider.ProviderType}");
                }
451
            }
452
        }
janskoruba's avatar
janskoruba committed
453
    }
454
}