DurnyklyYol/DurnyklyYol.Blazor.Server/Startup.cs

211 lines
11 KiB
C#
Raw Normal View History

2024-09-02 10:07:25 +00:00
using DevExpress.ExpressApp.Security;
using DevExpress.ExpressApp.ApplicationBuilder;
using DevExpress.ExpressApp.Blazor.ApplicationBuilder;
using DevExpress.ExpressApp.Blazor.Services;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Components.Server.Circuits;
using DurnyklyYol.Blazor.Server.Services;
using DevExpress.Persistent.BaseImpl.PermissionPolicy;
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Microsoft.AspNetCore.OData;
using DevExpress.ExpressApp.WebApi.Services;
using DurnyklyYol.WebApi.JWT;
using DevExpress.ExpressApp.Security.Authentication.ClientServer;
using DurnyklyYol.Blazor.Server.OData;
using Microsoft.AspNetCore.OData.Query.Validator;
namespace DurnyklyYol.Blazor.Server;
public class Startup {
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services) {
services.AddSingleton(typeof(Microsoft.AspNetCore.SignalR.HubConnectionHandler<>), typeof(ProxyHubConnectionHandler<>));
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddHttpContextAccessor();
services.AddScoped<IAuthenticationTokenProvider, JwtTokenProviderService>();
services.AddScoped<CircuitHandler, CircuitHandlerProxy>();
services.AddXaf(Configuration, builder => {
builder.UseApplication<DurnyklyYolBlazorApplication>();
builder.AddXafWebApi(webApiBuilder => {
webApiBuilder.AddXpoServices();
webApiBuilder.ConfigureOptions(options => {
// Make your business objects available in the Web API and generate the GET, POST, PUT, and DELETE HTTP methods for it.
// options.BusinessObject<YourBusinessObject>();
options.BusinessObject<Module.BusinessObjects.Contact>();
});
});
builder.Modules
.AddConditionalAppearance()
.AddFileAttachments()
.AddReports(options => {
options.EnableInplaceReports = true;
options.ReportDataType = typeof(DevExpress.Persistent.BaseImpl.ReportDataV2);
options.ReportStoreMode = DevExpress.ExpressApp.ReportsV2.ReportStoreModes.XML;
})
.AddValidation(options => {
options.AllowValidationDetailsAccess = false;
})
.AddViewVariants()
.Add<DurnyklyYol.Module.DurnyklyYolModule>()
.Add<DurnyklyYolBlazorModule>();
builder.ObjectSpaceProviders
.AddSecuredXpo((serviceProvider, options) => {
string connectionString = null;
if(Configuration.GetConnectionString("ConnectionString") != null) {
connectionString = Configuration.GetConnectionString("ConnectionString");
}
#if EASYTEST
if(Configuration.GetConnectionString("EasyTestConnectionString") != null) {
connectionString = Configuration.GetConnectionString("EasyTestConnectionString");
}
#endif
ArgumentNullException.ThrowIfNull(connectionString);
options.ConnectionString = connectionString;
options.ThreadSafe = true;
options.UseSharedDataStoreProvider = true;
})
.AddNonPersistent();
builder.Security
.UseIntegratedMode(options => {
options.Lockout.Enabled = true;
options.RoleType = typeof(PermissionPolicyRole);
// ApplicationUser descends from PermissionPolicyUser and supports the OAuth authentication. For more information, refer to the following topic: https://docs.devexpress.com/eXpressAppFramework/402197
// If your application uses PermissionPolicyUser or a custom user type, set the UserType property as follows:
options.UserType = typeof(DurnyklyYol.Module.BusinessObjects.ApplicationUser);
// ApplicationUserLoginInfo is only necessary for applications that use the ApplicationUser user type.
// If you use PermissionPolicyUser or a custom user type, comment out the following line:
options.UserLoginInfoType = typeof(DurnyklyYol.Module.BusinessObjects.ApplicationUserLoginInfo);
options.UseXpoPermissionsCaching();
options.Events.OnSecurityStrategyCreated += securityStrategy => {
// Use the 'PermissionsReloadMode.NoCache' option to load the most recent permissions from the database once
// for every Session instance when secured data is accessed through this instance for the first time.
// Use the 'PermissionsReloadMode.CacheOnFirstAccess' option to reduce the number of database queries.
// In this case, permission requests are loaded and cached when secured data is accessed for the first time
// and used until the current user logs out.
// See the following article for more details: https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Security.SecurityStrategy.PermissionsReloadMode.
((SecurityStrategy)securityStrategy).PermissionsReloadMode = PermissionsReloadMode.NoCache;
};
})
.AddPasswordAuthentication(options => {
options.IsSupportChangePassword = true;
});
});
var authentication = services.AddAuthentication(options => {
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
});
authentication.AddCookie(options => {
options.LoginPath = "/LoginPage";
});
authentication.AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters() {
ValidateIssuerSigningKey = true,
//ValidIssuer = Configuration["Authentication:Jwt:Issuer"],
//ValidAudience = Configuration["Authentication:Jwt:Audience"],
ValidateIssuer = false,
ValidateAudience = false,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Authentication:Jwt:IssuerSigningKey"]))
};
});
services.AddAuthorization(options => {
options.DefaultPolicy = new AuthorizationPolicyBuilder(
JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.RequireXafAuthentication()
.Build();
});
services
.AddControllers()
.AddOData((options, serviceProvider) => {
options
.AddRouteComponents("api/odata", new EdmModelBuilder(serviceProvider).GetEdmModel(),
odataServices => {
odataServices.AddSingleton<ODataQueryValidator, MyODataQueryValidator>();
})
.EnableQueryFeatures(100);
});
services.AddSwaggerGen(c => {
c.EnableAnnotations();
c.SwaggerDoc("v1", new OpenApiInfo {
Title = "DurnyklyYol API",
Version = "v1",
Description = @"Use AddXafWebApi(options) in the DurnyklyYol.Blazor.Server\Startup.cs file to make Business Objects available in the Web API."
});
c.AddSecurityDefinition("JWT", new OpenApiSecurityScheme() {
Type = SecuritySchemeType.Http,
Name = "Bearer",
Scheme = "bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement() {
{
new OpenApiSecurityScheme() {
Reference = new OpenApiReference() {
Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme,
Id = "JWT"
}
},
new string[0]
},
});
});
services.Configure<Microsoft.AspNetCore.Mvc.JsonOptions>(o => {
//The code below specifies that the naming of properties in an object serialized to JSON must always exactly match
//the property names within the corresponding CLR type so that the property names are displayed correctly in the Swagger UI.
//XPO is case-sensitive and requires this setting so that the example request data displayed by Swagger is always valid.
//Comment this code out to revert to the default behavior.
//See the following article for more information: https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.propertynamingpolicy
o.JsonSerializerOptions.PropertyNamingPolicy = null;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if(env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => {
c.SwaggerEndpoint("/swagger/v1/swagger.json", "DurnyklyYol WebApi v1");
});
}
else {
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. To change this for production scenarios, see: https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseRequestLocalization();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseXaf();
app.UseEndpoints(endpoints => {
endpoints.MapXafEndpoints();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
endpoints.MapControllers();
});
}
}