Пример #1
0
        private async Task CreateNewUserReleaseInvite(Guid releaseId, string email)
        {
            var hasExistingInvite = await _context
                                    .UserReleaseInvites
                                    .Where(
                i =>
                i.ReleaseId == releaseId &&
                i.Email.ToLower() == email.ToLower() &&
                i.Role == ReleaseRole.PrereleaseViewer
                )
                                    .AnyAsync();

            if (hasExistingInvite)
            {
                return;
            }

            _context.Add(
                new UserReleaseInvite
            {
                Email       = email.ToLower(),
                ReleaseId   = releaseId,
                Role        = ReleaseRole.PrereleaseViewer,
                Created     = UtcNow,
                CreatedById = _userService.GetUserId()
            }
                );
            await _context.SaveChangesAsync();

            var hasExistingSystemInvite = await _usersAndRolesDbContext
                                          .UserInvites
                                          .Where(i => i.Email.ToLower() == email.ToLower())
                                          .AnyAsync();

            // TODO EES-1181 - allow multiple invites per email address to allow people to
            // be assigned multiple roles upon first login
            if (!hasExistingSystemInvite)
            {
                var role = await GetPreReleaseUserRole();

                _usersAndRolesDbContext.Add(
                    new UserInvite
                {
                    Email   = email.ToLower(),
                    Role    = role,
                    Created = UtcNow,
                    // TODO
                    CreatedBy = ""
                }
                    );

                await _usersAndRolesDbContext.SaveChangesAsync();
            }
        }
        public async Task <UserInvite> Create(string email, string roleId, Guid createdById)
        {
            var existingInvite = await _usersAndRolesDbContext
                                 .UserInvites
                                 .AsQueryable()
                                 .SingleOrDefaultAsync(i => i.Email.ToLower().Equals(email.ToLower()));

            if (existingInvite != null)
            {
                return(existingInvite);
            }

            var newInvite = new UserInvite
            {
                Email       = email.ToLower(),
                RoleId      = roleId,
                Created     = DateTime.UtcNow,
                CreatedById = createdById.ToString(),
            };

            _usersAndRolesDbContext.Add(newInvite);
            await _usersAndRolesDbContext.SaveChangesAsync();

            return(newInvite);
        }
Пример #3
0
        public async Task <Either <ActionResult, UserInvite> > InviteUser(string email, string inviteCreatedByUser,
                                                                          string roleId)
        {
            return(await _userService
                   .CheckCanManageAllUsers()
                   .OnSuccess <ActionResult, Unit, UserInvite>(async() =>
            {
                if (string.IsNullOrWhiteSpace(email))
                {
                    return ValidationActionResult(InvalidEmailAddress);
                }

                if (_usersAndRolesDbContext.Users.Any(u => u.Email.ToLower() == email.ToLower()))
                {
                    return ValidationActionResult(UserAlreadyExists);
                }

                var role = await _usersAndRolesDbContext.Roles.FirstOrDefaultAsync(r => r.Id == roleId);
                if (role == null)
                {
                    return ValidationActionResult(InvalidUserRole);
                }

                var invite = new UserInvite
                {
                    Email = email.ToLower(),
                    Created = DateTime.UtcNow,
                    CreatedBy = inviteCreatedByUser,
                    Role = role
                };
                await _usersAndRolesDbContext.UserInvites.AddAsync(invite);
                await _usersAndRolesDbContext.SaveChangesAsync();
                SendInviteEmail(email);
                return invite;
            }));
        }
Пример #4
0
        public async Task <Either <ActionResult, Unit> > CancelInvite(string email)
        {
            return(await _userService
                   .CheckCanManageAllUsers()
                   .OnSuccess <ActionResult, Unit, Unit>(async() =>
            {
                var invite = await _usersAndRolesDbContext.UserInvites
                             .AsQueryable()
                             .FirstOrDefaultAsync(i => i.Email == email);

                if (invite == null)
                {
                    return ValidationActionResult(InviteNotFound);
                }

                _usersAndRolesDbContext.UserInvites.Remove(invite);
                await _usersAndRolesDbContext.SaveChangesAsync();

                return Unit.Instance;
            }));
        }
        public async Task <Either <ActionResult, Unit> > RemovePreReleaseUser(Guid releaseId, string email)
        {
            if (!new EmailAddressAttribute().IsValid(email))
            {
                return(ValidationActionResult(InvalidEmailAddress));
            }

            return(await _persistenceHelper
                   .CheckEntityExists <Release>(releaseId)
                   .OnSuccess(_userService.CheckCanAssignPrereleaseContactsToRelease)
                   .OnSuccessVoid(
                       async() =>
            {
                var userReleaseRolesToRemove = await _context
                                               .UserReleaseRoles
                                               .Include(r => r.User)
                                               .Where(
                    r =>
                    r.ReleaseId == releaseId &&
                    r.User.Email.ToLower().Equals(email.ToLower()) &&
                    r.Role == PrereleaseViewer
                    ).ToListAsync();
                await _userReleaseRoleRepository.RemoveMany(userReleaseRolesToRemove, _userService.GetUserId());

                _context.RemoveRange(
                    _context
                    .UserReleaseInvites
                    .AsQueryable()
                    .Where(
                        i =>
                        i.ReleaseId == releaseId &&
                        i.Email.ToLower().Equals(email.ToLower()) &&
                        i.Role == PrereleaseViewer
                        )
                    );
                await _context.SaveChangesAsync();

                // NOTE: UserInvites only stores whether a user has a particular role - not which release
                // that role may be against. So we only wanted to remove the user's prerelease role from
                // UserInvites if they no longer have any PrereleaseView roles.
                var remainingReleaseInvites = await _context
                                              .UserReleaseInvites
                                              .AsQueryable()
                                              .Where(
                    i =>
                    i.Email.ToLower().Equals(email.ToLower()) &&
                    i.Role == PrereleaseViewer
                    )
                                              .CountAsync();

                if (remainingReleaseInvites == 0)
                {
                    _usersAndRolesDbContext.UserInvites.RemoveRange(
                        _usersAndRolesDbContext.UserInvites
                        .AsQueryable()
                        .Where(
                            i =>
                            i.Email.ToLower().Equals(email.ToLower()) &&
                            i.RoleId == Role.PrereleaseUser.GetEnumValue() &&
                            !i.Accepted
                            )
                        );

                    await _usersAndRolesDbContext.SaveChangesAsync();
                }
            }
                       ));
        }
        public async Task <IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
        {
            returnUrl = returnUrl ?? Url.Content("~/");
            if (remoteError != null)
            {
                ErrorMessage = $"Error from external provider: {remoteError}";
                return(RedirectToPage("./Login", new { ReturnUrl = returnUrl }));
            }

            var info = await _signInManager.GetExternalLoginInfoAsync();

            if (info == null)
            {
                ErrorMessage = "Error loading external login information.";
                return(RedirectToPage("./Login", new { ReturnUrl = returnUrl }));
            }

            // Sign in the user with this external login provider if the user already has a login.
            var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey,
                                                                       isPersistent : false, bypassTwoFactor : true);

            if (result.Succeeded)
            {
                _logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name,
                                       info.LoginProvider);
                return(LocalRedirect(returnUrl));
            }

            if (result.IsLockedOut)
            {
                return(RedirectToPage("./Lockout"));
            }

            var firstName = info.Principal.FindFirstValue(ClaimTypes.GivenName);
            var lastName  = info.Principal.FindFirstValue(ClaimTypes.Surname);
            var email     = info.Principal.FindFirstValue(ClaimTypes.Email) != null
                ? info.Principal.FindFirstValue(ClaimTypes.Email)
                : info.Principal.FindFirstValue(ClaimTypes.Name);

            // Ensure names are set
            if (firstName == null && lastName == null)
            {
                var nameClaim = info.Principal.FindFirstValue(JwtClaimTypes.Name);

                if (nameClaim.IndexOf(' ') > 0)
                {
                    firstName = nameClaim.Substring(0, nameClaim.IndexOf(' '));
                    lastName  = nameClaim.Substring(nameClaim.IndexOf(' ') + 1);
                }
                else
                {
                    firstName = nameClaim;
                    lastName  = "";
                }
            }

            if (email == null)
            {
                ErrorMessage = "Email address not returned from Azure Active Directory";
                return(RedirectToPage("./Login", new { ReturnUrl = returnUrl }));
            }

            // Check if the user is invited
            var inviteToSystem = await _usersAndRolesDbContext
                                 .UserInvites
                                 .Include(i => i.Role)
                                 .FirstOrDefaultAsync(i =>
                                                      i.Email.ToLower() == email.ToLower() &&
                                                      i.Accepted == false);

            // If the user has an invite register them automatically
            if (inviteToSystem != null)
            {
                var user = new ApplicationUser
                {
                    UserName  = email,
                    Email     = email,
                    FirstName = firstName,
                    LastName  = lastName
                };

                var createdUserResult = await _userManager.CreateAsync(user);

                var addedUserRoles = await _userManager.AddToRoleAsync(user, inviteToSystem.Role.Name);

                if (createdUserResult.Succeeded && addedUserRoles.Succeeded)
                {
                    var newUser = new User
                    {
                        Id        = new Guid(user.Id),
                        FirstName = user.FirstName,
                        LastName  = user.LastName,
                        Email     = user.Email
                    };

                    _contentDbContext.Users.Add(newUser);

                    await _contentDbContext.SaveChangesAsync();

                    createdUserResult = await _userManager.AddLoginAsync(user, info);

                    if (createdUserResult.Succeeded)
                    {
                        await _signInManager.SignInAsync(user, isPersistent : false);

                        _logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider);

                        inviteToSystem.Accepted = true;
                        _usersAndRolesDbContext.UserInvites.Update(inviteToSystem);
                        await _usersAndRolesDbContext.SaveChangesAsync();

                        var releaseInvites = _contentDbContext
                                             .UserReleaseInvites
                                             .Where(i => i.Email.ToLower() == user.Email.ToLower());

                        await releaseInvites.ForEachAsync(invite =>
                        {
                            _contentDbContext.Add(new UserReleaseRole
                            {
                                ReleaseId = invite.ReleaseId,
                                Role      = invite.Role,
                                UserId    = newUser.Id,
                            });

                            invite.Accepted = true;
                        });

                        await _contentDbContext.SaveChangesAsync();

                        await _usersAndRolesDbContext.SaveChangesAsync();

                        return(LocalRedirect(returnUrl));
                    }
                }

                foreach (var error in createdUserResult.Errors)
                {
                    ModelState.AddModelError(string.Empty, error.Description);
                }

                foreach (var error in addedUserRoles.Errors)
                {
                    ModelState.AddModelError(string.Empty, error.Description);
                }
            }

            ReturnUrl = returnUrl;

            return(Page());
        }
        private async Task <IActionResult> HandleNewInvitedUser(
            UserInvite inviteToSystem,
            string email,
            string firstName,
            string lastName,
            ExternalLoginInfo info,
            string returnUrl)
        {
            // Mark the invite as accepted.
            inviteToSystem.Accepted = true;
            _usersAndRolesDbContext.UserInvites.Update(inviteToSystem);

            // See if we have an "internal" User record in existence yet that has a matching email address to the
            // new user logging in.  If we do, create this new AspNetUser record with a matching one-to-one id.
            // Otherwise, later on we'll create a new "internal" Users record with an id matching this AspNetUser's
            // id, continuing to establish the one-to-one relationship.
            var existingInternalUser = await _contentDbContext
                                       .Users
                                       .AsQueryable()
                                       .SingleOrDefaultAsync(u => u.Email.ToLower() == email.ToLower());

            // Create a new set of AspNetUser records for the Identity Framework.
            var newAspNetUser = new ApplicationUser
            {
                Id        = existingInternalUser?.Id.ToString() ?? Guid.NewGuid().ToString(),
                UserName  = email,
                Email     = email,
                FirstName = firstName,
                LastName  = lastName
            };

            var createdIdentityUserResult = await _userManager.CreateAsync(newAspNetUser);

            if (!createdIdentityUserResult.Succeeded)
            {
                return(HandleCreateIdentityFailure(returnUrl, createdIdentityUserResult));
            }

            var addedIdentityUserRoles = await _userManager.AddToRoleAsync(newAspNetUser, inviteToSystem.Role.Name);

            if (!addedIdentityUserRoles.Succeeded)
            {
                _logger.LogError("Error adding role to invited User - unable to log in");

                return(HandleIdentityResultFailure(returnUrl, addedIdentityUserRoles));
            }

            var recordIdpLoginDetailsResult = await _userManager.AddLoginAsync(newAspNetUser, info);

            if (!recordIdpLoginDetailsResult.Succeeded)
            {
                return(HandleAddingLoginIdentityFailure(returnUrl, newAspNetUser, recordIdpLoginDetailsResult));
            }

            // If adding the new Identity Framework user records succeeded, continue on to create internal User
            // and Role records for the application itself and sign the user in.

            // If we didn't yet have an existing "internal" User record matching this new login in the Users
            // table, create one now, being sure to establish the one-to-one id relationship between the
            // AspNetUsers record and the Users record.
            if (existingInternalUser == null)
            {
                var newInternalUser = new User
                {
                    Id        = Guid.Parse(newAspNetUser.Id),
                    FirstName = newAspNetUser.FirstName,
                    LastName  = newAspNetUser.LastName,
                    Email     = newAspNetUser.Email
                };

                await _contentDbContext.Users.AddAsync(newInternalUser);

                var releaseInvites = _contentDbContext
                                     .UserReleaseInvites
                                     .AsQueryable()
                                     .Where(i => i.Email.ToLower() == newAspNetUser.Email.ToLower());

                await releaseInvites.ForEachAsync(invite =>
                {
                    _contentDbContext.AddAsync(new UserReleaseRole
                    {
                        ReleaseId   = invite.ReleaseId,
                        Role        = invite.Role,
                        UserId      = newInternalUser.Id,
                        Created     = DateTime.UtcNow,
                        CreatedById = invite.CreatedById,
                    });

                    invite.Accepted = true;
                });
            }

            await _contentDbContext.SaveChangesAsync();

            await _usersAndRolesDbContext.SaveChangesAsync();

            await _signInManager.ExternalLoginSignInAsync(
                info.LoginProvider,
                info.ProviderKey,
                isPersistent : false,
                bypassTwoFactor : true);

            return(LocalRedirect(returnUrl));
        }