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";
-}
-
-
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