Added basic authentication and localization
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,3 +17,4 @@ src/Indexer/logs
|
|||||||
src/Server/logs
|
src/Server/logs
|
||||||
src/Shared/bin
|
src/Shared/bin
|
||||||
src/Shared/obj
|
src/Shared/obj
|
||||||
|
src/Server/wwwroot/logs/*
|
||||||
|
|||||||
65
src/Server/Controllers/AccountController.cs
Normal file
65
src/Server/Controllers/AccountController.cs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
using System.Security.Claims;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Server.Models;
|
||||||
|
|
||||||
|
namespace Server.Controllers;
|
||||||
|
|
||||||
|
[Route("[Controller]")]
|
||||||
|
public class AccountController : Controller
|
||||||
|
{
|
||||||
|
private readonly SimpleAuthOptions _options;
|
||||||
|
|
||||||
|
public AccountController(IOptions<SimpleAuthOptions> options)
|
||||||
|
{
|
||||||
|
_options = options.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("Login")]
|
||||||
|
public IActionResult Login(string? returnUrl = null)
|
||||||
|
{
|
||||||
|
ViewData["ReturnUrl"] = returnUrl;
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("Login")]
|
||||||
|
public async Task<IActionResult> Login(
|
||||||
|
string username,
|
||||||
|
string password,
|
||||||
|
string? returnUrl = null)
|
||||||
|
{
|
||||||
|
var user = _options.Users.SingleOrDefault(u =>
|
||||||
|
u.Username == username && u.Password == password);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError("", "Invalid credentials");
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
var claims = new List<Claim>
|
||||||
|
{
|
||||||
|
new(ClaimTypes.Name, user.Username)
|
||||||
|
};
|
||||||
|
|
||||||
|
claims.AddRange(user.Roles.Select(r =>
|
||||||
|
new Claim(ClaimTypes.Role, r)));
|
||||||
|
|
||||||
|
var identity = new ClaimsIdentity(
|
||||||
|
claims, "AppCookie");
|
||||||
|
|
||||||
|
await HttpContext.SignInAsync(
|
||||||
|
"AppCookie",
|
||||||
|
new ClaimsPrincipal(identity));
|
||||||
|
|
||||||
|
return Redirect(returnUrl ?? "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("Logout")]
|
||||||
|
public async Task<IActionResult> Logout()
|
||||||
|
{
|
||||||
|
await HttpContext.SignOutAsync("AppCookie");
|
||||||
|
return RedirectToAction("Login");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ public class HomeController : Controller
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authorize]
|
||||||
[HttpGet("/")]
|
[HttpGet("/")]
|
||||||
public IActionResult Index()
|
public IActionResult Index()
|
||||||
{
|
{
|
||||||
|
|||||||
13
src/Server/Models/Auth.cs
Normal file
13
src/Server/Models/Auth.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace Server.Models;
|
||||||
|
|
||||||
|
public class SimpleAuthOptions
|
||||||
|
{
|
||||||
|
public List<SimpleUser> Users { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SimpleUser
|
||||||
|
{
|
||||||
|
public string Username { get; set; } = "";
|
||||||
|
public string Password { get; set; } = "";
|
||||||
|
public string[] Roles { get; set; } = Array.Empty<string>();
|
||||||
|
}
|
||||||
21
src/Server/Resources/SharedResources.de.resx
Normal file
21
src/Server/Resources/SharedResources.de.resx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="LoggedInAs" xml:space="preserve">
|
||||||
|
<value>Angemeldet als</value>
|
||||||
|
</data>
|
||||||
|
<data name="Logout" xml:space="preserve">
|
||||||
|
<value>Abmelden</value>
|
||||||
|
</data>
|
||||||
|
<data name="Login" xml:space="preserve">
|
||||||
|
<value>Anmelden</value>
|
||||||
|
</data>
|
||||||
|
<data name="Username" xml:space="preserve">
|
||||||
|
<value>Benutzername</value>
|
||||||
|
</data>
|
||||||
|
<data name="Password" xml:space="preserve">
|
||||||
|
<value>Passwort</value>
|
||||||
|
</data>
|
||||||
|
<data name="InvalidCredentials" xml:space="preserve">
|
||||||
|
<value>Ungültiger Benutzername oder Passwort.</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
21
src/Server/Resources/SharedResources.en.resx
Normal file
21
src/Server/Resources/SharedResources.en.resx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<data name="LoggedInAs" xml:space="preserve">
|
||||||
|
<value>Logged in as</value>
|
||||||
|
</data>
|
||||||
|
<data name="Logout" xml:space="preserve">
|
||||||
|
<value>Log out</value>
|
||||||
|
</data>
|
||||||
|
<data name="Login" xml:space="preserve">
|
||||||
|
<value>Login</value>
|
||||||
|
</data>
|
||||||
|
<data name="Username" xml:space="preserve">
|
||||||
|
<value>Username</value>
|
||||||
|
</data>
|
||||||
|
<data name="Password" xml:space="preserve">
|
||||||
|
<value>Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="InvalidCredentials" xml:space="preserve">
|
||||||
|
<value>Invalid credentials.</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
18
src/Server/Services/LocalizationService.cs
Normal file
18
src/Server/Services/LocalizationService.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
|
||||||
|
namespace Server.Services;
|
||||||
|
|
||||||
|
public class LocalizationService
|
||||||
|
{
|
||||||
|
private readonly IStringLocalizer _localizer;
|
||||||
|
|
||||||
|
public LocalizationService(IStringLocalizerFactory factory)
|
||||||
|
{
|
||||||
|
_localizer = factory.Create("SharedResources", "Server");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Get(string key) => _localizer[key];
|
||||||
|
|
||||||
|
public string this[string key] => _localizer[key];
|
||||||
|
public string this[string key, params object[] args] => _localizer[key, args];
|
||||||
|
}
|
||||||
28
src/Server/Views/Account/Login.cshtml
Normal file
28
src/Server/Views/Account/Login.cshtml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
@using Server.Services
|
||||||
|
@inject LocalizationService T
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "Login";
|
||||||
|
var returnUrl = ViewData["ReturnUrl"] as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="text-center">
|
||||||
|
<h1>Login</h1>
|
||||||
|
<form asp-action="Login" method="post" class="mt-4" style="max-width: 400px; margin: auto;">
|
||||||
|
<div class="form-group mb-3">
|
||||||
|
<label for="username" class="form-label">@T["Username"]</label>
|
||||||
|
<input autofocus type="text" class="form-control" id="username" name="username" autocomplete="username" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group mb-3">
|
||||||
|
<label for="password" class="form-label">@T["Password"]</label>
|
||||||
|
<input type="password" class="form-control" id="password" name="password" autocomplete="current-password" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary w-100">@T["Login"]</button>
|
||||||
|
|
||||||
|
@if (!ViewData.ModelState.IsValid)
|
||||||
|
{
|
||||||
|
<p style="color:red">Invalid username or password</p>
|
||||||
|
}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
@@ -19,12 +19,21 @@
|
|||||||
</button>
|
</button>
|
||||||
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
|
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
|
||||||
<ul class="navbar-nav flex-grow-1">
|
<ul class="navbar-nav flex-grow-1">
|
||||||
<li class="nav-item">
|
@if (User.Identity?.IsAuthenticated == true)
|
||||||
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
|
{
|
||||||
</li>
|
<li class="nav-item">
|
||||||
<li class="nav-item">
|
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
|
||||||
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
|
</li>
|
||||||
</li>
|
<li class="nav-item">
|
||||||
|
<a class="nav-link text-dark" asp-area="" asp-controller="Account" asp-action="Logout">Logout</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link text-dark" asp-area="" asp-controller="Account" asp-action="Login">Login</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user