2025-05-28 13:34:48 -07:00

401 lines
12 KiB
C#

#if !NET8
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
#endif
#if NET8
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
#endif
#if !NET8
using Fab2ApprovalSystem.DMO;
using Fab2ApprovalSystem.Misc;
using Fab2ApprovalSystem.Models;
#endif
#if !NET8
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
#endif
#if !NET8
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Newtonsoft.Json;
#endif
namespace Fab2ApprovalSystem.Controllers;
[Authorize]
#if NET8
[Route("[controller]")]
#endif
public class AccountController : Controller {
#if !NET8
public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()))) {
}
public AccountController(UserManager<ApplicationUser> userManager) {
UserManager = userManager;
}
public UserManager<ApplicationUser> UserManager { get; private set; }
#endif
#if !NET8
// GET: /Account/Login
[AllowAnonymous]
// try to make the browser refresh the login page every time, to prevent issues with changing usernames and the anti-forgery token validation
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
#endif
public ActionResult Login(string returnUrl) {
ViewBag.ReturnUrl = returnUrl;
return View();
}
#if !NET8
private void SetSessionParameters(LoginResult loginResult, LoginModel user) {
GlobalVars.SetSessionParameters(GetSession(), loginResult, user);
FormsAuthentication.SetAuthCookie(user.LoginID, true);
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginModel model, string returnUrl) {
try {
bool isLoginValid;
HttpClient httpClient = HttpClientFactory.Create();
httpClient.BaseAddress = new Uri(GlobalVars.AppSettings.ApiBaseUrl);
LoginResult loginResult = await AccountDMO.LoginAsync(httpClient, model);
#if (DEBUG)
isLoginValid = true;
#endif
#if (!DEBUG)
bool isIFX = false;
if (GlobalVars.DBConnection.ToUpper() == "TEST" || GlobalVars.DBConnection.ToUpper() == "QUALITY") {
isLoginValid = true;
} else {
isLoginValid = loginResult.IsAuthenticated;
if (isLoginValid)
isIFX = true;
}
#endif
if (isLoginValid) {
UserAccountDMO userDMO = new UserAccountDMO();
LoginModel user = userDMO.GetUser(model.LoginID);
if (user != null) {
SetSessionParameters(loginResult, user);
return RedirectToLocal(returnUrl);
} else {
ModelState.AddModelError("", "The user name does not exist in the DB. Please contact the System Admin");
}
} else {
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
} catch (Exception ex) {
Functions.WriteEvent(GlobalVars.AppSettings, GetUserIdentityName() + " " + ex.InnerException, System.Diagnostics.EventLogEntryType.Error);
EventLogDMO.Add(new WinEventLog() { IssueID = 99999, UserID = GetUserIdentityName(), DocumentType = "Login", OperationType = "Error", Comments = "Reject - " + ex.Message });
ModelState.AddModelError("", ex.Message);
}
return View(model);
// If we got this far, something failed, redisplay form
}
[HttpPost]
[AllowAnonymous]
public async Task<HttpResponseMessage> ExternalAuthSetup(AuthAttempt authAttempt) {
try {
bool isLoginValid;
HttpClient httpClient = HttpClientFactory.Create();
httpClient.BaseAddress = new Uri(GlobalVars.AppSettings.ApiBaseUrl);
LoginResult loginResult = await AccountDMO.ExternalAuthSetupAsync(httpClient, authAttempt);
#if (DEBUG)
isLoginValid = true;
#endif
#if (!DEBUG)
bool isIFX = false;
if (GlobalVars.DBConnection.ToUpper() == "TEST" || GlobalVars.DBConnection.ToUpper() == "QUALITY") {
isLoginValid = true;
} else {
isLoginValid = loginResult.IsAuthenticated;
if (isLoginValid)
isIFX = true;
}
#endif
if (isLoginValid) {
UserAccountDMO userDMO = new UserAccountDMO();
LoginModel user = userDMO.GetUser(authAttempt.LoginID);
if (user != null) {
SetSessionParameters(loginResult, user);
return new HttpResponseMessage(HttpStatusCode.OK);
} else {
ModelState.AddModelError("", "The user name does not exist in the DB. Please contact the System Admin");
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
} else {
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
}
} catch (Exception ex) {
Functions.WriteEvent(GlobalVars.AppSettings, GetUserIdentityName() + " " + ex.InnerException, System.Diagnostics.EventLogEntryType.Error);
EventLogDMO.Add(new WinEventLog() { IssueID = 99999, UserID = GetUserIdentityName(), DocumentType = "Login", OperationType = "Error", Comments = "Reject - " + ex.Message });
ModelState.AddModelError("", ex.Message);
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
}
#endif
// GET: /Account/Register
[AllowAnonymous]
public ActionResult Register() {
return View();
}
#if !NET8
// POST: /Account/Disassociate
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Disassociate(string loginProvider, string providerKey) {
ManageMessageId? message = null;
IdentityResult result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey));
if (result.Succeeded) {
message = ManageMessageId.RemoveLoginSuccess;
} else {
message = ManageMessageId.Error;
}
return RedirectToAction("Manage", new { Message = message });
}
#endif
// GET: /Account/Manage
#pragma warning disable IDE0060 // Remove unused parameter
public ActionResult Manage(ManageMessageId? message) {
return View();
}
#pragma warning restore IDE0060 // Remove unused parameter
#if !NET8
// POST: /Account/ExternalLogin
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl) {
// Request a redirect to the external login provider
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
}
// POST: /Account/LinkLogin
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LinkLogin(string provider) {
// Request a redirect to the external login provider to link a login for the current user
return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account"), User.Identity.GetUserId());
}
// GET: /Account/LinkLoginCallback
public async Task<ActionResult> LinkLoginCallback() {
ExternalLoginInfo loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId());
if (loginInfo == null) {
return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
}
IdentityResult result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login);
if (result.Succeeded) {
return RedirectToAction("Manage");
}
return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff() {
FormsAuthentication.SignOut();
return RedirectToAction("Login", "Account");
}
#endif
[AllowAnonymous]
public ActionResult ExternalLoginFailure() {
return View();
}
#if !NET8
[ChildActionOnly]
public ActionResult RemoveAccountList() {
IList<UserLoginInfo> linkedAccounts = UserManager.GetLogins(User.Identity.GetUserId());
ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;
return (ActionResult)PartialView("_RemoveAccountPartial", linkedAccounts);
}
protected override void Dispose(bool disposing) {
if (disposing && UserManager != null) {
UserManager.Dispose();
UserManager = null;
}
base.Dispose(disposing);
}
#endif
#region Helpers
// Used for XSRF protection when adding external logins
private const string XsrfKey = "XsrfId";
#if !NET8
private IAuthenticationManager AuthenticationManager {
get {
return HttpContext.GetOwinContext().Authentication;
}
}
private async Task SignInAsync(ApplicationUser user, bool isPersistent) {
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
ClaimsIdentity identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
private void AddErrors(IdentityResult result) {
foreach (string error in result.Errors) {
ModelState.AddModelError("", error);
}
}
private bool HasPassword() {
ApplicationUser user = UserManager.FindById(User.Identity.GetUserId());
if (user != null) {
return user.PasswordHash != null;
}
return false;
}
#endif
public enum ManageMessageId {
ChangePasswordSuccess,
SetPasswordSuccess,
RemoveLoginSuccess,
Error
}
private ActionResult RedirectToLocal(string returnUrl) {
if (Url.IsLocalUrl(returnUrl)) {
return Redirect(returnUrl);
} else {
return RedirectToAction("MyTasks", "Home");
}
}
#if !NET8
private class ChallengeResult : HttpUnauthorizedResult {
#endif
#if NET8
private class ChallengeResult {
#endif
public ChallengeResult(string provider, string redirectUri) : this(provider, redirectUri, null) {
}
public ChallengeResult(string provider, string redirectUri, string userId) {
LoginProvider = provider;
RedirectUri = redirectUri;
UserId = userId;
}
public string LoginProvider { get; set; }
public string RedirectUri { get; set; }
public string UserId { get; set; }
#if !NET8
public override void ExecuteResult(ControllerContext context) {
AuthenticationProperties properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
if (UserId != null) {
properties.Dictionary[XsrfKey] = UserId;
}
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}
#endif
}
#endregion
#if !NET8
private System.Web.HttpSessionStateBase GetSession() =>
Session;
private JsonResult GetJsonResult(object? data) =>
Json(data, JsonRequestBehavior.AllowGet);
private bool IsAjaxRequest() =>
Request.IsAjaxRequest();
#endif
#if NET8
private Microsoft.AspNetCore.Http.ISession GetSession() =>
HttpContext.Session;
private JsonResult GetJsonResult(object? data) =>
Json(data);
private bool IsAjaxRequest() =>
Request.Headers.TryGetValue("X-Requested-With", out Microsoft.Extensions.Primitives.StringValues strings) && strings[0] == "XMLHttpRequest";
#endif
private string GetUserIdentityName() =>
@User.Identity.Name;
}