804 lines
37 KiB
C#
Raw Permalink Blame History

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();