mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-10-03 05:43:31 +00:00
206 lines
9.6 KiB
Text
206 lines
9.6 KiB
Text
@page "/Account/Login"
|
|
@layout EmptyLayout
|
|
@using System.ComponentModel.DataAnnotations
|
|
@using global::Data.SeaHavenIndustries
|
|
@using Microsoft.AspNetCore.Authentication
|
|
@using Microsoft.AspNetCore.Identity
|
|
@using SeaHavenIndustries.Components.Layout
|
|
|
|
@inject SignInManager<ApplicationUser> SignInManager
|
|
@inject UserManager<ApplicationUser> _userManager
|
|
@inject ILogger<Login> Logger
|
|
@inject NavigationManager NavigationManager
|
|
@inject IdentityRedirectManager RedirectManager
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
<link rel="icon" type="image/png" href="./assets/img/Fav Icon.svg">
|
|
|
|
<title>Sea Haven Industries</title>
|
|
|
|
<!-- Fonts and icons -->
|
|
<link rel="stylesheet" type="text/css"
|
|
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,900|Roboto+Slab:400,700" />
|
|
<!-- Nucleo Icons -->
|
|
<link href="./assets/css/nucleo-icons.css" rel="stylesheet" />
|
|
<!-- <link href=".../assets/css/nucleo-icons.css" rel="stylesheet" /> -->
|
|
<link href="./assets/css/nucleo-svg.css" rel="stylesheet" />
|
|
<!-- Material Icons -->
|
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
|
|
|
|
<link rel="stylesheet" href="_content/Radzen.Blazor/css/default-base.css">
|
|
<!-- JS File -->
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
|
<link rel="stylesheet" href="/css/site.css" />
|
|
<!-- CSS Files -->
|
|
<link href="/assets/css/custom.css" rel="stylesheet" />
|
|
<link id="pagestyle" href="/assets/css/material-dashboard.css?v=3.0.5" rel="stylesheet" />
|
|
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0" />
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
|
</head>
|
|
|
|
<body>
|
|
<!-- Navbar -->
|
|
<nav class="navbar navbar-expand-lg position-absolute top-0 z-index-3 w-100 shadow-none py-4">
|
|
<div class="container">
|
|
<img src="./assets/img/Logo.png" class="w-15 ">
|
|
</div>
|
|
</nav>
|
|
|
|
<main class="main-content mt-0">
|
|
|
|
<section>
|
|
<div class="page-header min-vh-100">
|
|
<div class="container">
|
|
<div class="row justify-content-center">
|
|
<div class="col-xl-4 col-lg-5 col-md-7 d-flex flex-column me-auto me-lg-5">
|
|
<form method="post">
|
|
<div class="card mt-6 mx-4" style="background-color:#fff !important;">
|
|
<EditForm Model="Input" method="post" OnValidSubmit="LoginUser" FormName="login">
|
|
<DataAnnotationsValidator />
|
|
<div class="card-header p-0 position-relative mt-n4 mx-3 z-index-2 border-radius-lg">
|
|
<div class="bg-gradient-info shadow-info border-radius-lg py-3 pe-1 text-center py-4">
|
|
<h4 class="font-weight-bolder mt-1" style="color:#fff !important;">Sign In</h4>
|
|
<p class="mb-1 text-sm text-white">Enter your email and password to Sign In</p>
|
|
</div>
|
|
<p class="text-danger pt-1" role="alert">@errorMessage</p>
|
|
</div>
|
|
<div class="mb-0 px-4 text-center mt-2">
|
|
<div class="card-body py-1 p-0 ">
|
|
<div class="input-group input-group-static mb-1">
|
|
<InputText @bind-Value="Input.Email" class="form-control" autocomplete="username" aria-required="true" placeholder="Email" />
|
|
<ValidationMessage For="() => Input.Email" class="text-danger text-xs pt-1" />
|
|
</div>
|
|
|
|
<div class="input-group input-group-static my-2">
|
|
<InputText type="password" @bind-Value="Input.Password" class="form-control" autocomplete="current-password" aria-required="true" placeholder="password" />
|
|
<ValidationMessage For="() => Input.Password" class="text-danger text-xs pt-1" />
|
|
</div>
|
|
|
|
<div class="col-12 d-flex">
|
|
<div class="form-check form-switch d-flex align-items-center my-2">
|
|
<InputCheckbox @bind-Value="Input.RememberMe" checked class="form-check-input" />
|
|
<label class="form-check-label mb-0 ms-3" style="color: #6a6f7c !important;" for="rememberMe">Remember me</label>
|
|
</div>
|
|
<a href="Account/ForgotPassword" class="font-weight-normal float-end my-2 ms-auto " style="color: #0066FF;"> Forgot Password?</a>
|
|
</div>
|
|
</div>
|
|
<div class="mb-3 text-center">
|
|
<button type="submit" class="btn btn-lg w-100 py-2 bg-info text-light ms-1 mr-1 my-2">
|
|
SIGN IN
|
|
</button>
|
|
</div>
|
|
<div class="my-1 text-center">
|
|
<span class="font-weight-bold">Or</span> Login with
|
|
</div>
|
|
<div class="mb-3 text-center">
|
|
<button type="button" style="background:#fff" class="btn btn-lg w-100 py-2 shadow-lg text-light ms-1 mr-1 my-2">
|
|
<img src="./assets/img/Google.png" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</EditForm>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
<!-- Core JS Files -->
|
|
<script src="./assets/js/core/popper.min.js"></script>
|
|
<script src="./assets/js/core/bootstrap.min.js"></script>
|
|
<script src="./assets/js/plugins/perfect-scrollbar.min.js"></script>
|
|
<script src="./assets/js/plugins/smooth-scrollbar.min.js"></script>
|
|
<!-- Kanban scripts -->
|
|
|
|
<script>
|
|
var win = navigator.platform.indexOf('Win') > -1;
|
|
if (win && document.querySelector('#sidenav-scrollbar')) {
|
|
var options = {
|
|
damping: '0.5'
|
|
}
|
|
Scrollbar.init(document.querySelector('#sidenav-scrollbar'), options);
|
|
}
|
|
</script>
|
|
<!-- Github buttons -->
|
|
<script src="/assets/js/material-dashboard.min.js"></script>
|
|
</body>
|
|
</html>
|
|
|
|
|
|
@code {
|
|
private string? errorMessage;
|
|
|
|
[CascadingParameter]
|
|
private HttpContext HttpContext { get; set; } = default!;
|
|
|
|
[SupplyParameterFromForm]
|
|
private InputModel Input { get; set; } = new();
|
|
|
|
[SupplyParameterFromQuery]
|
|
private string? ReturnUrl { get; set; }
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
if (HttpMethods.IsGet(HttpContext.Request.Method))
|
|
{
|
|
// Clear the existing external cookie to ensure a clean login process
|
|
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
|
|
}
|
|
}
|
|
|
|
public async Task LoginUser()
|
|
{
|
|
// This doesn't count login failures towards account lockout
|
|
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
|
|
var result = await SignInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
|
|
if (result.Succeeded)
|
|
{
|
|
var user = await _userManager.FindByEmailAsync(Input.Email);
|
|
var roles = await _userManager.GetRolesAsync(user);
|
|
if (roles.Contains("User"))
|
|
{
|
|
ReturnUrl = "/UserHome";
|
|
}
|
|
Logger.LogInformation("User logged in.");
|
|
RedirectManager.RedirectTo(ReturnUrl);
|
|
}
|
|
else if (result.RequiresTwoFactor)
|
|
{
|
|
RedirectManager.RedirectTo(
|
|
"Account/LoginWith2fa",
|
|
new() { ["returnUrl"] = ReturnUrl, ["rememberMe"] = Input.RememberMe });
|
|
}
|
|
else if (result.IsLockedOut)
|
|
{
|
|
Logger.LogWarning("User account locked out.");
|
|
RedirectManager.RedirectTo("Account/Lockout");
|
|
}
|
|
else
|
|
{
|
|
errorMessage = "Invalid login attempt.";
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
|
|
private sealed class InputModel
|
|
{
|
|
[Required]
|
|
[EmailAddress]
|
|
public string Email { get; set; } = "";
|
|
|
|
[Required]
|
|
[DataType(DataType.Password)]
|
|
public string Password { get; set; } = "";
|
|
|
|
[Display(Name = "Remember me?")]
|
|
public bool RememberMe { get; set; }
|
|
}
|
|
}
|