private static IEnumerable <Claim> ExtractGuestClaims(ProjectGuestContext projectGuestContext) { yield return(new Claim(ClaimTypes.GuestTenant, projectGuestContext.TenantId.ToString())); yield return(new Claim(ClaimTypes.GuestProject, projectGuestContext.ProjectId.ToString())); yield return(new Claim(ClaimTypes.GuestSession, projectGuestContext.GuestSessionId.ToString())); yield return(new Claim(ClaimTypes.GuestState, projectGuestContext.GuestState.ToString())); }
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)); }
private bool UserHasActiveProjectGuestContext(ProjectGuestContext context) { return(context != null && context.ProjectId != Guid.Empty && context.TenantId != Guid.Empty && context.GuestSessionId != Guid.Empty && context.GuestState != GuestState.Ended); }
public ProjectGuestContextControllerTests() { _defaultProject = new Project() { Id = _defaultProjectId, TenantId = _projectTenantId, GuestAccessCode = _defaultAccessCode }; _defaultPrincipalId = Guid.NewGuid(); _defaultProjectTenantHeaders = new List <KeyValuePair <string, string> >() { new KeyValuePair <string, string>(HeaderKeys.Tenant, _defaultProject.TenantId.ToString()) }; _defaultUser = new User { Id = _currentUserId, Username = "******" }; var defaultProjectLobbyState = new ProjectLobbyState { LobbyState = LobbyState.Normal, ProjectId = _defaultProjectId }; _defaultGuestSession = new GuestSession { Id = Guid.NewGuid(), ProjectId = _defaultProjectId, UserId = _currentUserId, ProjectAccessCode = _defaultAccessCode, GuestSessionState = GuestState.InLobby, SessionId = _defaultUserSessionId }; _defaultProjectGuestContext = new ProjectGuestContext { GuestSessionId = _defaultGuestSession.Id, GuestState = Guest.ProjectContext.Enums.GuestState.InLobby, ProjectId = _defaultProjectId, TenantId = _projectTenantId }; var repositoryFactoryMock = new Mock <IRepositoryFactory>(); repositoryFactoryMock .Setup(x => x.CreateRepository <GuestSession>()) .Returns(_guestSessionRepositoryMock.Object); _projectGuestContextServiceMock .Setup(x => x.GetProjectGuestContextAsync(It.IsAny <string>())) .ReturnsAsync(_defaultProjectGuestContext); _projectAccessApiMock .Setup(x => x.GrantProjectMembershipAsync(It.IsAny <GrantProjectMembershipRequest>(), _defaultProjectTenantHeaders)) .ReturnsAsync(MicroserviceResponse.Create(HttpStatusCode.OK)); _guestSessionControllerMock .Setup(x => x.UpdateGuestSessionStateAsync(It.IsAny <UpdateGuestSessionStateRequest>(), It.IsAny <Guid>())) .ReturnsAsync(new UpdateGuestSessionStateResponse()); _guestSessionControllerMock .Setup(x => x.VerifyGuestAsync(It.IsAny <GuestVerificationRequest>(), It.IsAny <Project>(), It.IsAny <Guid?>())) .ReturnsAsync(new GuestVerificationResponse() { ResultCode = VerifyGuestResponseCode.Success }); _guestSessionControllerMock .Setup(x => x.CreateGuestSessionAsync(It.IsAny <GuestSession>(), _defaultPrincipalId, It.IsAny <Guid>())) .ReturnsAsync(_defaultGuestSession); _userApiMock .Setup(x => x.GetUserAsync(_currentUserId)) .ReturnsAsync(MicroserviceResponse.Create(HttpStatusCode.OK, _defaultUser)); _serviceToServiceProjectApiMock .Setup(x => x.GetProjectByIdAsync(_defaultProjectId, null)) .ReturnsAsync(MicroserviceResponse.Create(HttpStatusCode.OK, _defaultProject)); _projectAccessApiMock .Setup(x => x.GetProjectMemberUserIdsAsync(_defaultProjectId, MemberRoleFilter.FullUser, _defaultProjectTenantHeaders)) .ReturnsAsync(MicroserviceResponse.Create(HttpStatusCode.OK, (new List <Guid>() { _currentUserId }).AsEnumerable())); _projectLobbyStateControllerMock .Setup(x => x.GetProjectLobbyStateAsync(_defaultProjectId)) .ReturnsAsync(defaultProjectLobbyState); _target = new ProjectGuestContextController(repositoryFactoryMock.Object, _guestSessionControllerMock.Object, _projectLobbyStateControllerMock.Object, _projectGuestContextServiceMock.Object, _projectAccessApiMock.Object, _serviceToServiceProjectApiMock.Object, _userApiMock.Object); }