Before remove session func

This commit is contained in:
Wvader 2022-09-29 00:37:24 +01:00
parent 81abab2cbe
commit 961ed87266
18 changed files with 739 additions and 109 deletions

View File

@ -1,13 +0,0 @@
namespace BlueWest.WebApi.Configuration
{
internal class BlueWestConnectionString
{
public string Redis { get; set; }
public string MySql { get; set; }
}
internal class ConnectionStringDocker : BlueWestConnectionString { }
internal class ConnectionStringNoDocker : BlueWestConnectionString { }
}

View File

@ -141,7 +141,6 @@ namespace BlueWest.WebApi
.AddJsonFile("config.json") .AddJsonFile("config.json")
.Build(); .Build();
var allowedDatabase = configuration["database"];
services services
.AddSingleton<EventManager>(); .AddSingleton<EventManager>();
@ -150,21 +149,8 @@ namespace BlueWest.WebApi
services.AddAuthServerServices( _configuration, _environment, configuration); services.AddAuthServerServices( _configuration, _environment, configuration);
services.AddScoped<ExchangeInterface>(); services.AddScoped<ExchangeInterface>();
services.PrepareMySqlDatabasePool(_configuration, _environment, configuration);
switch (allowedDatabase)
{
case "mysql":
services.PrepareMySqlDatabasePool(_configuration, _environment, configuration);
break;
case "sqlite":
services.PrepareSqlLiteDatabasePool(_configuration, _environment);
break;
default:
services.PrepareMySqlDatabasePool(_configuration, _environment, configuration);
break;
}
} }

View File

@ -121,27 +121,6 @@ namespace BlueWest.WebApi
options.GetMySqlSettings(configuration, configurationRoot, environment)); options.GetMySqlSettings(configuration, configurationRoot, environment));
} }
/// <summary>
/// Setup database Contexts
/// </summary>
/// <param name="serviceCollection"></param>
/// <param name="configuration"></param>
/// <param name="environment"></param>
/// <returns></returns>
public static IServiceCollection PrepareSqlLiteDatabasePool(this IServiceCollection serviceCollection,
IConfiguration configuration, IWebHostEnvironment environment)
{
var sqliteConString = "Data Source=BlueWest.Api.db";
return serviceCollection
.AddDbContextPool<UserDbContext>(options => options.UseSqlite(sqliteConString))
.AddDbContextPool<CountryDbContext>(options => options.UseSqlite(sqliteConString))
.AddDbContextPool<FinanceDbContext>(options => options.UseSqlite(sqliteConString))
.AddDbContextPool<CompanyDbContext>(options => options.UseSqlite(sqliteConString))
.AddDbContextPool<ApplicationUserDbContext>(options => options.UseSqlite(sqliteConString));
}
internal static IServiceCollection AddAuthServerServices(this IServiceCollection services, IConfiguration configuration , IWebHostEnvironment environment, IConfigurationRoot configurationRoot) internal static IServiceCollection AddAuthServerServices(this IServiceCollection services, IConfiguration configuration , IWebHostEnvironment environment, IConfigurationRoot configurationRoot)
{ {

View File

@ -0,0 +1,13 @@
namespace BlueWest.WebApi.Configuration
{
public class BlueWestConnectionString
{
public string Redis { get; set; }
public string MySql { get; set; }
}
public class ConnectionStringDocker : BlueWestConnectionString { }
public class ConnectionStringNoDocker : BlueWestConnectionString { }
}

View File

@ -0,0 +1,18 @@
using System.Text.Json;
using Microsoft.AspNetCore.Http;
namespace BlueWest.WebApi.Session;
public static class SessionExtensions
{
public static void Set<T>(this ISession session, string key, T value) where T: class
{
session.SetString(key, JsonSerializer.Serialize(value));
}
public static T Get<T>(this ISession session, string key) where T: class
{
var value = session.GetString(key);
return value == null ? default : JsonSerializer.Deserialize<T>(value);
}
}

View File

@ -1,3 +1,4 @@
using System;
using System.Security.Claims; using System.Security.Claims;
using BlueWest.Cryptography; using BlueWest.Cryptography;
using BlueWest.Data.Application; using BlueWest.Data.Application;

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

278
BlueWest.Startup/Class1.cs Normal file
View File

@ -0,0 +1,278 @@
using System;
using System.Text;
using System.Threading.Tasks;
using BlueWest.Domain;
using BlueWest.Domain;
using BlueWest.Cryptography;
using BlueWest.Data.Application.Users;
using BlueWest.Data.Auth;
using BlueWest.Data.Auth.Context.Users;
using BlueWest.WebApi.Configuration;
using BlueWest.WebApi.Context.Users;
using BlueWest.WebApi.Session;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using Redis.OM;
namespace BlueWest.Startyp
{
/// <summary>
/// Startup Extensions
/// </summary>
public static class StartupExtensions
{
private static MySqlServerVersion GetMySqlServerVersion(int major, int minor, int build) => new (new Version(major, minor, build));
private static BlueWestConnectionString GetConnectionString(this IConfigurationRoot configurationRoot)
{
// Docker / No-Docker
var startupMode = configurationRoot["mode"];
if (startupMode == "docker")
{
var config = configurationRoot.Get<ConnectionStringDocker>();
return config;
}
else
{
var config = configurationRoot.Get<ConnectionStringNoDocker>();
return config;
}
return null;
}
/// <summary>
/// Get MYSQL Connection String
/// </summary>
/// <param name="optionsBuilder"></param>
/// <param name="configuration"></param>
/// <param name="environment"></param>
private static DbContextOptionsBuilder GetMySqlSettings(
this DbContextOptionsBuilder optionsBuilder,
IConfiguration configuration,
IConfigurationRoot configurationRoot,
IWebHostEnvironment environment)
{
var sqlVersion = GetMySqlServerVersion(8, 0, 11);
// Docker / No-Docker
string mySqlConnectionString = configurationRoot.GetConnectionString().MySql;
if (mySqlConnectionString == string.Empty)
{
throw new InvalidOperationException("Fatal error: MySQL Connection string is empty.");
}
optionsBuilder
.UseMySql(
mySqlConnectionString,
sqlVersion)
.UseMySql(sqlVersion,
builder =>
{
builder.EnableRetryOnFailure(6, TimeSpan.FromSeconds(3), null);
});
// The following three options help with debugging, but should
// be changed or removed for production.
if (environment.IsDevelopment())
{
optionsBuilder
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging()
.EnableDetailedErrors();
}
return optionsBuilder;
}
/// <summary>
/// Setup database Contexts
/// </summary>
/// <param name="serviceCollection"></param>
/// <param name="configuration"></param>
/// <param name="environment"></param>
/// <returns></returns>
public static IServiceCollection PrepareMySqlDatabasePool(this IServiceCollection serviceCollection,
IConfiguration configuration, IWebHostEnvironment environment, IConfigurationRoot configurationRoot)
{
return serviceCollection
.AddDbContextPool<UserDbContext>(options =>
options.GetMySqlSettings(configuration, configurationRoot, environment))
.AddDbContextPool<CountryDbContext>(options =>
options.GetMySqlSettings(configuration, configurationRoot, environment))
.AddDbContextPool<FinanceDbContext>(options =>
options.GetMySqlSettings(configuration, configurationRoot, environment))
.AddDbContextPool<CompanyDbContext>(options =>
options.GetMySqlSettings(configuration, configurationRoot, environment))
.AddDbContextPool<ApplicationUserDbContext>(options =>
options.GetMySqlSettings(configuration, configurationRoot, environment));
}
/// <summary>
/// Setup database Contexts
/// </summary>
/// <param name="serviceCollection"></param>
/// <param name="configuration"></param>
/// <param name="environment"></param>
/// <returns></returns>
public static IServiceCollection PrepareSqlLiteDatabasePool(this IServiceCollection serviceCollection,
IConfiguration configuration, IWebHostEnvironment environment)
{
var sqliteConString = "Data Source=BlueWest.Api.db";
return serviceCollection
.AddDbContextPool<UserDbContext>(options => options.UseSqlite(sqliteConString))
.AddDbContextPool<CountryDbContext>(options => options.UseSqlite(sqliteConString))
.AddDbContextPool<FinanceDbContext>(options => options.UseSqlite(sqliteConString))
.AddDbContextPool<CompanyDbContext>(options => options.UseSqlite(sqliteConString))
.AddDbContextPool<ApplicationUserDbContext>(options => options.UseSqlite(sqliteConString));
}
internal static IServiceCollection AddAuthServerServices(this IServiceCollection services, IConfiguration configuration , IWebHostEnvironment environment, IConfigurationRoot configurationRoot)
{
var connectionString = configurationRoot.GetConnectionString();
if (connectionString == null)
{
throw new InvalidOperationException("Redis connection string is empty");
}
services
.AddSingleton(new RedisConnectionProvider(connectionString.Redis))
.AddScoped<IJwtTokenHandler, JwtTokenHandler>()
.AddScoped<IJwtFactory, JwtFactory>()
.AddHostedService<SessionManager>()
.AddSingleton<ISessionCache, SessionManager>()
.AddScoped<UserRepository>()
.AddScoped<IUserManager, ApplicationUserManager>()
.AddScoped<IAuthManager, AuthManager>()
.AddScoped<IHasher, Hasher>();
// Database Context and Swagger
// Register the ConfigurationBuilder instance of AuthSettings
var authSettings = configuration.GetSection(nameof(AuthSettings));
services.Configure<AuthSettings>(authSettings);
var signingKey = new SymmetricSecurityKey
(Encoding.ASCII.GetBytes(authSettings[nameof(AuthSettings.SecretKey)]));
// jwt wire up
// Get options from app settings
var jwtAppSettingOptions = configuration
.GetSection(nameof(JwtIssuerOptions));
// Configure JwtIssuerOptions
services.Configure<JwtIssuerOptions>(options =>
{
options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
options.SigningCredentials = new SigningCredentials
(signingKey, SecurityAlgorithms.HmacSha256);
});
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],
ValidateAudience = true,
ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.Lax;
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
options.Cookie.MaxAge = SessionConstants.DefaultSessionMaxAge;
options.LoginPath = "/api/auth/logincookie";
options.LogoutPath = "/api/auth/logout";
})
.AddJwtBearer(configureOptions =>
{
configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
configureOptions.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
},
};
});
// api user claim policy
services.AddAuthorization(options =>
{
options.AddPolicy(SessionConstants.ApiNamePolicy,
policy => policy.RequireClaim(Data.Auth.Context.Users.Constants.JwtClaimIdentifiers.Rol,
Data.Auth.Context.Users.Constants.JwtClaims.ApiAccess));
});
// add identity
var identityBuilder = services.AddIdentityCore<ApplicationUser>(o =>
{
o.User.RequireUniqueEmail = true;
// configure identity options
o.Password.RequireDigit = false;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequiredLength = 6;
})
.AddUserManager<ApplicationUserManager>()
.AddUserStore<UserRepository>();
identityBuilder = new IdentityBuilder(identityBuilder.UserType, typeof(ApplicationRole), identityBuilder.Services);
identityBuilder
.AddEntityFrameworkStores<ApplicationUserDbContext>()
.AddDefaultTokenProviders();
return services;
}
}
}

View File

@ -11,6 +11,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.9" /> <PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.8" />
<PackageReference Include="Microsoft.Extensions.Caching.Redis" Version="2.2.0" />
<PackageReference Include="Redis.OM" Version="0.2.2" /> <PackageReference Include="Redis.OM" Version="0.2.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -97,4 +98,8 @@
<Compile Remove="Controllers\DataController.cs" /> <Compile Remove="Controllers\DataController.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Pages" />
</ItemGroup>
</Project> </Project>

View File

@ -1,10 +1,18 @@
using BlueWest.Views.Utils;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers namespace BlueWest.Views.Controllers
{ {
[System.Web.Mvc.Route("/login")]
public class AuthController : Controller public class AuthController : Controller
{ {
public IActionResult Index()
{
this.HandleGlobalization();
return View();
}
} }
} }

View File

@ -1,66 +1,41 @@
using BlueWest.Views.Utils;
using System.Globalization;
using BlueWest.Data.Auth;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Options;
var builder = WebApplication.CreateBuilder(args); using BlueWest.Views;
builder.Services.AddSingleton<LayoutCache>(); namespace BlueWest.WebApi
// Add services to the container.
builder.Services.Configure<CookiePolicyOptions>(options =>
{ {
// This lambda determines whether user consent for non-essential cookies is needed for a given request. /// <summary>
options.CheckConsentNeeded = context => true; /// Entry point of the application.
options.MinimumSameSitePolicy = SameSiteMode.None; /// </summary>
}); public class Program
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) {
.AddCookie(cookieOptions => {
cookieOptions.LoginPath = "/";
});
builder.Services.AddLogging(builder => /// <summary>
{ /// Host Interface of the application.
builder.AddSimpleConsole(); /// </summary>
}); public static IHost MainHost { get; private set; }
builder.Services.AddSession(options => /// <summary>
{ /// Entry point of the application
options.Cookie.Domain = SessionConstants.CookieDomain; /// </summary>
options.Cookie.HttpOnly = true; /// <param name="args">Command line arguments.</param>
}); public static void Main(string[] args)
builder.Services.AddControllersWithViews(); {
MainHost = CreateHostBuilder(args)
.UseContentRoot(Directory.GetCurrentDirectory())
.Build();
var app = builder.Build(); MainHost.Run();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment()) }
{
app.UseExceptionHandler("/Home/Error"); private static IHostBuilder CreateHostBuilder(string[] args) =>
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. Host.CreateDefaultBuilder(args)
app.UseHsts();
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
} }
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseRequestLocalization(options =>
{
var supportedCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
options.DefaultRequestCulture = new RequestCulture("en-GB");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();

100
BlueWest.Views/Startup.cs Normal file
View File

@ -0,0 +1,100 @@
using System.Globalization;
using BlueWest.Data.Auth;
using BlueWest.Views.Utils;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Localization;
namespace BlueWest.Views;
public class Startup
{
private readonly IConfiguration _configuration;
private readonly IWebHostEnvironment _environment;
/// <summary>
/// Startup ctor
/// </summary>
public Startup(IConfiguration configuration, IWebHostEnvironment hostEnvironment)
{
_configuration = configuration;
_environment = hostEnvironment;
}
/// <summary>
/// Configure Services
/// </summary>
/// <param name="services">Dependency injection</param>
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<LayoutCache>();
// Add services to the container.
IConfigurationRoot configuration = new ConfigurationBuilder()
.AddJsonFile("config.json")
.Build();
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;
});
services.AddLogging(builder =>
{
builder.AddSimpleConsole();
});
services.AddSession(options =>
{
options.Cookie.Domain = SessionConstants.CookieDomain;
options.Cookie.HttpOnly = true;
});
services.AddControllersWithViews(x => x.EnableEndpointRouting = false);
services.AddSession(options => options.IdleTimeout = TimeSpan.FromHours(8));
services.AddAuthServerServices(_configuration, _environment, configuration);
services.PrepareMySqlDatabasePool(_configuration, _environment, configuration);
}
/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
/// <param name="app">Object with the necessary data to configure an application's request pipeline</param>
/// <param name="env">Provides information about the web hosting environment an application is running in.</param>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Configure the HTTP request pipeline.
if (!env.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseRequestLocalization(options =>
{
var supportedCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
options.DefaultRequestCulture = new RequestCulture("en-GB");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseMvcWithDefaultRoute();
}
}

View File

@ -0,0 +1,246 @@
using System.Text;
using BlueWest.Cryptography;
using BlueWest.Data.Application.Users;
using BlueWest.Data.Auth;
using BlueWest.Data.Auth.Context.Users;
using BlueWest.Domain;
using BlueWest.WebApi.Configuration;
using BlueWest.WebApi.Context.Users;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Redis.OM;
namespace BlueWest.Views;
public static class StartupExtensions
{
private static MySqlServerVersion GetMySqlServerVersion(int major, int minor, int build) => new (new Version(major, minor, build));
private static BlueWestConnectionString GetConnectionString(this IConfigurationRoot configurationRoot)
{
// Docker / No-Docker
var startupMode = configurationRoot["mode"];
if (startupMode == "docker")
{
var config = configurationRoot.Get<ConnectionStringDocker>();
return config;
}
else
{
var config = configurationRoot.Get<ConnectionStringNoDocker>();
return config;
}
return null;
}
internal static IServiceCollection AddAuthServerServices(this IServiceCollection services, IConfiguration configuration , IWebHostEnvironment environment, IConfigurationRoot configurationRoot)
{
var connectionString = configurationRoot.GetConnectionString();
if (connectionString == null)
{
throw new InvalidOperationException("Redis connection string is empty");
}
services.AddDistributedRedisCache(options =>
{
options.Configuration = connectionString.Redis;
});
services
.AddSingleton(new RedisConnectionProvider(connectionString.Redis))
.AddScoped<IJwtTokenHandler, JwtTokenHandler>()
.AddScoped<IJwtFactory, JwtFactory>()
.AddHostedService<SessionManager>()
.AddSingleton<ISessionCache, SessionManager>()
.AddScoped<UserRepository>()
.AddScoped<IUserManager, ApplicationUserManager>()
.AddScoped<IAuthManager, AuthManager>()
.AddScoped<IHasher, Hasher>();
// Database Context and Swagger
// Register the ConfigurationBuilder instance of AuthSettings
var authSettings = configuration.GetSection(nameof(AuthSettings));
services.Configure<AuthSettings>(authSettings);
var signingKey = new SymmetricSecurityKey
(Encoding.ASCII.GetBytes(authSettings[nameof(AuthSettings.SecretKey)]));
// jwt wire up
// Get options from app settings
var jwtAppSettingOptions = configuration
.GetSection(nameof(JwtIssuerOptions));
// Configure JwtIssuerOptions
services.Configure<JwtIssuerOptions>(options =>
{
options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
options.SigningCredentials = new SigningCredentials
(signingKey, SecurityAlgorithms.HmacSha256);
});
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],
ValidateAudience = true,
ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = "/";
options.LogoutPath = "/logout";
})
.AddJwtBearer(configureOptions =>
{
configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
configureOptions.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
},
};
});
// api user claim policy
services.AddAuthorization(options =>
{
options.AddPolicy(SessionConstants.ApiNamePolicy,
policy => policy.RequireClaim(Data.Auth.Context.Users.Constants.JwtClaimIdentifiers.Rol,
Data.Auth.Context.Users.Constants.JwtClaims.ApiAccess));
});
// add identity
var identityBuilder = services.AddIdentityCore<ApplicationUser>(o =>
{
o.User.RequireUniqueEmail = true;
// configure identity options
o.Password.RequireDigit = false;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequiredLength = 6;
})
.AddUserManager<ApplicationUserManager>()
.AddUserStore<UserRepository>();
identityBuilder = new IdentityBuilder(identityBuilder.UserType, typeof(ApplicationRole), identityBuilder.Services);
identityBuilder
.AddEntityFrameworkStores<ApplicationUserDbContext>()
.AddDefaultTokenProviders();
return services;
}
/// <summary>
/// Get MYSQL Connection String
/// </summary>
/// <param name="optionsBuilder"></param>
/// <param name="configuration"></param>
/// <param name="environment"></param>
private static DbContextOptionsBuilder GetMySqlSettings(
this DbContextOptionsBuilder optionsBuilder,
IConfiguration configuration,
IConfigurationRoot configurationRoot,
IWebHostEnvironment environment)
{
var sqlVersion = GetMySqlServerVersion(8, 0, 11);
// Docker / No-Docker
string mySqlConnectionString = configurationRoot.GetConnectionString().MySql;
if (mySqlConnectionString == string.Empty)
{
throw new InvalidOperationException("Fatal error: MySQL Connection string is empty.");
}
optionsBuilder
.UseMySql(
mySqlConnectionString,
sqlVersion)
.UseMySql(sqlVersion,
builder =>
{
builder.EnableRetryOnFailure(6, TimeSpan.FromSeconds(3), null);
});
// The following three options help with debugging, but should
// be changed or removed for production.
if (environment.IsDevelopment())
{
optionsBuilder
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging()
.EnableDetailedErrors();
}
return optionsBuilder;
}
/// <summary>
/// Setup database Contexts
/// </summary>
/// <param name="serviceCollection"></param>
/// <param name="configuration"></param>
/// <param name="environment"></param>
/// <returns></returns>
public static IServiceCollection PrepareMySqlDatabasePool(this IServiceCollection serviceCollection,
IConfiguration configuration, IWebHostEnvironment environment, IConfigurationRoot configurationRoot)
{
return serviceCollection
.AddDbContextPool<UserDbContext>(options =>
options.GetMySqlSettings(configuration, configurationRoot, environment))
.AddDbContextPool<CountryDbContext>(options =>
options.GetMySqlSettings(configuration, configurationRoot, environment))
.AddDbContextPool<FinanceDbContext>(options =>
options.GetMySqlSettings(configuration, configurationRoot, environment))
.AddDbContextPool<CompanyDbContext>(options =>
options.GetMySqlSettings(configuration, configurationRoot, environment))
.AddDbContextPool<ApplicationUserDbContext>(options =>
options.GetMySqlSettings(configuration, configurationRoot, environment));
}
}

View File

@ -0,0 +1,6 @@
@model BlueWest.Data.Auth.Context.Users.LoginRequest
@using (Html.BeginForm()){
@Html.LabelFor(x => x.Password, "Password")
@Html.PasswordFor(x => x.Password);
@Html.NameFor(x => x.Email);
}

View File

@ -3,7 +3,7 @@
} }
<div class="text-center"> <div class="text-center">
<h1 class="display-4">Data Module</h1> <h1 class="display-4">Jobs Module</h1>
</div> </div>

View File

@ -5,5 +5,20 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"AllowedHosts": "*" "AllowedHosts": "*",
"ConnectionStringDocker": {
"MySQL": "server=db;user=blueuser;password=dXjw127124dJ;database=bluedb;",
"Redis": "redis://redisinstance:6379"
},
"ConnectionStringNoDocker": {
"MySQL": "server=localhost;user=blueuser;password=dXjw127124dJ;database=bluedb;",
"Redis": "redis://localhost:6379"
},
"AuthSettings": {
"SecretKey": "iJWHDmHLpUA283sqsfhqGbMRdRj1PVkH"
},
"JwtIssuerOptions": {
"Issuer": "SomeIssuer",
"Audience": "http://localhost:5000"
}
} }

View File

@ -0,0 +1,4 @@
{
"mode": "no-docker",
"database": "mysql"
}