0x00000FF/PEngine

View on GitHub
Sources/PEngine.Web/Controllers/MemberController.cs

Summary

Maintainability
A
1 hr
Test Coverage
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc;
using PEngine.Web.Helper;
using PEngine.Web.Models;
using PEngine.Web.Models.ViewModels;
 
namespace PEngine.Web.Controllers;
 
public class MemberController : CommonControllerBase<MemberController>
{
public MemberController(ILogger<MemberController> logger) : base(logger)
{
 
}
public IActionResult Login(string? returnUrl)
{
if (!_context.Users.Any())
{
return View("UserCreateFirst", new UserCreateFirstVM { });
}
 
ViewData.Add("ReturnUrl", returnUrl ?? "/");
return View();
}
 
Method `Login` has 27 lines of code (exceeds 25 allowed). Consider refactoring.
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Login(string username, string password, string? ipsec)
{
var user = _context.Users.FirstOrDefault(u => u.Username == username);
 
if (user is null)
{
return View("UserNotFound");
}
 
if (user.Password != password.Password(user.PasswordSalt!).ToBase64())
{
// TODO: make option for failing password matches:
// return View("UserNotFound");
 
return View("UserFail");
}
 
var claimPrincipal = new ClaimsPrincipal();
var claimsIdentity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
claimsIdentity.AddClaim(new Claim("Id", user.Id.ToString()));
claimsIdentity.AddClaim(new Claim("Name", user.Name!));
// IP-Security
if (ipsec == "y")
{
claimsIdentity.AddClaim(new Claim("IPSec", "y"));
 
var remoteIp = HttpContext.Connection.RemoteIpAddress;
if (remoteIp is null)
{
return View("UserFailIPAddr");
}
 
claimsIdentity.AddClaim(new Claim("IPAddress", remoteIp.ToString()));
}
 
claimPrincipal.AddIdentity(claimsIdentity);
 
return SignIn(claimPrincipal);
}
 
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateFirst(string username, string password, string name)
{
if (_context.Users.Any())
{
return Forbid();
}
var newSalt = CryptoHelper.Random(32).ToBase64();
_context.Users.Add(new User()
{
Username = username,
Password = password.Password(newSalt).ToBase64(),
PasswordSalt = newSalt,
Id = default,
Name = name,
Role = UserRole.Root
});
 
return await _context.SaveChangesAsync() > 0 ?
RedirectToAction("Login") : BadRequest();
}
 
public async Task<IActionResult> Logout(string? returnUrl)
{
if (IsAuthenticated)
{
await HttpContext.SignOutAsync();
}
 
return Redirect(returnUrl ?? "/");
}
}