private async Task <object> VerifyGuestAsync(dynamic input, CancellationToken cancellationToken)
        {
            GuestVerificationRequest request;

            try
            {
                request = this.Bind <GuestVerificationRequest>();
            }
            catch (Exception ex)
            {
                Logger.Error("Binding failed while attempting to verify a guest.", ex);
                return(Response.BadRequestBindingException(ResponseReasons.FailedToBindToRequest));
            }

            await RequiresAccess()
            .WithProjectIdExpansion(ctx => request.ProjectId)
            .ExecuteAsync(cancellationToken);

            try
            {
                return(await _guestSessionController.VerifyGuestAsync(request, TenantId));
            }
            catch (NotFoundException)
            {
                return(Response.NotFound(ResponseReasons.NotFoundGuestSession));
            }
            catch (ValidationFailedException ex)
            {
                return(Response.BadRequestValidationFailed(ex.Errors));
            }
            catch (Exception ex)
            {
                Logger.Error($"Failed to verify guest with username {request.Username} due to an error", ex);
                return(Response.InternalServerError(ResponseReasons.InternalServerErrorGetGuestSession));
            }
        }
        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));
        }