Api controller using cookie auth
This commit is contained in:
parent
05925a1d96
commit
a45c212592
|
@ -4,9 +4,9 @@
|
||||||
[submodule "include/Math-Expression-Evaluator"]
|
[submodule "include/Math-Expression-Evaluator"]
|
||||||
path = include/Math-Expression-Evaluator
|
path = include/Math-Expression-Evaluator
|
||||||
url = git@git.codeliturgy.com:P0/Math-Expression-Evaluator.git
|
url = git@git.codeliturgy.com:P0/Math-Expression-Evaluator.git
|
||||||
[submodule "BlueWest.Frontend"]
|
[submodule "CodeLiturgy.Dashboard.Frontend"]
|
||||||
path = BlueWest.Frontend
|
path = CodeLiturgy.Dashboard.Frontend
|
||||||
url = git@git.codeliturgy.com:P0/BlueWest.Frontend.git
|
url = git@git.codeliturgy.com:P0/CodeLiturgy.Dashboard.Frontend.git
|
||||||
[submodule "include/BlueWest.EfMethods"]
|
[submodule "include/BlueWest.EfMethods"]
|
||||||
path = include/BlueWest.EfMethods
|
path = include/BlueWest.EfMethods
|
||||||
url = git@git.codeliturgy.com:P0/BlueWest.EfGenerator.git
|
url = git@git.codeliturgy.com:P0/BlueWest.EfGenerator.git
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 8b2e541cfe92c7bfaada6a95e427a3d6c92ce768
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit d8e4df2c5d247b02accbbd5c668c4427145806d3
|
|
@ -12,7 +12,8 @@ namespace BlueWest.Data.Auth
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// API User policy Key
|
/// API User policy Key
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string ApiNamePolicy = "ApiUser";
|
public const string ApiNamePolicy = "Bearer";
|
||||||
|
public const string CookieNamePolicy = "Cookies";
|
||||||
public const string SessionTokenHeaderName = "x-bw2-auth";
|
public const string SessionTokenHeaderName = "x-bw2-auth";
|
||||||
public const string CookieDomain = "https://localhost:7022";
|
public const string CookieDomain = "https://localhost:7022";
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ namespace BlueWest.Data.Auth.Context.Users;
|
||||||
public static class Constants
|
public static class Constants
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public const string CorsPolicyName = "_myAllowSpecificOrigins";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// JwtClaimIdentifiers
|
/// JwtClaimIdentifiers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -21,4 +23,14 @@ public static class Constants
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string ApiAccess = "api_access";
|
public const string ApiAccess = "api_access";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class CookieClaims
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// JwtClaims.ApiAccess
|
||||||
|
/// </summary>
|
||||||
|
public const string CookieAccess = "cookie_access";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace CodeLiturgy.Data.Capital;
|
||||||
|
|
||||||
|
public enum EnvironmentType
|
||||||
|
{
|
||||||
|
Development,
|
||||||
|
Staging,
|
||||||
|
Production
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using MapTo;
|
||||||
|
|
||||||
|
namespace CodeLiturgy.Data.Capital
|
||||||
|
{
|
||||||
|
|
||||||
|
[MapFrom(new []
|
||||||
|
{
|
||||||
|
typeof(SiteUnique),
|
||||||
|
typeof(SiteCreate)
|
||||||
|
})]
|
||||||
|
public partial class Site
|
||||||
|
{
|
||||||
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Domain { get; set; }
|
||||||
|
|
||||||
|
public string Ip { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreatedDate { get; set; }
|
||||||
|
|
||||||
|
public DateTime LastChanged { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
using MapTo;
|
||||||
|
|
||||||
|
namespace CodeLiturgy.Data.Capital
|
||||||
|
{
|
||||||
|
[MapFrom(typeof(Site))]
|
||||||
|
public partial class SiteCreate
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Domain { get; set; }
|
||||||
|
|
||||||
|
public string Ip { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
using System;
|
||||||
|
using MapTo;
|
||||||
|
|
||||||
|
namespace CodeLiturgy.Data.Capital
|
||||||
|
{
|
||||||
|
|
||||||
|
[MapFrom(typeof(Site))]
|
||||||
|
public partial class SiteUnique
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Domain { get; set; }
|
||||||
|
|
||||||
|
public string Ip { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -53,7 +53,6 @@ namespace CodeLiturgy.Domain
|
||||||
{
|
{
|
||||||
base.OnModelCreating(builder);
|
base.OnModelCreating(builder);
|
||||||
|
|
||||||
|
|
||||||
builder.ConfigureCurrentDbModel();
|
builder.ConfigureCurrentDbModel();
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
using CodeLiturgy.Data.Capital;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using BlueWest.EfMethods;
|
||||||
|
|
||||||
|
namespace CodeLiturgy.Domain;
|
||||||
|
|
||||||
|
public class SiteDbContext: DbContext
|
||||||
|
{
|
||||||
|
[EfGetOneBy(nameof(Site.Id), typeof(SiteUnique))]
|
||||||
|
[EfGetOne(typeof(SiteUnique))]
|
||||||
|
[EfAddMethods(createType: typeof(SiteCreate), returnType: typeof(SiteUnique))]
|
||||||
|
[EfGetMany(typeof(SiteUnique))]
|
||||||
|
|
||||||
|
public DbSet<Site> Sites { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SiteDbContext Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options"></param>
|
||||||
|
public SiteDbContext(DbContextOptions<SiteDbContext> options) : base(options)
|
||||||
|
{
|
||||||
|
Database.EnsureCreated();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>disable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -79,10 +79,10 @@
|
||||||
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery\dist\jquery.min.map" />
|
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery\dist\jquery.min.map" />
|
||||||
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery\LICENSE.txt" />
|
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery\LICENSE.txt" />
|
||||||
<_ContentIncludedByDefault Remove="Views\Data\Roles\Index.cshtml" />
|
<_ContentIncludedByDefault Remove="Views\Data\Roles\Index.cshtml" />
|
||||||
</ItemGroup>
|
<_ContentIncludedByDefault Remove="Views\Account\ChangePassword.cshtml" />
|
||||||
|
<_ContentIncludedByDefault Remove="Views\Account\Curriculums\Index.cshtml" />
|
||||||
<ItemGroup>
|
<_ContentIncludedByDefault Remove="Views\Account\Curriculums\Upload.cshtml" />
|
||||||
<AdditionalFiles Include="Views\Account\Index.cshtml" />
|
<_ContentIncludedByDefault Remove="Views\Account\Index.cshtml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -109,4 +109,9 @@
|
||||||
<Folder Include="wwwroot\static\profile" />
|
<Folder Include="wwwroot\static\profile" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<AdditionalFiles Include="Views\Auth\Account.cshtml" />
|
||||||
|
<AdditionalFiles Include="Views\EnvironmentsPage\Index.cshtml" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -12,7 +12,6 @@ public class AccountController : UserController
|
||||||
{
|
{
|
||||||
private readonly ILogger<AccountController> _logger;
|
private readonly ILogger<AccountController> _logger;
|
||||||
|
|
||||||
|
|
||||||
public AccountController(ApplicationUserManager userManager, ILogger<AccountController> logger) : base(userManager, logger)
|
public AccountController(ApplicationUserManager userManager, ILogger<AccountController> logger) : base(userManager, logger)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
@ -27,19 +26,9 @@ public class AccountController : UserController
|
||||||
|
|
||||||
public override void OnInitialization()
|
public override void OnInitialization()
|
||||||
{
|
{
|
||||||
SetFooterMenu(LayoutCache.AccountRouteRecord.Children);
|
SetFooterMenu(LayoutCache.AccountRouteRecord.ChildrenToUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public async Task<IActionResult> Curriculums()
|
|
||||||
{
|
|
||||||
await OnEveryAction();
|
|
||||||
|
|
||||||
return View("Curriculums/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async Task<IActionResult> Change()
|
public async Task<IActionResult> Change()
|
||||||
{
|
{
|
||||||
await OnEveryAction();
|
await OnEveryAction();
|
||||||
|
@ -47,14 +36,6 @@ public class AccountController : UserController
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Microsoft.AspNetCore.Mvc.Route("[controller]/upload")]
|
|
||||||
public async Task<IActionResult> UploadCurriculum()
|
|
||||||
{
|
|
||||||
await OnEveryAction();
|
|
||||||
return View("Curriculums/Upload");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
public async Task<IActionResult> Error()
|
public async Task<IActionResult> Error()
|
||||||
{
|
{
|
||||||
|
|
|
@ -62,6 +62,13 @@ namespace CodeLiturgy.Views.Controllers
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IActionResult> Account()
|
||||||
|
{
|
||||||
|
await OnEveryAction();
|
||||||
|
this.HandleGlobalization();
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<IActionResult> Logout()
|
public async Task<IActionResult> Logout()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
using BlueWest.Data.Auth.Context.Users;
|
||||||
|
using CodeLiturgy.Data.Capital;
|
||||||
|
using CodeLiturgy.Domain;
|
||||||
|
using CodeLiturgy.Views.Utils;
|
||||||
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Cors;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
|
||||||
|
namespace CodeLiturgy.Views.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/envs")]
|
||||||
|
[ApiController]
|
||||||
|
[Authorize]
|
||||||
|
|
||||||
|
public class EnvironmentsController : ControllerBase
|
||||||
|
{
|
||||||
|
private ApplicationUserManager _userManager;
|
||||||
|
private ILogger<UserController> _logger;
|
||||||
|
private SiteDbContext _siteDbContext;
|
||||||
|
|
||||||
|
public EnvironmentsController(ApplicationUserManager userManager, ILogger<UserController> logger, SiteDbContext siteDbContext)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_userManager = userManager;
|
||||||
|
_siteDbContext = siteDbContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult<Site>> GetSites()
|
||||||
|
{
|
||||||
|
return Ok(new Site());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
using BlueWest.Data.Auth.Context.Users;
|
||||||
|
using CodeLiturgy.Views.Utils;
|
||||||
|
using Duende.IdentityServer.Extensions;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace CodeLiturgy.Views.Controllers;
|
||||||
|
|
||||||
|
|
||||||
|
public class EnvironmentsPageController : UserController
|
||||||
|
{
|
||||||
|
public EnvironmentsPageController(ApplicationUserManager userManager, ILogger<UserController> logger) : base(userManager, logger) { }
|
||||||
|
|
||||||
|
public override void OnInitialization()
|
||||||
|
{
|
||||||
|
base.OnInitialization();
|
||||||
|
SetHeaderMenu(new List<Url>()
|
||||||
|
{
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IActionResult> Index()
|
||||||
|
{
|
||||||
|
await OnEveryAction();
|
||||||
|
|
||||||
|
|
||||||
|
if (!User.IsAuthenticated())
|
||||||
|
{
|
||||||
|
return Redirect("/auth/login");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,12 @@ public class HomeController : UserController
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void OnInitialization()
|
||||||
|
{
|
||||||
|
var menu = LayoutCache.Root.ChildrenToUrl();
|
||||||
|
SetHeaderMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public async Task<IActionResult> Index()
|
public async Task<IActionResult> Index()
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace CodeLiturgy.Views.Controllers
|
||||||
|
|
||||||
public override void OnInitialization()
|
public override void OnInitialization()
|
||||||
{
|
{
|
||||||
SetFooterMenu(LayoutCache.SystemRoute.Children);
|
SetFooterMenu(LayoutCache.SystemRoute.ChildrenToUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IActionResult> Users()
|
public async Task<IActionResult> Users()
|
||||||
|
|
|
@ -15,22 +15,24 @@ public class UserController : Controller
|
||||||
protected ILogger<UserController> _logger;
|
protected ILogger<UserController> _logger;
|
||||||
protected ApplicationUserManager _userManager;
|
protected ApplicationUserManager _userManager;
|
||||||
|
|
||||||
private List<RouteRecord> _footerMenu;
|
private List<Url> _footerMenu;
|
||||||
|
private List<Url> _headerMenu;
|
||||||
|
|
||||||
public UserController(ApplicationUserManager userManager, ILogger<UserController> logger)
|
public UserController(ApplicationUserManager userManager, ILogger<UserController> logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_footerMenu = new List<RouteRecord>();
|
_footerMenu = new List<Url>();
|
||||||
|
_headerMenu = new List<Url>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task OnEveryAction()
|
public async Task OnEveryAction()
|
||||||
{
|
{
|
||||||
HandleGlobalization();
|
HandleGlobalization();
|
||||||
SetFooterMenuViewData();
|
|
||||||
await SetUserProfileViewData();
|
await SetUserProfileViewData();
|
||||||
OnInitialization();
|
OnInitialization();
|
||||||
SetFooterMenuViewData();
|
SetFooterMenuViewData();
|
||||||
|
SetHeaderMenuViewData();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnInitialization()
|
public virtual void OnInitialization()
|
||||||
|
@ -42,9 +44,21 @@ public class UserController : Controller
|
||||||
ViewData[FooterMenuViewDataId] = _footerMenu;
|
ViewData[FooterMenuViewDataId] = _footerMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetFooterMenu(List<RouteRecord> routeRecords)
|
protected void SetHeaderMenuViewData()
|
||||||
{
|
{
|
||||||
_footerMenu = routeRecords;
|
ViewData[HeaderMenuId] = _headerMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void SetFooterMenu(List<Url> urls)
|
||||||
|
{
|
||||||
|
_footerMenu = urls;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void SetHeaderMenu(List<Url> urls)
|
||||||
|
{
|
||||||
|
_headerMenu = urls;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetUserProfileViewData()
|
public async Task SetUserProfileViewData()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace CodeLiturgy.Views.Languages;
|
namespace CodeLiturgy.Views.Languages;
|
||||||
|
|
||||||
public static class SiteContent
|
public static class Translations
|
||||||
{
|
{
|
||||||
internal static readonly Dictionary<string, Dictionary<string, string>> RouteTitle =
|
internal static readonly Dictionary<string, Dictionary<string, string>> RouteTitle =
|
||||||
new Dictionary<string, Dictionary<string, string>>
|
new Dictionary<string, Dictionary<string, string>>
|
||||||
|
@ -21,14 +21,6 @@ public static class SiteContent
|
||||||
{"en-gb", "System"},
|
{"en-gb", "System"},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
DataKeyName, new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{"pt", "Dados"},
|
|
||||||
{"eng", "Data"},
|
|
||||||
{"en-gb", "Data"}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
RolesKeyName, new Dictionary<string, string>()
|
RolesKeyName, new Dictionary<string, string>()
|
||||||
|
@ -62,68 +54,23 @@ public static class SiteContent
|
||||||
{"en-gb", "Settings"},
|
{"en-gb", "Settings"},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
CompaniesKeyName, new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{"pt", "Empresas"},
|
|
||||||
{"eng", "Companies"},
|
|
||||||
{"en-gb", "Companies"},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
IndustriesKeyName, new Dictionary<string, string>()
|
AuthAccountKeyName, new Dictionary<string, string>()
|
||||||
{
|
{
|
||||||
{"pt", "Indústrias"},
|
{"pt", "Conta"},
|
||||||
{"en-gb", "Industries"},
|
|
||||||
{"eng", "Industries"},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
CurrenciesKeyName, new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{"pt", "Moedas"},
|
|
||||||
{"en-gb", "Currencies"},
|
|
||||||
{"eng", "Currencies"},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CountriesKeyName, new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{"pt", "Países"},
|
|
||||||
{"eng", "Countries"},
|
|
||||||
{"en-gb", "Countries"}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
BanksKeyName, new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{"pt", "Bancos"},
|
|
||||||
{"eng", "Banks"},
|
|
||||||
{"en-gb", "Banks"},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
DataUsersKeyName, new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{"pt", "Utilizadores"},
|
|
||||||
{"eng", "Users"},
|
|
||||||
{"en-gb", "Users"},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
AccountKeyName, new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{"pt", "Perfil"},
|
|
||||||
{"eng", "Account"},
|
{"eng", "Account"},
|
||||||
{"en-gb", "Account"},
|
{"en-gb", "Account"},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
EnvironmentsKeyName, new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{"pt", "Ambientes"},
|
||||||
|
{"eng", "Environments"},
|
||||||
|
{"en-gb", "Environments"},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
ChangePasswordKeyName, new Dictionary<string, string>()
|
ChangePasswordKeyName, new Dictionary<string, string>()
|
|
@ -112,6 +112,24 @@ public static class StartupExtensions
|
||||||
{
|
{
|
||||||
options.LoginPath = Routes.AuthLoginRoute;
|
options.LoginPath = Routes.AuthLoginRoute;
|
||||||
options.LogoutPath = Routes.AuthLogoutRoute;
|
options.LogoutPath = Routes.AuthLogoutRoute;
|
||||||
|
})
|
||||||
|
.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;
|
||||||
|
},
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -121,6 +139,10 @@ public static class StartupExtensions
|
||||||
options.AddPolicy(SessionConstants.ApiNamePolicy,
|
options.AddPolicy(SessionConstants.ApiNamePolicy,
|
||||||
policy => policy.RequireClaim(Constants.JwtClaimIdentifiers.Rol,
|
policy => policy.RequireClaim(Constants.JwtClaimIdentifiers.Rol,
|
||||||
Constants.JwtClaims.ApiAccess));
|
Constants.JwtClaims.ApiAccess));
|
||||||
|
options.AddPolicy(SessionConstants.CookieNamePolicy, policy =>
|
||||||
|
{
|
||||||
|
policy.RequireClaim(Constants.CookieClaims.CookieAccess);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// add identity
|
// add identity
|
||||||
|
@ -168,6 +190,7 @@ public static class StartupExtensions
|
||||||
{
|
{
|
||||||
return serviceCollection
|
return serviceCollection
|
||||||
.AddDbContextPool<UserDbContext>(options => options.UsePsqlConfiguration(configuration))
|
.AddDbContextPool<UserDbContext>(options => options.UsePsqlConfiguration(configuration))
|
||||||
|
.AddDbContextPool<SiteDbContext>(options => options.UsePsqlConfiguration(configuration))
|
||||||
.AddDbContextPool<CountryDbContext>(options => options.UsePsqlConfiguration(configuration))
|
.AddDbContextPool<CountryDbContext>(options => options.UsePsqlConfiguration(configuration))
|
||||||
.AddDbContextPool<ApplicationUserDbContext>(options =>
|
.AddDbContextPool<ApplicationUserDbContext>(options =>
|
||||||
options.UsePsqlConfiguration(configuration));
|
options.UsePsqlConfiguration(configuration));
|
||||||
|
|
|
@ -10,16 +10,22 @@ internal class LayoutCache
|
||||||
#region Route Tree
|
#region Route Tree
|
||||||
|
|
||||||
private static readonly RouteRecord NonLoggedInRoot = new RouteRecord(
|
private static readonly RouteRecord NonLoggedInRoot = new RouteRecord(
|
||||||
|
"Login",
|
||||||
AuthLoginRoute,
|
AuthLoginRoute,
|
||||||
AuthLoginKeyName,
|
AuthLoginKeyName,
|
||||||
nameof(AuthController), new List<RouteRecord>());
|
nameof(AuthController), new List<RouteRecord>());
|
||||||
|
|
||||||
|
|
||||||
private static readonly RouteRecord Root = new RouteRecord(
|
internal static readonly RouteRecord Root = new RouteRecord(
|
||||||
|
"Code Liturgy - Dashboard",
|
||||||
RootKeyName,
|
RootKeyName,
|
||||||
RootLocation,
|
RootLocation,
|
||||||
nameof(HomeController),
|
nameof(HomeController),
|
||||||
new List<RouteRecord>(), ViewType.Root);
|
new List<RouteRecord>()
|
||||||
|
{
|
||||||
|
new RouteRecord("Environments", EnvironmentsKeyName, EnvironmentsRouteLocation, nameof(EnvironmentsPageController), new List<RouteRecord>(), ViewType.Environments)
|
||||||
|
|
||||||
|
}, ViewType.Root);
|
||||||
|
|
||||||
#endregion Route Tree
|
#endregion Route Tree
|
||||||
|
|
||||||
|
@ -28,9 +34,6 @@ internal class LayoutCache
|
||||||
internal static readonly RouteRecord SystemRoute =
|
internal static readonly RouteRecord SystemRoute =
|
||||||
Root.Children.FirstOrDefault(x => x.ViewType == ViewType.System)!;
|
Root.Children.FirstOrDefault(x => x.ViewType == ViewType.System)!;
|
||||||
|
|
||||||
internal static readonly RouteRecord DataRouteRecord =
|
|
||||||
Root.Children.FirstOrDefault(x => x.ViewType == ViewType.Data)!;
|
|
||||||
|
|
||||||
internal static readonly RouteRecord AccountRouteRecord =
|
internal static readonly RouteRecord AccountRouteRecord =
|
||||||
Root.Children.FirstOrDefault(x => x.ViewType == ViewType.Account)!;
|
Root.Children.FirstOrDefault(x => x.ViewType == ViewType.Account)!;
|
||||||
|
|
||||||
|
@ -38,70 +41,48 @@ internal class LayoutCache
|
||||||
|
|
||||||
#region Internal Menus
|
#region Internal Menus
|
||||||
|
|
||||||
internal static List<RouteView> GetDefaultFooterMenu(ViewDataDictionary dictionary)
|
|
||||||
|
internal static List<Url> GetDefaultHeaderMenu(ViewDataDictionary dictionary, bool userAuthenticated = false)
|
||||||
{
|
{
|
||||||
var location = GetUserLanguage(dictionary);
|
var menuToShow = new List<Url>();
|
||||||
|
|
||||||
var menu = LayoutCache
|
menuToShow.Add(Root.ToUrl());
|
||||||
.Root
|
|
||||||
.Children;
|
|
||||||
|
|
||||||
if (dictionary[FooterMenuViewDataId] is List<RouteRecord> footerMenu)
|
|
||||||
{
|
|
||||||
menu = footerMenu;
|
|
||||||
}
|
|
||||||
|
|
||||||
return menu
|
|
||||||
.Select(x =>
|
|
||||||
{
|
|
||||||
if (SiteContent.RouteTitle[x.routeKey].ContainsKey(location))
|
|
||||||
{
|
|
||||||
return new RouteView(SiteContent.RouteTitle[x.routeKey][location],
|
|
||||||
location);
|
|
||||||
}
|
|
||||||
return new RouteView(SiteContent.RouteTitle[x.routeKey][DefaultCultureName],
|
|
||||||
x.location);
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static List<RouteView> GetDefaultHeaderMenu(ViewDataDictionary dictionary, bool userAuthenticated = false)
|
|
||||||
{
|
|
||||||
if (!userAuthenticated)
|
if (!userAuthenticated)
|
||||||
{
|
{
|
||||||
var menuToShow = new List<RouteView>();
|
|
||||||
menuToShow.Add(new RouteView("CodeLiturgy Dashboard", "/"));
|
|
||||||
return menuToShow;
|
return menuToShow;
|
||||||
}
|
}
|
||||||
|
|
||||||
var location = GetUserLanguage(dictionary);
|
if (dictionary[HeaderMenuId] is List<Url> headerMenu)
|
||||||
|
|
||||||
var menu = LayoutCache
|
|
||||||
.Root
|
|
||||||
.Children;
|
|
||||||
|
|
||||||
if (dictionary[HeaderMenuId] is List<RouteRecord> footerMenu)
|
|
||||||
{
|
{
|
||||||
menu = footerMenu;
|
menuToShow = menuToShow
|
||||||
|
.Concat(headerMenu)
|
||||||
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return menu
|
return menuToShow;
|
||||||
.Select(x =>
|
}
|
||||||
{
|
|
||||||
if (SiteContent.RouteTitle[x.routeKey].ContainsKey(location))
|
|
||||||
{
|
|
||||||
return new RouteView(SiteContent.RouteTitle[x.routeKey][location],
|
|
||||||
x.Location);
|
|
||||||
}
|
|
||||||
return new RouteView(SiteContent.RouteTitle[x.routeKey][DefaultCultureName],
|
|
||||||
x.location);
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
.ToList();
|
internal static List<Url> GetDefaultFooterMenu(ViewDataDictionary dictionary, bool userAuthenticated)
|
||||||
|
{
|
||||||
|
var menuToShow = new List<Url>();
|
||||||
|
|
||||||
|
menuToShow.Add(Root.ToUrl());
|
||||||
|
|
||||||
|
if (!userAuthenticated)
|
||||||
|
{
|
||||||
|
return menuToShow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dictionary[FooterMenuViewDataId] is List<Url> footerMenu)
|
||||||
|
{
|
||||||
|
menuToShow = menuToShow
|
||||||
|
.Concat(footerMenu)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return menuToShow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,33 @@
|
||||||
namespace CodeLiturgy.Views.Utils
|
namespace CodeLiturgy.Views.Utils
|
||||||
{
|
{
|
||||||
public record RouteRecord(string routeKey, string location, string controllerName, List<RouteRecord> children, ViewType viewType = ViewType.Undefined)
|
public class Url
|
||||||
{
|
{
|
||||||
public string RouteKey = routeKey;
|
public string Name;
|
||||||
public string Location = location;
|
public string Location;
|
||||||
public string ControllerName;
|
|
||||||
public List<RouteRecord> Children = children;
|
public Url(string name, string location)
|
||||||
public ViewType ViewType = viewType;
|
{
|
||||||
|
Name = name;
|
||||||
|
Location = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public record RouteRecord(string Name, string RouteKey, string Location, string ControllerName, List<RouteRecord> Children, ViewType ViewType = ViewType.Undefined)
|
||||||
|
{
|
||||||
|
|
||||||
|
public List<Url> ChildrenToUrl()
|
||||||
|
{
|
||||||
|
return Children.Select(x => x.ToUrl()).ToList();
|
||||||
|
}
|
||||||
|
public Url ToUrl()
|
||||||
|
{
|
||||||
|
return new Url(Name, Location);
|
||||||
|
}
|
||||||
|
public Url ToUrl(string name)
|
||||||
|
{
|
||||||
|
return new Url(name, Location);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record RouteView(string Name, string Location);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,47 +46,22 @@ namespace CodeLiturgy.Views.Utils
|
||||||
internal const string SettingsRouteLocation = $"{SystemRouteLocation}/settings";
|
internal const string SettingsRouteLocation = $"{SystemRouteLocation}/settings";
|
||||||
internal const string SettingsKeyName = "settings";
|
internal const string SettingsKeyName = "settings";
|
||||||
|
|
||||||
internal const string DataLocation = $"/data";
|
|
||||||
internal const string DataKeyName = "data";
|
|
||||||
|
|
||||||
|
|
||||||
internal const string DataUsersLocation = "/data/users";
|
|
||||||
internal const string DataUsersKeyName = "users";
|
|
||||||
|
|
||||||
internal const string SystemRouteLocation = $"/system";
|
internal const string SystemRouteLocation = $"/system";
|
||||||
internal const string SystemKeyName = "system";
|
internal const string SystemKeyName = "system";
|
||||||
|
|
||||||
internal const string BanksKeyName = "banks";
|
|
||||||
internal const string BanksLocation = $"{DataLocation}/banks";
|
|
||||||
|
|
||||||
internal const string CountriesLocation = $"{DataLocation}/countries";
|
|
||||||
internal const string CountriesKeyName = "countries";
|
|
||||||
|
|
||||||
internal const string CurrenciesLocation = $"{DataLocation}/currencies";
|
|
||||||
internal const string CurrenciesKeyName = "currencies";
|
|
||||||
|
|
||||||
internal const string IndustriesKeyName = "industries";
|
|
||||||
internal const string IndustriesLocation = $"{DataLocation}/industries";
|
|
||||||
|
|
||||||
internal const string CompaniesLocation = $"{DataLocation}/companies";
|
|
||||||
internal const string CompaniesKeyName = "companies";
|
|
||||||
|
|
||||||
|
|
||||||
// Jobs
|
|
||||||
internal const string Curriculums = "curriculums";
|
|
||||||
internal const string Proposals = "proposals";
|
|
||||||
internal const string Offers = "offers";
|
|
||||||
internal const string Processes = "processes";
|
|
||||||
internal const string AuthLogoutRoute = "/auth/logout";
|
internal const string AuthLogoutRoute = "/auth/logout";
|
||||||
|
internal const string AuthAccountRoute = "/auth/account";
|
||||||
|
internal const string AuthAccountKeyName = "account";
|
||||||
|
|
||||||
// Account
|
// Account
|
||||||
internal const string AccountRouteLocation = "/account";
|
|
||||||
internal const string AccountKeyName = "profile";
|
|
||||||
internal const string ChangePasswordKeyName = "changepwd";
|
internal const string ChangePasswordKeyName = "changepwd";
|
||||||
internal const string ChangePasswordRouteLocation = $"{AccountRouteLocation}/change";
|
internal const string ChangePasswordRouteLocation = $"{AuthAccountRoute}/change";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Environments
|
||||||
|
internal const string EnvironmentsRouteLocation = "/environments";
|
||||||
|
internal const string EnvironmentsKeyName = "envs";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,8 +5,8 @@ namespace CodeLiturgy.Views
|
||||||
public enum ViewType
|
public enum ViewType
|
||||||
{
|
{
|
||||||
System,
|
System,
|
||||||
Data,
|
|
||||||
Account,
|
Account,
|
||||||
|
Environments,
|
||||||
Root,
|
Root,
|
||||||
Undefined
|
Undefined
|
||||||
|
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
@using CodeLiturgy.Views.Utils
|
|
||||||
@model BlueWest.Data.Application.Users.ApplicationUserUnique
|
|
||||||
@{
|
|
||||||
var user = @Model;
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="q-ma-lg">
|
|
||||||
<form method="POST" action="EditProfile" class="q-form q-gutter-md">
|
|
||||||
<label class="q-field row no-wrap items-start q-field--filled q-input q-field--labeled q-field--dark q-field--with-bottom">
|
|
||||||
<div class="q-field__inner relative-position col self-stretch">
|
|
||||||
<div class="q-field__control relative-position row no-wrap" tabindex="-1">
|
|
||||||
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
|
|
||||||
<input class="q-field__native q-placeholder" tabindex="0" aria-label="Phone Number" name="name" type="name" value="@Model.Id" disabled="disabled">
|
|
||||||
</div>
|
|
||||||
<div class="q-field__bottom row items-start q-field__bottom--animated">
|
|
||||||
<div class="q-field__messages col">
|
|
||||||
<div>Id</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label class="q-field row no-wrap items-start q-field--filled q-input q-field--labeled q-field--dark q-field--with-bottom">
|
|
||||||
<div class="q-field__inner relative-position col self-stretch">
|
|
||||||
<div class="q-field__control relative-position row no-wrap">
|
|
||||||
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
|
|
||||||
<input class="q-field__native q-placeholder" name="email" aria-label="Email" type="email" value="@user.Email">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="q-field__bottom row items-start q-field__bottom--animated">
|
|
||||||
<div class="q-field__messages col">
|
|
||||||
<div>Email address</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label class="q-field row no-wrap items-start q-field--filled q-input q-field--labeled q-field--dark q-field--with-bottom">
|
|
||||||
<div class="q-field__inner relative-position col self-stretch">
|
|
||||||
<div class="q-field__control relative-position row no-wrap" tabindex="-1">
|
|
||||||
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
|
|
||||||
<input class="q-field__native q-placeholder" tabindex="0" aria-label="Phone Number" name="name" type="name" value="@Model.PhoneNumber">
|
|
||||||
</div>
|
|
||||||
<div class="q-field__bottom row items-start q-field__bottom--animated">
|
|
||||||
<div class="q-field__messages col">
|
|
||||||
<div>Phone Number</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label class="q-field row no-wrap items-start q-field--filled q-input q-field--labeled q-field--dark q-field--with-bottom">
|
|
||||||
<div class="q-field__inner relative-position col self-stretch">
|
|
||||||
<div class="q-field__control relative-position row no-wrap" tabindex="-1">
|
|
||||||
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
|
|
||||||
<input class="q-field__native q-placeholder" tabindex="0" aria-label="Phone Number" name="name" type="name" value="@Model.NormalizedEmail" disabled="disabled">
|
|
||||||
</div>
|
|
||||||
<div class="q-field__bottom row items-start q-field__bottom--animated">
|
|
||||||
<div class="q-field__messages col">
|
|
||||||
<div>Normalized Email</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label class="q-field row no-wrap items-start q-field--filled q-input q-field--labeled q-field--dark q-field--with-bottom">
|
|
||||||
<div class="q-field__inner relative-position col self-stretch">
|
|
||||||
<div class="q-field__control relative-position row no-wrap" tabindex="-1">
|
|
||||||
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
|
|
||||||
<input class="q-field__native q-placeholder" tabindex="0" aria-label="Phone Number" name="name" type="name" value="@Model.UserName">
|
|
||||||
</div>
|
|
||||||
<div class="q-field__bottom row items-start q-field__bottom--animated">
|
|
||||||
<div class="q-field__messages col">
|
|
||||||
<div>Username</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label class="q-field row no-wrap items-start q-field--filled q-input q-field--labeled q-field--dark q-field--with-bottom">
|
|
||||||
<div class="q-field__inner relative-position col self-stretch">
|
|
||||||
<div class="q-field__control relative-position row no-wrap" tabindex="-1">
|
|
||||||
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
|
|
||||||
<input class="q-field__native q-placeholder" tabindex="0" aria-label="Password Hash" name="name" type="name" value="@Model.PasswordHash" disabled="disabled">
|
|
||||||
</div>
|
|
||||||
<div class="q-field__bottom row items-start q-field__bottom--animated">
|
|
||||||
<div class="q-field__messages col">
|
|
||||||
<div>Username</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<div>
|
|
||||||
<button class="q-btn q-btn-item non-selectable no-outline q-btn--standard q-btn--rectangle bg-primary text-white q-btn--actionable q-focusable q-hoverable">
|
|
||||||
<span class="q-focus-helper"></span>
|
|
||||||
<span class="q-btn__content text-center col items-center q-anchor--skip justify-center row">
|
|
||||||
<span class="block">Save</span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
<button class="q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--rectangle text-primary q-btn--actionable q-focusable q-hoverable q-ml-sm" type="reset">
|
|
||||||
<span class="q-focus-helper"></span>
|
|
||||||
<span class="q-btn__content text-center col items-center q-anchor--skip justify-center row">
|
|
||||||
<span class="block">Reset</span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
@await Html.PartialAsync("_FooterMenu")
|
|
|
@ -1,10 +0,0 @@
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Home Page";
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="text-center">
|
|
||||||
<h1 class="display-4">Curriculums Module</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
@Html.Partial("_FooterMenu");
|
|
|
@ -1,111 +0,0 @@
|
||||||
@using CodeLiturgy.Views.Utils
|
|
||||||
@model BlueWest.Data.Application.Users.ApplicationUserUnique
|
|
||||||
@{
|
|
||||||
var user = @Model;
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="q-ma-lg">
|
|
||||||
<form method="POST" action="EditProfile" class="q-form q-gutter-md">
|
|
||||||
<label class="q-field row no-wrap items-start q-field--filled q-input q-field--labeled q-field--dark q-field--with-bottom">
|
|
||||||
<div class="q-field__inner relative-position col self-stretch">
|
|
||||||
<div class="q-field__control relative-position row no-wrap" tabindex="-1">
|
|
||||||
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
|
|
||||||
<input class="q-field__native q-placeholder" tabindex="0" aria-label="Phone Number" name="name" type="name" value="@Model.Id" disabled="disabled">
|
|
||||||
</div>
|
|
||||||
<div class="q-field__bottom row items-start q-field__bottom--animated">
|
|
||||||
<div class="q-field__messages col">
|
|
||||||
<div>Id</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label class="q-field row no-wrap items-start q-field--filled q-input q-field--labeled q-field--dark q-field--with-bottom">
|
|
||||||
<div class="q-field__inner relative-position col self-stretch">
|
|
||||||
<div class="q-field__control relative-position row no-wrap">
|
|
||||||
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
|
|
||||||
<input class="q-field__native q-placeholder" name="email" aria-label="Email" type="email" value="@user.Email">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="q-field__bottom row items-start q-field__bottom--animated">
|
|
||||||
<div class="q-field__messages col">
|
|
||||||
<div>Email address</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label class="q-field row no-wrap items-start q-field--filled q-input q-field--labeled q-field--dark q-field--with-bottom">
|
|
||||||
<div class="q-field__inner relative-position col self-stretch">
|
|
||||||
<div class="q-field__control relative-position row no-wrap" tabindex="-1">
|
|
||||||
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
|
|
||||||
<input class="q-field__native q-placeholder" tabindex="0" aria-label="Phone Number" name="name" type="name" value="@Model.PhoneNumber">
|
|
||||||
</div>
|
|
||||||
<div class="q-field__bottom row items-start q-field__bottom--animated">
|
|
||||||
<div class="q-field__messages col">
|
|
||||||
<div>Phone Number</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label class="q-field row no-wrap items-start q-field--filled q-input q-field--labeled q-field--dark q-field--with-bottom">
|
|
||||||
<div class="q-field__inner relative-position col self-stretch">
|
|
||||||
<div class="q-field__control relative-position row no-wrap" tabindex="-1">
|
|
||||||
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
|
|
||||||
<input class="q-field__native q-placeholder" tabindex="0" aria-label="Phone Number" name="name" type="name" value="@Model.NormalizedEmail" disabled="disabled">
|
|
||||||
</div>
|
|
||||||
<div class="q-field__bottom row items-start q-field__bottom--animated">
|
|
||||||
<div class="q-field__messages col">
|
|
||||||
<div>Normalized Email</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label class="q-field row no-wrap items-start q-field--filled q-input q-field--labeled q-field--dark q-field--with-bottom">
|
|
||||||
<div class="q-field__inner relative-position col self-stretch">
|
|
||||||
<div class="q-field__control relative-position row no-wrap" tabindex="-1">
|
|
||||||
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
|
|
||||||
<input class="q-field__native q-placeholder" tabindex="0" aria-label="Phone Number" name="name" type="name" value="@Model.UserName">
|
|
||||||
</div>
|
|
||||||
<div class="q-field__bottom row items-start q-field__bottom--animated">
|
|
||||||
<div class="q-field__messages col">
|
|
||||||
<div>Username</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label class="q-field row no-wrap items-start q-field--filled q-input q-field--labeled q-field--dark q-field--with-bottom">
|
|
||||||
<div class="q-field__inner relative-position col self-stretch">
|
|
||||||
<div class="q-field__control relative-position row no-wrap" tabindex="-1">
|
|
||||||
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
|
|
||||||
<input class="q-field__native q-placeholder" tabindex="0" aria-label="Password Hash" name="name" type="name" value="@Model.PasswordHash" disabled="disabled">
|
|
||||||
</div>
|
|
||||||
<div class="q-field__bottom row items-start q-field__bottom--animated">
|
|
||||||
<div class="q-field__messages col">
|
|
||||||
<div>Username</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<div>
|
|
||||||
<button class="q-btn q-btn-item non-selectable no-outline q-btn--standard q-btn--rectangle bg-primary text-white q-btn--actionable q-focusable q-hoverable">
|
|
||||||
<span class="q-focus-helper"></span>
|
|
||||||
<span class="q-btn__content text-center col items-center q-anchor--skip justify-center row">
|
|
||||||
<span class="block">Save</span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
<button class="q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--rectangle text-primary q-btn--actionable q-focusable q-hoverable q-ml-sm" type="reset">
|
|
||||||
<span class="q-focus-helper"></span>
|
|
||||||
<span class="q-btn__content text-center col items-center q-anchor--skip justify-center row">
|
|
||||||
<span class="block">Reset</span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
@await Html.PartialAsync("_FooterMenu")
|
|
|
@ -0,0 +1 @@
|
||||||
|
<h1>Account</h1>
|
|
@ -1,5 +0,0 @@
|
||||||
@model BlueWest.Data.Auth.Context.Users.LoginRequest
|
|
||||||
@using (Html.BeginForm()){
|
|
||||||
@Html.LabelFor(x => x.Password, "Password")
|
|
||||||
@Html.PasswordFor(x => x.Password);
|
|
||||||
}
|
|
|
@ -101,7 +101,7 @@
|
||||||
<button class="q-btn q-btn-item non-selectable no-outline q-btn--standard q-btn--rectangle bg-primary text-white q-btn--actionable q-focusable q-hoverable">
|
<button class="q-btn q-btn-item non-selectable no-outline q-btn--standard q-btn--rectangle bg-primary text-white q-btn--actionable q-focusable q-hoverable">
|
||||||
<span class="q-focus-helper"></span>
|
<span class="q-focus-helper"></span>
|
||||||
<span class="q-btn__content text-center col items-center q-anchor--skip justify-center row">
|
<span class="q-btn__content text-center col items-center q-anchor--skip justify-center row">
|
||||||
<span class="block">Login</span>
|
<span class="block">Signup</span>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--rectangle text-primary q-btn--actionable q-focusable q-hoverable q-ml-sm" type="reset">
|
<button class="q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--rectangle text-primary q-btn--actionable q-focusable q-hoverable q-ml-sm" type="reset">
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
@model dynamic
|
|
||||||
|
|
||||||
@{
|
|
||||||
Layout = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>title</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<div class="text-center">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
@using CodeLiturgy.Views.Utils
|
@using CodeLiturgy.Views.Utils
|
||||||
|
@using Duende.IdentityServer.Extensions
|
||||||
@{
|
@{
|
||||||
Layout = null;
|
Layout = null;
|
||||||
var menu = LayoutCache.GetDefaultFooterMenu(ViewData);
|
var menu = LayoutCache.GetDefaultFooterMenu(ViewData, User.IsAuthenticated());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
@{
|
@{
|
||||||
Layout = null;
|
Layout = null;
|
||||||
var userAuthenticated = User.IsAuthenticated();
|
var userAuthenticated = User.IsAuthenticated();
|
||||||
var menu = LayoutCache.GetDefaultHeaderMenu(ViewData, userAuthenticated);
|
|
||||||
var user = ViewData.GetUserViewData();
|
var user = ViewData.GetUserViewData();
|
||||||
var rootUrl = SessionConstants.CookieDomain;
|
var rootUrl = SessionConstants.CookieDomain;
|
||||||
|
|
||||||
|
|
||||||
|
var menu = LayoutCache.GetDefaultHeaderMenu(ViewData, User.IsAuthenticated());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="q-tabs items-center row no-wrap items-center q-tabs--not-scrollable q-tabs--horizontal q-tabs__arrows--inside">
|
<div class="q-tabs items-center row no-wrap items-center q-tabs--not-scrollable q-tabs--horizontal q-tabs__arrows--inside">
|
||||||
|
@ -26,7 +28,7 @@
|
||||||
}
|
}
|
||||||
@if (userAuthenticated && user != null)
|
@if (userAuthenticated && user != null)
|
||||||
{
|
{
|
||||||
<div class="q-chip row inline no-wrap items-center q-chip--dark q-dark">
|
<div class="q-chip row inline no-wrap items-center q-chip--dark q-dark" id="profile-wrap">
|
||||||
<div class="q-chip__content col row no-wrap items-center q-anchor--skip">
|
<div class="q-chip__content col row no-wrap items-center q-anchor--skip">
|
||||||
<div class="q-avatar">
|
<div class="q-avatar">
|
||||||
<div class="q-avatar__content row flex-center overflow-hidden">
|
<div class="q-avatar__content row flex-center overflow-hidden">
|
||||||
|
@ -35,8 +37,46 @@
|
||||||
</div> @user.Email
|
</div> @user.Email
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<style lang="css">
|
||||||
|
|
||||||
|
</style>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@if (userAuthenticated && user != null)
|
||||||
|
{
|
||||||
|
<div class="profileMenuContainer" id="profile-menu" style="display: none">
|
||||||
|
<div>
|
||||||
|
<a href="@AuthAccountRoute" class="profile-link">
|
||||||
|
<button class="q-btn q-btn-item non-selectable no-outline q-btn--standard q-btn--rectangle bg-black text-white q-btn--actionable q-focusable q-hoverable q-btn--active" type="button">
|
||||||
|
<span class="q-btn__content text-center col items-center q-anchor--skip justify-center row">
|
||||||
|
<span class="block">Profile</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="@AuthLogoutRoute" class="profile-link">
|
||||||
|
<button class="q-btn q-btn-item non-selectable no-outline q-btn--standard q-btn--rectangle bg-black text-white q-btn--actionable q-focusable q-hoverable q-btn--active" type="button">
|
||||||
|
<span class="q-btn__content text-center col items-center q-anchor--skip justify-center row">
|
||||||
|
<span class="block">Logout</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<script >
|
||||||
|
(() => {
|
||||||
|
const wrapMenu = document.getElementById("profile-wrap");
|
||||||
|
const profileMenu = document.getElementById("profile-menu");
|
||||||
|
wrapMenu.onclick = () => {
|
||||||
|
if (profileMenu.style.display === "none") {
|
||||||
|
profileMenu.style.display = "block";
|
||||||
|
} else {
|
||||||
|
profileMenu.style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
|
@ -10,10 +10,9 @@
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<title>@ViewData["Title"] - CodeLiturgy.Views</title>
|
<title>@ViewData["Title"] - CodeLiturgy.Views</title>
|
||||||
<link rel="stylesheet" href="@rootUrl/static/main.css"/>
|
<link rel="stylesheet" href="@rootUrl/static/main.css" asp-append-version="true"/>
|
||||||
@*
|
<link rel="stylesheet" href="@rootUrl/static/site.css" asp-append-version="true"/>
|
||||||
<link rel="stylesheet" href="~/CodeLiturgy.Views.styles.css" asp-append-version="true"/>
|
|
||||||
*@
|
|
||||||
<link rel="preload" href="@rootUrl/static/material-icons/web-font/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff" as="font" type="font/woff" crossorigin>
|
<link rel="preload" href="@rootUrl/static/material-icons/web-font/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff" as="font" type="font/woff" crossorigin>
|
||||||
<link rel="preload" href="@rootUrl/static/material-icons/web-font/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2" as="font" type="font/woff2" crossorigin>
|
<link rel="preload" href="@rootUrl/static/material-icons/web-font/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
.router-link-active {
|
.router-link-active {
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.material-icons {
|
.material-icons {
|
||||||
font-family: 'Material Icons', "Roboto", "-apple-system", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
font-family: 'Material Icons', "Roboto", "-apple-system", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#profile-wrap {
|
||||||
|
cursor: pointer;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-link {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.profileMenuContainer {
|
||||||
|
position: absolute;
|
||||||
|
background-color: #505050;
|
||||||
|
padding: 12px 10px 12px;
|
||||||
|
right: 0;
|
||||||
|
border: 2px solid #0f0f0f;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
Loading…
Reference in New Issue