idk a lot of changes for the admin stuff

This commit is contained in:
Fishandchips321 2026-03-08 19:30:00 +00:00
parent 2cbbc00489
commit 5251ca6f99
23 changed files with 576 additions and 15 deletions

View file

@ -32,6 +32,28 @@ public class AuthController : ControllerBase
}
[HttpGet]
public async Task<IActionResult> GetLoginFromSession()
{
if (!await IsAuthenticated())
{
return Unauthorized();
}
var sessionToken = GetSessionToken();
try
{
var login = await _service.GetLoginFromSession(sessionToken!);
return Ok(login);
}
catch (LoginFailedException)
{
return Unauthorized();
}
}
[HttpGet("all")]
public async Task<IActionResult> GetLogins()
{
if (!await IsAdminAuthenticated())
@ -72,7 +94,7 @@ public class AuthController : ControllerBase
return Forbid();
}
var newLogin = await _service.CreateLogin(login.Username, login.Password);
var newLogin = await _service.CreateLogin(login.Username, login.Password, login.IsAdmin);
return Ok(newLogin);
}
@ -80,9 +102,9 @@ public class AuthController : ControllerBase
[HttpPut]
public async Task<IActionResult> UpdateLogin([FromBody] UpdateLoginDTO login)
{
if (!await IsAdminAuthenticated())
if (!await IsAuthenticated())
{
return Forbid();
return Unauthorized();
}
try

View file

@ -76,6 +76,7 @@ public class ServersController : ControllerBase
[HttpPost]
public async Task<IActionResult> AddServer([FromBody] AddServerDTO server)
{
_logger.LogInformation("Started adding server");
if (!await IsAdminAuthenticated())
{
return Forbid();

View file

@ -19,4 +19,11 @@ public class AuthAlreadyExistsException : AuthRepositoryException
public AuthAlreadyExistsException() { }
public AuthAlreadyExistsException(string message) : base(message) { }
public AuthAlreadyExistsException(string message, System.Exception inner) : base(message, inner) { }
}
public class UserNotDeletableException : AuthRepositoryException
{
public UserNotDeletableException() { }
public UserNotDeletableException(string message) : base(message) { }
public UserNotDeletableException(string message, System.Exception inner) : base(message, inner) { }
}

View file

@ -4,4 +4,5 @@ public class CreateLoginDTO
{
public required string Username { get; set; }
public required string Password { get; set; }
public bool IsAdmin { get; set; } = false;
}

View file

@ -8,4 +8,5 @@ public interface ISessionRepository
public Task<UserSession?> GetUserSession(string sessionToken);
public Task RefreshSessionExpiry(string sessionToken);
public Task DeleteSession(string sessionToken);
public Task DeleteUserSessions(string username);
}

View file

@ -78,8 +78,23 @@ public class LoginRepository : ILoginRepository
public async Task<UserLogin> DeleteLogin(string username)
{
if ((await _context.Logins.CountAsync()) == 1) //if there is only one user registered, make sure you can't delete it
{
throw new UserNotDeletableException("There is only one user registered");
}
var login = await GetUserLogin(username);
if (login.IsAdmin) //if they're trying to delete the only admin
{
var admins = _context.Logins.Where(u => u.IsAdmin);
if ((await admins.CountAsync()) == 1)
{
throw new UserNotDeletableException("You can't delete the only admin user");
}
}
_context.Logins.Remove(login);
await _context.SaveChangesAsync();

View file

@ -61,6 +61,18 @@ public class SessionRepository : ISessionRepository
}
}
public async Task DeleteUserSessions(string username)
{
var sessions = await _context.Sessions.Include(s => s.Login).Where(s => s.Login.Username == username).ToArrayAsync();
foreach (var session in sessions)
{
_context.Sessions.Remove(session);
}
await _context.SaveChangesAsync();
}
private static DateTime GenerateExpiryDate()
{
return DateTime.Now + TimeSpan.FromDays(30); //TODO: Make this configurable

View file

@ -8,11 +8,13 @@ public class AuthService : IAuthService
{
private ILoginRepository _loginRepo;
private ISessionRepository _sessionRepo;
private readonly ILogger<AuthService> _logger;
public AuthService(ILoginRepository loginRepo, ISessionRepository sessionRepo)
public AuthService(ILoginRepository loginRepo, ISessionRepository sessionRepo, ILogger<AuthService> logger)
{
_loginRepo = loginRepo;
_sessionRepo = sessionRepo;
_logger = logger;
}
public async Task<UserSessionDTO> AuthenticateUser(string username, string password)
@ -69,11 +71,13 @@ public class AuthService : IAuthService
{
var session = await _sessionRepo.GetUserSession(sessionToken);
if (session == null)
{
throw new SessionNotFoundException();
}
return session.Login.IsAdmin;
}
@ -98,11 +102,23 @@ public class AuthService : IAuthService
return new UserLoginDTO(login);
}
public async Task<UserLoginDTO> CreateLogin(string username, string password)
public async Task<UserLoginDTO> GetLoginFromSession(string sessionToken)
{
var session = await _sessionRepo.GetUserSession(sessionToken);
if (session == null)
{
throw new LoginFailedException();
}
return new UserLoginDTO(session.Login);
}
public async Task<UserLoginDTO> CreateLogin(string username, string password, bool isAdmin)
{
var hashedPassword = BCrypt.Net.BCrypt.HashPassword(password);
var newLogin = await _loginRepo.CreateLogin(username, hashedPassword, false);
var newLogin = await _loginRepo.CreateLogin(username, hashedPassword, isAdmin);
return new UserLoginDTO(newLogin);
}
@ -137,6 +153,8 @@ public class AuthService : IAuthService
{
var deletedLogin = await _loginRepo.DeleteLogin(username);
await _sessionRepo.DeleteUserSessions(username);
return new UserLoginDTO(deletedLogin);
}
}

View file

@ -9,7 +9,8 @@ public interface IAuthService
public Task<bool> IsAdmin(string sessionToken);
public Task<UserLoginDTO[]> GetLogins();
public Task<UserLoginDTO> GetLogin(string username);
public Task<UserLoginDTO> CreateLogin(string username, string password);
public Task<UserLoginDTO> GetLoginFromSession(string sessionToken);
public Task<UserLoginDTO> CreateLogin(string username, string password, bool isAdmin);
public Task UpdateLoginOwnPassword(string sessionToken, string newPassword, string oldPassword);
public Task UpdateLoginPassword(string username, string newPassword);
public Task<UserLoginDTO> DeleteLogin(string username);