Example #1
0
        public void ShouldPassWithEmptyProjectIdAndValidAccessCode(string accessCode)
        {
            var request = new GuestVerificationRequest
            {
                ProjectAccessCode = accessCode,
                ProjectId         = Guid.Empty,
                Username          = "******"
            };

            var result = _validator.Validate(request);

            Assert.True(result.IsValid);
        }
Example #2
0
        public void ShouldFailForEmptyProjectIdWhenAccessCodeMissing(string accessCode)
        {
            var request = new GuestVerificationRequest
            {
                ProjectAccessCode = accessCode,
                ProjectId         = Guid.Empty,
                Username          = "******"
            };

            var result = _validator.Validate(request);

            Assert.False(result.IsValid);
        }
Example #3
0
        public void ShouldPassForValidRequest()
        {
            var request = new GuestVerificationRequest
            {
                ProjectAccessCode = Guid.NewGuid().ToString(),
                ProjectId         = Guid.NewGuid(),
                Username          = "******"
            };

            var result = _validator.Validate(request);

            Assert.True(result.IsValid);
        }
Example #4
0
        public void ShouldFailForValidProjectIdAndInvalidAccessCode(string accessCode)
        {
            var request = new GuestVerificationRequest
            {
                ProjectAccessCode = accessCode,
                ProjectId         = Guid.NewGuid(),
                Username          = "******"
            };

            var result = _validator.Validate(request);

            Assert.False(result.IsValid);
        }
Example #5
0
        public GuestSessionModuleTests()
        {
            TenantId = Guid.NewGuid();
            var defaultGuestUser = User.GuestUserExample();

            defaultGuestUser.Id              = _principalId;
            defaultGuestUser.IsLocked        = false;
            defaultGuestUser.IsEmailVerified = true;
            defaultGuestUser.EmailVerifiedAt = DateTime.Now.AddDays(-1.0);

            _defaultProject.TenantId = TenantId;

            _defaultGuestVerificationRequest = new GuestVerificationRequest()
            {
                ProjectAccessCode = _defaultProject.GuestAccessCode, ProjectId = _defaultProject.Id, Username = defaultGuestUser.Username
            };
        }
        public async Task <CurrentProjectState> SetProjectGuestContextAsync(Guid projectId, string accessCode, Guid currentUserId, Guid?currentUserTenantId, Guid principalId)
        {
            if (projectId.Equals(Guid.Empty))
            {
                return(await ClearGuestSessionState(currentUserId));
            }

            var projectResponse = await _serviceToServiceProjectApi.GetProjectByIdAsync(projectId);

            if (!projectResponse.IsSuccess() || projectResponse.Payload == null)
            {
                throw new InvalidOperationException($"Error fetching project {projectId} with service to service client, {projectResponse?.ResponseCode} - {projectResponse?.ReasonPhrase}");
            }

            var projectTenantId = projectResponse.Payload.TenantId;

            (ProjectGuestContext guestContext,
             MicroserviceResponse <IEnumerable <Guid> > projectUsersResponse) = await LoadDataAsync(projectId, projectTenantId);


            if (!projectUsersResponse.IsSuccess() || projectUsersResponse.Payload == null)
            {
                throw new InvalidOperationException($"Error fetching project users {projectId}, {projectUsersResponse.ResponseCode} - {projectUsersResponse.ReasonPhrase}");
            }

            var project = projectResponse?.Payload;
            var userIsFullProjectMember = projectUsersResponse.Payload.Any(userId => userId == currentUserId);

            if (UserHasActiveProjectGuestContext(guestContext) && userIsFullProjectMember)
            {
                //User is in project's account and was a guest who was promoted to a full
                //member, clear guest properties. This changes the return value of ProjectGuestContextService.IsGuestAsync() to false.
                guestContext = new ProjectGuestContext();
                await _projectGuestContextService.SetProjectGuestContextAsync(guestContext);
            }

            var userHasAccess = UserHasActiveProjectGuestContext(guestContext) ?
                                await IsGuestCurrentlyAdmittedToProjectAsync(guestContext.GuestSessionId) :
                                userIsFullProjectMember;

            if (userHasAccess)
            {
                return(await CreateCurrentProjectState(project, true));
            }

            if (UserHasActiveProjectGuestContext(guestContext) && guestContext?.ProjectId == project?.Id)
            {
                return(await CreateCurrentProjectState(project, false));
            }

            var userResponse = await _userApi.GetUserAsync(currentUserId);

            if (!userResponse.IsSuccess() || userResponse?.Payload == null)
            {
                throw new InvalidOperationException($"Error fetching user for {currentUserId}, {userResponse?.ResponseCode} - {userResponse?.ReasonPhrase}");
            }

            var userName      = !string.IsNullOrEmpty(userResponse.Payload.Email) ? userResponse.Payload.Email : userResponse.Payload.Username;
            var verifyRequest = new GuestVerificationRequest {
                Username = userName, ProjectAccessCode = accessCode, ProjectId = projectId
            };

            var guestVerifyResponse = await _guestSessionController.VerifyGuestAsync(verifyRequest, project, currentUserTenantId);

            if (guestVerifyResponse.ResultCode != VerifyGuestResponseCode.Success)
            {
                throw new InvalidOperationException($"Failed to verify guest for User.Id = {currentUserId}, Project.Id = {projectId}. ResponseCode = {guestVerifyResponse.ResultCode}. Reason = {guestVerifyResponse.Message}");
            }

            var newSession = await _guestSessionController.CreateGuestSessionAsync(new GuestSession
            {
                UserId            = currentUserId,
                ProjectId         = projectId,
                ProjectAccessCode = project.GuestAccessCode,
                GuestSessionState = InternalApi.Enums.GuestState.InLobby
            }, principalId, projectTenantId);

            await _projectGuestContextService.SetProjectGuestContextAsync(new ProjectGuestContext()
            {
                GuestSessionId = newSession.Id,
                ProjectId      = project.Id,
                GuestState     = Guest.ProjectContext.Enums.GuestState.InLobby,
                TenantId       = project.TenantId
            });


            if (!userIsFullProjectMember)
            {
                var request = new GrantProjectMembershipRequest
                {
                    UserId    = currentUserId,
                    ProjectId = project.Id,
                    Role      = MemberRole.GuestUser
                };
                var grantUserResponse = await _serviceToServiceProjectAccessApi.GrantProjectMembershipAsync(request, new List <KeyValuePair <string, string> > {
                    HeaderKeys.CreateTenantHeaderKey(projectTenantId)
                });

                if (!grantUserResponse.IsSuccess())
                {
                    throw new InvalidOperationException("Failed to add user to project");
                }
            }

            return(await CreateCurrentProjectState(project, false));
        }
        /// <summary>
        /// Verifies the eligibility of a guest to enter a project lobby and potentially join the project.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="project"></param>
        /// <param name="guestTenantId"></param>
        /// <returns></returns>
        /// <remarks>This method is not intended for external use. It is a public interface member to make it available to
        /// the ProjectGuestContextController and for unit tests. The project argument on this method is a optimization to eliminate
        /// a redundant retrieval of the project when this method is invoked by the ProjectGuestContextController.SetProjectGuestContext method.</remarks>
        public async Task <GuestVerificationResponse> VerifyGuestAsync(GuestVerificationRequest request, Project project, Guid?guestTenantId)
        {
            var validationResult = _validatorLocator.Validate <GuestVerificationRequestValidator>(request);

            if (!validationResult.IsValid)
            {
                _logger.Error("Failed to validate the guest verification request.");
                throw new ValidationFailedException(validationResult.Errors);
            }

            var response = new GuestVerificationResponse();

            if (project != null)
            {
                if (request.ProjectId != Guid.Empty && request.ProjectId != project.Id)
                {
                    response.ResultCode = VerifyGuestResponseCode.InvalidCode;
                    response.Message    = "Could not find a project with that project Id.";
                    return(response);
                }

                if (request.ProjectAccessCode != project.GuestAccessCode && guestTenantId != project.TenantId)
                {
                    response.ResultCode = VerifyGuestResponseCode.InvalidCode;
                    response.Message    = "Could not find a project with that project access code.";
                    return(response);
                }
            }

            if (project == null)
            {
                if (request.ProjectId != Guid.Empty)
                {
                    var projectResponse = await _serviceToServiceProjectApi.GetProjectByIdAsync(request.ProjectId);

                    if (!projectResponse.IsSuccess())
                    {
                        response.ResultCode = VerifyGuestResponseCode.InvalidCode;
                        response.Message    = "Could not find a project with that project Id.";
                        return(response);
                    }

                    project = projectResponse.Payload;
                }
                else
                {
                    var projectResponse = await _serviceToServiceProjectApi.GetProjectByAccessCodeAsync(request.ProjectAccessCode);

                    if (!projectResponse.IsSuccess())
                    {
                        response.ResultCode = VerifyGuestResponseCode.InvalidCode;
                        response.Message    = "Could not find a project with that project access code.";
                        return(response);
                    }

                    project = projectResponse.Payload;
                }
            }

            if (project.TenantId == Guid.Empty)
            {
                response.ResultCode = VerifyGuestResponseCode.InvalidCode;
                response.Message    = "There is no tenant associated with this project. Please contact support to fix this project.";
                return(response);
            }

            response.ProjectAccessCode = request.ProjectAccessCode;
            response.ProjectName       = project.Name;
            response.Username          = request.Username;

            var userResponse = await _userApi.GetUserByUserNameOrEmailAsync(request.Username);

            if (!userResponse.IsSuccess())
            {
                if (userResponse.ResponseCode == HttpStatusCode.NotFound)
                {
                    var invite = (await _guestInviteRepository.GetItemsAsync(x => x.GuestEmail == request.Username && x.ProjectAccessCode == request.ProjectAccessCode)).FirstOrDefault();
                    if (!string.IsNullOrEmpty(invite?.GuestEmail))
                    {
                        response.ResultCode = VerifyGuestResponseCode.SuccessNoUser;
                        response.Message    = "This user does not exist but has been invited, so can join as a guest";
                        return(response);
                    }

                    response.ResultCode = VerifyGuestResponseCode.InvalidNoInvite;
                    response.Message    = "This user does not exist and has not been invited";
                    return(response);
                }

                _logger.Error($"An error occured while trying to retrieve the user with username: {request.Username}. ResponseCode: {userResponse.ResponseCode}. Reason: {userResponse.ReasonPhrase}");

                response.ResultCode = VerifyGuestResponseCode.Failed;
                response.Message    = $"An error occurred while trying to get the user with username: {request.Username}. {userResponse.ReasonPhrase}";
                return(response);
            }

            var user = userResponse.Payload;

            if (user.IsLocked)
            {
                response.ResultCode = VerifyGuestResponseCode.UserIsLocked;
                response.Message    = "This user is locked";
                return(response);
            }

            if (user.IsEmailVerified != true)
            {
                response.ResultCode = VerifyGuestResponseCode.EmailVerificationNeeded;
                response.Message    = "The user has not verified his email address";
                return(response);
            }

            var isProjectInUsersAccount = guestTenantId == project.TenantId;

            var userSettingsResponse = await _serviceToServiceAccountSettingsApi.GetUserSettingsAsync(project.TenantId);

            var isGuestModeEnableOnProjectAccountSettings = userSettingsResponse.IsSuccess() && userSettingsResponse.Payload.IsGuestModeEnabled;

            if (!isGuestModeEnableOnProjectAccountSettings && !isProjectInUsersAccount)
            {
                response.ResultCode = VerifyGuestResponseCode.Failed;
                response.Message    = "Guest mode is not enabled on the account";
                return(response);
            }

            if (!project.IsGuestModeEnabled && !isProjectInUsersAccount)
            {
                response.ResultCode = VerifyGuestResponseCode.Failed;
                response.Message    = "Guest mode is not enabled on the project";
                return(response);
            }

            response.ResultCode = VerifyGuestResponseCode.Success;
            response.Message    = "The user may join as a guest";
            return(response);
        }
 public async Task <GuestVerificationResponse> VerifyGuestAsync(GuestVerificationRequest request, Guid?guestTenantId)
 {
     return(await VerifyGuestAsync(request, null, guestTenantId));
 }
Example #9
0
        public void ShouldFailOnInvalidEmailInAddressList(GuestVerificationRequest request)
        {
            var result = _validator.Validate(request);

            Assert.False(result.IsValid);
        }