Example #1
0
        public async void ShouldListActionstepParticipants()
        {
            using (var authDelegatingHandler = new AuthDelegatingHandler()
            {
                InnerHandler = _handler
            })
                using (var httpClient = new HttpClient(authDelegatingHandler))
                    using (var memoryCache = new MemoryCache(new MemoryCacheOptions()))
                    {
                        var fakeClock           = new FakeClock(Instant.FromUtc(2019, 05, 07, 2, 3));
                        var testTokenRepository = new TestTokenSetRepository();
                        var testTokenSet        = GetTestTokenSet();
                        await testTokenRepository.AddOrUpdateTokenSet(testTokenSet);

                        var options           = new ActionstepServiceConfigurationOptions("clientId", "clientSecret");
                        var actionstepService = new ActionstepService(new NullLogger <ActionstepService>(), httpClient, options, testTokenRepository, fakeClock, memoryCache);

                        var request = new ListParticipantsRequest
                        {
                            TokenSetQuery = new TokenSetQuery(testTokenSet.UserId, testTokenSet.OrgKey)
                        };

                        var response = await actionstepService.Handle <ListParticipantsResponse>(request);

                        var admin = response.Participants.SingleOrDefault(p => p.Id == 1);

                        Assert.NotNull(admin);
                        var expectedBirthTimestamp = new LocalDate(2000, 1, 1);
                        var expectedDeathTimestamp = new LocalDate(2001, 1, 1);
                        Assert.Equal(expectedBirthTimestamp, admin.BirthTimestamp);
                        Assert.Equal(expectedDeathTimestamp, admin.DeathTimestamp);
                    }
        }
Example #2
0
        public async Task ShouldGetActionWithMultipleMatterIds()
        {
            using (var authDelegatingHandler = new AuthDelegatingHandler()
            {
                InnerHandler = _handler
            })
                using (var httpClient = new HttpClient(authDelegatingHandler))
                    using (var memoryCache = new MemoryCache(new MemoryCacheOptions()))
                    {
                        var fakeClock           = new FakeClock(Instant.FromUtc(2019, 05, 07, 2, 3));
                        var testTokenRepository = new TestTokenSetRepository();
                        var testTokenSet        = GetTestTokenSet();
                        await testTokenRepository.AddOrUpdateTokenSet(testTokenSet);

                        var options            = new ActionstepServiceConfigurationOptions("clientId", "clientSecret");
                        var actionstepService  = new ActionstepService(new NullLogger <ActionstepService>(), httpClient, options, testTokenRepository, fakeClock, memoryCache);
                        var listActionsRequest = new ListActionsRequest();
                        listActionsRequest.ActionstepIds.AddRange(new[] { 1, 7 });
                        listActionsRequest.TokenSetQuery = new TokenSetQuery(testTokenSet.UserId, testTokenSet.OrgKey);

                        var response = await actionstepService.Handle <ListActionsResponse>(listActionsRequest);

                        Assert.Equal(2, response.Actions.Count);
                        Assert.True(response.Actions.Exists(a => a.Id == 1));
                        Assert.True(response.Actions.Exists(a => a.Id == 7));
                    }
        }
Example #3
0
        public async void ShouldGetDataCollectionValues()
        {
            using (var authDelegatingHandler = new AuthDelegatingHandler()
            {
                InnerHandler = _handler
            })
                using (var httpClient = new HttpClient(authDelegatingHandler))
                    using (var memoryCache = new MemoryCache(new MemoryCacheOptions()))
                    {
                        var fakeClock           = new FakeClock(Instant.FromUtc(2019, 05, 07, 2, 3));
                        var testTokenRepository = new TestTokenSetRepository();
                        var testTokenSet        = GetTestTokenSet();
                        await testTokenRepository.AddOrUpdateTokenSet(testTokenSet);

                        var options           = new ActionstepServiceConfigurationOptions("clientId", "clientSecret");
                        var actionstepService = new ActionstepService(new NullLogger <ActionstepService>(), httpClient, options, testTokenRepository, fakeClock, memoryCache);

                        var dataCollectionRecordValuesRequest = new ListDataCollectionRecordValuesRequest();
                        dataCollectionRecordValuesRequest.ActionstepId  = 7;
                        dataCollectionRecordValuesRequest.TokenSetQuery = new TokenSetQuery(testTokenSet.UserId, testTokenSet.OrgKey);
                        dataCollectionRecordValuesRequest.DataCollectionRecordNames.AddRange(new[] { "property", "convdet", "keydates" });
                        dataCollectionRecordValuesRequest.DataCollectionFieldNames.AddRange(new[] { "titleref", "lotno", "planno", "plantype", "smtdateonly", "smttime", "purprice" });

                        var response = await actionstepService.Handle <ListDataCollectionRecordValuesResponse>(dataCollectionRecordValuesRequest);

                        Assert.Equal(6, response.DataCollectionRecordValues.Count);
                        Assert.Equal("test-title-ref", response["property", "titleref"]);
                    }
        }
Example #4
0
        public async void ShouldGetActionWithMatterId()
        {
            using (var authDelegatingHandler = new AuthDelegatingHandler()
            {
                InnerHandler = _handler
            })
                using (var httpClient = new HttpClient(authDelegatingHandler))
                    using (var memoryCache = new MemoryCache(new MemoryCacheOptions()))
                    {
                        var fakeClock          = new FakeClock(Instant.FromUtc(2019, 05, 07, 2, 3));
                        var options            = new ActionstepServiceConfigurationOptions("clientId", "clientSecret");
                        var tokenSetRepository = new TestTokenSetRepository();
                        var testTokenSet       = GetTestTokenSet();
                        await tokenSetRepository.AddOrUpdateTokenSet(testTokenSet);

                        var actionstepService = new ActionstepService(new NullLogger <ActionstepService>(), httpClient, options, tokenSetRepository, fakeClock, memoryCache);
                        var response          = await actionstepService.Handle <GetActionResponse>(new GetActionRequest
                        {
                            ActionId      = 1,
                            TokenSetQuery = new TokenSetQuery(testTokenSet.UserId, testTokenSet.OrgKey)
                        });

                        Assert.Equal(1, response.Action.Id);
                        Assert.Null(response.Action.IsBillableOverride);
                        Assert.False(response.Action.IsDeleted);
                        Assert.True(response.Action.IsFavorite);
                    }
        }
Example #5
0
        public async Task ShouldRetryRefreshingInvalidToken()
        {
            using (var authDelegatingHandler = new AuthDelegatingHandler()
            {
                InnerHandler = _handler
            })
                using (var httpClient = new HttpClient(authDelegatingHandler))
                    using (var memoryCache = new MemoryCache(new MemoryCacheOptions()))
                    {
                        var tokenHandler        = new TestTokenSetRepository();
                        var fakeClock           = new FakeClock(Instant.FromUtc(2019, 05, 07, 2, 3));
                        var testTokenRepository = new TestTokenSetRepository();
                        var testTokenSet        = GetTestTokenSet(isInvalid: true);
                        await testTokenRepository.AddOrUpdateTokenSet(testTokenSet);

                        var options           = new ActionstepServiceConfigurationOptions("clientId", "clientSecret");
                        var actionstepService = new ActionstepService(new NullLogger <ActionstepService>(), httpClient, options, testTokenRepository, fakeClock, memoryCache);

                        var response = await actionstepService.Handle <GetActionResponse>(new GetActionRequest
                        {
                            ActionId      = 1,
                            TokenSetQuery = new TokenSetQuery(testTokenSet.UserId, testTokenSet.OrgKey)
                        });

                        // Should be called 3 times. First from this test method to arrange this test token, second from the handler to set the lock, and third time to unlock/update with refreshed data.
                        Assert.Equal(3, testTokenRepository.AddOrUpdateTokenSetCount);
                    }
        }
Example #6
0
        public void GetJwtPublicKeyThrowsOnHttpProblem()
        {
            var localHandler = A.Fake <MockHandler>(opt => opt.CallsBaseMethods());

            A.CallTo(() => localHandler.SendAsync(HttpMethod.Get, "https://cdn.actionstep.com/jwt-discovery-public.json"))
            .ReturnsLazily(() => new HttpResponseMessage(HttpStatusCode.BadRequest));

            using (var authDelegatingHandler = new AuthDelegatingHandler()
            {
                InnerHandler = localHandler
            })
                using (var httpClient = new HttpClient(authDelegatingHandler))
                    using (var memoryCache = new MemoryCache(new MemoryCacheOptions()))
                    {
                        var fakeClock          = new FakeClock(Instant.FromUtc(2019, 05, 07, 2, 3));
                        var options            = new ActionstepServiceConfigurationOptions("clientId", "clientSecret");
                        var tokenSetRepository = new TestTokenSetRepository();
                        IActionstepService actionstepService = new ActionstepService(new NullLogger <ActionstepService>(), httpClient, options, tokenSetRepository, fakeClock, memoryCache);

                        var ex = Assert.Throws <InvalidJwtDiscoveryResponseException>(() => { actionstepService.GetJwtPublicKeyData(); });

                        Assert.Equal("There was a problem retrieving the JWT Discovery public key data.", ex.Message);
                        Assert.IsType <HttpRequestException>(ex.InnerException);
                    }
        }
Example #7
0
        public void CanGetJwtPublicKeysUri()
        {
            using (var httpClient = new HttpClient())
                using (var memoryCache = new MemoryCache(new MemoryCacheOptions()))
                {
                    var options            = new ActionstepServiceConfigurationOptions("clientId", "clientSecret");
                    var tokenSetRepository = new TestTokenSetRepository();
                    var fakeClock          = new FakeClock(Instant.FromUtc(2019, 05, 07, 2, 3));
                    var actionstepService  = new ActionstepService(new NullLogger <ActionstepService>(), httpClient, options, tokenSetRepository, fakeClock, memoryCache);

                    Assert.Equal(new Uri("https://cdn.actionstep.com/jwt-discovery-public.json", UriKind.Absolute), actionstepService.JwtPublicKeysUri);
                }
        }
Example #8
0
        public async Task ShouldRefreshAllRefreshableTokens()
        {
            using (var authDelegatingHandler = new AuthDelegatingHandler()
            {
                InnerHandler = _handler
            })
                using (var httpClient = new HttpClient(authDelegatingHandler))
                    using (var memoryCache = new MemoryCache(new MemoryCacheOptions()))
                    {
                        var fakeClock = FakeClock.FromUtc(2019, 10, 10);
                        var now       = fakeClock.GetCurrentInstant();

                        var testTokenSetRepository = new TestTokenSetRepository();

                        //// Add test tokens

                        // Valid tokens (shouldn't be refreshed)
                        await testTokenSetRepository.AddOrUpdateTokenSet(new TokenSet("token0", "bearer0", 3600, new Uri("https://test-endpoint/api/"), "testOrgKey", "testRefreshToken", now, "0", "0"));

                        await testTokenSetRepository.AddOrUpdateTokenSet(new TokenSet("token1", "bearer1", 3600, new Uri("https://test-endpoint/api/"), "testOrgKey", "testRefreshToken", now, "1", "1"));

                        // Nearing expiry (should be refreshed)
                        await testTokenSetRepository.AddOrUpdateTokenSet(new TokenSet("token2", "bearer2", 3600, new Uri("https://test-endpoint/api/"), "testOrgKey", "testRefreshToken", now.Minus(Duration.FromDays(18)), "2", "2"));

                        // Expired (shouldn't be refreshed, as it will fail anyway)
                        await testTokenSetRepository.AddOrUpdateTokenSet(new TokenSet("token3", "bearer3", 3600, new Uri("https://test-endpoint/api/"), "testOrgKey", "testRefreshToken", now.Minus(Duration.FromDays(30)), "3", "3"));

                        var actionstepServiceConfigurationOptions = new ActionstepServiceConfigurationOptions("clientId", "clientSecret");
                        var actionstepService = new ActionstepService(new NullLogger <ActionstepService>(), httpClient, actionstepServiceConfigurationOptions, testTokenSetRepository, fakeClock, memoryCache);

                        var config = new ConfigurationBuilder();
                        config.AddInMemoryCollection(new Dictionary <string, string>()
                        {
                            { "WCACoreSettings:PEXASettings:Environment", "Test" }
                        });

                        var wcaCoreSettingsOptions = Options.Create(config.Build().Get <WCACoreSettings>());

                        var refreshTokens = new RefreshAllTokens(testTokenSetRepository, actionstepService, fakeClock);

                        await refreshTokens.Run(null, new NullLogger <RefreshAllTokens>());

                        Assert.Equal("token0", testTokenSetRepository.TokenSets.Single(t => t.Id == "0").AccessToken);
                        Assert.Equal("token1", testTokenSetRepository.TokenSets.Single(t => t.Id == "1").AccessToken);
                        Assert.Equal("updatedAccessToken", testTokenSetRepository.TokenSets.Single(t => t.Id == "2").AccessToken);
                        Assert.Equal("token3", testTokenSetRepository.TokenSets.Single(t => t.Id == "3").AccessToken);
                    }
        }
Example #9
0
        public async void ShouldRefreshActionstepToken()
        {
            using (var authDelegatingHandler = new AuthDelegatingHandler()
            {
                InnerHandler = _handler
            })
                using (var httpClient = new HttpClient(authDelegatingHandler))
                    using (var memoryCache = new MemoryCache(new MemoryCacheOptions()))
                    {
                        var tokenHandler        = new TestTokenSetRepository();
                        var fakeClock           = new FakeClock(Instant.FromUtc(2019, 05, 07, 2, 3));
                        var testTokenRepository = new TestTokenSetRepository();
                        var options             = new ActionstepServiceConfigurationOptions("clientId", "clientSecret");
                        var actionstepService   = new ActionstepService(new NullLogger <ActionstepService>(), httpClient, options, testTokenRepository, fakeClock, memoryCache);

                        // Expired token
                        var tokenSet = new TokenSet(
                            accessToken: "testAccessToken",
                            tokenType: "bearer",
                            expiresIn: 60 * 20,
                            apiEndpoint: new Uri("https://api.uri/api/"),
                            orgKey: "testOrgKey",
                            refreshToken: "testRefreshToken",
                            userId: "1",
                            id: "tokenId",
                            receivedAt: fakeClock.GetCurrentInstant().Minus(Duration.FromDays(365)));

                        var response = await actionstepService.RefreshAccessTokenIfExpired(tokenSet);

                        Assert.NotNull(response);
                        Assert.Equal("updatedAccessToken", response.AccessToken);
                        Assert.Equal(3600, response.ExpiresIn);
                        Assert.Equal("updatedRefreshToken", response.RefreshToken);
                        Assert.Equal("testOrg", response.OrgKey);
                        Assert.Equal(new Uri("https://test-endpoint/api/"), response.ApiEndpoint);
                        Assert.Equal("tokenId", response.Id);
                        Assert.Equal(2, testTokenRepository.AddOrUpdateTokenSetCount);
                    }
        }
Example #10
0
        public void GetJwtPublicKeyReturnsValue()
        {
            using (var authDelegatingHandler = new AuthDelegatingHandler()
            {
                InnerHandler = _handler
            })
                using (var httpClient = new HttpClient(authDelegatingHandler))
                    using (var memoryCache = new MemoryCache(new MemoryCacheOptions()))
                    {
                        var fakeClock          = new FakeClock(Instant.FromUtc(2019, 05, 07, 2, 3));
                        var options            = new ActionstepServiceConfigurationOptions("clientId", "clientSecret");
                        var tokenSetRepository = new TestTokenSetRepository();
                        IActionstepService actionstepService = new ActionstepService(new NullLogger <ActionstepService>(), httpClient, options, tokenSetRepository, fakeClock, memoryCache);

                        var receivedPublicKeyJObject = actionstepService.GetJwtPublicKeyData();
                        var receivedPublicKey        = receivedPublicKeyJObject.Value <string>(JwtPublicKeyIds.ProdPublicKey);

                        const string EXPECTED_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp2ikRwK8OpklNc3U9y2n\n3JE+B1sQftl8TbZs++PHiActfqHqVbdh2n8Pjaft2NDGB9BXOEO9I/F0J3jZJT+H\n2FdO8HoFPLfeMvcrRKvXa2UmSXRrZLA6YIf+wzgI0wgbb+lkEH3LUgHk0XxalnRE\nMmNUpAWtO0ZX2jh8tkp+3ymhzCtXHwYpiI1iJUDUje/kBXvKfdP+QcDgkshehY/w\nph5SEXS/a//r2TWRPbFHlzi96fL7ySZIjTWyQtZ1UwzjTqkA0gRYQLtXEQW5tLgJ\niiwivJ1UiGoGTfp4nj+ZU7OVYV5I/k+t4cv+s1jYAP/hmdW98932DavR9Mmlb80g\nXwIDAQAB\n-----END PUBLIC KEY-----";

                        Assert.Equal(EXPECTED_PUBLIC_KEY, receivedPublicKey);
                    }
        }
Example #11
0
        public async Task SecondTokenRefreshWaitsForFirst()
        {
            using (var authDelegatingHandler = new AuthDelegatingHandler()
            {
                InnerHandler = _handler
            })
                using (var httpClient = new HttpClient(authDelegatingHandler))
                    using (var memoryCache = new MemoryCache(new MemoryCacheOptions()))
                    {
                        var tokenHandler        = new TestTokenSetRepository();
                        var fakeClock           = new FakeClock(Instant.FromUtc(2019, 05, 07, 2, 3));
                        var testTokenRepository = new TestTokenSetRepository();
                        var options             = new ActionstepServiceConfigurationOptions("clientId", "clientSecret");
                        var actionstepService   = new ActionstepService(new NullLogger <ActionstepService>(), httpClient, options, testTokenRepository, fakeClock, memoryCache);

                        var now = fakeClock.GetCurrentInstant();

                        /// We're using the TokenType purely as a mechanism to talk to <see cref="TestTokenSetRepository"/>.
                        /// This allows us to delay one refresh while queueing another to ensure the locking/retry works correctly
                        /// with concurrent refresh requests.
                        var tokenTypeTest1 = "bearer-test1";
                        var tokenTypeTest2 = "bearer-test2";

                        // First, store a locked expired token
                        var tokenId   = "locking test token";
                        var tokenSet1 = new TokenSet(
                            "testAccessToken1",
                            tokenTypeTest1,
                            3600,
                            new Uri("https://api.uri/api/auto-increment/"),
                            "testOrgKey",
                            "testRefreshToken1",
                            now.Minus(Duration.FromMinutes(120)),
                            "testUser",
                            tokenId);

                        tokenSet1.LockForRefresh(now.Plus(Duration.FromMinutes(60)));
                        var storedTokenSet1 = await testTokenRepository.AddOrUpdateTokenSet(tokenSet1);

                        // Now we set up a second expired token with the same id.
                        var tokenSet2 = new TokenSet(
                            "testAccessToken2",
                            tokenTypeTest2,
                            3600,
                            new Uri("https://api.uri/api/auto-increment/"),
                            "testOrgKey",
                            "testRefreshToken2",
                            now.Minus(Duration.FromMinutes(120)),
                            "testUser",
                            tokenId);

                        // Try to refresh using the second token (which has the same tokenId). It should be blocked by the locked token1 from above.
                        var tokenSet2RefreshTask = actionstepService.RefreshAccessTokenIfExpired(tokenSet2, forceRefresh: false);

                        /// Delay to give the <see cref="RefreshAccessTokenIfExpired"/> a chance to
                        await Task.Delay(50);

                        // Now store a valid token of test type 1, this will unlock the token
                        tokenSet1 = new TokenSet(
                            "testAccessToken1",
                            tokenTypeTest1,
                            3600,
                            new Uri("https://api.uri/api/auto-increment/"),
                            "testOrgKey",
                            "testRefreshToken1",
                            now,
                            "testUser",
                            tokenId);

                        await testTokenRepository.AddOrUpdateTokenSet(tokenSet1);

                        tokenSet2RefreshTask.Wait();

                        // The token from the refresh should be the one we put in the repository.
                        Assert.Equal(tokenTypeTest1, tokenSet2RefreshTask.Result.TokenType);
                    }
        }
        public async Task ShouldCreatePEXAWorkspaceRequestFromActionstep()
        {
            var testUser = await _containerFixture.GetTestUser();

            await _containerFixture.ExecuteScopeAsync(async serviceProvider =>
            {
                using (var authDelegatingHandler = new AuthDelegatingHandler()
                {
                    InnerHandler = _handler
                })
                    using (var httpClient = new HttpClient(authDelegatingHandler))
                    {
                        var fakeClock = new FakeClock(new Instant());
                        var testTokenSetRepository = new TestTokenSetRepository();
                        await testTokenSetRepository.AddOrUpdateTokenSet(new TokenSet("accessToken", "bearer", 3600, new Uri("https://uri/api"), "testOrg", "refreshToken", fakeClock.GetCurrentInstant(), testUser.Id));

                        var options               = new ActionstepServiceConfigurationOptions("clientId", "clientSecret");
                        var actionstepService     = new ActionstepService(new NullLogger <ActionstepService>(), httpClient, options, testTokenSetRepository, fakeClock, new MemoryCache(new MemoryCacheOptions()));
                        var mapper                = serviceProvider.GetService <IMapper>();
                        var actionstepToWcaMapper = serviceProvider.GetService <IActionstepToWCAMapper>();
                        PrepareTestData(serviceProvider);

                        var handler = new PEXAWorkspaceCreationRequestFromActionstepQueryHandler(actionstepService, mapper, actionstepToWcaMapper);
                        var token   = new CancellationToken();

                        var query = new PEXAWorkspaceCreationRequestFromActionstepQuery
                        {
                            AuthenticatedUser = testUser,
                            MatterId          = 1,
                            ActionstepOrg     = "testOrg"
                        };

                        var pexaWorkspaceCreationResponse = await handler.Handle(query, token);

                        Assert.Equal("1", pexaWorkspaceCreationResponse.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.SubscriberReference);
                        Assert.Equal("Yes", pexaWorkspaceCreationResponse.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.FinancialSettlement);

                        var config = new ConfigurationBuilder();
                        config.AddInMemoryCollection(new Dictionary <string, string>()
                        {
                            { "WCACoreSettings:PEXASettings:Environment", "Test" }
                        });

                        var pexaService = new PEXAService(httpClient, config.Build());
                        var request     = new WorkspaceCreationRequestCommand(pexaWorkspaceCreationResponse.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest, "dummyToken");
                        var response    = await pexaService.Handle <WorkspaceCreationResponse>(request, CancellationToken.None);
                        Assert.Equal("PEXA190167645", response.WorkspaceId);
                        Assert.Equal("In Preparation", response.WorkspaceStatus);

                        var xmldiff     = new XmlDiff(XmlDiffOptions.IgnoreChildOrder | XmlDiffOptions.IgnoreNamespaces | XmlDiffOptions.IgnorePrefixes);
                        var expectedXml = EmbeddedResource.Read("ResponseData.create-workspace-result.xml");
                        var actualXml   = _handler.RequestContent;

                        var expectedReader = XElement.Parse(expectedXml).CreateReader();
                        var actualReader   = XElement.Parse(actualXml).CreateReader();

                        using (var diffStringWriter = new StringWriter())
                            using (var diffWriter = XmlWriter.Create(diffStringWriter))
                            {
                                var areXmlIdentical = xmldiff.Compare(expectedReader, actualReader, diffWriter);
                                diffWriter.Flush();

                                foreach (var diffLine in diffStringWriter.ToString().Split(diffStringWriter.NewLine))
                                {
                                    _output.WriteLine(diffLine);
                                }

                                Assert.True(areXmlIdentical);
                            }
                    }
            });
        }