Cleanup Auth Controller
Docker Build and Release Upload / build (push) Successful in 1m21s

This commit is contained in:
2025-07-24 21:07:54 -07:00
parent b1a0f1d96f
commit c167cbc267
2 changed files with 243 additions and 159 deletions
+167 -154
View File
@@ -2,11 +2,12 @@
using Auth.Services;
using Auth.Services.DatabaseService;
using Auth.Entities;
using Auth.DTO;
using System.Web.Http;
namespace Auth.Controllers {
[ApiController]
[Route("api/account/")]
[Route("api/")]
public class AuthenticationController : MistoxControllerBase {
EmailService _emailContext;
@@ -15,113 +16,6 @@ namespace Auth.Controllers {
_emailContext = emailContext;
}
[Route("login")]
[HttpPost]
public async Task<ActionResult<Account>> Login([FromForm] string UserName, [FromForm] string PasswordHash, [FromForm] bool StayLoggedIn) {
try {
Account? test = await _databaseService.GetAccount(UserName.ToLower());
if (test != null) {
if (test.EmailVerified == true) {
if (test.FailedPasswordLock) {
if (test.CurrentPasswordAttempts >= test.PasswordAttempts) {
return NotFound("Too many failed password attempts. Please reset your password");
}
}
if (BCrypt.Net.BCrypt.Verify(PasswordHash, test.PasswordHash)) {
test.CurrentPasswordAttempts = 0;
await _databaseService.SetAccount(test);
string jwt = AuthJWT.GenereateJWTToken(test.ID, StayLoggedIn);
AuthJWT.SignIn(Response, StayLoggedIn, jwt);
return Ok(test);
} else {
test.CurrentPasswordAttempts += 1;
await _databaseService.SetAccount(test);
return NotFound("Wrong Password");
}
} else {
await SendVerify(test.UserName);
return NotFound("A new verify email has been sent. \n Note only 1 email send every 5 mintes");
}
}
return NotFound("Account Not Found");
} catch (Exception ex) {
Console.WriteLine("Login Error: " + ex.Message);
return NotFound("An internal server error has occured");
}
}
[Route("register")]
[HttpPost]
public async Task<ActionResult<Account>> Register([FromForm] string Email, [FromForm] string UserName, [FromForm] string PasswordHash) {
try {
if (await _databaseService.GetAccount(UserName.ToLower()) == null) {
if (await _databaseService.GetAccount(Email.ToLower()) == null) {
Account created = new Account() {
UserName = UserName.ToLower(),
Email = Email.ToLower(),
EmailVerified = false,
PasswordHash = BCrypt.Net.BCrypt.HashPassword(PasswordHash),
};
await _databaseService.SetAccount(created);
Account? loadedAccount = await _databaseService.GetAccount(Email.ToLower());
if (loadedAccount != null) {
await SendVerify(loadedAccount.UserName);
return Ok(loadedAccount);
}
return NotFound("Unable to create the account");
} else {
return NotFound("Email is already in use");
}
} else {
return NotFound("UserName is taken");
}
} catch (Exception ex) {
Console.WriteLine("Register Error: " + ex.Message);
return NotFound("An internal server error has occured");
}
}
[Route("changepassword")]
[HttpPost]
public async Task<ActionResult> ChangePassword([FromForm] string OldPassword, [FromForm] string NewPassword) {
try {
if (isLoggedIn()) {
Account user = await getLoggedInUser();
if (BCrypt.Net.BCrypt.Verify(OldPassword, user.PasswordHash)) {
user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(NewPassword);
user.CurrentPasswordAttempts = 0;
await _databaseService.SetAccount(user);
return Ok();
}
}
return NotFound("Not logged in");
} catch (Exception ex) {
Console.WriteLine("ChangePassword Error: " + ex.Message);
return NotFound("An internal server error has occured");
}
}
[Route("toggleaccountlock")]
[HttpPost]
public async Task<ActionResult<string>> ToggleAccountLock([FromForm] bool AccountLock) {
try {
if (isLoggedIn()) {
Account user = await getLoggedInUser();
user.FailedPasswordLock = AccountLock;
user.CurrentPasswordAttempts = 0;
await _databaseService.SetAccount(user);
return Ok();
}
return NotFound("Not logged in");
} catch (Exception ex) {
Console.WriteLine("ToggleAccountLock Error: " + ex.Message);
return NotFound("An internal server error has occured");
}
}
[Route("get")]
[HttpPost]
public async Task<ActionResult<Account>> Get() {
@@ -129,10 +23,49 @@ namespace Auth.Controllers {
if (isLoggedIn()) {
return Ok(await getLoggedInUser());
}
return NotFound("Not logged in");
return BadRequest("Not logged in");
} catch (Exception ex) {
Console.WriteLine("Get Error: " + ex);
return NotFound("An internal server error has occured");
return BadRequest("An internal server error has occured");
}
}
[Route("login")]
[HttpPost]
public async Task<ActionResult<Account>> Login([FromBody] LoginRequest request) {
try {
Account? test = await _databaseService.GetAccount(request.UserName.ToLower());
if (test != null) {
if (test.EmailVerified == true) {
if (test.FailedPasswordLock) {
if (test.CurrentPasswordAttempts >= test.PasswordAttempts) {
return BadRequest("Too many failed password attempts. Please reset your password");
}
}
if (BCrypt.Net.BCrypt.Verify(request.Password, test.PasswordHash)) {
test.CurrentPasswordAttempts = 0;
await _databaseService.SetAccount(test);
string jwt = AuthJWT.GenereateJWTToken(test.ID, request.StayLoggedIn);
AuthJWT.SignIn(Response, request.StayLoggedIn, jwt);
return Ok(test);
} else {
test.CurrentPasswordAttempts += 1;
await _databaseService.SetAccount(test);
return BadRequest("Wrong Password");
}
} else {
await SendVerify(new SendVerifyEmailRequest {
UserName = test.UserName
});
return BadRequest("A new verify email has been sent. \n Note only 1 email send every 5 mintes");
}
}
return BadRequest("Account Not Found");
} catch (Exception ex) {
Console.WriteLine("Login Error: " + ex.Message);
return BadRequest("An internal server error has occured");
}
}
@@ -143,81 +76,157 @@ namespace Auth.Controllers {
AuthJWT.SignOut(Response);
return Ok();
}
return NotFound();
return BadRequest();
}
[Route("register")]
[HttpPost]
public async Task<ActionResult<Account>> Register([FromBody] RegisterRequest request) {
try {
if (await _databaseService.GetAccount(request.UserName.ToLower()) == null) {
if (await _databaseService.GetAccount(request.Email.ToLower()) == null) {
Account created = new Account() {
UserName = request.UserName.ToLower(),
Email = request.Email.ToLower(),
EmailVerified = false,
PasswordHash = BCrypt.Net.BCrypt.HashPassword(request.Password),
};
await _databaseService.SetAccount(created);
Account? loadedAccount = await _databaseService.GetAccount(request.Email.ToLower());
if (loadedAccount != null) {
await SendVerify(new SendVerifyEmailRequest {
UserName = loadedAccount.UserName
});
return Ok(loadedAccount);
}
return BadRequest("Unable to create the account");
} else {
return BadRequest("Email is already in use");
}
} else {
return BadRequest("UserName is taken");
}
} catch (Exception ex) {
Console.WriteLine("Register Error: " + ex.Message);
return BadRequest("An internal server error has occured");
}
}
[Route("changepassword")]
[HttpPost]
public async Task<ActionResult> ChangePassword([FromBody] ChangePasswordRequest request) {
try {
if (isLoggedIn()) {
Account user = await getLoggedInUser();
if (BCrypt.Net.BCrypt.Verify(request.OldPassword, user.PasswordHash)) {
user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(request.NewPassword);
user.CurrentPasswordAttempts = 0;
await _databaseService.SetAccount(user);
return Ok();
}
}
return BadRequest("Not logged in");
} catch (Exception ex) {
Console.WriteLine("ChangePassword Error: " + ex.Message);
return BadRequest("An internal server error has occured");
}
}
[Route("accountlock")]
[HttpPost]
public async Task<ActionResult<string>> setAccountLock([FromBody] AccountLockRequest request) {
try {
if (isLoggedIn()) {
Account user = await getLoggedInUser();
user.FailedPasswordLock = request.AccountLock;
user.CurrentPasswordAttempts = 0;
await _databaseService.SetAccount(user);
return Ok();
}
return BadRequest("Not logged in");
} catch (Exception ex) {
Console.WriteLine("ToggleAccountLock Error: " + ex.Message);
return BadRequest("An internal server error has occured");
}
}
[Route("sendverifyemail")]
[HttpPost]
public async Task<ActionResult<string>> SendVerify([FromForm] string UserName) {
public async Task<ActionResult<string>> SendVerify([FromBody] SendVerifyEmailRequest request) {
try {
string key = "v" + UserName;
string key = "v" + request.UserName.ToLower();
// Stop from sending multiple emails quickly
if (_emailContext._SentEmails.ContainsKey(key)) {
DateTime PreviousSentTime = _emailContext._SentEmails.GetValueOrDefault(key);
if (PreviousSentTime.AddMinutes(5) > DateTime.Now) {
return NotFound("Cannot sent another verify email until 5 minutes has elapsed");
}
else {
return BadRequest("Cannot sent another verify email until 5 minutes has elapsed");
} else {
_emailContext._SentEmails.Remove(key);
}
}
Account? test = await _databaseService.GetAccount(UserName.ToLower());
Account? test = await _databaseService.GetAccount(request.UserName.ToLower());
if (test != null) {
test.EmailToken = Guid.NewGuid().ToString();
test.EmailTokenCreated = DateTime.UtcNow;
await _databaseService.SetAccount(test);
string EmailContents = EmailService.VerifyEmailEmail;
EmailContents = Substitue(EmailContents, "@UserName", UserName);
EmailContents = Substitue(EmailContents, "@UserName", UserName);
EmailContents = Substitue(EmailContents, "@UserName", request.UserName);
EmailContents = Substitue(EmailContents, "@UserName", request.UserName);
EmailContents = Substitue(EmailContents, "@VerifyPassword", test.EmailToken);
string result = _emailContext.Send(test.Email, EmailService.VerifyEmailSubject, EmailContents);
_emailContext._SentEmails.Add(key, DateTime.Now);
return Ok(result);
}
return NotFound("Account not found");
return BadRequest("Account not found");
} catch (Exception) {
return NotFound("An internal server error has occured");
return BadRequest("An internal server error has occured");
}
}
[Route("verifyemail")]
[HttpPost]
public async Task<ActionResult<bool>> VerifyEmail([FromForm] string UserName, [FromForm] string EmailToken) {
public async Task<ActionResult<bool>> VerifyEmail([FromBody] VerifyEmailRequest request) {
try {
Account? test = await _databaseService.GetAccount(UserName.ToLower());
Account? test = await _databaseService.GetAccount(request.UserName.ToLower());
if (test != null) {
if (!string.IsNullOrEmpty(test.EmailToken) && test.EmailToken == EmailToken) {
test.EmailToken = "";
test.EmailVerified = true;
await _databaseService.SetAccount(test);
return Ok(true);
if (DateTime.UtcNow < test.EmailTokenCreated.AddMinutes(30)) {
if (test.EmailToken == request.EmailToken) {
test.EmailToken = "";
test.EmailVerified = true;
await _databaseService.SetAccount(test);
return Ok(true);
}
return BadRequest("The token isn't valid");
}
return BadRequest("Your email token has timed out");
}
return NotFound("Account not found or token is invalid");;
return BadRequest("Account not found");;
} catch {
return NotFound("An internal server error has occured");
return BadRequest("An internal server error has occured");
}
}
[Route("sendresetpassword")]
[HttpPost]
public async Task<ActionResult<string>> ResetPassword([FromForm] string Email) {
public async Task<ActionResult<string>> ResetPassword([FromBody] SendResetPasswordRequest request) {
try {
string key = "p" + Email.ToLower();
string key = "p" + request.Email.ToLower();
// Stop from sending multiple emails quickly
if (_emailContext._SentEmails.ContainsKey(key)) {
DateTime PreviousSentTime = _emailContext._SentEmails.GetValueOrDefault(key);
if (PreviousSentTime.AddMinutes(5) > DateTime.Now) {
return NotFound("Cannot sent another reset requests until 5 minutes has elapsed");
}
else {
return BadRequest("Cannot sent another reset requests until 5 minutes has elapsed");
} else {
_emailContext._SentEmails.Remove(key);
}
}
Account? test = await _databaseService.GetAccount(Email.ToLower());
Account? test = await _databaseService.GetAccount(request.Email.ToLower());
if (test != null) {
test.EmailToken = Guid.NewGuid().ToString();
test.PasswordToken = Guid.NewGuid().ToString();
test.PasswordTokenCreated = DateTime.UtcNow;
await _databaseService.SetAccount(test);
string EmailContents = EmailService.ResetPasswordEmail;
@@ -229,49 +238,53 @@ namespace Auth.Controllers {
_emailContext._SentEmails.Add(key, DateTime.Now);
return Ok(result);
}
return NotFound("Account Not Found");
return BadRequest("Account Not Found");
} catch (Exception e) {
Console.WriteLine("EmailService Error: " + e.ToString());
return NotFound("An internal server error has occured");
return BadRequest("An internal server error has occured");
}
}
[Route("resetpassword")]
[HttpPost]
public async Task<ActionResult<bool>> ResetPwdVerify([FromForm] string UserName, [FromForm] string NewPassword, [FromForm] string ResetToken) {
public async Task<ActionResult<bool>> ResetPwdVerify([FromBody] ResetPasswordRequest request) {
try {
Account? test = await _databaseService.GetAccount(UserName.ToLower());
if (test != null && !string.IsNullOrEmpty(test.EmailToken)) {
if (!string.IsNullOrEmpty(test.EmailToken) && test.EmailToken == ResetToken) {
test.CurrentPasswordAttempts = 0;
test.EmailToken = "";
test.PasswordHash = BCrypt.Net.BCrypt.HashPassword(NewPassword);
await _databaseService.SetAccount(test);
return Ok(true);
Account? test = await _databaseService.GetAccount(request.UserName.ToLower());
if (test != null) {
if (DateTime.UtcNow < test.PasswordTokenCreated.AddMinutes(30)) {
if (test.PasswordToken == request.PasswordToken) {
test.CurrentPasswordAttempts = 0;
test.PasswordToken = "";
test.PasswordHash = BCrypt.Net.BCrypt.HashPassword(request.NewPassword);
await _databaseService.SetAccount(test);
return Ok(true);
}
return BadRequest("The token isn't valid");
}
return BadRequest("Your email token has timed out");
}
return NotFound("Account not found or reset token is bad");
return BadRequest("Account not found");;
} catch {
return NotFound("An internal server error has occured");
return BadRequest("An internal server error has occured");
}
}
[Route("delete")]
[HttpPost]
public async Task<ActionResult> delete([FromForm] string Password) {
public async Task<ActionResult> delete([FromBody] DeleteRequest request) {
try {
if (isLoggedIn()) {
Account user = await getLoggedInUser();
if (BCrypt.Net.BCrypt.Verify(Password, user.PasswordHash)) {
if (BCrypt.Net.BCrypt.Verify(request.Password, user.PasswordHash)) {
await _databaseService.DeleteAccount(user.ID);
return Ok();
}
}
return NotFound("User is not logged in");
return BadRequest("User is not logged in");
} catch (Exception ex) {
Console.WriteLine("Delete Error: " + ex.Message);
return NotFound("An internal server error has occured");
return BadRequest("An internal server error has occured");
}
}