This commit is contained in:
@@ -1,285 +1,285 @@
|
|||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using MistoxWebsite.Server.Services;
|
using MistoxWebsite.Server.Services;
|
||||||
using MistoxWebsite.Server.Services.DatabaseService;
|
using MistoxWebsite.Server.Services.DatabaseService;
|
||||||
using MistoxWebsite.Server.Entities;
|
using MistoxWebsite.Server.Entities;
|
||||||
|
|
||||||
namespace MistoxWebsite.Server.Controllers {
|
namespace MistoxWebsite.Server.Controllers {
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/account/[controller]")]
|
[Route("api/account/")]
|
||||||
public class AuthenticationController : MistoxControllerBase {
|
public class AuthenticationController : MistoxControllerBase {
|
||||||
|
|
||||||
EmailService _emailContext;
|
EmailService _emailContext;
|
||||||
|
|
||||||
public AuthenticationController(DatabaseService db, EmailService emailContext) : base(db) {
|
public AuthenticationController(DatabaseService db, EmailService emailContext) : base(db) {
|
||||||
_emailContext = emailContext;
|
_emailContext = emailContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("login")]
|
[Route("login")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<Account>> Login([FromForm] string UserName, [FromForm] string PasswordHash, [FromForm] bool StayLoggedIn) {
|
public async Task<ActionResult<Account>> Login([FromForm] string UserName, [FromForm] string PasswordHash, [FromForm] bool StayLoggedIn) {
|
||||||
try {
|
try {
|
||||||
Account? test = await _databaseService.GetAccount(UserName.ToLower());
|
Account? test = await _databaseService.GetAccount(UserName.ToLower());
|
||||||
if (test != null) {
|
if (test != null) {
|
||||||
if (test.EmailVerified == true) {
|
if (test.EmailVerified == true) {
|
||||||
if (test.FailedPasswordLock) {
|
if (test.FailedPasswordLock) {
|
||||||
if (test.CurrentPasswordAttempts >= test.PasswordAttempts) {
|
if (test.CurrentPasswordAttempts >= test.PasswordAttempts) {
|
||||||
return new Account() { Error = "Too many failed password attempts. Please reset your password" };
|
return new Account() { Error = "Too many failed password attempts. Please reset your password" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (BCrypt.Net.BCrypt.Verify(PasswordHash, test.PasswordHash)) {
|
if (BCrypt.Net.BCrypt.Verify(PasswordHash, test.PasswordHash)) {
|
||||||
test.CurrentPasswordAttempts = 0;
|
test.CurrentPasswordAttempts = 0;
|
||||||
await _databaseService.SetAccount(test);
|
await _databaseService.SetAccount(test);
|
||||||
|
|
||||||
List<Claim> claims = new List<Claim>() {
|
List<Claim> claims = new List<Claim>() {
|
||||||
new Claim("ID", test.ID.ToString())
|
new Claim("ID", test.ID.ToString())
|
||||||
};
|
};
|
||||||
|
|
||||||
await HttpContext.SignInAsync(
|
await HttpContext.SignInAsync(
|
||||||
CookieAuthenticationDefaults.AuthenticationScheme,
|
CookieAuthenticationDefaults.AuthenticationScheme,
|
||||||
new ClaimsPrincipal(new ClaimsIdentity(claims, "Auth")),
|
new ClaimsPrincipal(new ClaimsIdentity(claims, "Auth")),
|
||||||
new AuthenticationProperties {
|
new AuthenticationProperties {
|
||||||
ExpiresUtc = DateTime.UtcNow.AddYears(30), // Add 30 years with sliding on
|
ExpiresUtc = DateTime.UtcNow.AddYears(30), // Add 30 years with sliding on
|
||||||
IsPersistent = StayLoggedIn, // Is set from the StayLoggedIn
|
IsPersistent = StayLoggedIn, // Is set from the StayLoggedIn
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
test.CurrentPasswordAttempts += 1;
|
test.CurrentPasswordAttempts += 1;
|
||||||
await _databaseService.SetAccount(test);
|
await _databaseService.SetAccount(test);
|
||||||
return new Account() { Error = "Wrong password" };
|
return new Account() { Error = "Wrong password" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
await SendVerify(test.UserName);
|
await SendVerify(test.UserName);
|
||||||
return new Account() { Error = "A new verify email has been sent. \n Note only 1 email send every 5 mintes" };
|
return new Account() { Error = "A new verify email has been sent. \n Note only 1 email send every 5 mintes" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Account() { Error = "User doesn't exist" };
|
return new Account() { Error = "User doesn't exist" };
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
return new Account() { Error = ex.Message };
|
return new Account() { Error = ex.Message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("register")]
|
[Route("register")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<Account>> Register([FromForm] string Email, [FromForm] string UserName, [FromForm] string PasswordHash) {
|
public async Task<ActionResult<Account>> Register([FromForm] string Email, [FromForm] string UserName, [FromForm] string PasswordHash) {
|
||||||
try {
|
try {
|
||||||
if (await _databaseService.GetAccount(UserName.ToLower()) == null) {
|
if (await _databaseService.GetAccount(UserName.ToLower()) == null) {
|
||||||
if (await _databaseService.GetAccount(Email.ToLower()) == null) {
|
if (await _databaseService.GetAccount(Email.ToLower()) == null) {
|
||||||
Account? created = new Account() {
|
Account? created = new Account() {
|
||||||
UserName = UserName.ToLower(),
|
UserName = UserName.ToLower(),
|
||||||
Email = Email.ToLower(),
|
Email = Email.ToLower(),
|
||||||
EmailVerified = false,
|
EmailVerified = false,
|
||||||
PasswordHash = BCrypt.Net.BCrypt.HashPassword(PasswordHash),
|
PasswordHash = BCrypt.Net.BCrypt.HashPassword(PasswordHash),
|
||||||
};
|
};
|
||||||
await _databaseService.SetAccount(created);
|
await _databaseService.SetAccount(created);
|
||||||
created = await _databaseService.GetAccount(Email.ToLower());
|
created = await _databaseService.GetAccount(Email.ToLower());
|
||||||
if (created != null) {
|
if (created != null) {
|
||||||
await SendVerify(created.UserName);
|
await SendVerify(created.UserName);
|
||||||
return created;
|
return created;
|
||||||
}
|
}
|
||||||
return new Account() { Error = "Unknown Error" };
|
return new Account() { Error = "Unknown Error" };
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new Account() { Error = "Email is already in use" };
|
return new Account() { Error = "Email is already in use" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new Account() { Error = "UserName is taken" };
|
return new Account() { Error = "UserName is taken" };
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Console.WriteLine("Error: " + ex.Message);
|
Console.WriteLine("Error: " + ex.Message);
|
||||||
return new Account() { Error = ex.Message };
|
return new Account() { Error = ex.Message };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("changepassword")]
|
[Route("changepassword")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<bool>> ChangePassword([FromForm] string OldPassword, [FromForm] string NewPassword) {
|
public async Task<ActionResult<bool>> ChangePassword([FromForm] string OldPassword, [FromForm] string NewPassword) {
|
||||||
try {
|
try {
|
||||||
if (isLoggedIn()) {
|
if (isLoggedIn()) {
|
||||||
Account user = await getLoggedInUser();
|
Account user = await getLoggedInUser();
|
||||||
if (BCrypt.Net.BCrypt.Verify(OldPassword, user.PasswordHash)) {
|
if (BCrypt.Net.BCrypt.Verify(OldPassword, user.PasswordHash)) {
|
||||||
user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(NewPassword);
|
user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(NewPassword);
|
||||||
user.CurrentPasswordAttempts = 0;
|
user.CurrentPasswordAttempts = 0;
|
||||||
await _databaseService.SetAccount(user);
|
await _databaseService.SetAccount(user);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("toggleaccountlock")]
|
[Route("toggleaccountlock")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<string>> ToggleAccountLock([FromForm] bool AccountLock) {
|
public async Task<ActionResult<string>> ToggleAccountLock([FromForm] bool AccountLock) {
|
||||||
try {
|
try {
|
||||||
if (isLoggedIn()) {
|
if (isLoggedIn()) {
|
||||||
Account user = await getLoggedInUser();
|
Account user = await getLoggedInUser();
|
||||||
user.FailedPasswordLock = AccountLock;
|
user.FailedPasswordLock = AccountLock;
|
||||||
user.CurrentPasswordAttempts = 0;
|
user.CurrentPasswordAttempts = 0;
|
||||||
await _databaseService.SetAccount(user);
|
await _databaseService.SetAccount(user);
|
||||||
return "Account Lock Status Updated";
|
return "Account Lock Status Updated";
|
||||||
}
|
}
|
||||||
return "Unknown Error Occurred";
|
return "Unknown Error Occurred";
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
return ex.Message;
|
return ex.Message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("get")]
|
[Route("get")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<Account?>> Get() {
|
public async Task<ActionResult<Account?>> Get() {
|
||||||
try {
|
try {
|
||||||
if (isLoggedIn()) {
|
if (isLoggedIn()) {
|
||||||
return await getLoggedInUser();
|
return await getLoggedInUser();
|
||||||
}
|
}
|
||||||
return Ok();
|
return Ok();
|
||||||
} catch {
|
} catch {
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("logout")]
|
[Route("logout")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task Logout() {
|
public async Task Logout() {
|
||||||
await HttpContext.SignOutAsync();
|
await HttpContext.SignOutAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("sendverifyemail")]
|
[Route("sendverifyemail")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<string>> SendVerify([FromForm] string UserName) {
|
public async Task<ActionResult<string>> SendVerify([FromForm] string UserName) {
|
||||||
try {
|
try {
|
||||||
string key = "v" + UserName;
|
string key = "v" + UserName;
|
||||||
// Stop from sending multiple emails quickly
|
// Stop from sending multiple emails quickly
|
||||||
if (_emailContext._SentEmails.ContainsKey(key)) {
|
if (_emailContext._SentEmails.ContainsKey(key)) {
|
||||||
DateTime PreviousSentTime = _emailContext._SentEmails.GetValueOrDefault(key);
|
DateTime PreviousSentTime = _emailContext._SentEmails.GetValueOrDefault(key);
|
||||||
if (PreviousSentTime.AddMinutes(5) > DateTime.Now) {
|
if (PreviousSentTime.AddMinutes(5) > DateTime.Now) {
|
||||||
return "Cannot sent another verify email until 5 minutes has elapsed ";
|
return "Cannot sent another verify email until 5 minutes has elapsed ";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_emailContext._SentEmails.Remove(key);
|
_emailContext._SentEmails.Remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Account? test = await _databaseService.GetAccount(UserName.ToLower());
|
Account? test = await _databaseService.GetAccount(UserName.ToLower());
|
||||||
if (test != null) {
|
if (test != null) {
|
||||||
test.EmailToken = Guid.NewGuid().ToString();
|
test.EmailToken = Guid.NewGuid().ToString();
|
||||||
await _databaseService.SetAccount(test);
|
await _databaseService.SetAccount(test);
|
||||||
|
|
||||||
string EmailContents = EmailService.VerifyEmailEmail;
|
string EmailContents = EmailService.VerifyEmailEmail;
|
||||||
EmailContents = Substitue(EmailContents, "@UserName", UserName);
|
EmailContents = Substitue(EmailContents, "@UserName", UserName);
|
||||||
EmailContents = Substitue(EmailContents, "@UserName", UserName);
|
EmailContents = Substitue(EmailContents, "@UserName", UserName);
|
||||||
EmailContents = Substitue(EmailContents, "@VerifyPassword", test.EmailToken);
|
EmailContents = Substitue(EmailContents, "@VerifyPassword", test.EmailToken);
|
||||||
|
|
||||||
string result = _emailContext.Send(test.Email, EmailService.VerifyEmailSubject, EmailContents);
|
string result = _emailContext.Send(test.Email, EmailService.VerifyEmailSubject, EmailContents);
|
||||||
_emailContext._SentEmails.Add(key, DateTime.Now);
|
_emailContext._SentEmails.Add(key, DateTime.Now);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return "Account not found";
|
return "Account not found";
|
||||||
} catch (Exception) {
|
} catch (Exception) {
|
||||||
return "The connection couldn't be established to the email server";
|
return "The connection couldn't be established to the email server";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("verifyemail")]
|
[Route("verifyemail")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<bool>> VerifyEmail([FromForm] string UserName, [FromForm] string EmailToken) {
|
public async Task<ActionResult<bool>> VerifyEmail([FromForm] string UserName, [FromForm] string EmailToken) {
|
||||||
try {
|
try {
|
||||||
Account? test = await _databaseService.GetAccount(UserName.ToLower());
|
Account? test = await _databaseService.GetAccount(UserName.ToLower());
|
||||||
if (test != null) {
|
if (test != null) {
|
||||||
if (!string.IsNullOrEmpty(test.EmailToken) && test.EmailToken == EmailToken) {
|
if (!string.IsNullOrEmpty(test.EmailToken) && test.EmailToken == EmailToken) {
|
||||||
test.EmailToken = "";
|
test.EmailToken = "";
|
||||||
test.EmailVerified = true;
|
test.EmailVerified = true;
|
||||||
await _databaseService.SetAccount(test);
|
await _databaseService.SetAccount(test);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("sendresetpassword")]
|
[Route("sendresetpassword")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<string>> ResetPassword([FromForm] string Email) {
|
public async Task<ActionResult<string>> ResetPassword([FromForm] string Email) {
|
||||||
try {
|
try {
|
||||||
string key = "p" + Email.ToLower();
|
string key = "p" + Email.ToLower();
|
||||||
// Stop from sending multiple emails quickly
|
// Stop from sending multiple emails quickly
|
||||||
if (_emailContext._SentEmails.ContainsKey(key)) {
|
if (_emailContext._SentEmails.ContainsKey(key)) {
|
||||||
DateTime PreviousSentTime = _emailContext._SentEmails.GetValueOrDefault(key);
|
DateTime PreviousSentTime = _emailContext._SentEmails.GetValueOrDefault(key);
|
||||||
if (PreviousSentTime.AddMinutes(5) > DateTime.Now) {
|
if (PreviousSentTime.AddMinutes(5) > DateTime.Now) {
|
||||||
return "Cannot sent another reset requests until 5 minutes has elapsed";
|
return "Cannot sent another reset requests until 5 minutes has elapsed";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_emailContext._SentEmails.Remove(key);
|
_emailContext._SentEmails.Remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Account? test = await _databaseService.GetAccount(Email.ToLower());
|
Account? test = await _databaseService.GetAccount(Email.ToLower());
|
||||||
if (test != null) {
|
if (test != null) {
|
||||||
test.EmailToken = Guid.NewGuid().ToString();
|
test.EmailToken = Guid.NewGuid().ToString();
|
||||||
await _databaseService.SetAccount(test);
|
await _databaseService.SetAccount(test);
|
||||||
|
|
||||||
string EmailContents = EmailService.ResetPasswordEmail;
|
string EmailContents = EmailService.ResetPasswordEmail;
|
||||||
EmailContents = Substitue(EmailContents, "@UserName", test.UserName);
|
EmailContents = Substitue(EmailContents, "@UserName", test.UserName);
|
||||||
EmailContents = Substitue(EmailContents, "@UserName", test.UserName);
|
EmailContents = Substitue(EmailContents, "@UserName", test.UserName);
|
||||||
EmailContents = Substitue(EmailContents, "@ResetPassWord", test.EmailToken);
|
EmailContents = Substitue(EmailContents, "@ResetPassWord", test.EmailToken);
|
||||||
|
|
||||||
string result = _emailContext.Send(test.Email, EmailService.VerifyEmailSubject, EmailContents);
|
string result = _emailContext.Send(test.Email, EmailService.VerifyEmailSubject, EmailContents);
|
||||||
_emailContext._SentEmails.Add(key, DateTime.Now);
|
_emailContext._SentEmails.Add(key, DateTime.Now);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return "Account Not Found";
|
return "Account Not Found";
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Console.WriteLine("EmailService Error: " + e.ToString());
|
Console.WriteLine("EmailService Error: " + e.ToString());
|
||||||
return "The connection couldn't be established to the email server";
|
return "The connection couldn't be established to the email server";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("resetpassword")]
|
[Route("resetpassword")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<bool>> ResetPwdVerify([FromForm] string UserName, [FromForm] string NewPassword, [FromForm] string ResetToken) {
|
public async Task<ActionResult<bool>> ResetPwdVerify([FromForm] string UserName, [FromForm] string NewPassword, [FromForm] string ResetToken) {
|
||||||
try {
|
try {
|
||||||
Account? test = await _databaseService.GetAccount(UserName.ToLower());
|
Account? test = await _databaseService.GetAccount(UserName.ToLower());
|
||||||
if (test != null && !string.IsNullOrEmpty(test.EmailToken)) {
|
if (test != null && !string.IsNullOrEmpty(test.EmailToken)) {
|
||||||
if (!string.IsNullOrEmpty(test.EmailToken) && test.EmailToken == ResetToken) {
|
if (!string.IsNullOrEmpty(test.EmailToken) && test.EmailToken == ResetToken) {
|
||||||
test.CurrentPasswordAttempts = 0;
|
test.CurrentPasswordAttempts = 0;
|
||||||
test.EmailToken = "";
|
test.EmailToken = "";
|
||||||
test.PasswordHash = BCrypt.Net.BCrypt.HashPassword(NewPassword);
|
test.PasswordHash = BCrypt.Net.BCrypt.HashPassword(NewPassword);
|
||||||
await _databaseService.SetAccount(test);
|
await _databaseService.SetAccount(test);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("delete")]
|
[Route("delete")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<bool>> delete([FromForm] string Password) {
|
public async Task<ActionResult<bool>> delete([FromForm] string Password) {
|
||||||
try {
|
try {
|
||||||
if (isLoggedIn()) {
|
if (isLoggedIn()) {
|
||||||
Account user = await getLoggedInUser();
|
Account user = await getLoggedInUser();
|
||||||
if (BCrypt.Net.BCrypt.Verify(Password, user.PasswordHash)) {
|
if (BCrypt.Net.BCrypt.Verify(Password, user.PasswordHash)) {
|
||||||
await _databaseService.DeleteAccount(user.ID);
|
await _databaseService.DeleteAccount(user.ID);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user