Redis working
This commit is contained in:
parent
3b8d82049f
commit
b697a4b357
|
@ -87,11 +87,6 @@ namespace BlueWest.WebApi.EF.Model
|
|||
builder.Entity<ApplicationRoleClaim>().ToTable("RoleClaims");
|
||||
builder.Entity<ApplicationUserRole>().ToTable("UserRole");
|
||||
|
||||
// Session Token
|
||||
builder.Entity<SessionToken>()
|
||||
.HasOne(b => b.User)
|
||||
.WithMany(x => x.SessionToken)
|
||||
.HasForeignKey(x => x.UserId);
|
||||
|
||||
// Session Token Primary Key
|
||||
builder.Entity<SessionToken>(b =>
|
||||
|
@ -105,12 +100,6 @@ namespace BlueWest.WebApi.EF.Model
|
|||
.WithMany(x => x.SessionDatas)
|
||||
.HasForeignKey(x => x.UserId);
|
||||
|
||||
// Session Data
|
||||
builder.Entity<SessionData>()
|
||||
.HasOne(b => b.SessionToken)
|
||||
.WithOne(x => x.SessionData);
|
||||
|
||||
|
||||
|
||||
// Session Data Primary Key
|
||||
builder.Entity<SessionData>(b =>
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
using BlueWest.Data.Application;
|
||||
using BlueWest.WebApi.EF.Model;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.InMemory;
|
||||
|
||||
namespace BlueWest.WebApi.Context
|
||||
{
|
||||
|
||||
public class SessionDbContext : DbContext
|
||||
{
|
||||
/// <summary>
|
||||
/// CountryDbContext Constructor.
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
|
||||
public SessionDbContext(DbContextOptions<SessionDbContext> options) : base(options)
|
||||
{
|
||||
Database.EnsureCreated();
|
||||
}
|
||||
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
modelBuilder.ConfigureCurrentDbModel();
|
||||
}
|
||||
|
||||
public DbSet<SessionToken> SessionTokens { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,14 +1,10 @@
|
|||
using System;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using BlueWest.Cryptography;
|
||||
using BlueWest.Data.Application;
|
||||
using BlueWest.WebApi.Context.Users;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
|
@ -19,29 +15,24 @@ namespace BlueWest.WebApi.Controllers;
|
|||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
|
||||
[Authorize(Policy = "ApiUser")]
|
||||
[Authorize(Policy = SessionConstants.ApiNamePolicy)]
|
||||
|
||||
/*[EnableCors(Constants.CorsPolicyName)]*/
|
||||
public class AuthController : Controller
|
||||
{
|
||||
private readonly IAuthManager _authManager;
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly ISessionManager _sessionManager;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="authManager"></param>
|
||||
/// <param name="userManager"></param>
|
||||
public AuthController( IAuthManager authManager, IUserManager userManager, ISessionManager sessionManager)
|
||||
public AuthController( IAuthManager authManager, IUserManager userManager)
|
||||
{
|
||||
_authManager = authManager;
|
||||
_userManager = userManager;
|
||||
_sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Signup user
|
||||
/// </summary>
|
||||
|
@ -62,64 +53,49 @@ namespace BlueWest.WebApi.Controllers;
|
|||
/// <param name="loginViewModel"></param>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost("token")]
|
||||
public async Task<ActionResult<IdentityResult>> GetTokenAsync(LoginRequest loginViewModel)
|
||||
[HttpPost("login")]
|
||||
public async Task<ActionResult<IdentityResult>> GetSessionToken(LoginRequest loginViewModel)
|
||||
{
|
||||
var (success, sessionToken, token) = await _authManager.GetToken(loginViewModel);
|
||||
var (success, sessionToken, identity) = await _authManager.GetSessionTokenId(loginViewModel);
|
||||
|
||||
if (success)
|
||||
{
|
||||
return Ok(new {sessionToken, token});
|
||||
return Ok(new {sessionToken});
|
||||
|
||||
}
|
||||
return Problem();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Check if user is logged in
|
||||
/// Gets a bearer token
|
||||
/// </summary>
|
||||
/// <param name="loginViewModel"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("isLoggedIn")]
|
||||
|
||||
public ActionResult<bool> IsLoggedIn()
|
||||
[AllowAnonymous]
|
||||
[HttpPost("bearer")]
|
||||
public async Task<ActionResult<IdentityResult>> GetBearerBySessionId(string sessionId)
|
||||
{
|
||||
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
var (success, bearer) = await _authManager.GetBearerTokenBySessionTokenId(sessionId);
|
||||
|
||||
if (identity.IsAuthenticated)
|
||||
if (success)
|
||||
{
|
||||
return Ok(true);
|
||||
return Ok(new {bearer});
|
||||
|
||||
}
|
||||
|
||||
return Ok(false);
|
||||
return new UnauthorizedObjectResult(new {message = "The provided sessionId didn't return a valid Token."});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the session is authorized
|
||||
/// </summary>
|
||||
/// <param name="hash"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("isAuthorized")]
|
||||
|
||||
public ActionResult IsAuthorized(string hash)
|
||||
{
|
||||
var isAuthorized = _sessionManager.IsAuthorized(hash);
|
||||
|
||||
return Ok(isAuthorized ? new {authenticated = true} : new {authenticated = false});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Do Cookie based login.
|
||||
/// </summary>
|
||||
/// <param name="loginDto"></param>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
/*[AllowAnonymous]
|
||||
[HttpPost("login")]
|
||||
public async Task<ActionResult> DoLoginAsync(LoginRequest loginDto)
|
||||
public async Task<ActionResult> DoLoginByCookie(LoginRequest loginDto)
|
||||
{
|
||||
var (success, identity, sessionToken) = await _authManager.DoLogin(loginDto);
|
||||
var (success, sessionToken, identity) = await _authManager.GetSessionTokenId(loginDto);
|
||||
|
||||
if (success)
|
||||
{
|
||||
|
@ -129,23 +105,22 @@ namespace BlueWest.WebApi.Controllers;
|
|||
new AuthenticationProperties
|
||||
{
|
||||
IsPersistent = true,
|
||||
ExpiresUtc = DateTime.UtcNow.AddDays(1)
|
||||
ExpiresUtc = DateTime.UtcNow.Add(SessionConstants.DefaultValidForSpan)
|
||||
});
|
||||
|
||||
return Ok(new {authenticated = true, sessionToken});
|
||||
}
|
||||
|
||||
return new ForbidResult(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
}
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Do Cookie based logout
|
||||
/// </summary>
|
||||
/// <param name="loginDto"></param>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost("logout")]
|
||||
public async Task DoLogoutAsync()
|
||||
public async Task DoCookieLogoutAsync()
|
||||
{
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace BlueWest.WebApi.Controllers
|
|||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
[Authorize(Policy = "ApiUser")]
|
||||
[Authorize(Policy = SessionConstants.ApiNamePolicy)]
|
||||
[EnableCors(Constants.CorsPolicyName)]
|
||||
// [Authorize(Roles = "Administrator")]
|
||||
public class CountryController : ControllerBase
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BlueWest.Data.Application;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Redis.OM;
|
||||
|
||||
namespace BlueWest.WebApi
|
||||
{
|
||||
public class IndexCreationDevice : IHostedService
|
||||
{
|
||||
private readonly RedisConnectionProvider _provider;
|
||||
|
||||
/// <summary>
|
||||
/// Index Creation Device
|
||||
/// </summary>
|
||||
/// <param name="provider"></param>
|
||||
public IndexCreationDevice(RedisConnectionProvider provider)
|
||||
{
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _provider.Connection.CreateIndexAsync(typeof(SessionToken)); }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
using System.Threading.Tasks;
|
||||
using BlueWest.Data.Application;
|
||||
using BlueWest.WebApi.Context.Users;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace BlueWest.WebApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Methods for handling session cache data.
|
||||
/// </summary>
|
||||
public interface ISessionCache : IHostedService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a Bearer By Access Token Id
|
||||
/// </summary>
|
||||
/// <param name="sessionTokenId"></param>
|
||||
/// <returns></returns>
|
||||
Task<string> GetBearerByAccessTokenId(string sessionTokenId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a Session Token by Id.
|
||||
/// </summary>
|
||||
/// <param name="tokenId"></param>
|
||||
/// <returns></returns>
|
||||
Task<SessionToken> GetSessionTokenByIdAsync(string tokenId);
|
||||
/// <summary>
|
||||
/// Create a new session token
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
Task AddSessionToken(SessionToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Save Cache
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task SaveAsync();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Save Cache
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
void Save();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
using BlueWest.Data.Application;
|
||||
using BlueWest.WebApi.Context.Users;
|
||||
|
||||
namespace BlueWest.WebApi
|
||||
{
|
||||
public interface ISessionManager
|
||||
{
|
||||
bool IsAuthorized(string tokenHash);
|
||||
|
||||
SessionToken GetSessionToken(string hash, ApplicationUser applicationUser);
|
||||
|
||||
SessionToken GetSessionToken(LoginRequest loginRequest, ApplicationUser user);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
|
||||
namespace BlueWest.WebApi
|
||||
{
|
||||
internal static class SessionConstants
|
||||
{
|
||||
|
||||
public static TimeSpan DefaultValidForSpan = TimeSpan.FromHours(24);
|
||||
public const string ApiNamePolicy = "ApiUser";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BlueWest.Cryptography;
|
||||
using BlueWest.Data.Application;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Redis.OM;
|
||||
using Redis.OM.Searching;
|
||||
|
||||
namespace BlueWest.WebApi.Session
|
||||
{
|
||||
/// <summary>
|
||||
/// Session Provider Context
|
||||
/// </summary>
|
||||
public sealed class SessionDataService : IHostedService, ISessionCache
|
||||
{
|
||||
private readonly RedisConnectionProvider _provider;
|
||||
private RedisCollection<SessionToken> _sessionTokens;
|
||||
/// <summary>
|
||||
/// Index Creation Device
|
||||
/// </summary>
|
||||
/// <param name="provider">Redis connection</param>
|
||||
public SessionDataService(
|
||||
RedisConnectionProvider provider)
|
||||
{
|
||||
_provider = provider;
|
||||
_sessionTokens = (RedisCollection<SessionToken>)provider.RedisCollection<SessionToken>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Empty constructor
|
||||
/// </summary>
|
||||
public SessionDataService() { }
|
||||
|
||||
/// <summary>
|
||||
/// Get a session token by the respective Id.
|
||||
/// </summary>
|
||||
/// <param name="tokenId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<SessionToken> GetSessionTokenByIdAsync(string tokenId)
|
||||
{
|
||||
return await _sessionTokens.Where(x => x.Id == tokenId)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new session token
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
public async Task AddSessionToken(SessionToken token)
|
||||
{
|
||||
await _sessionTokens.InsertAsync(token);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SaveAsync()
|
||||
{
|
||||
await _sessionTokens.SaveAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save session data
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
_sessionTokens.Save();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a Bearer By Access Token Id
|
||||
/// </summary>
|
||||
/// <param name="sessionTokenId"></param>
|
||||
public async Task<string> GetBearerByAccessTokenId(string sessionTokenId)
|
||||
{
|
||||
var accessToken = await _sessionTokens.Where(t => t.Id == sessionTokenId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (accessToken == null) return string.Empty;
|
||||
|
||||
if (accessToken.IsValid)
|
||||
{
|
||||
var createdDate = DateTime.UnixEpoch.AddMilliseconds(accessToken.CreatedDate);
|
||||
if (createdDate.AddMilliseconds(accessToken.ValidFor) < DateTime.Now)
|
||||
{
|
||||
accessToken.IsValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
await _sessionTokens.SaveAsync();
|
||||
|
||||
return accessToken.IsValid ? accessToken.AccessToken : string.Empty;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _provider.Connection.CreateIndexAsync(typeof(SessionToken));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using BlueWest.Cryptography;
|
||||
using BlueWest.Data.Application;
|
||||
using BlueWest.WebApi.Context;
|
||||
using BlueWest.WebApi.Context.Users;
|
||||
|
||||
namespace BlueWest.WebApi
|
||||
{
|
||||
internal class SessionManager : ISessionManager
|
||||
{
|
||||
private readonly SessionDbContext _dbContex;
|
||||
private readonly IHasher _hasher;
|
||||
|
||||
public SessionManager(SessionDbContext sessionDbContext, IHasher hasher)
|
||||
{
|
||||
_dbContex = sessionDbContext;
|
||||
_hasher = hasher;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Check if token is authorized
|
||||
/// </summary>
|
||||
/// <param name="hash"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsAuthorized(string hash)
|
||||
{
|
||||
var sessionToken = _dbContex.SessionTokens.FirstOrDefault(x => x.Token == hash);
|
||||
|
||||
if (sessionToken is not {IsValid: true}) return false;
|
||||
|
||||
var expirationDate = sessionToken.CreatedDate.Add(sessionToken.ValidFor);
|
||||
|
||||
if (expirationDate >= DateTime.Now)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a new or existing session token
|
||||
/// </summary>
|
||||
/// <param name="hash"></param>
|
||||
/// <param name="applicationUser"></param>
|
||||
/// <returns></returns>
|
||||
public SessionToken GetSessionToken(string hash, ApplicationUser applicationUser)
|
||||
{
|
||||
var sessionToken = _dbContex.SessionTokens.FirstOrDefault(x => x.Token == hash);
|
||||
|
||||
if (sessionToken == null)
|
||||
{
|
||||
// Create token;
|
||||
var newToken = new SessionToken
|
||||
{
|
||||
Token = hash,
|
||||
CreatedDate = DateTime.Now,
|
||||
ValidFor = TimeSpan.FromDays(1),
|
||||
UserId = applicationUser.Id
|
||||
};
|
||||
|
||||
_dbContex.SessionTokens.Add(newToken);
|
||||
var result = _dbContex.SaveChanges() >= 0;
|
||||
|
||||
return !result ? null : newToken;
|
||||
}
|
||||
|
||||
var expirationDate = sessionToken.CreatedDate.Add(sessionToken.ValidFor);
|
||||
|
||||
if (expirationDate >= DateTime.Now)
|
||||
{
|
||||
return sessionToken;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a session token for the user following a login request
|
||||
/// </summary>
|
||||
/// <param name="loginRequest"></param>
|
||||
/// <param name="user"></param>
|
||||
/// <returns></returns>
|
||||
public SessionToken GetSessionToken(LoginRequest loginRequest, ApplicationUser user)
|
||||
{
|
||||
var content = $"{loginRequest.Uuid}|{user.Email}";
|
||||
var hash = _hasher.CreateHash(content, BaseCryptoItem.HashAlgorithm.SHA2_512);
|
||||
var sessionToken = GetSessionToken(hash, user);
|
||||
return sessionToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -153,7 +153,7 @@ namespace BlueWest.WebApi
|
|||
switch (allowedDatabase)
|
||||
{
|
||||
case "mysql":
|
||||
services.PrepareMySqlDatabasePool(_configuration, _environment);
|
||||
services.PrepareMySqlDatabasePool(_configuration, _environment, configuration);
|
||||
break;
|
||||
|
||||
case "sqlite":
|
||||
|
|
|
@ -5,21 +5,19 @@ using BlueWest.Cryptography;
|
|||
using BlueWest.WebApi.Context;
|
||||
using BlueWest.WebApi.Context.Users;
|
||||
using BlueWest.WebApi.EF;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using BlueWest.WebApi.Session;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
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.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Redis.OM;
|
||||
|
||||
namespace BlueWest.WebApi
|
||||
{
|
||||
|
@ -39,13 +37,36 @@ namespace BlueWest.WebApi
|
|||
private static DbContextOptionsBuilder GetMySqlSettings(
|
||||
this DbContextOptionsBuilder optionsBuilder,
|
||||
IConfiguration configuration,
|
||||
IConfigurationRoot configurationRoot,
|
||||
IWebHostEnvironment environment)
|
||||
{
|
||||
var sqlVersion = GetMySqlServerVersion(8, 0, 11);
|
||||
|
||||
// Docker / No-Docker
|
||||
var startupMode = configurationRoot["mode"];
|
||||
|
||||
string mySqlConnectionString = String.Empty;
|
||||
|
||||
if (startupMode == "docker")
|
||||
{
|
||||
var config = configuration.Get<ConnectionStringDocker>();
|
||||
if(config != null) mySqlConnectionString = config.MySql;
|
||||
}
|
||||
else
|
||||
{
|
||||
var config = configuration.Get<ConnectionStringNoDocker>();
|
||||
if(config != null) mySqlConnectionString = config.MySql;
|
||||
}
|
||||
|
||||
if (mySqlConnectionString == string.Empty)
|
||||
{
|
||||
throw new InvalidOperationException("Fatal error: MySQL Connection string is empty.");
|
||||
}
|
||||
|
||||
|
||||
optionsBuilder
|
||||
.UseMySql(
|
||||
configuration.GetConnectionString("DockerMySQL"),
|
||||
mySqlConnectionString,
|
||||
sqlVersion)
|
||||
.UseMySql(sqlVersion,
|
||||
builder =>
|
||||
|
@ -74,16 +95,19 @@ namespace BlueWest.WebApi
|
|||
/// <param name="environment"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection PrepareMySqlDatabasePool(this IServiceCollection serviceCollection,
|
||||
IConfiguration configuration, IWebHostEnvironment environment)
|
||||
IConfiguration configuration, IWebHostEnvironment environment, IConfigurationRoot configurationRoot)
|
||||
{
|
||||
return serviceCollection
|
||||
.AddDbContextPool<UserDbContext>(options => options.GetMySqlSettings(configuration, environment))
|
||||
.AddDbContextPool<CountryDbContext>(options => options.GetMySqlSettings(configuration, environment))
|
||||
.AddDbContextPool<FinanceDbContext>(options => options.GetMySqlSettings(configuration, environment))
|
||||
.AddDbContextPool<CompanyDbContext>(options => options.GetMySqlSettings(configuration, environment))
|
||||
.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, environment))
|
||||
.AddDbContextPool<SessionDbContext>(options => options.UseInMemoryDatabase("_s"));
|
||||
options.GetMySqlSettings(configuration, configurationRoot, environment));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -103,22 +127,23 @@ namespace BlueWest.WebApi
|
|||
.AddDbContextPool<CountryDbContext>(options => options.UseSqlite(sqliteConString))
|
||||
.AddDbContextPool<FinanceDbContext>(options => options.UseSqlite(sqliteConString))
|
||||
.AddDbContextPool<CompanyDbContext>(options => options.UseSqlite(sqliteConString))
|
||||
.AddDbContextPool<ApplicationUserDbContext>(options => options.UseSqlite(sqliteConString))
|
||||
.AddDbContextPool<SessionDbContext>(options => options.UseInMemoryDatabase("_s"));
|
||||
.AddDbContextPool<ApplicationUserDbContext>(options => options.UseSqlite(sqliteConString));
|
||||
|
||||
}
|
||||
|
||||
internal static IServiceCollection AddAuthServerServices(this IServiceCollection services, IConfiguration configuration , IWebHostEnvironment environment)
|
||||
{
|
||||
|
||||
services.AddScoped<IJwtTokenHandler, JwtTokenHandler>()
|
||||
|
||||
services
|
||||
.AddSingleton(new RedisConnectionProvider("redis://redisinstance:6379"))
|
||||
.AddScoped<IJwtTokenHandler, JwtTokenHandler>()
|
||||
.AddScoped<IJwtFactory, JwtFactory>()
|
||||
.AddSingleton<IndexCreationDevice>()
|
||||
.AddScoped<ISessionManager, SessionManager>()
|
||||
.AddHostedService<SessionDataService>()
|
||||
.AddSingleton<ISessionCache, SessionDataService>()
|
||||
.AddScoped<UserRepository>()
|
||||
.AddScoped<IUserManager, ApplicationUserManager>()
|
||||
.AddScoped<IAuthManager, AuthManager>()
|
||||
|
||||
.AddScoped<IHasher, Hasher>();
|
||||
|
||||
// Database Context and Swagger
|
||||
|
@ -201,7 +226,7 @@ namespace BlueWest.WebApi
|
|||
// api user claim policy
|
||||
services.AddAuthorization(options =>
|
||||
{
|
||||
options.AddPolicy("ApiUser",
|
||||
options.AddPolicy(SessionConstants.ApiNamePolicy,
|
||||
policy => policy.RequireClaim(Context.Users.Constants.JwtClaimIdentifiers.Rol,
|
||||
Context.Users.Constants.JwtClaims.ApiAccess));
|
||||
|
||||
|
@ -230,6 +255,15 @@ namespace BlueWest.WebApi
|
|||
return services;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class BlueWestConnectionString
|
||||
{
|
||||
public string Redis { get; set; }
|
||||
public string MySql { get; set; }
|
||||
}
|
||||
internal class ConnectionStringDocker : BlueWestConnectionString { }
|
||||
internal class ConnectionStringNoDocker : BlueWestConnectionString { }
|
||||
|
||||
|
|
|
@ -1,92 +1,130 @@
|
|||
using System;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BlueWest.Cryptography;
|
||||
using BlueWest.Data.Application;
|
||||
using Duende.IdentityServer.Extensions;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace BlueWest.WebApi.Context.Users;
|
||||
|
||||
internal class AuthManager : IAuthManager
|
||||
namespace BlueWest.WebApi.Context.Users
|
||||
{
|
||||
internal class AuthManager : IAuthManager
|
||||
{
|
||||
private readonly ApplicationUserManager _userManager;
|
||||
private readonly UserRepository _usersRepo;
|
||||
private readonly ISessionManager _sessionManager;
|
||||
private readonly IHasher _hasher;
|
||||
private readonly IJwtFactory _jwtFactory;
|
||||
private readonly ISessionCache _sessionCache;
|
||||
|
||||
/// <summary>
|
||||
/// Auth manager constructor
|
||||
/// </summary>
|
||||
/// <param name="userManager"></param>
|
||||
/// <param name="hasher"></param>
|
||||
/// <param name="usersRepo"></param>
|
||||
/// <param name="jwtFactory"></param>
|
||||
/// <param name="sessionCache"></param>
|
||||
public AuthManager(
|
||||
ApplicationUserManager userManager,
|
||||
IHasher hasher,
|
||||
UserRepository usersRepo,
|
||||
ISessionManager sessionManager,
|
||||
IJwtFactory jwtFactory)
|
||||
IJwtFactory jwtFactory,
|
||||
ISessionCache sessionCache)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_hasher = hasher;
|
||||
_usersRepo = usersRepo;
|
||||
_jwtFactory = jwtFactory;
|
||||
_sessionManager = sessionManager;
|
||||
_sessionCache = sessionCache;
|
||||
}
|
||||
|
||||
public async Task<(bool, ClaimsIdentity, SessionTokenUnique)> DoLogin(LoginRequest loginRequest)
|
||||
private async Task<SessionToken> GetSessionToken(LoginRequest loginRequest)
|
||||
{
|
||||
var uuid = loginRequest.GetUuid();
|
||||
var hashUuid = GetHashFromUuid(uuid);
|
||||
var sessionToken = await _sessionCache.GetSessionTokenByIdAsync(hashUuid);
|
||||
if (sessionToken != null) return sessionToken;
|
||||
return null;
|
||||
}
|
||||
|
||||
private string GetHashFromUuid(string uuid)
|
||||
{
|
||||
return _hasher.CreateHash(uuid, BaseCryptoItem.HashAlgorithm.SHA2_512);
|
||||
}
|
||||
|
||||
private SessionToken GetNewSessionToken(LoginRequest loginRequest, ApplicationUser user, string token)
|
||||
{
|
||||
long unixTime = ((DateTimeOffset)DateTimeOffset.Now).ToUnixTimeMilliseconds();;
|
||||
var newToken = new SessionToken
|
||||
{
|
||||
Id = GetHashFromUuid(loginRequest.GetUuid()),
|
||||
UserId = user.Id,
|
||||
CreatedDate = unixTime,
|
||||
IsValid = true,
|
||||
AccessToken = token
|
||||
};
|
||||
return newToken;
|
||||
}
|
||||
|
||||
public bool SessionTokenIsValid(SessionToken token)
|
||||
{
|
||||
var nowMilliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
|
||||
var isExpired = token.CreatedDate + token.ValidFor > nowMilliseconds;
|
||||
|
||||
if (isExpired)
|
||||
{
|
||||
token.IsValid = false;
|
||||
_sessionCache.SaveAsync();
|
||||
}
|
||||
|
||||
return token.IsValid;
|
||||
}
|
||||
|
||||
public async Task<(bool, string, ClaimsIdentity)> GetSessionTokenId(LoginRequest loginRequest)
|
||||
{
|
||||
var user = await _userManager.FindByEmailAsync(loginRequest.Email);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
if(await _userManager.CheckPasswordAsync(user, loginRequest.Password))
|
||||
{
|
||||
// Identity
|
||||
if (user == null) return (false, string.Empty, null);
|
||||
|
||||
if (!await _userManager.CheckPasswordAsync(user, loginRequest.Password)) return (false, string.Empty, null);
|
||||
|
||||
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
identity.AddClaim(new Claim(ClaimTypes.Email, user.Email));
|
||||
|
||||
// Session
|
||||
var sessionToken = _sessionManager.GetSessionToken(loginRequest, user);
|
||||
var sessionResponse = new SessionTokenUnique(sessionToken);
|
||||
return (true, identity, sessionResponse);
|
||||
}
|
||||
}
|
||||
var sessionToken = await GetSessionToken(loginRequest);
|
||||
|
||||
return (false, null, null);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<(bool, SessionTokenUnique, AccessToken)> GetToken(LoginRequest loginRequest)
|
||||
if (sessionToken != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(loginRequest.Email) && !string.IsNullOrEmpty(loginRequest.Password))
|
||||
if (SessionTokenIsValid(sessionToken))
|
||||
{
|
||||
var user = await _userManager.FindByEmailAsync(loginRequest.Email);
|
||||
if (user != null)
|
||||
{
|
||||
if (await VerifyLoginByEmailAsync(loginRequest.Email,loginRequest.Password))
|
||||
{
|
||||
await _usersRepo.UpdateAsync(user, CancellationToken.None);
|
||||
// Session
|
||||
var sessionToken = _sessionManager.GetSessionToken(loginRequest, user);
|
||||
var sessionResponse = new SessionTokenUnique(sessionToken);
|
||||
|
||||
var token = await _jwtFactory.GenerateEncodedToken(user.Id, user.UserName);
|
||||
var completed = await _userManager.SetAuthenticationTokenAsync(user, "ApiUser", "ApiUser", token.Token);
|
||||
|
||||
return (completed == IdentityResult.Success, sessionResponse, token);
|
||||
}
|
||||
return (true, sessionToken.Id, identity);
|
||||
}
|
||||
}
|
||||
|
||||
return (false, null, null);
|
||||
var (success, bearerToken) = await GenerateBearerToken(identity, user);
|
||||
|
||||
var newSessionToken = GetNewSessionToken(loginRequest, user, bearerToken);
|
||||
await _sessionCache.AddSessionToken(newSessionToken);
|
||||
|
||||
return (success, newSessionToken.Id, identity);
|
||||
}
|
||||
|
||||
private async Task<(bool, string)> GenerateBearerToken(ClaimsIdentity identity, ApplicationUser user)
|
||||
{
|
||||
var jwtToken = await _jwtFactory.GenerateEncodedToken(user.Id, user.UserName);
|
||||
var completed = await _userManager.SetAuthenticationTokenAsync(user, SessionConstants.ApiNamePolicy,
|
||||
SessionConstants.ApiNamePolicy, jwtToken.Token);
|
||||
return (completed == IdentityResult.Success, jwtToken.Token);
|
||||
}
|
||||
|
||||
|
||||
public async Task<(bool, string)> GetBearerTokenBySessionTokenId(string sessionId)
|
||||
{
|
||||
if (sessionId.IsNullOrEmpty()) return (false, string.Empty);
|
||||
var bearer = await _sessionCache.GetBearerByAccessTokenId(sessionId);
|
||||
return (bearer != string.Empty, bearer);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> VerifyLoginByEmailAsync(string email, string password)
|
||||
{
|
||||
|
@ -113,5 +151,5 @@ internal class AuthManager : IAuthManager
|
|||
RegisterViewModel userToCreate = FromSignupToUser(userSignupDto);
|
||||
return await _userManager.CreateAsync(userToCreate.ToUser());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -80,18 +80,19 @@ namespace BlueWest.Cryptography
|
|||
keyIndex = null;
|
||||
trimmedCipherText = cipherText;
|
||||
|
||||
if (cipherText.Length <= 5 || cipherText[0] != '[') return;
|
||||
if (cipherText.Length <= 5 ) return;
|
||||
|
||||
var cipherInfo = cipherText.Substring(1, cipherText.IndexOf(']') - 1).Split(",");
|
||||
var cipherInfo = cipherText[0].ToString();
|
||||
|
||||
if (int.TryParse(cipherInfo[0], out var foundAlgorithm))
|
||||
if (int.TryParse(cipherInfo, out int foundAlgorithm))
|
||||
{
|
||||
algorithm = foundAlgorithm;
|
||||
}
|
||||
|
||||
if (cipherInfo.Length == 2 && int.TryParse(cipherInfo[1], out var foundKeyIndex))
|
||||
if (int.TryParse(cipherInfo, out int foundKeyIndex))
|
||||
keyIndex = foundKeyIndex;
|
||||
trimmedCipherText = cipherText.Substring(cipherText.IndexOf(']') + 1);
|
||||
|
||||
trimmedCipherText = cipherText.Substring(cipherText.IndexOf(cipherInfo, StringComparison.Ordinal) + 1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -39,7 +39,7 @@ internal class JwtIssuerOptions
|
|||
/// <summary>
|
||||
/// Set the timespan the token will be valid for (default is 120 min)
|
||||
/// </summary>
|
||||
public TimeSpan ValidFor { get; set; } = TimeSpan.FromMinutes(120);
|
||||
public TimeSpan ValidFor { get; set; } = SessionConstants.DefaultValidForSpan;
|
||||
|
||||
/// <summary>
|
||||
/// "jti" (JWT ID) Claim (default ID is a GUID)
|
||||
|
|
|
@ -26,11 +26,11 @@ namespace BlueWest.Cryptography
|
|||
|
||||
if (storeSalt)
|
||||
{
|
||||
hash = $"[{(int)HashAlgorithm.SHA3_512}]{salt}{asString}";
|
||||
hash = $"{(int)HashAlgorithm.SHA3_512}{salt}{asString}";
|
||||
return hash;
|
||||
}
|
||||
|
||||
hash = $"[{(int)HashAlgorithm.SHA3_512}]{asString}";
|
||||
hash = $"{(int)HashAlgorithm.SHA3_512}{asString}";
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,26 +18,18 @@ public interface IAuthManager
|
|||
/// <returns></returns>
|
||||
Task<IdentityResult> CreateUserAsync(RegisterViewModel registerViewModel);
|
||||
|
||||
/// <summary>
|
||||
/// VerifyLoginAsync
|
||||
/// </summary>
|
||||
/// <param name="email"></param>
|
||||
/// <param name="password"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> VerifyLoginByEmailAsync(string email, string password);
|
||||
|
||||
/// <summary>
|
||||
/// GetToken
|
||||
/// </summary>
|
||||
/// <param name="loginRequest"></param>
|
||||
/// <returns></returns>
|
||||
Task<(bool, SessionTokenUnique, AccessToken)> GetToken(LoginRequest loginRequest);
|
||||
|
||||
/// <summary>
|
||||
/// Does Login
|
||||
/// </summary>
|
||||
/// <param name="loginRequest"></param>
|
||||
/// <returns></returns>
|
||||
Task<(bool, ClaimsIdentity, SessionTokenUnique)> DoLogin(LoginRequest loginRequest);
|
||||
public Task<(bool, string, ClaimsIdentity)> GetSessionTokenId(LoginRequest loginRequest);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a valid bearer token by the session id
|
||||
/// </summary>
|
||||
/// <param name="sessionId"></param>
|
||||
/// <returns></returns>
|
||||
Task<(bool, string)> GetBearerTokenBySessionTokenId(string sessionId);
|
||||
|
||||
}
|
|
@ -25,6 +25,15 @@ namespace BlueWest.WebApi.Context.Users
|
|||
[Required]
|
||||
public string Uuid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets Uuid for this login request
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetUuid()
|
||||
{
|
||||
return $"{Uuid}|{Email}";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BlueWest.WebApi.EF;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace BlueWest.WebApi.Context.Users;
|
||||
|
||||
/// <summary>
|
||||
/// Users Repository
|
||||
/// </summary>
|
||||
public class UserRepository : UserStore<ApplicationUser,
|
||||
namespace BlueWest.WebApi.Context.Users
|
||||
{
|
||||
/// <summary>
|
||||
/// Users Repository
|
||||
/// </summary>
|
||||
public class UserRepository : UserStore<ApplicationUser,
|
||||
ApplicationRole,
|
||||
ApplicationUserDbContext,
|
||||
string,
|
||||
|
@ -21,7 +19,7 @@ public class UserRepository : UserStore<ApplicationUser,
|
|||
ApplicationUserLogin,
|
||||
ApplicationUserToken,
|
||||
ApplicationRoleClaim>
|
||||
{
|
||||
{
|
||||
private readonly ApplicationUserDbContext _context;
|
||||
|
||||
/// <summary>
|
||||
|
@ -66,4 +64,5 @@ public class UserRepository : UserStore<ApplicationUser,
|
|||
return Task.FromResult(!string.IsNullOrEmpty(user.PasswordHash));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -7,10 +7,15 @@
|
|||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"DockerMySQL": "server=db;user=blueuser;password=dXjw127124dJ;database=bluedb;"
|
||||
"ConnectionStringDocker": {
|
||||
"MySQL": "server=db;user=blueuser;password=dXjw127124dJ;database=bluedb;",
|
||||
"Redis": "redis://redisinstance:6379"
|
||||
},
|
||||
"REDIS_CONNECTION_STRING": "redis://localhost:6379",
|
||||
"ConnectionStringNoDocker": {
|
||||
"MySQL": "server=localhost;user=blueuser;password=dXjw127124dJ;database=bluedb;",
|
||||
"Redis": "redis://localhost:6379"
|
||||
},
|
||||
"REDIS_CONNECTION_STRING": "redis://redis:6379",
|
||||
"AuthSettings": {
|
||||
"SecretKey": "iJWHDmHLpUA283sqsfhqGbMRdRj1PVkH"
|
||||
},
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"mode": "docker",
|
||||
"database": "sqlite",
|
||||
"environment": "dev"
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
using BlueWest.WebApi.Context.Users;
|
||||
using MapTo;
|
||||
using Redis.OM.Modeling;
|
||||
|
||||
namespace BlueWest.Data.Application
|
||||
{
|
||||
[Document(StorageType = StorageType.Json, Prefixes = new []{"SessionToken"})]
|
||||
[MapFrom(new []
|
||||
{
|
||||
typeof(SessionTokenUnique)
|
||||
|
@ -10,23 +12,18 @@ namespace BlueWest.Data.Application
|
|||
public partial class SessionToken
|
||||
{
|
||||
[IgnoreMemberMapTo]
|
||||
public string Id { get; set; }
|
||||
[Indexed] public string Id { get; set; }
|
||||
|
||||
public string Token { get; set; }
|
||||
public TimeSpan ValidFor { get; set;}
|
||||
[Indexed] public int ValidFor { get; set;}
|
||||
|
||||
public bool IsValid { get; set; }
|
||||
[Indexed] public bool IsValid { get; set; }
|
||||
|
||||
public DateTime CreatedDate { get; set; }
|
||||
[Indexed] public long CreatedDate { get; set; }
|
||||
|
||||
public ApplicationUser User { get; set; }
|
||||
public string UserId { get; set; }
|
||||
[Indexed] public string UserId { get; set; }
|
||||
|
||||
public ApplicationDevice ApplicationDevice { get; set; }
|
||||
[Indexed] public string AccessToken { get; set; }
|
||||
|
||||
public SessionData SessionData { get; set; }
|
||||
|
||||
public string AccessToken { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,8 @@ namespace BlueWest.Data.Application
|
|||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Token { get; set; }
|
||||
public TimeSpan ValidFor { get; set;}
|
||||
public DateTime CreatedDate { get; set; }
|
||||
public int ValidFor { get; set;}
|
||||
public long CreatedDate { get; set; }
|
||||
public string UserId { get; set; }
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{D7BF4A
|
|||
ProjectSection(SolutionItems) = preProject
|
||||
docker-compose.yml = docker-compose.yml
|
||||
BlueWest.Api\Dockerfile = BlueWest.Api\Dockerfile
|
||||
docker-compose.db.only.yml = docker-compose.db.only.yml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "README", "README", "{E9E3CEB0-D00C-46E3-B497-B4ED7B291190}"
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
version: '3'
|
||||
services:
|
||||
db:
|
||||
container_name: BW1_DB_MYSQL
|
||||
image: mysql/mysql-server:8.0
|
||||
environment:
|
||||
MYSQL_ROOT_HOST: db
|
||||
MYSQL_USER_HOST: db
|
||||
MYSQL_ROOT_PASSWORD: dXjw127124dJ
|
||||
MYSQL_USER: blueuser
|
||||
MYSQL_PASSWORD: dXjw127124dJ
|
||||
MYSQL_DATABASE: bluedb
|
||||
volumes:
|
||||
- ./docker-entrypoint-initdb.d/:/docker-entrypoint-initdb.d/
|
||||
phpmyadmin:
|
||||
container_name: BW_PHPMYADMIN
|
||||
image: phpmyadmin/phpmyadmin
|
||||
ports:
|
||||
- 80:80
|
||||
environment:
|
||||
MYSQL_USERNAME: 'blueuser'
|
||||
MYSQL_ROOT_PASSWORD: 'dXjw127124dJ'
|
||||
# ports:
|
||||
# - "3308:3306"
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
command: redis-server
|
||||
ports:
|
||||
- "6379:6379"
|
|
@ -1,7 +1,7 @@
|
|||
version: '3'
|
||||
services:
|
||||
db:
|
||||
container_name: BW1_DB_MYSQL
|
||||
container_name: BW1_MYSQL
|
||||
image: mysql/mysql-server:8.0
|
||||
environment:
|
||||
MYSQL_ROOT_HOST: db
|
||||
|
@ -12,16 +12,21 @@ services:
|
|||
MYSQL_DATABASE: bluedb
|
||||
volumes:
|
||||
- ./docker-entrypoint-initdb.d/:/docker-entrypoint-initdb.d/
|
||||
phpmyadmin:
|
||||
container_name: BW_PHPMYADMIN
|
||||
image: phpmyadmin/phpmyadmin
|
||||
ports:
|
||||
- 80:80
|
||||
environment:
|
||||
MYSQL_USERNAME: 'blueuser'
|
||||
MYSQL_ROOT_PASSWORD: 'dXjw127124dJ'
|
||||
# phpmyadmin:
|
||||
# container_name: BW_PHPMYADMIN
|
||||
# image: phpmyadmin/phpmyadmin
|
||||
# ports:
|
||||
# - 80:80
|
||||
# environment:
|
||||
# MYSQL_USERNAME: 'blueuser'
|
||||
# MYSQL_ROOT_PASSWORD: 'dXjw127124dJ'
|
||||
# ports:
|
||||
# - "3308:3306"
|
||||
redisinstance:
|
||||
image: "redislabs/redismod"
|
||||
ports:
|
||||
- "6379:6379"
|
||||
container_name: BW1_REDIS
|
||||
bapi120:
|
||||
build:
|
||||
context: ./
|
||||
|
@ -33,13 +38,5 @@ services:
|
|||
restart: always
|
||||
links:
|
||||
- db:db
|
||||
- redisinstance:redisinstance
|
||||
container_name: BW1_API
|
||||
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
command: redis-server --requirepass Sup3rSecurePass0rd
|
||||
ports:
|
||||
- "6379:6379"
|
||||
|
||||
environment:
|
||||
- REDIS_REPLICATION_MODE=master
|
||||
|
|
Loading…
Reference in New Issue