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> Login(LoginViewModel model, string returnUrl = null) { if (!ModelState.IsValid) { return(View(model)); } AuthOperation attemptedOperation; ApplicationUser userToSignTokenWith; var email = _userManager.NormalizeKey(model.Email); var userWithConfirmedEmail = await _userManager.FindByLoginAsync("Email", email); var userCurrentlySignedIn = await _userManager.GetUserAsync(User); if (userCurrentlySignedIn == null) // No locally signed-in user (trying to register or login) { // Clear the existing external cookie to ensure a clean login process await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); if (userWithConfirmedEmail == null) // Email not associated with any other accounts (trying to register) { userToSignTokenWith = new ApplicationUser() { Id = email, Email = email, SecurityStamp = TemporarySecurityStamp }; attemptedOperation = AuthOperation.Registering; } else // Email associated with an account (trying to login) { userToSignTokenWith = userWithConfirmedEmail; attemptedOperation = AuthOperation.LoggingIn; } } else // A user is currently locally signed-in (trying to add email) { userToSignTokenWith = userCurrentlySignedIn; if (userWithConfirmedEmail == null) // Email not associated with any other accounts (trying to add a novel email) { // Check to see if user reached max logins if (DidReachMaxLoginsAllowed(userCurrentlySignedIn)) { return(View(nameof(Login), new LoginViewModel { MaxLoginsAllowed = MaxLoginsAllowed, DidReachMaxLoginsAllowed = true })); } attemptedOperation = AuthOperation.AddingNovelEmail; } else // Email associated with another user's account { if (userWithConfirmedEmail.Id == userCurrentlySignedIn.Id) // Email already added to user's account { _notice.AddErrors(ModelState, "This email is already in your account."); return(View(model)); } else // Email associated with another account that's not the user's { attemptedOperation = AuthOperation.AddingOtherUserEmail; } } } var token = ""; var purpose = ""; switch (attemptedOperation) { case AuthOperation.AddingOtherUserEmail: purpose = "AddEmail"; break; case AuthOperation.AddingNovelEmail: purpose = "AddEmail"; token = await _userManager.GenerateUserTokenAsync(userToSignTokenWith, "Email", purpose); break; case AuthOperation.Registering: case AuthOperation.LoggingIn: purpose = "RegisterOrLogin"; token = await _userManager.GenerateUserTokenAsync(userToSignTokenWith, "Email", purpose); break; } // Add a space every 3 characters for readability token = String.Concat(token.SelectMany((c, i) => (i + 1) % 3 == 0 ? $"{c} " : $"{c}")).Trim(); var callbackUrl = Url.TokenInputLink(Request.Scheme, new TokenInputViewModel { Token = token, RememberMe = model.RememberMe, ReturnUrl = returnUrl, Email = email, Purpose = purpose }); // Will not wait for email to be sent #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed _emailSender.SendTokenAsync(email, attemptedOperation, callbackUrl, token); #pragma warning restore CS4014 return(View(nameof(TokenInput), new TokenInputViewModel { RememberMe = model.RememberMe, ReturnUrl = returnUrl, Email = email, Purpose = purpose })); }
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))); }