804 lines
37 KiB
C#
804 lines
37 KiB
C#
using Azure.Storage.Blobs;
|
||
using Microsoft.ApplicationInsights.Extensibility;
|
||
using Microsoft.AspNetCore;
|
||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||
using Microsoft.AspNetCore.Authorization;
|
||
using Microsoft.AspNetCore.Builder;
|
||
using Microsoft.AspNetCore.DataProtection;
|
||
using Microsoft.AspNetCore.Hosting;
|
||
using Microsoft.AspNetCore.Http;
|
||
using Microsoft.AspNetCore.Http.Features;
|
||
using Microsoft.AspNetCore.Identity;
|
||
using Microsoft.AspNetCore.Localization;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.Configuration;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||
using Microsoft.Extensions.Hosting;
|
||
using Microsoft.Extensions.Logging;
|
||
using Microsoft.Extensions.Options;
|
||
using Microsoft.IdentityModel.Tokens;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Globalization;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Net.Http.Headers;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using gehGassi.Common;
|
||
using gehGassi.Core.Interfaces;
|
||
using gehGassi.Core.Services;
|
||
using gehGassi.Domain.Localization;
|
||
using gehGassi.Domain.Roles;
|
||
using gehGassi.Domain.Users;
|
||
using gehGassi.External.Services;
|
||
using gehGassi.Persistence;
|
||
using gehGassi.Pwned;
|
||
using gehGassi.Web.Auth;
|
||
using gehGassi.Web.Auth.AuthorizationHandlers;
|
||
using gehGassi.Web.Auth.Requirements;
|
||
using gehGassi.Web.Helper;
|
||
using gehGassi.Web.Hubs;
|
||
using gehGassi.Web.Services;
|
||
using Microsoft.Graph;
|
||
using Newtonsoft.Json;
|
||
using BackgroundService = gehGassi.Web.BackgroundServices.BackgroundService;
|
||
using WebApplication = Microsoft.AspNetCore.Builder.WebApplication;
|
||
using Microsoft.Graph.Models;
|
||
using Asp.Versioning;
|
||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||
using gehGassi.Web.Controllers.WebsiteApi;
|
||
using gehGassi.Klarna.Checkout;
|
||
|
||
var builder = WebApplication.CreateBuilder(args);
|
||
if (builder.Environment.EnvironmentName == "Live")
|
||
{
|
||
builder.Logging.AddAzureWebAppDiagnostics();
|
||
}
|
||
|
||
var defaultCulture = builder.Configuration.GetSection("LocalizationOptions")?["DefaultCulture"].ToString();
|
||
var availableLanguages = builder.Configuration.GetSection("LocalizationOptions")?["Languages"].ToString();
|
||
var sessionTimeout = int.Parse(builder.Configuration.GetSection("SessionSettings")?["ClientTimeOut"]);
|
||
var sessionTimeoutBackend = int.Parse(builder.Configuration.GetSection("SessionSettings")?["TimeOut"]);
|
||
|
||
//Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("ORg4AjUWIQA/Gnt2VVhjQlFac1lJXGFWfVJpTGpQdk5xdV9DaVZUTWY/P1ZhSXxRd0RiXX5cdHxRR2JZWEY=;NRAiBiAaIQQuGjN/V0Z+X09EaFpEVmJLYVB3WmpQdldgdVRMZVVbQX9PIiBoS35RdERiWHtfcnBdQmFeVkZ0;Mgo+DSMBMAY9C3t2VVhjQlFac1lJXGFWfVJpTGpQdk5xdV9DaVZUTWY/P1ZhSXxRd0RiXX5cdHxRR2JUVEY=");
|
||
//Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("ORg4AjUWIQA/Gnt2VVhkQlFacltJXGFWfVJpTGpQdk5xdV9DaVZUTWY/P1ZhSXxQdkRhXX9Xc3NQQmFYWUc=;NRAiBiAaIQQuGjN/V0Z+WE9EaFtGVmJLYVB3WmpQdldgdVRMZVVbQX9PIiBoS35RdUViW3teeXdSQ2RdV0F1;Mgo+DSMBMAY9C3t2VVhkQlFacltJXGFWfVJpTGpQdk5xdV9DaVZUTWY/P1ZhSXxQdkRhXX9Xc3NQQmJdWUc=");
|
||
//Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("NRAiBiAaIQQuGjN/V0J+XU9Ad1RDX3xKf0x/TGpQb19xflBPallYVBYiSV9jS3pTd0RqWXpcdnZRRGVVUA==;Mgo+DSMBMAY9C3t2UVhhQlVFfV5AQmBIYVp/TGpJfl96cVxMZVVBJAtUQF1hTX5Sd0xjXH1YcnBXQWRb");
|
||
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("Ngo9BigBOggjHTQxAR8/V1NHaF5cWWdCf1FpRmJGdld5fUVHYVZUTXxaS00DNHVRdkdnWX5feXRQQ2NcUUx+Vko=");
|
||
|
||
builder.Services.Configure<CookiePolicyOptions>(options =>
|
||
{
|
||
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
|
||
options.CheckConsentNeeded = context => true;
|
||
options.MinimumSameSitePolicy = SameSiteMode.None;
|
||
options.Secure = CookieSecurePolicy.Always;
|
||
});
|
||
|
||
builder.Services.AddDbContext<SqlDbContext>(options =>
|
||
options.UseSqlServer(builder.Configuration.GetConnectionString("SqlDbContext"),
|
||
sqlOptions => sqlOptions.UseNetTopologySuite().MigrationsAssembly(typeof(SqlDbContext).Assembly.GetName().Name)));
|
||
|
||
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||
builder.Services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
|
||
builder.Services.AddSingleton<IScriptVersionCalculator, ScriptVersionCalculator>();
|
||
builder.Services.TryAddSingleton<PartialViewResultExecutor>();
|
||
builder.Services.TryAddSingleton<ViewResultExecutor>();
|
||
builder.Services.AddSingleton<Microsoft.Extensions.Localization.IStringLocalizerFactory, FixedStringLocalizerFactory>();
|
||
|
||
builder.Services.Configure<RequestLocalizationOptions>(o =>
|
||
{
|
||
var supportedCultures = new List<CultureInfo>();
|
||
foreach (var lang in availableLanguages.Split(","))
|
||
{
|
||
supportedCultures.Add(new CultureInfo(lang));
|
||
}
|
||
|
||
o.DefaultRequestCulture = new RequestCulture(new CultureInfo(defaultCulture));
|
||
// Formatting numbers, dates, etc.
|
||
o.SupportedCultures = supportedCultures;
|
||
// UI strings that we have localized.
|
||
o.SupportedUICultures = supportedCultures;
|
||
o.RequestCultureProviders.Clear();
|
||
o.RequestCultureProviders = new List<IRequestCultureProvider>
|
||
{
|
||
// Order is important, its in which order they will be evaluated
|
||
new RouteValueRequestCultureProvider(){Options = o},
|
||
new CookieRequestCultureProvider(),
|
||
new QueryStringRequestCultureProvider(),
|
||
new AcceptLanguageHeaderRequestCultureProvider()
|
||
};
|
||
//var requestProvider = o.RequestCultureProviders.OfType<AcceptLanguageHeaderRequestCultureProvider>().FirstOrDefault();
|
||
//if (requestProvider != null)
|
||
// o.RequestCultureProviders.Remove(requestProvider);
|
||
});
|
||
|
||
//Statische Variable als Hilfe f<>r "ILocalizable" und LocalizableBase
|
||
LocalizableHelper.DefaultLanguage = defaultCulture;
|
||
LocalizableHelper.Languages = availableLanguages;
|
||
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo(defaultCulture);
|
||
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(defaultCulture);
|
||
|
||
builder.Services.Configure<LocalizationOptions>(builder.Configuration.GetSection("LocalizationOptions"));
|
||
builder.Services.Configure<EmailSenderOptions>(builder.Configuration.GetSection("EmailSenderOptions"));
|
||
builder.Services.Configure<LicenseOptions>(builder.Configuration.GetSection("LicenseOptions"));
|
||
builder.Services.Configure<AuthOptions>(builder.Configuration.GetSection("AuthOptions"));
|
||
builder.Services.Configure<SessionSettings>(builder.Configuration.GetSection("SessionSettings"));
|
||
builder.Services.Configure<SystemJsOptions>(builder.Configuration.GetSection("SystemJsOptions"));
|
||
builder.Services.Configure<AuditOptions>(builder.Configuration.GetSection("AuditOptions"));
|
||
builder.Services.Configure<VatValidationSettings>(builder.Configuration.GetSection("VatValidation"));
|
||
builder.Services.Configure<ApplicationInsightsOptions>(builder.Configuration.GetSection("ApplicationInsightsOptions"));
|
||
builder.Services.Configure<Fido2Options>(builder.Configuration.GetSection("fido2"));
|
||
builder.Services.Configure<JwtTokenOptions>(builder.Configuration.GetSection("JWT"));
|
||
builder.Services.Configure<FileServiceModeOptions>(builder.Configuration.GetSection("FileServiceModeOptions"));
|
||
builder.Services.Configure<WebJobApiOptions>(builder.Configuration.GetSection("WebJobApi"));
|
||
builder.Services.Configure<CachingOptions>(builder.Configuration.GetSection("CachingOptions"));
|
||
builder.Services.Configure<BackgroundServiceOptions>(builder.Configuration.GetSection("BackgroundServiceOptions"));
|
||
builder.Services.Configure<GeoLocationOptions>(builder.Configuration.GetSection("GeoLocationOptions"));
|
||
builder.Services.Configure<ListingOptions>(builder.Configuration.GetSection("ListingOptions"));
|
||
builder.Services.Configure<ShopOptions>(builder.Configuration.GetSection("ShopOptions"));
|
||
builder.Services.Configure<AppleOptions>(builder.Configuration.GetSection("AppleOptions"));
|
||
builder.Services.Configure<MangoPayOptions>(builder.Configuration.GetSection("MangoPayOptions"));
|
||
builder.Services.Configure<PushNotificationOptions>(builder.Configuration.GetSection("PushNotificationOptions"));
|
||
builder.Services.Configure<WalkComplaintOptions>(builder.Configuration.GetSection("WalkComplaintOptions"));
|
||
builder.Services.Configure<CoinsOptions>(builder.Configuration.GetSection("CoinsOptions"));
|
||
builder.Services.Configure<MinCoinsForPot>(builder.Configuration.GetSection("MinCoinsForPot"));
|
||
builder.Services.AddTransient<IEmailSender, EmailSender>();
|
||
builder.Services.AddScoped<DbContext, SqlDbContext>();
|
||
builder.Services.AddScoped<IAuditDbContext, SqlDbContext>();
|
||
builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();
|
||
builder.Services.AddScoped<ICurrentTimeZoneService, CurrentTimeZoneService>();
|
||
builder.Services.AddTransient<IKeyGeneratorService, KeyGeneratorService>();
|
||
|
||
builder.Services.Configure<CountryServiceOptions>(o =>
|
||
{
|
||
o.Languages = new List<string>(availableLanguages.Split(","));
|
||
o.Directory = "app_files\\countries";
|
||
});
|
||
builder.Services.AddSingleton<ICountryService, CountryService>();
|
||
|
||
builder.Services.Configure<EmailValidationOptions>(o =>
|
||
{
|
||
o.File = "app_files\\fakemails.csv";
|
||
});
|
||
builder.Services.AddSingleton<IEmailValidationService, EmailValidationService>();
|
||
|
||
builder.Services.AddTransient<IUserService, UserService>();
|
||
|
||
var useCloud = bool.Parse(builder.Configuration["FileServiceModeOptions:Cloud"]);
|
||
if (useCloud)
|
||
{
|
||
var azureStorageKey = builder.Configuration["FileServiceModeOptions:AzureStorage"];
|
||
builder.Services.AddScoped<IFileService>(s => new AzureBlobFileService(azureStorageKey));
|
||
builder.Services.AddScoped<IFileShareService>(s => new AzureStorageFileShareService(azureStorageKey));
|
||
}
|
||
else
|
||
{
|
||
builder.Services.AddScoped<IFileService>(s => new FileService(builder.Environment.WebRootPath + "\\app_files"));
|
||
builder.Services.AddScoped<IFileShareService>(s => new LocalFileShareService(builder.Environment.WebRootPath + "\\app_files\\shares"));
|
||
}
|
||
|
||
builder.Services.AddHttpClient<IGeoLocationService, GeoLocationService>(client =>
|
||
{
|
||
// Set the base address of the named client.
|
||
client.BaseAddress = new Uri(builder.Configuration.GetSection("GeoLocationOptions:BaseUri").Value ?? string.Empty);
|
||
// Add a user-agent default request header.
|
||
client.DefaultRequestHeaders.UserAgent.Add(
|
||
new ProductInfoHeaderValue(builder.Configuration.GetSection("GeoLocationOptions:UserAgentName").Value ?? string.Empty, builder.Configuration.GetSection("GeoLocationOptions:UserAgentVersion").Value ?? string.Empty)
|
||
);
|
||
});
|
||
|
||
builder.Services.AddScoped<IPayPalService, PayPalService>();
|
||
builder.Services.AddScoped<IKlarnaService, KlarnaService>();
|
||
builder.Services.AddScoped<IMangoPayService, MangoPayService>();
|
||
builder.Services.AddScoped<IVatValidationService, VatValidationService>();
|
||
builder.Services.AddTransient<IAuditService, AuditService>();
|
||
builder.Services.AddTransient<IFidoService, FidoService>();
|
||
builder.Services.AddTransient<ITokenService, TokenService>();
|
||
builder.Services.AddTransient<IRefreshTokenService, RefreshTokenService>();
|
||
builder.Services.AddTransient<IPersistedTicketService, PersistedTicketService>();
|
||
builder.Services.AddSingleton<ILanguageService, LanguageService>();
|
||
|
||
builder.Services.AddTransient<IShopCalculationService, ShopCalculationService>();
|
||
|
||
//Custom Services here
|
||
builder.Services.AddTransient<ICustomerTypeService, CustomerTypeService>();
|
||
builder.Services.AddTransient<ICustomerService, CustomerService>();
|
||
builder.Services.AddTransient<IAppUserService, AppUserService>();
|
||
builder.Services.AddTransient<IBranchService, BranchService>();
|
||
builder.Services.AddTransient<IAdvertisementCategoryService, AdvertisementCategoryService>();
|
||
builder.Services.AddTransient<IShopSettingsService, ShopSettingsService>();
|
||
builder.Services.AddTransient<IShipmentCostService, ShipmentCostService>();
|
||
builder.Services.AddTransient<ITaxRateService, TaxRateService>();
|
||
builder.Services.AddTransient<IProductCategoryService, ProductCategoryService>();
|
||
builder.Services.AddTransient<IProductService, ProductService>();
|
||
builder.Services.AddTransient<ICartService, CartService>();
|
||
builder.Services.AddTransient<IListingService, ListingService>();
|
||
builder.Services.AddTransient<IAdvertisementService, AdvertisementService>();
|
||
builder.Services.AddTransient<IBannerService, BannerService>();
|
||
builder.Services.AddTransient<IPinService, PinService>();
|
||
builder.Services.AddTransient<IOrderService, OrderService>();
|
||
builder.Services.AddTransient<IInvoiceService, InvoiceService>();
|
||
builder.Services.AddTransient<ICreditNoteService, CreditNoteService>();
|
||
builder.Services.AddTransient<IDogRaceService, DogRaceService>();
|
||
builder.Services.AddTransient<IDogService, DogService>();
|
||
builder.Services.AddTransient<INewsCategoryService, NewsCategoryService>();
|
||
builder.Services.AddTransient<INewsService, NewsService>();
|
||
builder.Services.AddTransient<IAppUserRelationService, AppUserRelationService>();
|
||
builder.Services.AddTransient<IMessageService, MessageService>();
|
||
builder.Services.AddTransient<IPageService, PageService>();
|
||
builder.Services.AddTransient<IFaqService, FaqService>();
|
||
builder.Services.AddTransient<IPublicWalkRequestService, PublicWalkRequestService>();
|
||
builder.Services.AddTransient<IPublicWalkResponseService, PublicWalkResponseService>();
|
||
builder.Services.AddTransient<IWalkService, WalkService>();
|
||
builder.Services.AddTransient<IWalkComplaintService, WalkComplaintService>();
|
||
builder.Services.AddTransient<IWalkingTimeService, WalkingTimeService>();
|
||
builder.Services.AddTransient<IRatingService, RatingService>();
|
||
builder.Services.AddTransient<IAppFeedbackService, AppFeedbackService>();
|
||
builder.Services.AddTransient<IFavouriteService, FavouritesService>();
|
||
builder.Services.AddTransient<ISystemMessageService, SystemMessageService>();
|
||
builder.Services.AddTransient<IDeviceService, DeviceService>();
|
||
builder.Services.AddTransient<IPushNotificationService, PushNotificationService>();
|
||
builder.Services.AddTransient<IUserOnlineService, UserOnlineService>();
|
||
builder.Services.AddTransient<IWalletService, WalletService>();
|
||
builder.Services.AddTransient<ITransactionFeeService, TransactionFeeService>();
|
||
builder.Services.AddTransient<IPaymentTransactionService, PaymentTransactionService>();
|
||
builder.Services.AddTransient<IIdentityDocumentService, IdentityDocumentService>();
|
||
builder.Services.AddTransient<IPayoutService, PayoutService>();
|
||
builder.Services.AddTransient<IStatisticService, StatistcService>();
|
||
builder.Services.AddTransient<IAppUserReportService, AppUserReportService>();
|
||
builder.Services.AddTransient<ICoinsService, CoinsService>();
|
||
builder.Services.AddTransient<IAppVersionService, AppVersionService>();
|
||
builder.Services.AddTransient<IVoucherCampaignService, VoucherCampaignService>();
|
||
builder.Services.AddTransient<ISubscriptionService, SubscriptionService>();
|
||
|
||
builder.Services.AddScoped<IPlaceHolderService>(s => new PlaceHolderService(builder.Environment.WebRootPath + "\\app_files\\placeholders"));
|
||
|
||
builder.Services.AddSingleton<ISystemHubUsers, SystemHubUsers>();
|
||
builder.Services.AddSingleton<ISystemHubSender, SystemHubSender>();
|
||
|
||
builder.Services.AddSingleton<IAppHubUsers, AppHubUsers>();
|
||
builder.Services.AddSingleton<IAppHubSender, AppHubSender>();
|
||
|
||
builder.Services.AddHostedService<BackgroundService>();
|
||
|
||
#region DataProtection
|
||
|
||
var applicationNameForDataProtection = $"gehGassi-{builder.Environment.EnvironmentName}";
|
||
if (builder.Environment.IsEnvironment("Production") || builder.Environment.IsEnvironment("Staging") || builder.Environment.IsEnvironment("Live"))
|
||
{
|
||
applicationNameForDataProtection = "gehgassi";
|
||
}
|
||
var dataProtectionBuilder = builder.Services.AddDataProtection()
|
||
.SetApplicationName(applicationNameForDataProtection);
|
||
|
||
var dataProtectionMode = builder.Configuration["DataProtectionOptions:Mode"];
|
||
if (dataProtectionMode == "File")
|
||
dataProtectionBuilder.PersistKeysToFileSystem(new DirectoryInfo($@"{builder.Environment.ContentRootPath}\keys"));
|
||
else
|
||
{
|
||
var client = new BlobServiceClient(builder.Configuration["DataProtectionOptions:AzureStorage"]);
|
||
var container = client.GetBlobContainerClient("data-protection");
|
||
container.CreateIfNotExists();
|
||
var blobClient = container.GetBlobClient("keys.xml");
|
||
dataProtectionBuilder.PersistKeysToAzureBlobStorage(blobClient);
|
||
}
|
||
|
||
#endregion
|
||
|
||
builder.Services.AddMemoryCache();
|
||
//if (builder.Environment.IsEnvironment("Production") || builder.Environment.IsEnvironment("Staging"))
|
||
if (builder.Environment.IsEnvironment("Production") || builder.Environment.IsEnvironment("Live"))
|
||
{
|
||
builder.Services.AddStackExchangeRedisCache(options =>
|
||
{
|
||
options.Configuration = builder.Configuration["RedisOptions:ConnectionString"];
|
||
options.InstanceName = builder.Configuration["RedisOptions:InstanceName"];
|
||
});
|
||
}
|
||
else
|
||
builder.Services.AddDistributedMemoryCache();
|
||
|
||
builder.Services.Configure<DbInitializerOptions>(o =>
|
||
{
|
||
o.Directory = "app_files\\rolePermissions";
|
||
});
|
||
builder.Services.AddTransient<DbInitializer>();
|
||
|
||
builder.Services.AddPwned();
|
||
builder.Services.AddIdentity<ApplicationUser, ApplicationRole>(c =>
|
||
{
|
||
c.SignIn.RequireConfirmedEmail = true;
|
||
c.Password.RequireDigit = false;
|
||
c.Password.RequireLowercase = false;
|
||
c.Password.RequireNonAlphanumeric = false;
|
||
c.Password.RequireUppercase = false;
|
||
c.Password.RequiredUniqueChars = 0;
|
||
c.Password.RequiredLength = 12;
|
||
}).AddEntityFrameworkStores<SqlDbContext>()
|
||
.AddPwnedPasswordValidator<ApplicationUser>(builder.Configuration)
|
||
.AddDefaultTokenProviders()
|
||
.AddTokenProvider<DataProtectorTokenProvider<ApplicationUser>>("deleteAccount")
|
||
.AddErrorDescriber<LocalizedIdentityErrorDescriber>();
|
||
|
||
builder.Services.Configure<IdentityOptions>(o =>
|
||
{
|
||
o.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
|
||
o.Lockout.MaxFailedAccessAttempts = 5;
|
||
o.Lockout.AllowedForNewUsers = true;
|
||
});
|
||
|
||
builder.Services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, CustomClaimsPrincipalFactory>();
|
||
|
||
builder.Services.AddAuthorization(options =>
|
||
{
|
||
options.AddPolicy(Policies.AdministratorOnly, policy => policy.AddRequirements(new IsInRoleRequirement("Administrator")));
|
||
options.AddPolicy(Policies.PowerUserOnly, policy => policy.AddRequirements(new IsInRoleRequirement("Administrator", "PowerUser")));
|
||
options.AddPolicy(Policies.CustomerOnly, policy => policy.AddRequirements(new IsInRoleRequirement("Administrator", "PowerUser", "Customer")));
|
||
options.AddPolicy(Policies.AppUserOnly, policy => policy.AddRequirements(new IsInRoleRequirement("Administrator", "PowerUser", "AppUser")));
|
||
|
||
//options.AddPolicy("GivenName", policy => policy.RequireClaim(ClaimTypes.GivenName, "Florian"));
|
||
//options.AddPolicy("Special", policy => policy.RequireClaim(ClaimTypes.GivenName, "Florian"));
|
||
});
|
||
builder.Services.AddSingleton<IAuthorizationHandler, IsInRoleHandler>();
|
||
|
||
builder.Services.AddSingleton<ITicketStore, DistributedCachePersistedTicketStore>();
|
||
builder.Services.AddSingleton<IPostConfigureOptions<CookieAuthenticationOptions>, ConfigureCookieAuthenticationOptions>();
|
||
|
||
builder.Services.AddScoped<LocalizedCookieAuthenticationEvents>();
|
||
builder.Services.ConfigureApplicationCookie(o =>
|
||
{
|
||
o.Cookie.Name = "gehGassiCookie";
|
||
o.LoginPath = $"/{CultureInfo.CurrentCulture.TwoLetterISOLanguageName}/account/login";
|
||
o.AccessDeniedPath = $"/{CultureInfo.CurrentCulture.TwoLetterISOLanguageName}/account/accessdenied";
|
||
o.LogoutPath = $"/{CultureInfo.CurrentCulture.TwoLetterISOLanguageName}/account/Logout";
|
||
o.EventsType = typeof(LocalizedCookieAuthenticationEvents);
|
||
//o.Cookie.Expiration = TimeSpan.FromDays(30);
|
||
o.ExpireTimeSpan = TimeSpan.FromMinutes(sessionTimeoutBackend);
|
||
o.SlidingExpiration = true;
|
||
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
|
||
});
|
||
|
||
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
||
.AddJwtBearer(o =>
|
||
{
|
||
o.SaveToken = true;
|
||
o.TokenValidationParameters = new TokenValidationParameters()
|
||
{
|
||
ValidAudience = builder.Configuration["JWT:ValidAudience"],
|
||
ValidIssuer = builder.Configuration["JWT:ValidIssuer"],
|
||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JWT:Secret"]))
|
||
};
|
||
o.Events = new JwtBearerEvents
|
||
{
|
||
OnAuthenticationFailed = context =>
|
||
{
|
||
context.NoResult();
|
||
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
|
||
return Task.CompletedTask;
|
||
},
|
||
OnMessageReceived = context =>
|
||
{
|
||
var accessToken = context.Request.Query["access_token"];
|
||
|
||
// If the request is for our hub...
|
||
var path = context.HttpContext.Request.Path;
|
||
if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/appHub")))
|
||
{
|
||
// Read the token out of the query string
|
||
context.Token = accessToken;
|
||
}
|
||
return Task.CompletedTask;
|
||
}
|
||
};
|
||
})
|
||
.AddGoogle(g =>
|
||
{
|
||
g.ClientId = builder.Configuration["LoginProvider:Google:ClientId"];
|
||
g.ClientSecret = builder.Configuration["LoginProvider:Google:Secret"];
|
||
g.SaveTokens = true;
|
||
});
|
||
|
||
builder.Services.Configure<FormOptions>(x =>
|
||
{
|
||
//x.ValueLengthLimit = 5000; // Limit on individual form values
|
||
x.MultipartBodyLengthLimit = 1073741824; // Limit on form body size
|
||
x.MultipartHeadersLengthLimit = 15728640; // Limit on form header size
|
||
});
|
||
builder.Services.Configure<IISServerOptions>(options =>
|
||
{
|
||
options.MaxRequestBodySize = 1073741824; // Limit on request body size
|
||
});
|
||
|
||
//Register the Permission policy handlers
|
||
builder.Services.AddTransient<IAuthorizationPolicyProvider, AuthorizationPolicyProvider>();
|
||
builder.Services.AddTransient<IAuthorizationHandler, PermissionHandler>();
|
||
builder.Services.AddTransient<IAuthorizationHandler, CustomerHandler>();
|
||
builder.Services.AddTransient<IAuthorizationHandler, ApplicationUserHandler>();
|
||
builder.Services.AddTransient<IAuthorizationHandler, HasHeaderHandler>();
|
||
|
||
builder.Services.AddResponseCaching();
|
||
|
||
//Automapper
|
||
builder.Services.AddAutoMapper(typeof(Program));
|
||
|
||
builder.Services.AddCors(options => options.AddPolicy("CorsPolicy",
|
||
builder =>
|
||
{
|
||
builder.AllowAnyHeader()
|
||
.AllowAnyMethod()
|
||
.SetIsOriginAllowed((host) => true)
|
||
.AllowCredentials();
|
||
}));
|
||
|
||
#if (!DEBUG)
|
||
builder.Services.AddHttpsRedirection(o => { o.HttpsPort = 443; });
|
||
#endif
|
||
|
||
|
||
builder.Services.AddSignalR();
|
||
|
||
builder.Services.AddSession(options =>
|
||
{
|
||
options.IdleTimeout = TimeSpan.FromMinutes(sessionTimeout);
|
||
options.Cookie.HttpOnly = true;
|
||
options.Cookie.IsEssential = true;
|
||
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
|
||
|
||
});
|
||
|
||
var mvc = builder.Services.AddControllersWithViews().AddMvcOptions(options =>
|
||
{
|
||
options.ModelBinderProviders.Insert(0, new DateTimeModelBinderProvider());
|
||
|
||
var resourcesCache = int.Parse(builder.Configuration.GetSection("CachingOptions")?["ResourcesCache"]);
|
||
options.CacheProfiles.Add("ResourcesCache", new CacheProfile() { Duration = resourcesCache, Location = ResponseCacheLocation.Any, VaryByQueryKeys = new[] { "resource", "lang" } });
|
||
})
|
||
.AddViewLocalization()
|
||
.AddDataAnnotationsLocalization(o =>
|
||
{
|
||
o.DataAnnotationLocalizerProvider = (type, factory) => factory.Create("Annotations", "gehGassi.Common");
|
||
})
|
||
.AddJsonOptions(jo =>
|
||
{
|
||
jo.JsonSerializerOptions.Converters.Add(new DateTimeOffsetJsonConverter());
|
||
jo.JsonSerializerOptions.Converters.Add(new NullableDateTimeOffsetJsonConverter());
|
||
jo.JsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter());
|
||
jo.JsonSerializerOptions.Converters.Add(new NullableDateOnlyJsonConverter());
|
||
})
|
||
.AddNewtonsoftJson(jsonOptions =>
|
||
{
|
||
jsonOptions.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
|
||
jsonOptions.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.IsoDateFormat;
|
||
jsonOptions.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
|
||
jsonOptions.SerializerSettings.Converters.Add(new NetTopologySuite.IO.Converters.GeometryConverter());
|
||
|
||
//jsonOptions.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
|
||
});
|
||
|
||
#if (DEBUG)
|
||
mvc.AddRazorRuntimeCompilation();
|
||
#endif
|
||
|
||
builder.Services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||
builder.Services.AddApplicationInsightsTelemetry();
|
||
builder.Services.AddApplicationInsightsTelemetryProcessor<ApplicationInsightsTelemetryProcessor>();
|
||
|
||
builder.Services.AddApiVersioning(options =>
|
||
{
|
||
options.DefaultApiVersion = new ApiVersion(1);
|
||
options.ReportApiVersions = true;
|
||
options.AssumeDefaultVersionWhenUnspecified = true;
|
||
options.ApiVersionReader = ApiVersionReader.Combine(
|
||
new UrlSegmentApiVersionReader(),
|
||
new HeaderApiVersionReader("X-Api-Version"));
|
||
}).AddApiExplorer(options =>
|
||
{
|
||
options.GroupNameFormat = "'v'V";
|
||
options.SubstituteApiVersionInUrl = true;
|
||
});
|
||
builder.Services.AddEndpointsApiExplorer();
|
||
builder.Services.AddSwaggerGen(c =>
|
||
{
|
||
c.DocumentFilter<WebsiteApiDocumentFilter>();
|
||
});
|
||
|
||
var app = builder.Build();
|
||
|
||
if (app.Environment.EnvironmentName == "Development")
|
||
{
|
||
//app.UseSecurityHeaders(policies =>
|
||
// policies
|
||
// .AddDefaultSecurityHeaders()
|
||
// .RemoveServerHeader()
|
||
// .AddContentSecurityPolicy(builder =>
|
||
// {
|
||
// builder.AddUpgradeInsecureRequests(); // upgrade-insecure-requests
|
||
// builder.AddBlockAllMixedContent(); // block-all-mixed-content
|
||
// builder.AddDefaultSrc() // default-src 'self'
|
||
// .Self();
|
||
|
||
// builder.AddConnectSrc() // connect-src 'self'
|
||
// .Self()
|
||
// .Blob()
|
||
// .From("https://germanywestcentral-1.in.applicationinsights.azure.com/v2/track")
|
||
// .From("https://germanywestcentral-1.in.applicationinsights.azure.com//v2/track")
|
||
// .From("https://dc.services.visualstudio.com/v2/track")
|
||
// .From("https://app.getsentry.com")
|
||
// .From("https://noembed.com")
|
||
// .From("https://*.klarnaevt.com"); ;
|
||
|
||
// builder.AddFontSrc() // font-src 'self'
|
||
// .Self()
|
||
// .Data();
|
||
// builder.AddObjectSrc() // object-src 'none'
|
||
// .Self();
|
||
// builder.AddFormAction() // form-action 'self'
|
||
// .Self();
|
||
// builder.AddImgSrc() // img-src https:
|
||
// .Self()
|
||
// .Data()
|
||
// .Blob()
|
||
// .OverHttps();
|
||
|
||
// builder.AddScriptSrc() // script-src 'self' 'unsafe-inline' 'unsafe-eval' 'report-sample'
|
||
// .Self()
|
||
// .UnsafeInline()
|
||
// .UnsafeEval()
|
||
// //.From("https://localhost:*")
|
||
// .From("https://az416426.vo.msecnd.net/scripts/b/ai.2.min.js")
|
||
// .From("https://*.klarna.com");
|
||
|
||
// builder.AddStyleSrc() // style-src 'self' 'strict-dynamic'
|
||
// .Self()
|
||
// .UnsafeInline();
|
||
// builder.AddMediaSrc() // media-src https:
|
||
// .OverHttps();
|
||
// builder.AddFrameSrc()
|
||
// .Self()
|
||
// .From("https://*.klarna.com");
|
||
// builder.AddFrameAncestors() // frame-ancestors 'none'
|
||
// .Self();
|
||
// builder.AddBaseUri() // base-ri 'self'
|
||
// .Self();
|
||
// })
|
||
// );
|
||
}
|
||
else
|
||
{
|
||
app.UseSecurityHeaders(policies =>
|
||
policies
|
||
.AddDefaultSecurityHeaders()
|
||
.RemoveServerHeader()
|
||
.AddContentSecurityPolicy(builder =>
|
||
{
|
||
builder.AddUpgradeInsecureRequests(); // upgrade-insecure-requests
|
||
builder.AddBlockAllMixedContent(); // block-all-mixed-content
|
||
builder.AddDefaultSrc() // default-src 'self'
|
||
.Self();
|
||
|
||
builder.AddConnectSrc() // connect-src 'self'
|
||
.Self()
|
||
.Blob()
|
||
.From("https://germanywestcentral-1.in.applicationinsights.azure.com/v2/track")
|
||
.From("https://germanywestcentral-1.in.applicationinsights.azure.com//v2/track")
|
||
.From("https://dc.services.visualstudio.com/v2/track")
|
||
.From("https://app.getsentry.com")
|
||
.From("https://noembed.com")
|
||
.From("https://*.klarnaevt.com");
|
||
|
||
builder.AddFontSrc() // font-src 'self'
|
||
.Self()
|
||
.Data();
|
||
builder.AddObjectSrc() // object-src 'none'
|
||
.Self();
|
||
builder.AddFormAction() // form-action 'self'
|
||
.Self();
|
||
builder.AddImgSrc() // img-src https:
|
||
.Self()
|
||
.Data()
|
||
.Blob()
|
||
.OverHttps();
|
||
|
||
builder.AddScriptSrc() // script-src 'self' 'unsafe-inline' 'unsafe-eval' 'report-sample'
|
||
.Self()
|
||
.UnsafeInline()
|
||
.UnsafeEval()
|
||
.From("https://js.monitor.azure.com/scripts/b/ai.2.min.js")
|
||
.From("https://az416426.vo.msecnd.net/scripts/b/ai.2.min.js")
|
||
.From("https://*.klarna.com");
|
||
|
||
builder.AddStyleSrc() // style-src 'self' 'strict-dynamic'
|
||
.Self()
|
||
.UnsafeInline();
|
||
builder.AddMediaSrc() // media-src https:
|
||
.OverHttps();
|
||
builder.AddFrameSrc()
|
||
.Self()
|
||
.From("https://*.klarna.com");
|
||
builder.AddFrameAncestors() // frame-ancestors 'none'
|
||
.Self();
|
||
builder.AddBaseUri() // base-ri 'self'
|
||
.Self();
|
||
})
|
||
);
|
||
}
|
||
|
||
var localizationOptions = app.Services.GetService<IOptions<LocalizationOptions>>();
|
||
var locOptions = app.Services.GetService<IOptions<RequestLocalizationOptions>>();
|
||
var appInsightOptions = app.Services.GetService<IOptions<ApplicationInsightsOptions>>();
|
||
app.UseRequestLocalization(locOptions.Value);
|
||
|
||
if (!appInsightOptions.Value.IsEnabled)
|
||
{
|
||
var telemetryConfig = app.Services.GetService<TelemetryConfiguration>();
|
||
telemetryConfig.DisableTelemetry = true;
|
||
}
|
||
|
||
if (app.Environment.IsDevelopment() == false)
|
||
{
|
||
app.UseMiddleware<SwaggerBasicAuthMiddleware>();
|
||
}
|
||
|
||
app.UseSwagger();
|
||
app.UseSwaggerUI(o =>
|
||
{
|
||
o.DefaultModelsExpandDepth(-1);
|
||
});
|
||
app.MapSwagger().RequireAuthorization();
|
||
|
||
if (app.Environment.IsDevelopment())
|
||
{
|
||
app.UseDeveloperExceptionPage();
|
||
//app.UseDatabaseErrorPage();
|
||
}
|
||
else
|
||
{
|
||
app.UseExceptionHandler("/Home/Error");
|
||
app.UseHsts();
|
||
}
|
||
|
||
app.UseStatusCodePages(async context =>
|
||
{
|
||
if (context.HttpContext.Response.StatusCode == 405)
|
||
{
|
||
context.HttpContext.Response.StatusCode = 404;
|
||
}
|
||
|
||
//Ajax-Requests werden anders behandelt!
|
||
if (!context.HttpContext.Request.IsAjaxRequest())
|
||
{
|
||
if (context.HttpContext.Response.StatusCode is >= 401 and <= 405)
|
||
{
|
||
var currentCulture = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;
|
||
var newPath = $"/{currentCulture}/Home/Status{context.HttpContext.Response.StatusCode}";
|
||
context.HttpContext.Response.Redirect(newPath);
|
||
}
|
||
else
|
||
{
|
||
await context.Next(context.HttpContext);
|
||
}
|
||
//context.HttpContext.Request.Path = newPath;
|
||
//await context.Next(context.HttpContext);
|
||
}
|
||
});
|
||
|
||
using (var scope = app.Services.CreateScope())
|
||
{
|
||
var services = scope.ServiceProvider;
|
||
try
|
||
{
|
||
var dbInitializer = services.GetRequiredService<DbInitializer>();
|
||
var success = await dbInitializer.SeedAsync();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine(ex.Message);
|
||
}
|
||
}
|
||
|
||
if (!app.Environment.IsDevelopment())
|
||
{
|
||
app.UseHttpsRedirection();
|
||
}
|
||
|
||
app.UseStaticFiles(new StaticFileOptions()
|
||
{
|
||
OnPrepareResponse = context =>
|
||
{
|
||
var cachingLib = int.Parse(app.Configuration.GetSection("CachingOptions")?["Lib"]);
|
||
var cachingConfig = int.Parse(app.Configuration.GetSection("CachingOptions")?["Config"]);
|
||
var cachingScripts = int.Parse(app.Configuration.GetSection("CachingOptions")?["Scripts"]);
|
||
var cachingImages = int.Parse(app.Configuration.GetSection("CachingOptions")?["Images"]);
|
||
var cachingDefault = int.Parse(app.Configuration.GetSection("CachingOptions")?["Default"]);
|
||
|
||
var isInternetExplorer = false;
|
||
var userAgent = context.Context.Request.Headers["User-Agent"].FirstOrDefault();
|
||
if (userAgent != null)
|
||
isInternetExplorer = userAgent.ToUpperInvariant().Contains("MSIE") || userAgent.ToUpperInvariant().Contains("TRIDENT");
|
||
if (app.Environment.IsDevelopment())
|
||
{
|
||
if (!context.Context.Request.Path.Value.Contains("fonts", StringComparison.OrdinalIgnoreCase) && !isInternetExplorer) //Wegen IE11 Bug
|
||
context.Context.Response.Headers.Add("Cache-Control", "no-cache, no-store");
|
||
else
|
||
context.Context.Response.Headers.Add("Expires", "-1");
|
||
}
|
||
else
|
||
{
|
||
if (context.Context.Request.Path.Value.Contains("/lib/", StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
context.Context.Response.Headers.Append("Cache-Control", $"public,max-age={cachingLib}");
|
||
}
|
||
else if (context.Context.Request.Path.Value.Contains("/config/", StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
context.Context.Response.Headers.Append("Cache-Control", $"public,max-age={cachingConfig}");
|
||
}
|
||
else if (context.Context.Request.Path.Value.Contains("/scripts/", StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
if (context.Context.Request.Path.Value.Contains(".min.js") && !string.IsNullOrWhiteSpace(context.Context.Request.QueryString.Value) && context.Context.Request.QueryString.Value.StartsWith("?v="))
|
||
context.Context.Response.Headers.Append("Cache-Control", $"public,max-age={cachingScripts}");
|
||
else
|
||
context.Context.Response.Headers.Add("Cache-Control", "no-cache, no-store");
|
||
//context.Context.Response.Headers.Add("Expires", "-1");
|
||
}
|
||
else if (context.Context.Request.Path.Value.Contains("/images/", StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
context.Context.Response.Headers.Append("Cache-Control", $"public,max-age={cachingImages}");
|
||
}
|
||
else
|
||
{
|
||
context.Context.Response.Headers.Append("Cache-Control", $"public,max-age={cachingDefault}");
|
||
}
|
||
}
|
||
}
|
||
});
|
||
app.UseStaticFiles(new StaticFileOptions()
|
||
{
|
||
RequestPath = new PathString("/lib")
|
||
});
|
||
//app.UseHttpLogging();
|
||
app.UseRouting();
|
||
|
||
app.UseCookiePolicy();
|
||
app.UseResponseCaching();
|
||
app.UseAuthentication();
|
||
app.UseAuthorization();
|
||
|
||
app.UseCors("CorsPolicy");
|
||
|
||
//app.UseSignalR(o => { o.MapHub<SessionHub>("/sessionHub"); });
|
||
|
||
app.UseSession();
|
||
|
||
app.UseEndpoints(endpoints =>
|
||
{
|
||
endpoints.MapGet(".well-known/acme-challenge/{id}", async context =>
|
||
{
|
||
var id = context.Request.RouteValues["id"] as string;
|
||
var file = Path.Combine(app.Environment.WebRootPath, ".well-known", "acme-challenge", id);
|
||
await context.Response.SendFileAsync(file);
|
||
});
|
||
endpoints.MapControllerRoute(
|
||
name: "error",
|
||
pattern: "{culture=" + localizationOptions.Value.DefaultCulture + "}/Home/Error", new { controller = "Home", action = "Error" }, new { culture = @"^[a-zA-Z]{2}$" });
|
||
endpoints.MapControllerRoute
|
||
(name: "notfound",
|
||
pattern: "{culture=" + localizationOptions.Value.DefaultCulture + "}/Home/Status404", new { controller = "Home", action = "Status404" }, new { culture = @"^[a-zA-Z]{2}$" });
|
||
endpoints.MapControllerRoute
|
||
(name: "deleteAccount",
|
||
pattern: "/App/DeleteAccount", new { controller = "App", action = "DeleteAccount" });
|
||
//endpoints.MapControllerRoute(name: "api", pattern: "/api/{controller}/{action}/{id}", new{id = RoutePatternParameterKind.Optional});
|
||
|
||
endpoints.MapControllerRoute(
|
||
name: "culture",
|
||
pattern: "{culture=" + localizationOptions.Value.DefaultCulture + "}/{controller=Home}/{action=Index}/{id?}", null, new { culture = @"^[a-zA-Z]{2}$" });
|
||
endpoints.MapControllers();
|
||
endpoints.MapHub<SystemHub>("/systemHub");
|
||
endpoints.MapHub<AppHub>("/appHub");
|
||
});
|
||
|
||
app.Run(); |