401 lines
12 KiB
C#
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;
|
|
|
|
} |