erp-platform/api/src/Kurs.Platform.HttpApi.Host/PlatformHttpApiHostModule.cs

423 lines
16 KiB
C#
Raw Normal View History

2025-05-06 06:45:49 +00:00
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;
2025-05-06 06:45:49 +00:00
using Kurs.Platform.EntityFrameworkCore;
using Kurs.Platform.Extensions;
using Kurs.Platform.FileManagement;
2025-05-06 06:45:49 +00:00
using Kurs.Platform.Identity;
using Kurs.Platform.Localization;
2025-05-06 06:45:49 +00:00
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;
2025-05-06 06:45:49 +00:00
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;
2025-06-11 06:44:27 +00:00
using static Kurs.Settings.SettingsConsts;
2025-05-06 06:45:49 +00:00
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>();
2025-10-25 23:42:35 +00:00
2025-05-06 06:45:49 +00:00
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();
2025-05-06 06:45:49 +00:00
2025-08-27 20:55:01 +00:00
context.Services.AddSignalR();
2025-05-06 06:45:49 +00:00
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));
2025-05-06 06:45:49 +00:00
});
}
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 =>
{
2025-05-06 08:04:37 +00:00
options.SwaggerDoc("v1", new OpenApiInfo { Title = "Platform API", Version = "v1" });
2025-05-06 06:45:49 +00:00
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 =>
{
2025-06-10 20:34:46 +00:00
switch (DefaultDatabaseProvider)
{
case DatabaseProvider.PostgreSql:
config.UsePostgreSqlStorage(c =>
2025-06-11 06:44:27 +00:00
c.UseNpgsqlConnection(configuration.GetConnectionString(DefaultDatabaseProvider)));
2025-06-10 20:34:46 +00:00
break;
case DatabaseProvider.SqlServer:
2025-06-11 06:44:27 +00:00
config.UseSqlServerStorage(configuration.GetConnectionString(DefaultDatabaseProvider));
2025-06-10 20:34:46 +00:00
break;
default:
throw new InvalidOperationException("Unsupported database provider configured for Hangfire.");
}
2025-05-06 06:45:49 +00:00
});
}
private void ConfigureBlobStoring(IConfiguration configuration)
{
Configure<AbpBlobStoringOptions>(options =>
{
2025-10-25 23:42:35 +00:00
options.Containers.ConfigureDefault(container =>
{
container.UseFileSystem(fileSystem =>
{
fileSystem.BasePath = configuration["App:CdnPath"];
});
});
2025-05-06 06:45:49 +00:00
});
}
private void ConfigureAuditing()
{
Configure<AbpAspNetCoreAuditingOptions>(options =>
{
options.IgnoredUrls.Add("/api/app/list-form-customization");
});
}
2025-05-06 06:45:49 +00:00
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>();
2025-05-06 06:45:49 +00:00
}
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()]
});
}
2025-08-27 20:55:01 +00:00
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ClassroomHub>("/classroomhub");
});
2025-05-06 06:45:49 +00:00
app.UseConfiguredEndpoints();
}
}