diff --git a/Components/Pages/Login.razor b/Components/Pages/Login.razor new file mode 100644 index 0000000..ebbd97c --- /dev/null +++ b/Components/Pages/Login.razor @@ -0,0 +1,93 @@ +@page "/login" +@using System.ComponentModel.DataAnnotations +@using System.Security.Claims +@using Microsoft.AspNetCore.Authentication +@using Microsoft.AspNetCore.Authentication.Cookies +@using AuthenticationService = JustShortIt.Service.AuthenticationService + +@inject AuthenticationService Authentication +@inject IHttpContextAccessor HttpContextAccessor +@inject NavigationManager Navigation + +Login - Just Short It + +
+ +

Login

+ + +
+ + + + + + + +
+
+ + + + + + + +
+ + +
+
+ +@code { + [SupplyParameterFromForm] + public LoginModel Model { get; set; } = default!; + + public string? Message { get; set; } + + protected override void OnInitialized() { + // ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract + Model ??= new LoginModel(); + } + + public sealed class LoginModel { + [Required(AllowEmptyStrings = false, ErrorMessage = "User name is required.")] + public string? Username { get; set; } + [Required(AllowEmptyStrings = false, ErrorMessage = "Password is required.")] + public string? Password { get; set; } + } + + private async Task Submit() { + if (Model.Username is null || Model.Password is null) return; + var context = HttpContextAccessor.HttpContext; + if (context is null) throw new ArgumentNullException("context"); + + if (Authentication.IsUser(Model.Username, Model.Password)) { + var claims = new List { + new(ClaimTypes.Name, Model.Username), + new(ClaimTypes.Role, "Administrator") + }; + var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); + + var properties = new AuthenticationProperties{ + AllowRefresh = true, + IsPersistent = true, + ExpiresUtc = DateTimeOffset.UtcNow.AddDays(1), + IssuedUtc = DateTimeOffset.UtcNow, + RedirectUri = "/" + }; + + await context.SignInAsync( + CookieAuthenticationDefaults.AuthenticationScheme, + new ClaimsPrincipal(identity), + properties); + + Navigation.NavigateTo("/urls", true); + } else { + Message = "Invalid user name or password."; + } + } +} diff --git a/Pages/Login.cshtml b/Pages/Login.cshtml deleted file mode 100644 index 5c58ee8..0000000 --- a/Pages/Login.cshtml +++ /dev/null @@ -1,34 +0,0 @@ -@page -@model JustShortIt.Pages.LoginModel -@{ - ViewData["Title"] = "Login"; -} - -
-
-

Login

- -
- - - - - - - -
-
- - - - - - - -
- -
- - -
-
diff --git a/Pages/Login.cshtml.cs b/Pages/Login.cshtml.cs deleted file mode 100644 index 4daba60..0000000 --- a/Pages/Login.cshtml.cs +++ /dev/null @@ -1,54 +0,0 @@ - -using System.Security.Claims; -using JustShortIt.Model; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using AuthenticationService = JustShortIt.Service.AuthenticationService; - -namespace JustShortIt.Pages; - -public class LoginModel : PageModel { - [BindProperty] - public User? UserModel { get; set; } - - private AuthenticationService Authentication { get; } - - public LoginModel(AuthenticationService authentication) { - Authentication = authentication; - } - - public async Task OnPostAsync() { - if (!ModelState.IsValid) return Page(); - - if (Authentication.IsUser(UserModel!.Username, UserModel!.Password)) { - - var claims = new List { - new(ClaimTypes.Name, UserModel.Username), - new(ClaimTypes.Role, "Administrator") - }; - var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); - - var properties = new AuthenticationProperties { - AllowRefresh = true, - IsPersistent = true, - ExpiresUtc = DateTimeOffset.UtcNow.AddDays(1), - IssuedUtc = DateTimeOffset.UtcNow, - RedirectUri = "/" - }; - - await HttpContext.SignInAsync( - CookieAuthenticationDefaults.AuthenticationScheme, - new ClaimsPrincipal(identity), - properties); - - return LocalRedirect("~/urls"); - } - - ModelState.AddModelError(string.Empty, "Invalid Username or Password"); - return Page(); - } - - public IActionResult OnGet() => Page(); -} \ No newline at end of file