public void GetUserSessionFromCookieReturnsSessionWhenCookieExists()
        {
            // Arrange
            var userSession = new DfcUserSession
            {
                SessionId    = "DummySessionId",
                Salt         = "DummySalt",
                CreatedDate  = DateTime.UtcNow,
                PartitionKey = "DummyPartitionKey",
            };
            var userSessionJson          = JsonConvert.SerializeObject(userSession);
            var httpContext              = A.Fake <HttpContext>();
            var localHttpContextAccessor = new HttpContextAccessor {
                HttpContext = httpContext
            };
            var cookies = new RequestCookieCollection(new Dictionary <string, string> {
                { SessionName, userSessionJson }
            });

            A.CallTo(() => localHttpContextAccessor.HttpContext.Request.Cookies).Returns(cookies);

            var localSessionClient = new SessionClient(sessionIdGenerator, partitionKeyGenerator, localHttpContextAccessor, config, logger);

            // Act
            var result = localSessionClient.GetUserSessionFromCookie();

            // Assert
            Assert.Equal(userSession.GetCookieSessionId, result.GetCookieSessionId);
        }
        public async Task TryFindSessionCodeUsesQueryDataWhenOnlyQueryStringAndCookieSourcesExist()
        {
            // Arrange
            const string expectedQueryStringValue = "qsValue";
            var          userSession = new DfcUserSession
            {
                SessionId    = "DummySessionId",
                Salt         = "DummySalt",
                CreatedDate  = DateTime.UtcNow,
                PartitionKey = "DummyPartitionKey",
            };
            var userSessionJson  = JsonConvert.SerializeObject(userSession);
            var httpContext      = A.Fake <HttpContext>();
            var dummyQueryString = new QueryString($"?{SessionName.TrimStart('.')}={expectedQueryStringValue}");
            var cookies          = new RequestCookieCollection(new Dictionary <string, string> {
                { SessionName, userSessionJson }
            });

            var localHttpContextAccessor = new HttpContextAccessor {
                HttpContext = httpContext
            };

            A.CallTo(() => localHttpContextAccessor.HttpContext.Request.Cookies).Returns(cookies);
            A.CallTo(() => localHttpContextAccessor.HttpContext.Request.QueryString).Returns(dummyQueryString);

            var localSessionClient = new SessionClient(sessionIdGenerator, partitionKeyGenerator, localHttpContextAccessor, config, logger);

            // Act
            var result = await localSessionClient.TryFindSessionCode().ConfigureAwait(false);

            // Assert
            Assert.Equal(expectedQueryStringValue, result);
        }
        public async Task <IActionResult> GetUserSession([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "assessment/session/{sessionId}")] HttpRequest request, string sessionId)
        {
            request.LogRequestHeaders(logService);

            var correlationId = Guid.Parse(correlationIdProvider.CorrelationId);

            logService.LogMessage($"CorrelationId: {correlationId} - Creating a new assessment", SeverityLevel.Information);

            var partitionKey        = sessionClient.GeneratePartitionKey(sessionId);
            var existingUserSession = await userSessionRepository.GetByIdAsync(sessionId, partitionKey).ConfigureAwait(false);

            if (existingUserSession is null)
            {
                logService.LogMessage($"Unable to find User Session with id {sessionId}.", SeverityLevel.Information);
                return(responseWithCorrelation.ResponseWithCorrelationId(HttpStatusCode.NoContent, correlationId));
            }

            var dfcUserSession = new DfcUserSession
            {
                SessionId    = existingUserSession.UserSessionId,
                CreatedDate  = existingUserSession.StartedDt,
                PartitionKey = existingUserSession.PartitionKey,
                Salt         = existingUserSession.Salt,
            };

            return(responseWithCorrelation.ResponseObjectWithCorrelationId(dfcUserSession, correlationId));
        }
예제 #4
0
            public void Init()
            {
                _cosmosSettings = Options.Create(new CosmosSettings()
                {
                    ApiUrl                 = "https://test-account-not-real.documents.azure.com:443/",
                    ApiKey                 = "VGhpcyBpcyBteSB0ZXN0",
                    DatabaseName           = "DatabaseName",
                    UserSessionsCollection = "UserSessions"
                });
                var dummySession = new DfcUserSession()
                {
                    SessionId = "partitionkey-sessionid"
                };

                _client        = Substitute.For <CosmosClient>();
                _cosmosService = Substitute.For <ICosmosService>();
                _sessionClient = Substitute.For <ISessionClient>();
                _sessionConfig = Options.Create(new SessionConfig()
                {
                    Salt            = "ThisIsASalt",
                    ApplicationName = "matchskills"
                });

                _sessionClient.NewSession().Returns(dummySession);
            }
            public void When_InitiateDysacWithErrors_ThrowException()
            {
                var userSession = new DfcUserSession();

                userSession.PartitionKey = "key";

                var restClient = Substitute.For <IRestClient>();

                var lastResponse = Substitute.For <RestClient.APIResponse>(new HttpResponseMessage()
                {
                    Content = new StringContent("something", Encoding.UTF8), StatusCode = HttpStatusCode.BadRequest
                });

                restClient.LastResponse.Returns(lastResponse);

                restClient.PostAsync <AssessmentShortResponse>(apiPath: "", content: null).ReturnsForAnyArgs(new AssessmentShortResponse()
                {
                    CreatedDate  = DateTime.Now,
                    SessionId    = "sesionId",
                    Salt         = "salt",
                    PartitionKey = "p-key"
                });

                IDysacSessionReader dysacService = new DysacService(_log, restClient, _dysacServiceSetings, _oldDysacServiceSetings, _sessionClient);

                Assert.ThrowsAsync <DysacException>(() => dysacService.InitiateDysac(userSession));
            }
            public async Task When_InitiateDysacOnlySessionWithNoErrors_ReturnOK()
            {
                var userSession = new DfcUserSession();

                userSession.PartitionKey = "key";

                var lastResponse = Substitute.For <RestClient.APIResponse>(new HttpResponseMessage()
                {
                    Content = new StringContent("something", Encoding.UTF8), StatusCode = HttpStatusCode.Created
                });

                _restClient.LastResponse.Returns(lastResponse);

                _restClient.PostAsync <AssessmentShortResponse>(Arg.Any <string>(), Arg.Any <HttpRequestMessage>())
                .ReturnsForAnyArgs(new AssessmentShortResponse
                {
                    CreatedDate  = DateTime.Now,
                    SessionId    = "sesionId",
                    Salt         = "salt",
                    PartitionKey = "p-key"
                }
                                   );

                IDysacSessionReader dysacService = new DysacService(_log, _restClient, _dysacServiceSetings, _oldDysacServiceSetings, _sessionClient);
                await dysacService.InitiateDysacOnly();
            }
예제 #7
0
 private void CreateCookie(DfcUserSession userSession)
 {
     httpContextAccessor.HttpContext.Response.Cookies.Append(SessionName, $"{HttpUtility.UrlEncode(JsonConvert.SerializeObject(userSession))}", new CookieOptions
     {
         Secure      = true,
         IsEssential = true,
         HttpOnly    = true,
         SameSite    = SameSiteMode.Strict,
     });
 }
예제 #8
0
        public void CreateCookie(string sessionIdAndPartionKey)
        {
            var sessionIdAndPartitionKeyDetails = GetSessionAndPartitionKey(sessionIdAndPartionKey);
            var dfcUserSession = new DfcUserSession()
            {
                Salt = "ncs", PartitionKey = sessionIdAndPartitionKeyDetails.Item1, SessionId = sessionIdAndPartitionKeyDetails.Item2
            };

            sessionServiceClient.CreateCookie(dfcUserSession, false);
        }
        public void CreateCookieThrowsExceptionWhenSessionNotValid()
        {
            // Arrange
            A.CallTo(() => sessionIdGenerator.ValidateSessionId(A <DfcUserSession> .Ignored)).Returns(false);
            var userSession = new DfcUserSession();

            // Act
            Assert.Throws <ArgumentException>(() => sessionClient.CreateCookie(userSession, true));

            // Assert
            A.CallTo(() => logger.Log(LogLevel.Warning, 0, A <FormattedLogValues> .Ignored, A <Exception> .Ignored, A <Func <object, Exception, string> > .Ignored)).MustHaveHappenedOnceExactly();
        }
        private async Task CreateUserSession(QuestionSet currentQuestionSetInfo, DfcUserSession dfcUserSession, string partitionKey = null)
        {
            var userSession = new UserSession
            {
                UserSessionId   = dfcUserSession.SessionId,
                Salt            = dfcUserSession.Salt,
                StartedDt       = dfcUserSession.CreatedDate,
                LanguageCode    = "en",
                PartitionKey    = !string.IsNullOrWhiteSpace(partitionKey) ? partitionKey : dfcUserSession.PartitionKey,
                AssessmentState = new AssessmentState(currentQuestionSetInfo.QuestionSetVersion, currentQuestionSetInfo.MaxQuestions),
                AssessmentType  = currentQuestionSetInfo.AssessmentType.ToLowerInvariant(),
            };

            await userSessionRepository.CreateUserSession(userSession).ConfigureAwait(false);
        }
        public bool ValidateSessionId(DfcUserSession userSession)
        {
            var splitSalt = userSession.Salt.Split('|');
            var hashids   = new Hashids(splitSalt[0], 4, Alphabet);

            if (!int.TryParse(splitSalt[1], out var currentCounter))
            {
                return(false);
            }

            var sessionId        = GenerateSessionId(userSession.CreatedDate, currentCounter);
            var encodedSessionId = hashids.EncodeLong(sessionId);

            return(encodedSessionId == userSession.SessionId);
        }
예제 #12
0
        public void ValidateSessionReturnsFalseWhenInvalidSession()
        {
            // Arrange
            var creationResult = sessionGenerator.CreateSession(DummySalt, currentDate);
            var session        = new DfcUserSession
            {
                Salt        = $"{DummySalt}|{creationResult.Counter}",
                CreatedDate = currentDate.AddDays(1),
                SessionId   = "SomeInvalidSessionId",
            };

            // Act
            var validateResult = sessionGenerator.ValidateSessionId(session);

            // Assert
            Assert.False(validateResult);
        }
예제 #13
0
        public void ValidateSessionReturnsTrueWhenValidSession()
        {
            // Arrange
            var creationResult = sessionGenerator.CreateSession(DummySalt, currentDate);
            var session        = new DfcUserSession
            {
                Salt        = $"{DummySalt}|{creationResult.Counter}",
                CreatedDate = currentDate,
                SessionId   = creationResult.EncodedSessionId,
            };

            // Act
            var validateResult = sessionGenerator.ValidateSessionId(session);

            // Assert
            Assert.True(validateResult);
        }
        public void ValidateUserSessionWhenCalledThenReturnsWhetherUserSessionIsValid(bool sessionIsValid)
        {
            // Arrange
            var dfcUserSession = new DfcUserSession
            {
                CreatedDate  = DateTime.UtcNow,
                PartitionKey = "partitionKey",
                Salt         = "salt",
                SessionId    = "sessionId",
            };

            A.CallTo(() => sessionIdGenerator.ValidateSessionId(dfcUserSession)).Returns(sessionIsValid);

            // Act
            var result = sessionClient.ValidateUserSession(dfcUserSession);

            // Assert
            Assert.Equal(sessionIsValid, result);
            A.CallTo(() => sessionIdGenerator.ValidateSessionId(dfcUserSession)).MustHaveHappenedOnceExactly();
        }
예제 #15
0
        public async Task InitiateDysac(DfcUserSession userSession)
        {
            Throw.IfNull(userSession, nameof(userSession));
            var serviceUrl = $"{_dysacSettings.Value.ApiUrl}assessment/skills";
            var request    = GetDysacRequestMessage();

            request.Content = new StringContent($"{{\"PartitionKey\":\"{userSession.PartitionKey}\"," +
                                                $"\"SessionId\":\"{userSession.SessionId}\"," +
                                                $"\"Salt\":\"{userSession.Salt}\"," +
                                                $"\"CreatedDate\":{JsonConvert.SerializeObject(userSession.CreatedDate)}}}",
                                                Encoding.UTF8, "application/json");


            await _restClient.PostAsync <AssessmentShortResponse>(serviceUrl, request);

            if (_restClient.LastResponse.StatusCode != HttpStatusCode.Created && _restClient.LastResponse.StatusCode != HttpStatusCode.AlreadyReported)
            {
                throw new DysacException("Invalid Dysac API Code " + _restClient.LastResponse.StatusCode ?? "");
            }
        }
예제 #16
0
 public void CreateCookie(DfcUserSession userSession, bool validateSessionId)
 {
     if (validateSessionId)
     {
         if (sessionIdGenerator.ValidateSessionId(userSession))
         {
             CreateCookie(userSession);
         }
         else
         {
             var message = $"SessionId not valid for session '{userSession?.SessionId}'";
             logger?.LogWarning(message);
             throw new ArgumentException(message, nameof(userSession));
         }
     }
     else
     {
         CreateCookie(userSession);
     }
 }
예제 #17
0
        public async Task TryFindSessionCodeReturnsCookieValue()
        {
            // Arrange
            var userSession = new DfcUserSession
            {
                SessionId    = "DummySessionId",
                Salt         = "DummySalt",
                PartitionKey = "DummyPartitionKey",
            };
            var userSessionJson = JsonConvert.SerializeObject(userSession);
            var cookies         = new RequestCookieCollection(new Dictionary <string, string> {
                { DefaultSessionName, HttpUtility.UrlEncode(userSessionJson) }
            });

            contextAccessor.HttpContext = new DefaultHttpContext();
            contextAccessor.HttpContext.Request.Cookies = cookies;

            var result = await sessionClient.TryFindSessionCode().ConfigureAwait(false);

            Assert.Equal(userSession.GetCookieSessionId, result);
        }
        public void CreateCookieAddsSetCookieHeaderWhenSessionIsValid()
        {
            // Arrange
            A.CallTo(() => sessionIdGenerator.ValidateSessionId(A <DfcUserSession> .Ignored)).Returns(true);
            var userSession = new DfcUserSession
            {
                SessionId    = "DummySessionId",
                Salt         = "DummySalt",
                CreatedDate  = DateTime.UtcNow,
                PartitionKey = "DummyPartitionKey",
            };

            // Act
            sessionClient.CreateCookie(userSession, true);
            var headers         = httpContextAccessor.HttpContext.Response.Headers;
            var setCookieHeader = headers["Set-Cookie"][0];

            // Assert
            Assert.True(headers.Count == 1);
            Assert.Contains(SessionName, setCookieHeader, StringComparison.OrdinalIgnoreCase);
        }
        public async Task ReturnsCreatedDfcUserSession()
        {
            // Arrange
            var dfcSession = new DfcUserSession
            {
                PartitionKey = "partitionKey",
                CreatedDate  = DateTime.UtcNow,
                SessionId    = "sessionId",
                Salt         = "ncs",
            };

            A.CallTo(() => sessionClient.NewSession()).Returns(dfcSession);

            var questionSet = new QuestionSet
            {
                QuestionSetVersion = "qsVersion",
                AssessmentType     = "short",
                MaxQuestions       = 5,
                PartitionKey       = "partitionKey",
                Description        = "short description",
                IsCurrent          = true,
                LastUpdated        = DateTimeOffset.UtcNow,
                QuestionSetKey     = "qsKey",
                Title   = "qstitle",
                Version = 1,
            };

            A.CallTo(() => questionSetRepository.GetCurrentQuestionSet(A <string> .Ignored)).Returns(questionSet);

            // Act
            var result = await functionApp.CreateNewShortAssessment(httpRequest).ConfigureAwait(false);

            var okObjectResult     = Assert.IsType <OkObjectResult>(result);
            var deserialisedResult = JsonConvert.DeserializeObject <DfcUserSession>(okObjectResult.Value.ToString());

            // Assert
            deserialisedResult.Should().BeEquivalentTo(dfcSession);
            A.CallTo(() => userSessionRepository.CreateUserSession(A <UserSession> .Ignored)).MustHaveHappenedOnceExactly();
        }
        public async Task ReturnsMappedDfcUserSessionWhenUserSessionExists()
        {
            // Arrange
            const string userSessionId   = "userSessionId";
            const string partitionKey    = "partitionKey";
            const string salt            = "salt";
            var          startedDateTime = DateTime.UtcNow;

            var userSession = new UserSession
            {
                UserSessionId = userSessionId,
                PartitionKey  = partitionKey,
                Salt          = salt,
                StartedDt     = startedDateTime,
            };

            var expectedDfcUserSession = new DfcUserSession
            {
                Salt         = salt,
                SessionId    = userSessionId,
                CreatedDate  = startedDateTime,
                PartitionKey = partitionKey,
            };

            A.CallTo(() => userSessionRepository.GetByIdAsync(A <string> .Ignored, A <string> .Ignored)).Returns(userSession);
            A.CallTo(() => sessionClient.GeneratePartitionKey(A <string> .Ignored)).Returns(partitionKey);

            // Act
            var result = await functionApp.GetUserSession(httpRequest, "DummySessionId").ConfigureAwait(false);

            // Assert
            var okObjectResult     = Assert.IsType <OkObjectResult>(result);
            var deserialisedResult = JsonConvert.DeserializeObject <DfcUserSession>(okObjectResult.Value.ToString());

            deserialisedResult.Should().BeEquivalentTo(expectedDfcUserSession);
        }
        public async Task <UserSession> Reload(string sessionId)
        {
            var partitionKey = _sessionClient.GeneratePartitionKey(sessionId);
            var result       = await _cosmosService.ReadItemAsync(sessionId, partitionKey, CosmosCollection.Session);

            if (!result.IsSuccessStatusCode)
            {
                return(null);
            }

            var userSession =
                JsonConvert.DeserializeObject <UserSession>(await result.Content.ReadAsStringAsync());
            var dfcUserSession = new DfcUserSession()
            {
                Salt         = userSession.Salt,
                PartitionKey = userSession.PartitionKey,
                SessionId    = userSession.UserSessionId,
                Origin       = Origin.MatchSkills,
                CreatedDate  = userSession.SessionCreatedDate
            };

            _sessionClient.CreateCookie(dfcUserSession, false);
            return(userSession);
        }
예제 #22
0
        private DysacServiceResponse  CreateDysacServiceResponse(AssessmentShortResponse response, Origin creationOrigin, HttpStatusCode statusCode)
        {
            var dysacServiceResponse = new DysacServiceResponse();

            if (response != null && !string.IsNullOrEmpty(response.SessionId))
            {
                dysacServiceResponse.ResponseCode = DysacReturnCode.Ok;
                var userSession = new DfcUserSession()
                {
                    CreatedDate  = DateTime.Now,
                    PartitionKey = response.PartitionKey,
                    Salt         = response.Salt,
                    SessionId    = response.SessionId,
                    Origin       = creationOrigin
                };
                _sessionClient.CreateCookie(userSession, false);
            }
            else
            {
                throw new DysacException("No session. Error Code " + statusCode);
            }

            return(dysacServiceResponse);
        }
예제 #23
0
 public bool ValidateUserSession(DfcUserSession dfcUserSession)
 {
     return(sessionIdGenerator.ValidateSessionId(dfcUserSession));
 }