|
- using System;
- using System.IO;
- using Blazorise.Bootstrap5;
- using Blazorise.Icons.FontAwesome;
- using Medallion.Threading;
- using Medallion.Threading.Redis;
- using Microsoft.AspNetCore.Authentication.Cookies;
- using Microsoft.AspNetCore.Authentication.OpenIdConnect;
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.DataProtection;
- using Microsoft.AspNetCore.Hosting;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Hosting;
- using Microsoft.Extensions.Options;
- using Microsoft.IdentityModel.Protocols.OpenIdConnect;
- using Microsoft.OpenApi.Models;
- using Acme.BookStore.Blazor.WebApp.Tiered.Client;
- using Acme.BookStore.Blazor.WebApp.Tiered.Client.Menus;
- using Acme.BookStore.Blazor.WebApp.Tiered.Components;
- using Acme.BookStore.Blazor.WebApp.Tiered.Menus;
- using Acme.BookStore.Localization;
- using Acme.BookStore.MultiTenancy;
- using StackExchange.Redis;
- using Volo.Abp;
- using Volo.Abp.AspNetCore.Authentication.OpenIdConnect;
- using Volo.Abp.AspNetCore.Components.Web;
- using Volo.Abp.AspNetCore.Components.Server.LeptonXLiteTheme;
- using Volo.Abp.AspNetCore.Components.Server.LeptonXLiteTheme.Bundling;
- using Volo.Abp.AspNetCore.Components.Web.Theming.Routing;
- using Volo.Abp.AspNetCore.Mvc.Client;
- using Volo.Abp.AspNetCore.Mvc.Localization;
- using Volo.Abp.AspNetCore.Mvc.UI;
- using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
- using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
- using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
- using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite;
- using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling;
- using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
- using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars;
- using Volo.Abp.AspNetCore.Serilog;
- using Volo.Abp.Autofac;
- using Volo.Abp.AutoMapper;
- using Volo.Abp.Caching;
- using Volo.Abp.Caching.StackExchangeRedis;
- using Volo.Abp.DistributedLocking;
- using Volo.Abp.Http.Client.IdentityModel.Web;
- using Volo.Abp.Identity.Blazor.Server;
- using Volo.Abp.Modularity;
- using Volo.Abp.MultiTenancy;
- using Volo.Abp.Security.Claims;
- using Volo.Abp.SettingManagement.Blazor.Server;
- using Volo.Abp.Swashbuckle;
- using Volo.Abp.TenantManagement.Blazor.Server;
- using Volo.Abp.UI;
- using Volo.Abp.UI.Navigation;
- using Volo.Abp.UI.Navigation.Urls;
- using Volo.Abp.VirtualFileSystem;
-
- namespace Acme.BookStore.Blazor.WebApp.Tiered;
-
- [DependsOn(
- typeof(BookStoreHttpApiClientModule),
- typeof(AbpCachingStackExchangeRedisModule),
- typeof(AbpDistributedLockingModule),
- typeof(AbpAspNetCoreMvcClientModule),
- typeof(AbpAspNetCoreAuthenticationOpenIdConnectModule),
- typeof(AbpHttpClientIdentityModelWebModule),
- typeof(AbpAspNetCoreComponentsServerLeptonXLiteThemeModule),
- typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule),
- typeof(AbpAutofacModule),
- typeof(AbpSwashbuckleModule),
- typeof(AbpAspNetCoreSerilogModule),
- typeof(AbpIdentityBlazorServerModule),
- typeof(AbpTenantManagementBlazorServerModule),
- typeof(AbpSettingManagementBlazorServerModule)
- )]
- public class BookStoreBlazorModule : AbpModule
- {
- public override void PreConfigureServices(ServiceConfigurationContext context)
- {
- context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
- {
- options.AddAssemblyResource(
- typeof(BookStoreResource),
- typeof(BookStoreDomainSharedModule).Assembly,
- typeof(BookStoreApplicationContractsModule).Assembly,
- typeof(BookStoreBlazorModule).Assembly
- );
- });
-
- PreConfigure<AbpAspNetCoreComponentsWebOptions>(options =>
- {
- options.IsBlazorWebApp = true;
- });
- }
-
- public override void ConfigureServices(ServiceConfigurationContext context)
- {
- var hostingEnvironment = context.Services.GetHostingEnvironment();
- var configuration = context.Services.GetConfiguration();
-
- // Add services to the container.
- context.Services.AddRazorComponents()
- .AddInteractiveServerComponents()
- .AddInteractiveWebAssemblyComponents();
-
- ConfigureUrls(configuration);
- ConfigureCache();
- ConfigureBundles();
- ConfigureMultiTenancy();
- ConfigureAuthentication(context, configuration);
- ConfigureAutoMapper();
- ConfigureVirtualFileSystem(hostingEnvironment);
- ConfigureBlazorise(context);
- ConfigureRouter(context);
- ConfigureMenu(configuration);
- ConfigureDataProtection(context, configuration, hostingEnvironment);
- ConfigureDistributedLocking(context, configuration);
- ConfigureSwaggerServices(context.Services);
- }
-
- private void ConfigureUrls(IConfiguration configuration)
- {
- Configure<AppUrlOptions>(options =>
- {
- options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
- });
- }
-
- private void ConfigureCache()
- {
- Configure<AbpDistributedCacheOptions>(options =>
- {
- options.KeyPrefix = "BookStore:";
- });
- }
-
- private void ConfigureBundles()
- {
- Configure<AbpBundlingOptions>(options =>
- {
- // MVC UI
- options.StyleBundles.Configure(
- LeptonXLiteThemeBundles.Styles.Global,
- bundle =>
- {
- bundle.AddFiles("/global-styles.css");
- }
- );
-
- //BLAZOR UI
- options.StyleBundles.Configure(
- BlazorLeptonXLiteThemeBundles.Styles.Global,
- bundle =>
- {
- bundle.AddFiles("/blazor-global-styles.css");
- //You can remove the following line if you don't use Blazor CSS isolation for components
- bundle.AddFiles(new BundleFile("/Acme.BookStore.Blazor.WebApp.Tiered.Client.styles.css", true));
- }
- );
- });
- }
-
- private void ConfigureMultiTenancy()
- {
- Configure<AbpMultiTenancyOptions>(options =>
- {
- options.IsEnabled = MultiTenancyConsts.IsEnabled;
- });
- }
-
- private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
- {
- context.Services.AddAuthentication(options =>
- {
- options.DefaultScheme = "Cookies";
- options.DefaultChallengeScheme = "oidc";
- })
- .AddCookie("Cookies", options =>
- {
- options.ExpireTimeSpan = TimeSpan.FromDays(365);
- options.IntrospectAccessToken();
- })
- .AddAbpOpenIdConnect("oidc", options =>
- {
- options.Authority = configuration["AuthServer:Authority"];
- options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata");
- options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
-
- options.ClientId = configuration["AuthServer:ClientId"];
- options.ClientSecret = configuration["AuthServer:ClientSecret"];
-
- options.SaveTokens = true;
- options.GetClaimsFromUserInfoEndpoint = true;
-
- options.Scope.Add("roles");
- options.Scope.Add("email");
- options.Scope.Add("phone");
- options.Scope.Add("BookStore");
- });
- /*
- * This configuration is used when the AuthServer is running on the internal network such as docker or k8s.
- * Configuring the redirecting URLs for internal network and the web
- * The login and the logout URLs are configured to redirect to the AuthServer real DNS for browser.
- * The token acquired and validated from the the internal network AuthServer URL.
- */
- if (configuration.GetValue<bool>("AuthServer:IsContainerized"))
- {
- context.Services.Configure<OpenIdConnectOptions>("oidc", options =>
- {
- options.TokenValidationParameters.ValidIssuers = new[]
- {
- configuration["AuthServer:MetaAddress"]!.EnsureEndsWith('/'),
- configuration["AuthServer:Authority"]!.EnsureEndsWith('/')
- };
-
- options.MetadataAddress = configuration["AuthServer:MetaAddress"]!.EnsureEndsWith('/') +
- ".well-known/openid-configuration";
-
- var previousOnRedirectToIdentityProvider = options.Events.OnRedirectToIdentityProvider;
- options.Events.OnRedirectToIdentityProvider = async ctx =>
- {
- // Intercept the redirection so the browser navigates to the right URL in your host
- ctx.ProtocolMessage.IssuerAddress = configuration["AuthServer:Authority"]!.EnsureEndsWith('/') + "connect/authorize";
-
- if (previousOnRedirectToIdentityProvider != null)
- {
- await previousOnRedirectToIdentityProvider(ctx);
- }
- };
- var previousOnRedirectToIdentityProviderForSignOut = options.Events.OnRedirectToIdentityProviderForSignOut;
- options.Events.OnRedirectToIdentityProviderForSignOut = async ctx =>
- {
- // Intercept the redirection for signout so the browser navigates to the right URL in your host
- ctx.ProtocolMessage.IssuerAddress = configuration["AuthServer:Authority"]!.EnsureEndsWith('/') + "connect/logout";
-
- if (previousOnRedirectToIdentityProviderForSignOut != null)
- {
- await previousOnRedirectToIdentityProviderForSignOut(ctx);
- }
- };
- });
- }
-
- context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
- {
- options.IsDynamicClaimsEnabled = true;
- });
- }
-
- private void ConfigureVirtualFileSystem(IWebHostEnvironment hostingEnvironment)
- {
- if (hostingEnvironment.IsDevelopment())
- {
- Configure<AbpVirtualFileSystemOptions>(options =>
- {
- options.FileSets.ReplaceEmbeddedByPhysical<BookStoreDomainSharedModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Acme.BookStore.Domain.Shared"));
- options.FileSets.ReplaceEmbeddedByPhysical<BookStoreApplicationContractsModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}Acme.BookStore.Application.Contracts"));
- options.FileSets.ReplaceEmbeddedByPhysical<BookStoreBlazorModule>(hostingEnvironment.ContentRootPath);
- });
- }
- }
-
- private void ConfigureBlazorise(ServiceConfigurationContext context)
- {
- context.Services
- .AddBootstrap5Providers()
- .AddFontAwesomeIcons();
- }
-
- private void ConfigureMenu(IConfiguration configuration)
- {
- Configure<AbpNavigationOptions>(options =>
- {
- options.MenuContributors.Add(new BookStoreMenuContributor(configuration));
- });
-
- Configure<AbpToolbarOptions>(options =>
- {
- options.Contributors.Add(new BookStoreToolbarContributor());
- });
- }
-
- private void ConfigureRouter(ServiceConfigurationContext context)
- {
- Configure<AbpRouterOptions>(options =>
- {
- options.AppAssembly = typeof(BookStoreBlazorModule).Assembly;
- options.AdditionalAssemblies.Add(typeof(BookStoreBlazorClientModule).Assembly);
- });
- }
-
- private void ConfigureAutoMapper()
- {
- Configure<AbpAutoMapperOptions>(options =>
- {
- options.AddMaps<BookStoreBlazorModule>();
- });
- }
-
- private void ConfigureSwaggerServices(IServiceCollection services)
- {
- services.AddAbpSwaggerGen(
- options =>
- {
- options.SwaggerDoc("v1", new OpenApiInfo { Title = "BookStore 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("BookStore");
- if (!hostingEnvironment.IsDevelopment())
- {
- var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
- dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "BookStore-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());
- });
- }
-
- public override void OnApplicationInitialization(ApplicationInitializationContext context)
- {
- var env = context.GetEnvironment();
- var app = context.GetApplicationBuilder();
-
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
-
- app.UseAbpRequestLocalization();
-
- if (!env.IsDevelopment())
- {
- app.UseErrorPage();
- }
-
- app.UseCorrelationId();
- app.UseStaticFiles();
- app.UseRouting();
- app.UseAuthentication();
-
- if (MultiTenancyConsts.IsEnabled)
- {
- app.UseMultiTenancy();
- }
- app.UseDynamicClaims();
- app.UseAntiforgery();
- app.UseAuthorization();
- app.UseSwagger();
- app.UseAbpSwaggerUI(options =>
- {
- options.SwaggerEndpoint("/swagger/v1/swagger.json", "BookStore API");
- });
- app.UseAbpSerilogEnrichers();
- app.UseConfiguredEndpoints(builder =>
- {
- builder.MapRazorComponents<App>()
- .AddInteractiveServerRenderMode()
- .AddInteractiveWebAssemblyRenderMode()
- .AddAdditionalAssemblies(builder.ServiceProvider.GetRequiredService<IOptions<AbpRouterOptions>>().Value.AdditionalAssemblies.ToArray());
- });
- }
- }
|