Feature/admin (#831)

* fix redirect to login for admin page
fix logout

* add admin part url

Co-authored-by: cedri <cedri@BAS>
This commit is contained in:
Cédric Michel
2022-12-22 16:03:16 +01:00
committed by GitHub
parent 2e6fc6ca44
commit 61d2d6cdd0
6 changed files with 49 additions and 17 deletions

View File

@@ -47,7 +47,9 @@ The store's home page should look like this:
![eShopOnWeb home page screenshot](https://user-images.githubusercontent.com/782127/88414268-92d83a00-cdaa-11ea-9b4c-db67d95be039.png) ![eShopOnWeb home page screenshot](https://user-images.githubusercontent.com/782127/88414268-92d83a00-cdaa-11ea-9b4c-db67d95be039.png)
Most of the site's functionality works with just the web application running. However, the site's Admin page relies on Blazor WebAssembly running in the browser, and it must communicate with the server using the site's PublicApi web application. You'll need to also run this project. You can configure Visual Studio to start multiple projects, or just go to the PublicApi folder in a terminal window and run `dotnet run` from there. After that from the Web folder you should run `dotnet run --launch-profile Web`. Now you should be able to browse to `https://localhost:5001/`. Note that if you use this approach, you'll need to stop the application manually in order to build the solution (otherwise you'll get file locking errors). Most of the site's functionality works with just the web application running. However, the site's Admin page relies on Blazor WebAssembly running in the browser, and it must communicate with the server using the site's PublicApi web application. You'll need to also run this project. You can configure Visual Studio to start multiple projects, or just go to the PublicApi folder in a terminal window and run `dotnet run` from there. After that from the Web folder you should run `dotnet run --launch-profile Web`. Now you should be able to browse to `https://localhost:5001/`. The admin part in Blazor is accessible to `https://localhost:5001/admin`
Note that if you use this approach, you'll need to stop the application manually in order to build the solution (otherwise you'll get file locking errors).
After cloning or downloading the sample you must setup your database. After cloning or downloading the sample you must setup your database.
To use the sample with a persistent database, you will need to run its Entity Framework Core migrations before you will be able to run the app. To use the sample with a persistent database, you will need to run its Entity Framework Core migrations before you will be able to run the app.

View File

@@ -63,7 +63,7 @@ public class CustomAuthStateProvider : AuthenticationStateProvider
if (user == null || !user.IsAuthenticated) if (user == null || !user.IsAuthenticated)
{ {
return null; return new ClaimsPrincipal(new ClaimsIdentity());
} }
var identity = new ClaimsIdentity( var identity = new ClaimsIdentity(

View File

@@ -7,7 +7,7 @@
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
await HttpClient.PostAsync("Identity/Account/Logout", null); await HttpClient.PostAsync("User/Logout", null);
await new Route(JSRuntime).RouteOutside("/Identity/Account/Login"); await new Route(JSRuntime).RouteOutside("/Identity/Account/Login");
} }

View File

@@ -1,9 +1,12 @@
@inject NavigationManager Navigation @using System.Web;
@inject NavigationManager Navigation
@inject IJSRuntime JsRuntime
@code { @code {
protected override void OnInitialized() protected override void OnInitialized()
{ {
Navigation.NavigateTo($"Identity/Account/Login?returnUrl=" + var returnUrl = HttpUtility.UrlEncode($"/{Uri.EscapeDataString(Navigation.ToBaseRelativePath(Navigation.Uri))}");
$"/{Uri.EscapeDataString(Navigation.ToBaseRelativePath(Navigation.Uri))}"); JsRuntime.InvokeVoidAsync("location.replace", $"Identity/Account/Login?returnUrl={returnUrl}");
} }
} }

View File

@@ -1,7 +1,4 @@
using System; using System.Security.Claims;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
@@ -10,7 +7,6 @@ using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.eShopWeb.Infrastructure.Identity; using Microsoft.eShopWeb.Infrastructure.Identity;
using Microsoft.eShopWeb.Web.Configuration; using Microsoft.eShopWeb.Web.Configuration;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
namespace Microsoft.eShopWeb.Web.Areas.Identity.Pages.Account; namespace Microsoft.eShopWeb.Web.Areas.Identity.Pages.Account;

View File

@@ -1,11 +1,14 @@
using System.Collections.Generic; using System.Security.Claims;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using BlazorShared.Authorization; using BlazorShared.Authorization;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopWeb.ApplicationCore.Interfaces; using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Microsoft.eShopWeb.Infrastructure.Identity;
using Microsoft.eShopWeb.Web.Configuration;
using Microsoft.Extensions.Caching.Memory;
namespace Microsoft.eShopWeb.Web.Controllers; namespace Microsoft.eShopWeb.Web.Controllers;
@@ -14,10 +17,19 @@ namespace Microsoft.eShopWeb.Web.Controllers;
public class UserController : ControllerBase public class UserController : ControllerBase
{ {
private readonly ITokenClaimsService _tokenClaimsService; private readonly ITokenClaimsService _tokenClaimsService;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly ILogger<UserController> _logger;
private readonly IMemoryCache _cache;
public UserController(ITokenClaimsService tokenClaimsService) public UserController(ITokenClaimsService tokenClaimsService,
SignInManager<ApplicationUser> signInManager,
ILogger<UserController> logger,
IMemoryCache cache)
{ {
_tokenClaimsService = tokenClaimsService; _tokenClaimsService = tokenClaimsService;
_signInManager = signInManager;
_logger = logger;
_cache = cache;
} }
[HttpGet] [HttpGet]
@@ -26,6 +38,25 @@ public class UserController : ControllerBase
public async Task<IActionResult> GetCurrentUser() => public async Task<IActionResult> GetCurrentUser() =>
Ok(await CreateUserInfo(User)); Ok(await CreateUserInfo(User));
[Route("Logout")]
[HttpPost]
[Authorize]
[AllowAnonymous]
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
var userId = _signInManager.Context.User.Claims.First(c => c.Type == ClaimTypes.Name);
var identityKey = _signInManager.Context.Request.Cookies[ConfigureCookieSettings.IdentifierCookieName];
_cache.Set($"{userId.Value}:{identityKey}", identityKey, new MemoryCacheEntryOptions
{
AbsoluteExpiration = DateTime.Now.AddMinutes(ConfigureCookieSettings.ValidityMinutesPeriod)
});
_logger.LogInformation("User logged out.");
return Ok();
}
private async Task<UserInfo> CreateUserInfo(ClaimsPrincipal claimsPrincipal) private async Task<UserInfo> CreateUserInfo(ClaimsPrincipal claimsPrincipal)
{ {
if (claimsPrincipal.Identity == null || claimsPrincipal.Identity.Name == null || !claimsPrincipal.Identity.IsAuthenticated) if (claimsPrincipal.Identity == null || claimsPrincipal.Identity.Name == null || !claimsPrincipal.Identity.IsAuthenticated)