public async Task <IActionResult> EditUserInfo(EditUserInfoViewModel model) { var user = await _userManager.GetUserAsync(User); if (user == null) { await _signInManager.SignOutAsync(); _notice.AddErrors(ModelState); return(View(model)); } var emailToMakePrimary = _userManager.NormalizeKey(model.Email); var userLogins = await _userManager.GetLoginsAsync(user); model.Logins = userLogins; // Since model binding doesn't work with IList if (!ModelState.IsValid) { return(View(model)); } user.UserName = model.UserName; user.FullName = model.FullName; user.SendCodesViaSms = model.SendCodesViaSms; user.MobileNumber = model.MobileNumber; // If the user's email is confirmed (ie. local login) and they provided a different email that exists, set it to the primary if (user.EmailConfirmed && user.NormalizedEmail != emailToMakePrimary && userLogins.Any(l => l.LoginProvider == "Email" && l.ProviderKey == emailToMakePrimary)) { user.Email = emailToMakePrimary; } // Update sumbitted user info, including changing email if required var updateResult = await _userManager.UpdateAsync(user); if (!updateResult.Succeeded) { _notice.AddErrors(ModelState, updateResult); return(View(model)); } await _events.AddEvent(AuthEventType.EditUserInfo, JsonConvert.SerializeObject(model), user); await _signInManager.RefreshSignInAsync(user); return(_notice.Success(this, "Your profile has been updated.")); }
public async Task <IActionResult> SubmitTokenInput(TokenInputViewModel model) { if (!ModelState.IsValid || String.IsNullOrWhiteSpace(model.Email) || String.IsNullOrWhiteSpace(model.Purpose) || String.IsNullOrWhiteSpace(model.Token)) { return(View(model)); } var email = _userManager.NormalizeKey(model.Email); model.Token = model.Token.Replace(" ", ""); var userWithConfirmedEmail = await _userManager.FindByLoginAsync("Email", email); var userCurrentlySignedIn = await _userManager.GetUserAsync(User); var userEmpty = new ApplicationUser() { Id = email, Email = email, SecurityStamp = TemporarySecurityStamp }; var isTokenValid = false; if (model.Purpose == "RegisterOrLogin") // Trying to register or login { await _signInManager.SignOutAsync(); isTokenValid = await _userManager.VerifyUserTokenAsync( userWithConfirmedEmail // Case: logging-in ?? userEmpty, // Case: registering, "Email", model.Purpose, model.Token); } else // Trying to add email { if (userCurrentlySignedIn == null) // If the user is not signed in, prompt them to, with the return url leading back here { return(RedirectToAction(nameof(Login), new { returnUrl = Request.Path + Request.QueryString })); } isTokenValid = await _userManager.VerifyUserTokenAsync( userCurrentlySignedIn, "Email", model.Purpose, model.Token); } if (!isTokenValid) { _notice.AddErrors(ModelState, "Error validating code, it might have expired. Please try again!"); return(View(model)); } // Invalidates all tokens for user when trying to login or add login // Note: this also invalidates any attempts to add more logins than allowed if ((userCurrentlySignedIn ?? userWithConfirmedEmail) != null) { var updateSecStampResult = await _userManager.UpdateSecurityStampAsync(userCurrentlySignedIn ?? userWithConfirmedEmail); if (!updateSecStampResult.Succeeded) { _notice.AddErrors(ModelState); return(View(model)); } } // Valid {token + email (user) + purpose} supplied if (model.Purpose == "RegisterOrLogin") // Trying to register or login { if (userWithConfirmedEmail == null) // Success trying to register { var token = await _userManager.GenerateUserTokenAsync(userEmpty, "Default", "Register"); return(View(nameof(Register), new RegisterViewModel { RememberMe = model.RememberMe, Email = email, UserName = GenerateUserName(email), Token = token, ReturnUrl = model.ReturnUrl })); } else // Success trying to login { await _events.AddEvent(AuthEventType.Login, JsonConvert.SerializeObject(new { LoginProvider = "Email", ProviderKey = model.Email }), userWithConfirmedEmail); await _signInManager.SignInAsync(userWithConfirmedEmail, isPersistent : model.RememberMe); } } else // Trying to add email { var userWithConfirmedEmailToAdd = await _userManager.FindByLoginAsync("Email", email); if (userWithConfirmedEmailToAdd == null) // Email to be added never seen before, add email to userCurrentlySignedIn { var addLoginResult = await _userManager.AddLoginAsync(userCurrentlySignedIn, new UserLoginInfo("Email", email, "Email")); if (!addLoginResult.Succeeded) { _notice.AddErrors(ModelState, addLoginResult); return(View(model)); } userCurrentlySignedIn.Email = email; userCurrentlySignedIn.EmailConfirmed = true; var updateUserResult = await _userManager.UpdateAsync(userCurrentlySignedIn); if (!updateUserResult.Succeeded) { _notice.AddErrors(ModelState, updateUserResult); return(View(model)); } await _events.AddEvent(AuthEventType.AddLogin, JsonConvert.SerializeObject(new { LoginProvider = "Email", ProviderKey = model.Email }), userCurrentlySignedIn); } else // Email to be added is in use { // Note: this area is unlikely to be reached since security stamp is changed once a login is added if (userWithConfirmedEmailToAdd.Id == userCurrentlySignedIn.Id) // Email is already in user's account { _notice.AddErrors(ModelState, "This email is already in your account."); return(View(model)); } else // Email associated with another account (same user since both verified!) { _notice.AddErrors(ModelState, "This email is in another user's account. Try logging in using that email instead."); return(View(model)); } } } // Success return(RedirectToLocal(model.ReturnUrl)); }
public async Task <IActionResult> Create([Bind("Email,Name,PinCode")] BarcoMemberViewModel barcoMember) { //Register locally var email = _userManager.NormalizeKey(barcoMember.Email); var userEmpty = new ApplicationUser() { UserName = email, Email = email, DateCreated = DateTimeOffset.UtcNow, SecurityStamp = new Guid().ToString(), FullName = barcoMember.Name, NickName = barcoMember.Name.Split()[0], PinCode = barcoMember.PinCode, EmailConfirmed = true }; var userWithConfirmedEmail = await _userManager.FindByLoginAsync("Email", email); if (userWithConfirmedEmail != null) //user does not exist { _notice.AddErrors(ModelState); return(View(nameof(Create))); } var info = new UserLoginInfo("Email", userEmpty.Email, "Email"); var createResult = await _userManager.CreateAsync(userEmpty); if (createResult.Succeeded) { var addLoginResult = await _userManager.AddLoginAsync(userEmpty, info); if (addLoginResult.Succeeded) { var user = await _userManager.FindByNameAsync(userEmpty.UserName); // This works because usernames are unique var makeAdminResult = await _userManager.AddToRolesAsync(user, new[] { Constants.ROTA_ROLE, Constants.WOLF_ROLE }); await _events.AddEvent(AuthEventType.Register, JsonConvert.SerializeObject(new { LoginProvider = info?.LoginProvider ?? "Email", ProviderKey = info?.ProviderKey ?? email }), user); //Register with application try { var createBarcoUserResult = await new HttpClient().PostAsync("http://localhost:8000/api/BarcoMembers", new JsonContent(new { Name = user.FullName, NickName = user.NickName, UserName = user.UserName, RotaStatus = barcoMember.RotaStatus })); } catch (Exception) { //mute } return(RedirectToAction(nameof(Index))); } else { _notice.AddErrors(ModelState, addLoginResult); } } else { _notice.AddErrors(ModelState, createResult); } await _userManager.DeleteAsync(userEmpty); // TODO: make atomic return(RedirectToAction(nameof(Index))); }