erp-platform/api/src/Kurs.Platform.HttpApi.Host/PlatformHttpApiHostModule.cs
Sedat Öztürk 697c7c1d65 Dosya Yöneticisi
File exists, Toolbar ve style güncellemeleri
2025-10-26 19:27:19 +03:00

422 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Hangfire;
using Hangfire.PostgreSql;
using Kurs.Languages;
using Kurs.MailQueue;
using Kurs.Notifications.Application;
using Kurs.Platform.Classrooms;
using Kurs.Platform.EntityFrameworkCore;
using Kurs.Platform.Extensions;
using Kurs.Platform.FileManagement;
using Kurs.Platform.Identity;
using Kurs.Platform.Localization;
using Kurs.Settings;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using OpenIddict.Server.AspNetCore;
using OpenIddict.Validation.AspNetCore;
using Volo.Abp;
using Volo.Abp.Account.Web;
using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.BackgroundWorkers.Hangfire;
using Volo.Abp.BlobStoring;
using Volo.Abp.BlobStoring.FileSystem;
using Volo.Abp.Caching;
using Volo.Abp.Hangfire;
using Volo.Abp.Identity;
using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Swashbuckle;
using Volo.Abp.UI.Navigation.Urls;
using Volo.Abp.VirtualFileSystem;
using static Kurs.Platform.PlatformConsts;
using static Kurs.Settings.SettingsConsts;
namespace Kurs.Platform;
[DependsOn(
typeof(PlatformHttpApiModule),
typeof(AbpAutofacModule),
typeof(AbpAspNetCoreMultiTenancyModule),
typeof(PlatformApplicationModule),
typeof(PlatformEntityFrameworkCoreModule),
typeof(AbpAspNetCoreMvcUiBasicThemeModule),
typeof(AbpAccountWebOpenIddictModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpSwashbuckleModule),
typeof(AbpBackgroundWorkersHangfireModule)
)]
public class PlatformHttpApiHostModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<OpenIddictBuilder>(builder =>
{
builder.AddServer(server =>
{
server.SetAccessTokenLifetime(TimeSpan.FromMinutes(60));
server.SetRefreshTokenLifetime(TimeSpan.FromMinutes(90));
});
builder.AddValidation(options =>
{
options.AddAudiences(PlatformConsts.AppName);
options.UseLocalServer();
options.UseAspNetCore();
});
});
PreConfigure<IdentityBuilder>(builder =>
{
builder.AddClaimsPrincipalFactory<PlatformUserClaimsPrincipalFactory>();
builder.AddSignInManager<PlatformSignInManager>();
});
context.Services.Replace(
ServiceDescriptor.Transient<AbpUserClaimsPrincipalFactory, PlatformUserClaimsPrincipalFactory>());
context.Services.AddTransient<IPlatformSignInManager, PlatformSignInManager>();
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
//Tenant bazında lokalizasyon ayarları için
//TenantLocalization Middleware kaydı
context.Services.AddTransient<TenantLocalizationMiddleware>();
context.Services.AddTransient<TenantLocalizationInitializer>();
ConfigureAuthentication(context);
ConfigureBundles();
ConfigureUrls(configuration);
ConfigureConventionalControllers();
//Localization'ı veritabanından kullandıgımız icin bir json resource kullanmıyoruz
//Dolayısıyla şimdilik ihtiyacımız yok ama ileride başka bir sebepten kullanabiliriz diye silmedik
//ConfigureVirtualFileSystem(context);
ConfigureCors(context, configuration);
ConfigureSwaggerServices(context, configuration);
ConfigureIdentity(configuration);
ConfigureCache();
ConfigureHangfire(context, configuration);
ConfigureBlobStoring(configuration);
ConfigureAuditing();
context.Services.AddSignalR();
Configure<AbpExceptionHttpStatusCodeOptions>(options =>
{
options.Map(AppErrorCodes.NoAuth, System.Net.HttpStatusCode.Unauthorized);
});
Configure<OpenIddictServerAspNetCoreOptions>(options =>
{
options.DisableTransportSecurityRequirement = true;
});
Configure<AbpApplicationConfigurationOptions>(options =>
{
options.Contributors.AddIfNotContains(new PlatformApplicationConfigurationContributor());
});
}
private void ConfigureAuthentication(ServiceConfigurationContext context)
{
context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
}
private void ConfigureBundles()
{
Configure<AbpBundlingOptions>(options =>
{
options.StyleBundles.Configure(
BasicThemeBundles.Styles.Global,
bundle =>
{
bundle.AddFiles("/global-styles.css");
}
);
});
}
private void ConfigureUrls(IConfiguration configuration)
{
Configure<AppUrlOptions>(options =>
{
options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"]?.Split(',') ?? Array.Empty<string>());
options.Applications[PlatformConsts.React].RootUrl = configuration["App:ClientUrl"];
options.Applications[PlatformConsts.React].Urls[PlatformConsts.Urls.EmailConfirmation] = "account/confirm";
options.Applications[PlatformConsts.React].Urls[PlatformConsts.Urls.PasswordReset] = "account/reset-password";
options.Applications[PlatformConsts.React].Urls[PlatformConsts.Urls.UserDetail] = "account/{0}";
//options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
//options.Applications["MVC"].Urls[PlatformConsts.Urls.EmailConfirmation] = "Account/Confirm";
//options.Applications["MVC"].Urls[PlatformConsts.Urls.TwoFactor] = "Account/TwoFactor";
//options.Applications["MVC"].Urls[PlatformConsts.Urls.Login] = "Account/Login";
//options.Applications["MVC"].Urls[PlatformConsts.Urls.UserDetail] = "Identity/Users/Detail";
});
}
private void ConfigureConventionalControllers()
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(PlatformApplicationModule).Assembly, opts =>
{
opts.TypePredicate = t => t.Namespace == "Kurs.Platform.ListForms.Administration";
opts.RootPath = "admin";
});
options.ConventionalControllers.Create(typeof(PlatformApplicationModule).Assembly, opts =>
{
opts.TypePredicate = t => t.Namespace != "Kurs.Platform.ListForms.Administration";
opts.RootPath = "app";
});
options.ConventionalControllers.Create(typeof(LanguagesApplicationModule).Assembly);
options.ConventionalControllers.Create(typeof(SettingsApplicationModule).Assembly);
options.ConventionalControllers.Create(typeof(KursMailQueueModule).Assembly);
options.ConventionalControllers.Create(typeof(NotificationApplicationModule).Assembly);
options.ChangeControllerModelApiExplorerGroupName = false;
options.ConventionalControllers.FormBodyBindingIgnoredTypes.Add(typeof(PlatformUpdateProfileDto));
options.ConventionalControllers.FormBodyBindingIgnoredTypes.Add(typeof(UploadFileDto));
});
}
private void ConfigureVirtualFileSystem(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
if (hostingEnvironment.IsDevelopment())
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.ReplaceEmbeddedByPhysical<PlatformDomainSharedModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}Kurs.Platform.Domain.Shared"));
options.FileSets.ReplaceEmbeddedByPhysical<PlatformDomainModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}Kurs.Platform.Domain"));
options.FileSets.ReplaceEmbeddedByPhysical<PlatformApplicationContractsModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}Kurs.Platform.Application.Contracts"));
options.FileSets.ReplaceEmbeddedByPhysical<PlatformApplicationModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}Kurs.Platform.Application"));
options.FileSets.ReplaceEmbeddedByPhysical<KursMailQueueModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}Kurs.MailQueue"));
});
}
}
private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder
.WithOrigins(configuration["App:CorsOrigins"]?
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray() ?? Array.Empty<string>())
.WithAbpExposedHeaders()
.WithExposedHeaders(["X-Correlation-Id"])
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
}
private void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAbpSwaggerGenWithOAuth(
configuration["AuthServer:Authority"],
new Dictionary<string, string>
{
{"Platform", "Platform API"}
},
options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "Platform API", Version = "v1" });
options.DocInclusionPredicate((docName, description) => true);
options.CustomSchemaIds(type => type.FullName);
});
}
private void ConfigureIdentity(IConfiguration configuration)
{
//Veritabanından yonetildigi icin bunlar kapatildi
//Configure<IdentityOptions>(options =>
//{
// options.SignIn.RequireConfirmedEmail = true;
// options.SignIn.RequireConfirmedAccount = true;
// options.SignIn.RequireConfirmedPhoneNumber = false;
// options.User.RequireUniqueEmail = true;
// options.Lockout.AllowedForNewUsers = true;
// options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
// options.Lockout.MaxFailedAccessAttempts = 5;
// options.Password.RequiredLength = 6;
// options.Password.RequiredUniqueChars = 0;
// options.Password.RequireNonAlphanumeric = false;
// options.Password.RequireLowercase = false;
// options.Password.RequireUppercase = false;
// options.Password.RequireDigit = false;
//});
Configure<PlatformIdentityOptions>(configuration.GetSection(PlatformConsts.AbpIdentity.GroupName));
}
private void ConfigureCache()
{
Configure<AbpDistributedCacheOptions>(options =>
{
options.KeyPrefix = PlatformConsts.AppName;
});
Configure<RedisCacheOptions>(options =>
{
});
}
private void ConfigureHangfire(ServiceConfigurationContext context, IConfiguration configuration)
{
Configure<AbpHangfireOptions>(options =>
{
options.ServerOptions = new BackgroundJobServerOptions()
{
Queues = ["default", "platform"]
};
});
context.Services.AddHangfire(config =>
{
switch (DefaultDatabaseProvider)
{
case DatabaseProvider.PostgreSql:
config.UsePostgreSqlStorage(c =>
c.UseNpgsqlConnection(configuration.GetConnectionString(DefaultDatabaseProvider)));
break;
case DatabaseProvider.SqlServer:
config.UseSqlServerStorage(configuration.GetConnectionString(DefaultDatabaseProvider));
break;
default:
throw new InvalidOperationException("Unsupported database provider configured for Hangfire.");
}
});
}
private void ConfigureBlobStoring(IConfiguration configuration)
{
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureDefault(container =>
{
container.UseFileSystem(fileSystem =>
{
fileSystem.BasePath = configuration["App:CdnPath"];
});
});
});
}
private void ConfigureAuditing()
{
Configure<AbpAspNetCoreAuditingOptions>(options =>
{
options.IgnoredUrls.Add("/api/app/list-form-customization");
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAbpRequestLocalization();
// Auth hataları MVC tarafından /Error sayfasına yönlendirilmesin diye bu kaldırıldı
// if (!env.IsDevelopment())
// {
// app.UseErrorPage();
// }
app.UseCorrelationId();
app.MapAbpStaticAssets();
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseAbpOpenIddictValidation();
app.UseMiddleware<CaptchaMiddleware>();
if (PlatformConsts.IsMultiTenant)
{
app.UseMultiTenancy();
app.UseMiddleware<TenantLocalizationMiddleware>();
}
app.UseUnitOfWork();
app.UseDynamicClaims();
app.UseAuthorization();
app.UseSwagger();
app.UseAbpSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Platform API");
var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
c.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
c.OAuthScopes("Platform");
});
app.UseAuditing();
app.UseAbpSerilogEnrichers();
if (env.IsDevelopment())
{
app.UseHangfireDashboard();
}
else
{
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
AsyncAuthorization = [new AbpHangfireAuthorizationFilter()]
});
}
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ClassroomHub>("/classroomhub");
});
app.UseConfiguredEndpoints();
}
}