975 lines
40 KiB
C#
975 lines
40 KiB
C#
using System;
|
|
using System.Data.Entity;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using System.Web;
|
|
using System.Web.Mvc;
|
|
using EnVisage.Code.BLL;
|
|
using Microsoft.AspNet.Identity;
|
|
using Microsoft.AspNet.Identity.EntityFramework;
|
|
using Microsoft.Owin.Security;
|
|
using EnVisage.Models;
|
|
using EnVisage.Code;
|
|
using System.Net;
|
|
using EnVisage.Code.Cache;
|
|
using EnVisage.Code.UserVoice;
|
|
using EnVisage.Code.Session;
|
|
using Microsoft.IdentityModel.Claims;
|
|
using System.Security.Principal;
|
|
using System.Threading;
|
|
using System.Web.Script.Serialization;
|
|
using EnVisage.App_Start;
|
|
using EnVisage.Code.Validation;
|
|
using Resources;
|
|
using Microsoft.IdentityModel.Web;
|
|
using Prevu.Core.Main;
|
|
using EnVisage.Properties;
|
|
|
|
namespace EnVisage.Controllers
|
|
{
|
|
[Authorize]
|
|
public class AccountController : BaseController
|
|
{
|
|
#region Properties
|
|
|
|
private IUserManager UserManager { get; }
|
|
|
|
#endregion
|
|
|
|
#region Constructors and Overrides
|
|
|
|
public AccountController(ApplicationUserManager appUserManager, IUserManager userManager)
|
|
{
|
|
AppUserManager = appUserManager;
|
|
UserManager = userManager;
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (disposing && AppUserManager != null)
|
|
{
|
|
AppUserManager.Dispose();
|
|
AppUserManager = null;
|
|
}
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
private ApplicationUserManager AppUserManager { get; set; }
|
|
// Used for XSRF protection when adding external logins
|
|
private const string XsrfKey = "XsrfId";
|
|
|
|
private IAuthenticationManager AuthenticationManager => HttpContext.GetOwinContext().Authentication;
|
|
|
|
#endregion
|
|
|
|
#region Actions
|
|
|
|
//
|
|
// GET: /Account/Login
|
|
[AllowAnonymous]
|
|
public ActionResult Login(string returnUrl)
|
|
{
|
|
ViewBag.ReturnUrl = returnUrl;
|
|
return View();
|
|
}
|
|
[AllowAnonymous]
|
|
public ActionResult SSOFailureNoLocalAccount()
|
|
{
|
|
return View();
|
|
}
|
|
[Authorize]
|
|
public void SSOLogOff()
|
|
{
|
|
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(""), new string[0]);
|
|
}
|
|
[Authorize]
|
|
public async Task<ApplicationUser> SSOLoginConfirmation()
|
|
{
|
|
IClaimsPrincipal principal = Thread.CurrentPrincipal as IClaimsPrincipal;
|
|
if (principal == null)
|
|
{
|
|
Logger.Log(NLog.LogLevel.Debug, "user name from principal is null. in SSOLoginConfirmation()", "");
|
|
ssoDefault();
|
|
return null;
|
|
}
|
|
var identity = (IClaimsIdentity)principal.Identity;
|
|
if (identity.Name == null)
|
|
Logger.Log(NLog.LogLevel.Debug, "user name from identity is null. in SSOLoginConfirmation()", "");
|
|
if (identity.Name != null)
|
|
{
|
|
Logger.Log(NLog.LogLevel.Debug, "user name from adfs." + identity.Name, "");
|
|
string username = identity.Name;
|
|
string[] splprm = { "\\" };
|
|
string[] names = username.Split(splprm, StringSplitOptions.None);
|
|
if (names.Length >= 2)
|
|
username = names[1];
|
|
var user = await AppUserManager.FindByNameAsync(username);
|
|
if (user != null)
|
|
{
|
|
if (user.Type == (int)UserType.Active)
|
|
{
|
|
|
|
identity.Claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id));
|
|
|
|
//----Create UserVoice Token
|
|
UserVoiceApi userVoice = new UserVoiceApi();
|
|
string ssoToken = UserVoiceGenerator.create(userVoice.GetUserJsonObject(user));
|
|
//if (!SessionManager.Exists(Constants.USERVOICE_SSO_TOKEN))
|
|
if ((!SessionManager.Exists(Code.Constants.USERVOICE_SSO_TOKEN)) || string.IsNullOrEmpty(ssoToken))
|
|
{
|
|
SessionManager.SetValue(Code.Constants.USERVOICE_SSO_TOKEN, ssoToken);
|
|
HttpCookie ssoTokenCookie = new HttpCookie(Code.Constants.USERVOICE_COOKIE_CONTEXT);
|
|
ssoTokenCookie[Code.Constants.USERVOICE_SSO_TOKEN] = ssoToken;
|
|
ssoTokenCookie.Expires = DateTime.Now.AddDays(30d);
|
|
Response.Cookies.Add(ssoTokenCookie);
|
|
}
|
|
EnVisageEntities cntx = new EnVisageEntities();
|
|
var aspuser = cntx.AspNetUsers.FirstOrDefault(x => x.Id == user.Id);
|
|
if (aspuser != null)
|
|
{
|
|
aspuser.LastLoginDate = aspuser.LoginDate;
|
|
aspuser.LoginDate = DateTime.Now;
|
|
cntx.Entry(aspuser).State = EntityState.Modified;
|
|
cntx.SaveChanges();
|
|
}
|
|
}
|
|
}
|
|
return user;
|
|
}
|
|
return null;
|
|
}
|
|
[HttpGet]
|
|
public ActionResult ssoAuthRefresh()
|
|
{
|
|
return View();
|
|
}
|
|
//
|
|
// POST: /Account/Login
|
|
[HttpPost]
|
|
[AllowAnonymous]
|
|
[ValidateAntiForgeryToken]
|
|
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
|
|
{
|
|
if (ModelState.IsValid)
|
|
{
|
|
try
|
|
{
|
|
var user = await AppUserManager.FindAsync(model.UserName, model.Password);
|
|
if (user != null)
|
|
{
|
|
if (user.Type == (int)Code.UserType.Active)
|
|
{
|
|
await SignInAsync(user, model.RememberMe);
|
|
|
|
//----Create UserVoice Token
|
|
UserVoiceApi userVoice = new UserVoiceApi();
|
|
|
|
string ssoToken = UserVoiceGenerator.create(userVoice.GetUserJsonObject(user));
|
|
|
|
if (!SessionManager.Exists(Code.Constants.USERVOICE_SSO_TOKEN) || string.IsNullOrEmpty(ssoToken))
|
|
{
|
|
SessionManager.SetValue(Code.Constants.USERVOICE_SSO_TOKEN, ssoToken);
|
|
HttpCookie ssoTokenCookie = new HttpCookie(Code.Constants.USERVOICE_COOKIE_CONTEXT);
|
|
ssoTokenCookie[Code.Constants.USERVOICE_SSO_TOKEN] = ssoToken;
|
|
ssoTokenCookie.Expires = DateTime.Now.AddDays(30d);
|
|
Response.Cookies.Add(ssoTokenCookie);
|
|
}
|
|
EnVisageEntities cntx = new EnVisageEntities();
|
|
var aspuser = cntx.AspNetUsers.FirstOrDefault(x => x.Id == user.Id);
|
|
if (aspuser != null)
|
|
{
|
|
aspuser.LastLoginDate = aspuser.LoginDate;
|
|
aspuser.LoginDate = DateTime.Now;
|
|
cntx.Entry(aspuser).State = EntityState.Modified;
|
|
cntx.SaveChanges();
|
|
}
|
|
return RedirectToLocal(returnUrl, user.Id);
|
|
}
|
|
ModelState.AddModelError("", Messages.Account_NotActive);
|
|
}
|
|
else
|
|
{
|
|
//var LDAPLogin="planit\\serverLogin"; //For directory lookup
|
|
//var LDAPPass = "serverPass";
|
|
//DirectoryEntry entry = new DirectoryEntry("LDAP://planitserver/OU=People,O=planit", LDAPLogin, LDAPPass);
|
|
// //DirectorySearcher search = new DirectorySearcher(
|
|
// // entry,
|
|
// // "(uid=" + "planit\\" + model.UserName + ")",
|
|
// // new string[] { "uid" }
|
|
// //);
|
|
// //search.SearchScope = System.DirectoryServices.SearchScope.Subtree;
|
|
// //SearchResult found = search.FindOne();
|
|
// //if (found == null){
|
|
// // ModelState.AddModelError("", "Invalid username or password.");
|
|
// // return View(model);
|
|
// //}
|
|
//bool result;
|
|
//using(var context = new PrincipalContext(ContextType.Domain, "planit", LDAPLogin, LDAPPass)) {
|
|
// //Username and password for authentication.
|
|
// result = context.ValidateCredentials("planit\\" + model.UserName, model.Password);
|
|
//}
|
|
//if (result)
|
|
//{
|
|
// var newuser = new ApplicationUser();
|
|
// newuser.UserName = model.UserName;
|
|
// var creationResult = await AppUserManager.CreateAsync(user, model.Password);
|
|
|
|
// if (creationResult.Succeeded)
|
|
// creationResult = AppUserManager.AddToRole(newuser.Id, "User");
|
|
// await SignInAsync(newuser, model.RememberMe);
|
|
// return RedirectToLocal(returnUrl);
|
|
//}
|
|
//else
|
|
ModelState.AddModelError("", Messages.Account_InvalidUserNameOrPassword);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogException(ex);
|
|
}
|
|
}
|
|
// If we got this far, something failed, redisplay form
|
|
return View(model);
|
|
}
|
|
|
|
//
|
|
// GET: /Account/Register
|
|
[AllowAnonymous]
|
|
[Obsolete]
|
|
public ActionResult Register()
|
|
{
|
|
return View();
|
|
}
|
|
|
|
//
|
|
// POST: /Account/Register
|
|
[HttpPost]
|
|
[AllowAnonymous]
|
|
[ValidateAntiForgeryToken]
|
|
[Obsolete]
|
|
public async Task<ActionResult> Register(RegisterViewModel model)
|
|
{
|
|
if (ModelState.IsValid)
|
|
{
|
|
var user = new ApplicationUser { UserName = model.UserName };
|
|
var result = await AppUserManager.CreateAsync(user, model.Password);
|
|
if (result.Succeeded)
|
|
{
|
|
await SignInAsync(user, isPersistent: false);
|
|
return RedirectToAction("Index", "Home");
|
|
}
|
|
AddErrors(result);
|
|
}
|
|
|
|
// If we got this far, something failed, redisplay form
|
|
return View(model);
|
|
}
|
|
|
|
//
|
|
// POST: /Account/Disassociate
|
|
[HttpPost]
|
|
[ValidateAntiForgeryToken]
|
|
[Obsolete]
|
|
public async Task<ActionResult> Disassociate(string loginProvider, string providerKey)
|
|
{
|
|
IdentityResult result = await AppUserManager.RemoveLoginAsync(User.Identity.GetID(), new UserLoginInfo(loginProvider, providerKey));
|
|
ManageMessageId? message = result.Succeeded ? ManageMessageId.RemoveLoginSuccess : ManageMessageId.Error;
|
|
return RedirectToAction("Manage", new { Message = message });
|
|
}
|
|
|
|
//
|
|
// GET: /Account/Manage
|
|
public ActionResult Manage(ManageMessageId? message)
|
|
{
|
|
ViewBag.StatusMessage =
|
|
message == ManageMessageId.ChangePasswordSuccess ? Messages.Account_PasswordHasBeenChanged
|
|
: message == ManageMessageId.SetPasswordSuccess ? Messages.Account_PasswordHasBeenSet
|
|
: message == ManageMessageId.RemoveLoginSuccess ? Messages.Account_ExternalLoginWasRemoved
|
|
: message == ManageMessageId.Error ? Messages.Common_ErrorHasOccured
|
|
: "";
|
|
ViewBag.HasLocalPassword = HasPassword();
|
|
ViewBag.ReturnUrl = Url.Action("Manage");
|
|
|
|
var userId = User.Identity.GetID();
|
|
var user = DbContext.AspNetUsers.Find(userId);
|
|
var model = new ManageUserViewModel
|
|
{
|
|
Email = user.Email,
|
|
Phone = user.PhoneNumber,
|
|
PreferredResourceAllocation = user.PreferredResourceAllocation,
|
|
PreferredTotalsDisplaying = user.PreferredTotalsDisplaying,
|
|
ShowAutomaticViews = user.ShowAutomaticViews,
|
|
FirstName = user.FirstName,
|
|
LastName = user.LastName,
|
|
UserName = user.UserName,
|
|
OverUnderCoefficient = Convert.ToDouble(user.OverUnderCoefficient),
|
|
DomainUser = HttpContext.User.Identity.isSSO()
|
|
};
|
|
|
|
return View(model);
|
|
}
|
|
|
|
//
|
|
// POST: /Account/Manage
|
|
[HttpPost]
|
|
[ValidateAntiForgeryToken]
|
|
public async Task<ActionResult> Manage(ManageUserViewModel model)
|
|
{
|
|
bool hasPassword = HasPassword();
|
|
ViewBag.HasLocalPassword = hasPassword;
|
|
ViewBag.ReturnUrl = Url.Action("Manage");
|
|
if (hasPassword)
|
|
{
|
|
if (ModelState.IsValid)
|
|
{
|
|
IdentityResult result = await AppUserManager.ChangePasswordAsync(User.Identity.GetID(), model.OldPassword, model.NewPassword);
|
|
if (result.Succeeded)
|
|
return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
|
|
AddErrors(result);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// User does not have a password so remove any validation errors caused by a missing OldPassword field
|
|
ModelState state = ModelState["OldPassword"];
|
|
if (state != null)
|
|
state.Errors.Clear();
|
|
|
|
if (ModelState.IsValid)
|
|
{
|
|
IdentityResult result = await AppUserManager.AddPasswordAsync(User.Identity.GetID(), model.NewPassword);
|
|
if (result.Succeeded)
|
|
return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
|
|
AddErrors(result);
|
|
}
|
|
}
|
|
|
|
// If we got this far, something failed, redisplay form
|
|
return View(model);
|
|
}
|
|
|
|
//
|
|
// POST: /Account/ChangeEmail
|
|
[HttpPost]
|
|
[ValidateAntiForgeryToken]
|
|
public JsonResult ChangeEmailAndPhone(ManageUserViewModel model)
|
|
{
|
|
try
|
|
{
|
|
#region remove validation errors for password fields because of weak initial implementatiton
|
|
// ToDo: separate model to two models for each form separately
|
|
model.TrimStringProperties();
|
|
// User does not have a password so remove any validation errors caused by a missing OldPassword field
|
|
ModelState state = ModelState["OldPassword"];
|
|
if (state != null)
|
|
state.Errors.Clear();
|
|
state = ModelState["NewPassword"];
|
|
if (state != null)
|
|
state.Errors.Clear();
|
|
state = ModelState["ConfirmPassword"];
|
|
if (state != null)
|
|
state.Errors.Clear();
|
|
#endregion
|
|
|
|
var userId = User.Identity.GetID();
|
|
if (model == null || ContentLocker.IsLock("User", userId, User.Identity.Name))
|
|
{
|
|
ModelState.AddModelError(string.Empty, Messages.Account_UpdatedByAnotherUser);
|
|
return new FailedJsonResult(ModelState);
|
|
}
|
|
|
|
if (ModelState.IsValid)
|
|
{
|
|
var user = AppUserManager.FindById(userId);
|
|
|
|
if (user.Email != model.Email)
|
|
user.Email = model.Email;
|
|
if (user.PhoneNumber != model.Phone)
|
|
user.PhoneNumber = model.Phone;
|
|
if (user.FirstName != model.FirstName)
|
|
user.FirstName = model.FirstName;
|
|
if (user.LastName != model.LastName)
|
|
user.LastName = model.LastName;
|
|
|
|
user.PreferredResourceAllocation = model.PreferredResourceAllocation;
|
|
user.PreferredTotalsDisplaying = model.PreferredTotalsDisplaying;
|
|
user.ShowAutomaticViews = model.ShowAutomaticViews;
|
|
user.OverUnderCoefficient = Convert.ToDecimal(model.OverUnderCoefficient);
|
|
AppUserManager.Update(user);
|
|
|
|
new UsersCache().Invalidate();
|
|
|
|
ContentLocker.RemoveLock("User", userId, User.Identity.Name);
|
|
return new SuccessJsonResult();
|
|
}
|
|
}
|
|
catch (BLLException blEx) // handle any system specific error
|
|
{
|
|
// display error message if required
|
|
if (blEx.DisplayError)
|
|
ModelState.AddModelError(string.Empty, blEx.Message);
|
|
else // if display not requried then display modal form with general error message
|
|
{
|
|
LogException(blEx);
|
|
ModelState.AddModelError(string.Empty, Messages.Accoun_SaveUser_Error);
|
|
}
|
|
}
|
|
catch (Exception exception) // handle any unexpected error
|
|
{
|
|
LogException(exception);
|
|
ModelState.AddModelError(string.Empty, Messages.Accoun_SaveUser_Error);
|
|
}
|
|
|
|
return new FailedJsonResult(ModelState);
|
|
}
|
|
|
|
//
|
|
// POST: /Account/ExternalLogin
|
|
[HttpPost]
|
|
[AllowAnonymous]
|
|
[ValidateAntiForgeryToken]
|
|
[Obsolete]
|
|
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 }));
|
|
}
|
|
|
|
//
|
|
// GET: /Account/ExternalLoginCallback
|
|
[AllowAnonymous]
|
|
[Obsolete]
|
|
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
|
|
{
|
|
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
|
|
if (loginInfo == null)
|
|
{
|
|
return RedirectToAction("Login");
|
|
}
|
|
|
|
// Sign in the user with this external login provider if the user already has a login
|
|
var user = await AppUserManager.FindAsync(loginInfo.Login);
|
|
if (user != null)
|
|
{
|
|
await SignInAsync(user, false);
|
|
return RedirectToLocal(returnUrl, user.Id);
|
|
}
|
|
// If the user does not have an account, then prompt the user to create an account
|
|
ViewBag.ReturnUrl = returnUrl;
|
|
ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
|
|
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { UserName = loginInfo.DefaultUserName });
|
|
}
|
|
|
|
//
|
|
// 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.GetID());
|
|
}
|
|
|
|
//
|
|
// GET: /Account/LinkLoginCallback
|
|
public async Task<ActionResult> LinkLoginCallback()
|
|
{
|
|
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetID());
|
|
if (loginInfo == null)
|
|
{
|
|
return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
|
|
}
|
|
var result = await AppUserManager.AddLoginAsync(User.Identity.GetID(), loginInfo.Login);
|
|
return result.Succeeded ? RedirectToAction("Manage") : RedirectToAction("Manage", new { Message = ManageMessageId.Error });
|
|
}
|
|
|
|
//
|
|
// POST: /Account/ExternalLoginConfirmation
|
|
[HttpPost]
|
|
[AllowAnonymous]
|
|
[ValidateAntiForgeryToken]
|
|
public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
|
|
{
|
|
if (User.Identity.IsAuthenticated)
|
|
{
|
|
return RedirectToAction("Manage");
|
|
}
|
|
|
|
if (ModelState.IsValid)
|
|
{
|
|
// Get the information about the user from the external login provider
|
|
var info = await AuthenticationManager.GetExternalLoginInfoAsync();
|
|
if (info == null)
|
|
{
|
|
return View("ExternalLoginFailure");
|
|
}
|
|
var user = new ApplicationUser() { UserName = model.UserName };
|
|
var result = await AppUserManager.CreateAsync(user);
|
|
if (result.Succeeded)
|
|
{
|
|
result = await AppUserManager.AddLoginAsync(user.Id, info.Login);
|
|
if (result.Succeeded)
|
|
{
|
|
await SignInAsync(user, false);
|
|
return RedirectToLocal(returnUrl, user.Id);
|
|
}
|
|
}
|
|
AddErrors(result);
|
|
}
|
|
|
|
ViewBag.ReturnUrl = returnUrl;
|
|
return View(model);
|
|
}
|
|
|
|
//
|
|
// POST: /Account/LogOff
|
|
[HttpPost]
|
|
[ValidateAntiForgeryToken]
|
|
public ActionResult LogOff()
|
|
{
|
|
|
|
if (!HttpContext.User.Identity.isSSO())
|
|
{
|
|
AuthenticationManager.SignOut();
|
|
SessionManager.Remove(Code.Constants.USERVOICE_SSO_TOKEN);
|
|
return RedirectToAction("Index", "Home");
|
|
}
|
|
else
|
|
{
|
|
string absoluteUrl = HttpContext.Request.Url.AbsoluteUri;
|
|
string replyUrl = absoluteUrl.Substring(0, absoluteUrl.LastIndexOf("/") + 1);
|
|
WSFederationAuthenticationModule.FederatedSignOut(null, new Uri(replyUrl));
|
|
return RedirectToAction("Account", "Login");
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// GET: /Account/ExternalLoginFailure
|
|
[AllowAnonymous]
|
|
public ActionResult ExternalLoginFailure()
|
|
{
|
|
return View();
|
|
}
|
|
|
|
[ChildActionOnly]
|
|
[Obsolete]
|
|
public ActionResult RemoveAccountList()
|
|
{
|
|
var linkedAccounts = AppUserManager.GetLogins(User.Identity.GetID());
|
|
ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;
|
|
return (ActionResult)PartialView("_RemoveAccountPartial", linkedAccounts);
|
|
}
|
|
|
|
//
|
|
// GET: /Account/Activate
|
|
[AllowAnonymous]
|
|
public ActionResult Activate(string userId)
|
|
{
|
|
if (String.IsNullOrEmpty(userId))
|
|
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
|
|
|
|
var user = AppUserManager.FindById(userId);
|
|
if (user == null)
|
|
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
|
|
|
|
if (user.Type != (int)UserType.Pending)
|
|
ModelState.AddModelError("", Messages.Account_AlreadyActivated);
|
|
|
|
var activatedUser = new ActivationUserModel
|
|
{
|
|
Email = user.Email,
|
|
UserName = user.UserName,
|
|
Password = string.Empty,
|
|
ConfirmationPassword = string.Empty,
|
|
UserId = user.Id
|
|
};
|
|
|
|
return View(activatedUser);
|
|
}
|
|
|
|
//
|
|
// POST: /Accont/Activate
|
|
[AllowAnonymous]
|
|
[HttpPost]
|
|
public async Task<ActionResult> Activate(ActivationUserModel model)
|
|
{
|
|
if (ModelState.IsValid)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(model.UserId))
|
|
{
|
|
ApplicationDbContext cnt = new ApplicationDbContext();
|
|
var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(cnt));
|
|
var user = userManager.FindById(model.UserId);
|
|
if (user == null)
|
|
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
|
|
|
|
if (user.Type != (int)UserType.Pending)
|
|
{
|
|
ModelState.AddModelError("", Messages.Account_AlreadyActivated);
|
|
return View();
|
|
}
|
|
|
|
bool hasPassword = HasPassword(user.Id);
|
|
if (hasPassword)
|
|
{
|
|
var result = await AppUserManager.RemovePasswordAsync(user.Id);
|
|
if (!result.Succeeded)
|
|
{
|
|
AddErrors(result);
|
|
return View();
|
|
}
|
|
}
|
|
|
|
var addPwdResult = await AppUserManager.AddPasswordAsync(user.Id, model.Password);
|
|
if (!addPwdResult.Succeeded)
|
|
{
|
|
AddErrors(addPwdResult);
|
|
return View();
|
|
}
|
|
|
|
var passwordHash = userManager.PasswordHasher.HashPassword(model.Password);
|
|
user.PasswordHash = passwordHash;
|
|
user.Type = (int)UserType.Active;
|
|
cnt.SaveChanges();
|
|
|
|
await SignInAsync(user, false);
|
|
|
|
return RedirectToAction("Index", "Home");
|
|
}
|
|
ModelState.AddModelError("", Messages.Account_UserDoesNotExist);
|
|
}
|
|
|
|
return View();
|
|
}
|
|
|
|
[AllowAnonymous]
|
|
public ActionResult ForgotPassword()
|
|
{
|
|
return View(new ForgotPasswordModel());
|
|
}
|
|
|
|
[HttpPost]
|
|
[ValidateAntiForgeryToken]
|
|
[AllowAnonymous]
|
|
public async Task<ActionResult> ForgotPassword(ForgotPasswordModel model)
|
|
{
|
|
if (ModelState.IsValid)
|
|
{
|
|
try
|
|
{
|
|
var request = await UserManager.CreateResetPasswordTokenByEmailAsync(model.Email, Settings.Default.ForgotPasswordLinkTTLDays);
|
|
if (request != null)
|
|
{
|
|
MailManager.SendRestorePasswordMessage(request.Email, request.Token, request.UserName);
|
|
model.Sent = true;
|
|
}
|
|
}
|
|
catch (BLLException blEx) // handle any system specific error
|
|
{
|
|
// display error message if required
|
|
if (blEx.DisplayError)
|
|
ModelState.AddModelError(string.Empty, blEx.Message);
|
|
else // if display not requried then display modal form with general error message
|
|
{
|
|
LogException(blEx);
|
|
SetErrorScript();
|
|
}
|
|
}
|
|
catch (Exception exception) // handle any unexpected error
|
|
{
|
|
LogException(exception);
|
|
SetErrorScript();
|
|
}
|
|
}
|
|
return View(model);
|
|
}
|
|
|
|
[HttpPost]
|
|
public async Task<ActionResult> ResetPassword(string userId)
|
|
{
|
|
try
|
|
{
|
|
var request = await UserManager.CreateResetPasswordTokenByIdAsync(userId, Settings.Default.ForgotPasswordLinkTTLDays);
|
|
if (request != null)
|
|
MailManager.SendRestorePasswordMessage(request.Email, request.Token, request.UserName);
|
|
|
|
return Json(new { status = "OK" });
|
|
}
|
|
catch (Exception exception) // handle any unexpected error
|
|
{
|
|
LogException(exception);
|
|
return Json(new { status = "ERROR" });
|
|
}
|
|
}
|
|
|
|
[AllowAnonymous]
|
|
public ActionResult RestorePassword(Guid? token)
|
|
{
|
|
var model = new RestorePasswordModel();
|
|
try
|
|
{
|
|
if (!token.HasValue || Guid.Empty.Equals(token))
|
|
{
|
|
model.State = RestorePasswordModel.PageState.TokenIsEmpty;
|
|
return View(model);
|
|
}
|
|
model.Token = token.Value;
|
|
using (var db = new EnVisageEntities())
|
|
{
|
|
var request = db.PasswordResetRequests.AsNoTracking().Include(t => t.AspNetUser).FirstOrDefault(t => t.Token == token);
|
|
if (request == null)
|
|
{
|
|
model.State = RestorePasswordModel.PageState.TokenDoesNotExist;
|
|
return View(model);
|
|
}
|
|
var user = request.AspNetUser;
|
|
if (user != null)
|
|
model.Email = user.Email;
|
|
else
|
|
{
|
|
throw new BLLException(Messages.Account_TtokenDoesNotMatchAnyExistingUser_);
|
|
}
|
|
if (request.ValidUntil < DateTime.Now)
|
|
{
|
|
model.State = RestorePasswordModel.PageState.TokenExpired;
|
|
return View(model);
|
|
}
|
|
|
|
}
|
|
}
|
|
catch (BLLException blEx) // handle any system specific error
|
|
{
|
|
// display error message if required
|
|
if (blEx.DisplayError)
|
|
ModelState.AddModelError(string.Empty, blEx.Message);
|
|
else // if display not requried then display modal form with general error message
|
|
{
|
|
LogException(blEx);
|
|
SetErrorScript();
|
|
}
|
|
}
|
|
catch (Exception exception) // handle any unexpected error
|
|
{
|
|
LogException(exception);
|
|
SetErrorScript();
|
|
}
|
|
return View(model);
|
|
}
|
|
|
|
[HttpPost]
|
|
[ValidateAntiForgeryToken]
|
|
[AllowAnonymous]
|
|
public async Task<ActionResult> RestorePassword(RestorePasswordModel model)
|
|
{
|
|
if (ModelState.IsValid)
|
|
{
|
|
try
|
|
{
|
|
if (RestorePasswordModel.PageState.Initial.Equals(model.State))
|
|
{
|
|
using (var db = new EnVisageEntities())
|
|
{
|
|
var request = db.PasswordResetRequests.FirstOrDefault(t => t.Token == model.Token);
|
|
if (request == null)
|
|
{
|
|
model.State = RestorePasswordModel.PageState.TokenDoesNotExist;
|
|
return View(model);
|
|
}
|
|
|
|
if (request.ValidUntil < DateTime.Now)
|
|
{
|
|
model.State = RestorePasswordModel.PageState.TokenExpired;
|
|
return View(model);
|
|
}
|
|
var user = db.AspNetUsers.FirstOrDefault(t => t.Id == request.UserId);
|
|
if (user == null)
|
|
throw new BLLException(Messages.Account_TtokenDoesNotMatchAnyExistingUser_);
|
|
|
|
// make link expired
|
|
request.ValidUntil = DateTime.Now.AddMinutes(-1);
|
|
db.Entry(request).State = EntityState.Modified;
|
|
// reset password
|
|
var removePwdResult = AppUserManager.RemovePassword(user.Id);
|
|
if (!removePwdResult.Succeeded)
|
|
throw new BLLException(Messages.Account_SystemCannotRemovePassword, false);
|
|
var addPwdResult = AppUserManager.AddPassword(user.Id, model.Password);
|
|
if (!addPwdResult.Succeeded)
|
|
{
|
|
AddErrors(addPwdResult);
|
|
return View(model);
|
|
}
|
|
// make user able to enter web portal
|
|
user.Type = (int)UserType.Active;
|
|
// commit all changes
|
|
db.SaveChanges();
|
|
}
|
|
model.State = RestorePasswordModel.PageState.Restored;
|
|
}
|
|
else if (RestorePasswordModel.PageState.TokenExpired.Equals(model.State))
|
|
{
|
|
var request = await UserManager.CreateResetPasswordTokenByEmailAsync(model.Email, Settings.Default.ForgotPasswordLinkTTLDays);
|
|
if (request != null)
|
|
{
|
|
MailManager.SendRestorePasswordMessage(request.Email, request.Token, request.UserName);
|
|
model.State = RestorePasswordModel.PageState.TokenResent;
|
|
}
|
|
}
|
|
}
|
|
catch (BLLException blEx) // handle any system specific error
|
|
{
|
|
// display error message if required
|
|
if (blEx.DisplayError)
|
|
ModelState.AddModelError(string.Empty, blEx.Message);
|
|
else // if display not requried then display modal form with general error message
|
|
{
|
|
LogException(blEx);
|
|
ModelState.AddModelError(string.Empty, Messages.AccountController_RestorePassword_Error);
|
|
}
|
|
}
|
|
catch (Exception exception) // handle any unexpected error
|
|
{
|
|
LogException(exception);
|
|
ModelState.AddModelError(string.Empty, Messages.AccountController_RestorePassword_Error);
|
|
}
|
|
}
|
|
return View(model);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private Methods
|
|
|
|
private void ssoDefault()
|
|
{
|
|
var principal = Thread.CurrentPrincipal;
|
|
var i = principal.Identity as System.Security.Claims.ClaimsIdentity;
|
|
|
|
if (principal == null)
|
|
Logger.Log(NLog.LogLevel.Debug, "user name from principal is null. in ssoDefault()", "");
|
|
if (i == null)
|
|
Logger.Log(NLog.LogLevel.Debug, "user name from principal.Identity is null. in ssoDefault()", "");
|
|
|
|
string username = principal.Identity.Name;
|
|
Logger.Log(NLog.LogLevel.Debug, "user name from adfs." + username, "");
|
|
string[] splprm = { "\\" };
|
|
string[] names = username.Split(splprm, StringSplitOptions.None);
|
|
if (names.Length >= 2)
|
|
username = names[1];
|
|
var user = AppUserManager.FindByNameAsync(username).Result;
|
|
if (user != null)
|
|
{
|
|
if (user.Type == (int)UserType.Active)
|
|
{
|
|
|
|
i.AddClaim(new System.Security.Claims.Claim(ClaimTypes.NameIdentifier, user.Id));
|
|
UserVoiceApi userVoice = new UserVoiceApi();
|
|
string ssoToken = UserVoiceGenerator.create(userVoice.GetUserJsonObject(user));
|
|
if (!SessionManager.Exists(Code.Constants.USERVOICE_SSO_TOKEN) || string.IsNullOrEmpty(ssoToken))
|
|
{
|
|
SessionManager.SetValue(Code.Constants.USERVOICE_SSO_TOKEN, ssoToken);
|
|
HttpCookie ssoTokenCookie = new HttpCookie(Code.Constants.USERVOICE_COOKIE_CONTEXT);
|
|
ssoTokenCookie[Code.Constants.USERVOICE_SSO_TOKEN] = ssoToken;
|
|
ssoTokenCookie.Expires = DateTime.Now.AddDays(30d);
|
|
Response.Cookies.Add(ssoTokenCookie);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
|
|
{
|
|
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
|
|
var identity = await AppUserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
|
|
// identity.AddClaim(new System.Security.Claims.Claim("PrevuID",user.Id.ToString(),"PrevuID"));
|
|
var authProps = new AuthenticationProperties { IsPersistent = isPersistent };
|
|
if (isPersistent)
|
|
authProps.ExpiresUtc = DateTime.UtcNow.AddHours(12);
|
|
AuthenticationManager.SignIn(authProps, identity);
|
|
}
|
|
|
|
private void AddErrors(IdentityResult result)
|
|
{
|
|
foreach (var error in result.Errors)
|
|
{
|
|
ModelState.AddModelError("", error);
|
|
}
|
|
}
|
|
|
|
private bool HasPassword()
|
|
{
|
|
return HasPassword(User.Identity.GetID());
|
|
}
|
|
private bool HasPassword(string id)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(id))
|
|
return false;
|
|
var user = AppUserManager.FindById(id);
|
|
if (user != null)
|
|
return user.PasswordHash != null;
|
|
return false;
|
|
}
|
|
|
|
private ActionResult RedirectToLocal(string returnUrl, string userId)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(returnUrl) && Url.IsLocalUrl(returnUrl) && returnUrl != "/")
|
|
{
|
|
return Redirect(returnUrl);
|
|
}
|
|
//first of all, need to check if we have LastVisitedPage stored for the user
|
|
Guid userGuid;
|
|
if (Guid.TryParse(userId, out userGuid) && !SecurityManager.IsResourceOnlyAccess(userId))
|
|
{
|
|
var lastVisitedPage = UserManager.GetPagePreferencesValue<string>(Code.Constants.USER_PREFERENCE_LASTPAGE_URL, Code.Constants.USER_PREFERENCE_LASTPAGE_SECTION, Code.Constants.USER_PREFERENCE_LASTPAGE_SECTION, userGuid);
|
|
if (!string.IsNullOrWhiteSpace(lastVisitedPage))
|
|
return Redirect(lastVisitedPage);
|
|
}
|
|
|
|
SecurityManager.DefaultPageWithArea page = SecurityManager.RedirectToDefaultPage(userId);
|
|
return RedirectToAction(page.Action, page.Controller, page.Parameters);
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region Models
|
|
|
|
public enum ManageMessageId
|
|
{
|
|
ChangePasswordSuccess,
|
|
SetPasswordSuccess,
|
|
RemoveLoginSuccess,
|
|
Error
|
|
}
|
|
|
|
private class ChallengeResult : HttpUnauthorizedResult
|
|
{
|
|
public ChallengeResult(string provider, string redirectUri, string userId = null)
|
|
{
|
|
LoginProvider = provider;
|
|
RedirectUri = redirectUri;
|
|
UserId = userId;
|
|
}
|
|
|
|
public string LoginProvider { get; }
|
|
public string RedirectUri { get; }
|
|
public string UserId { get; }
|
|
|
|
public override void ExecuteResult(ControllerContext context)
|
|
{
|
|
var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
|
|
if (UserId != null)
|
|
{
|
|
properties.Dictionary[XsrfKey] = UserId;
|
|
}
|
|
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |