Example #1
0
        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."));
        }
Example #2
0
        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)));
        }