Пример #1
0
        public async Task Cancellation_token_is_passed_down_to_low_level_operations()
        {
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object) as IInternalAsyncDataStore;

            dataStore.RequestExecutor
            .ExecuteAsync(Arg.Any <IHttpRequest>(), Arg.Any <CancellationToken>())
            .Returns(async callInfo =>
            {
                // Will pause for 1 second, unless CancellationToken has been passed through to us
                await Task.Delay(1000, callInfo.Arg <CancellationToken>());
                return(new DefaultHttpResponse(204, "No Content", new HttpHeaders(), null, null, transportError: false) as IHttpResponse);
            });

            var fakeAccount = dataStore.InstantiateWithHref <IAccount>("http://api.foo.bar/accounts/1");

            var alreadyCanceledSource = new CancellationTokenSource();

            alreadyCanceledSource.Cancel();

            var stopwatch = Stopwatch.StartNew();
            var deleted   = false;

            try
            {
                await dataStore.DeleteAsync(fakeAccount, alreadyCanceledSource.Token);
            }
            catch (TaskCanceledException)
            {
                deleted = true;
            }

            stopwatch.Stop();
            stopwatch.ElapsedMilliseconds.ShouldBeLessThan(1000);
            deleted.ShouldBeTrue();
        }
        public async Task Handle_error(string id_, string jwtResponse, Type expectedExceptionType, int expectedCode, int expectedStatus, string expectedMessage, string expectedDeveloperMessage)
        {
            var testApiKey = ClientApiKeys.Builder()
                             .SetId("2EV70AHRTYF0JOA7OEFO3SM29")
                             .SetSecret("goPUHQMkS4dlKwl5wtbNd91I+UrRehCsEDJrIrMruK8")
                             .Build();
            var fakeRequestExecutor = Substitute.For <IRequestExecutor>();

            fakeRequestExecutor.ApiKey.Returns(testApiKey);

            this.dataStore = TestDataStore.Create(fakeRequestExecutor, Caches.NewInMemoryCacheProvider().Build());

            var request = new DefaultHttpRequest(HttpMethod.Get, new CanonicalUri($"https://foo.bar?{IdSiteClaims.JwtResponse}={jwtResponse}"));

            IIdSiteAsyncCallbackHandler callbackHandler = new DefaultIdSiteAsyncCallbackHandler(this.dataStore, request);

            try
            {
                var accountResult = await callbackHandler.GetAccountResultAsync(CancellationToken.None);

                throw new Exception("Should not reach here. Proper exception was not thrown.");
            }
            catch (IdSiteRuntimeException e) when(expectedExceptionType.IsAssignableFrom(e.GetType()))
            {
                e.Code.ShouldBe(expectedCode);
                e.HttpStatus.ShouldBe(expectedStatus);
                e.Message.ShouldBe(expectedMessage);
                e.DeveloperMessage.ShouldBe(expectedDeveloperMessage);
            }
            catch (Exception e) when(expectedExceptionType.IsAssignableFrom(e.GetType()))
            {
                e.Message.ShouldStartWith(expectedMessage);
            }
        }
Пример #3
0
        public async Task Single_item_data_is_deserialized_properly()
        {
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object);

            var account = await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None);

            // Verify against data from FakeJson.Account
            account.CreatedAt.ShouldBe(Iso8601.Parse("2015-07-21T23:50:49.078Z"));
            account.Email.ShouldBe("*****@*****.**");
            account.FullName.ShouldBe("Han Solo");
            account.GivenName.ShouldBe("Han");
            account.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount");
            account.MiddleName.ShouldBeNull();
            account.ModifiedAt.ShouldBe(Iso8601.Parse("2015-07-21T23:50:49.078Z"));
            account.Status.ShouldBe(AccountStatus.Enabled);
            account.Surname.ShouldBe("Solo");
            account.Username.ShouldBe("*****@*****.**");

            (account as DefaultAccount).AccessTokens.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/accessTokens");
            (account as DefaultAccount).ApiKeys.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/apiKeys");
            (account as DefaultAccount).Applications.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/applications");
            (account as DefaultAccount).CustomData.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/customData");
            (account as DefaultAccount).Directory.Href.ShouldBe("https://api.stormpath.com/v1/directories/foobarDirectory");
            (account as DefaultAccount).EmailVerificationToken.Href.ShouldBeNull();
            (account as DefaultAccount).GroupMemberships.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/groupMemberships");
            (account as DefaultAccount).Groups.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/groups");
            (account as DefaultAccount).ProviderData.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/providerData");
            (account as DefaultAccount).RefreshTokens.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount/refreshTokens");
            (account as DefaultAccount).Tenant.Href.ShouldBe("https://api.stormpath.com/v1/tenants/foobarTenant");
        }
Пример #4
0
        public async Task Saving_resource_posts_changed_values_only()
        {
            string savedHref = null;
            string savedJson = null;

            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object);

            dataStore.RequestExecutor
            .When(x => x.ExecuteAsync(Arg.Any <IHttpRequest>(), Arg.Any <CancellationToken>()))
            .Do(call =>
            {
                savedHref = call.Arg <IHttpRequest>().CanonicalUri.ToString();
                savedJson = call.Arg <IHttpRequest>().Body;
            });

            var account = await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None);

            account.Href.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount");

            account.SetMiddleName("Test");
            account.SetUsername("newusername");

            await account.SaveAsync();

            savedHref.ShouldBe("https://api.stormpath.com/v1/accounts/foobarAccount");

            var savedMap = Newtonsoft.Json.JsonConvert.DeserializeObject <Dictionary <string, string> >(savedJson);

            savedMap.Count.ShouldBe(2);
            savedMap["middleName"].ShouldBe("Test");
            savedMap["username"].ShouldBe("newusername");
        }
        public async Task Deleting_custom_data_with_proxy_updates_cache()
        {
            var cacheProvider = Caches.NewInMemoryCacheProvider().Build();

            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            // GET returns expanded request
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.AccountWithExpandedCustomData, "application/json", transportError: false) as IHttpResponse));

            // Save is not an expanded request
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(201, "Created", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false) as IHttpResponse));

            var account = await this.dataStore.GetResourceAsync <IAccount>("/accounts/foobarAccount?expand=customData");

            account.CustomData.Remove("isAdmin");
            await account.SaveAsync();

            var customData = await account.GetCustomDataAsync();

            customData["isAdmin"].ShouldBe(null);

            await this.dataStore.RequestExecutor.Received(1).ExecuteAsync(
                Arg.Is <IHttpRequest>(x => x.Method == HttpMethod.Get),
                Arg.Any <CancellationToken>());
        }
        public async Task Embedded_custom_data_is_cleared_for_all_instances_after_save()
        {
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object);

            var account = await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None);

            var account2 = await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None);

            account.CustomData.Put("foo", 123);

            await account.SaveAsync();

            var expectedBody = @"{""customData"":{""foo"":123}}";
            var body         = dataStore.RequestExecutor
                               .ReceivedCalls()
                               .Last()
                               .GetArguments()
                               .OfType <IHttpRequest>()
                               .First()
                               .Body;

            body.ShouldBe(expectedBody);

            dataStore.RequestExecutor.ClearReceivedCalls();
            await account2.SaveAsync();

            // Empty save, should not POST anything
            await dataStore.RequestExecutor.DidNotReceive().ExecuteAsync(
                Arg.Is <IHttpRequest>(req =>
                                      req.Method == HttpMethod.Post),
                Arg.Any <CancellationToken>());
        }
        public async Task Does_not_cache_email_verification_tokens()
        {
            var cacheProvider   = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            var emailVerificationTokenResponse = @"
{
    ""href"": ""https://api.stormpath.com/v1/accounts/foobarAccount""
}
";

            // POST returns email verification token response
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), emailVerificationTokenResponse, "application/json", transportError: false) as IHttpResponse));

            var href = $"/accounts/emailVerificationTokens/fooToken";

            await(this.dataStore as IInternalAsyncDataStore).CreateAsync <IResource, IEmailVerificationToken>(href, null, CancellationToken.None);
            await(this.dataStore as IInternalAsyncDataStore).CreateAsync <IResource, IEmailVerificationToken>(href, null, CancellationToken.None);

            // Not cached
            await this.dataStore.RequestExecutor.Received(2).ExecuteAsync(
                Arg.Any <IHttpRequest>(),
                Arg.Any <CancellationToken>());
        }
Пример #8
0
        public void Does_not_cache_password_reset_tokens()
        {
            var cacheProvider   = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            var passwordResetTokenResponse = @"
{
    ""href"": ""https://api.stormpath.com/v1/applications/foo/passwordResetTokens/bar"",
    ""email"": ""*****@*****.**"",
    ""account"": {
        ""href"": ""https://api.stormpath.com/v1/accounts/cJoiwcorTTmkDDBsf02bAb""
    }
}
";

            // POST returns token response
            requestExecutor
            .Execute(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post))
            .Returns(new DefaultHttpResponse(200, "OK", new HttpHeaders(), passwordResetTokenResponse, "application/json", transportError: false));

            // GET also returns token response
            requestExecutor
            .Execute(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get))
            .Returns(new DefaultHttpResponse(200, "OK", new HttpHeaders(), passwordResetTokenResponse, "application/json", transportError: false));

            this.dataStore.GetResource <IPasswordResetToken>("https://api.stormpath.com/v1/applications/foo/passwordResetTokens/bar");
            this.dataStore.GetResource <IPasswordResetToken>("https://api.stormpath.com/v1/applications/foo/passwordResetTokens/bar");

            // Not cached
            this.dataStore.RequestExecutor.Received(2).Execute(
                Arg.Any <IHttpRequest>());
        }
        public DefaultResourceFactory_tests()
        {
            var dataStore   = TestDataStore.Create();
            var identityMap = new MemoryCacheIdentityMap <ResourceData>(TimeSpan.FromSeconds(10), Substitute.For <ILogger>()); // arbitrary expiration time

            this.factory = new DefaultResourceFactory(dataStore, identityMap);
        }
Пример #10
0
        public async Task When_saving_returns_empty_response_without_status_202_throws_error()
        {
            // Expected behavior: Saving should always return the updated data unless we get back HTTP 202 (Accepted for Processing).
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object) as IInternalAsyncDataStore;

            dataStore.RequestExecutor
            .ExecuteAsync(Arg.Any <IHttpRequest>(), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult <IHttpResponse>(new DefaultHttpResponse(200, "OK", null, null, null, transportError: false)));

            var account = dataStore.Instantiate <IAccount>();

            account.SetMiddleName("Test");
            account.SetUsername("newusername");

            bool erroredAsExpected = false;

            try
            {
                await dataStore.CreateAsync("http://api.foo.bar/accounts", account, CancellationToken.None);
            }
            catch (ResourceException rex)
            {
                rex.DeveloperMessage.ShouldBe("Unable to obtain resource data from the API server.");
                erroredAsExpected = true;
            }

            erroredAsExpected.ShouldBeTrue();
        }
        public async Task Does_not_cache_login_attempts()
        {
            var cacheProvider   = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            var authResponse = @"
{
  ""account"": {
    ""href"" : ""https://api.stormpath.com/v1/accounts/5BedLIvyfLjdKKEEXAMPLE""
  }
}";

            // POST returns auth response
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), authResponse, "application/json", transportError: false) as IHttpResponse));

            var request       = new UsernamePasswordRequest("foo", "bar", null, null) as IAuthenticationRequest;
            var authenticator = new BasicAuthenticator(this.dataStore);

            var result1 = await authenticator.AuthenticateAsync("/loginAttempts", request, null, CancellationToken.None);

            var result2 = await authenticator.AuthenticateAsync("/loginAttempts", request, null, CancellationToken.None);

            // Not cached
            await this.dataStore.RequestExecutor.Received(2).ExecuteAsync(
                Arg.Any <IHttpRequest>(),
                Arg.Any <CancellationToken>());
        }
        public async Task Updating_resource_updates_cache()
        {
            var cacheProvider   = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            // GET returns original
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false) as IHttpResponse));

            // Save returns update data
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(201, "Created", new HttpHeaders(), FakeJson.Account.Replace("*****@*****.**", "*****@*****.**"), "application/json", transportError: false) as IHttpResponse));

            var account1 = await this.dataStore.GetResourceAsync <IAccount>("/accounts/foobarAccount");

            account1.Email.ShouldBe("*****@*****.**");

            account1.SetEmail("*****@*****.**");
            await account1.SaveAsync();

            account1.Email.ShouldBe("*****@*****.**");

            var account2 = await this.dataStore.GetResourceAsync <IAccount>("/accounts/foobarAccount");

            account2.Email.ShouldBe("*****@*****.**");

            // Only one GET; second is intercepted by the cache (but the updated data is returned!) #magic
            await this.dataStore.RequestExecutor.Received(1).ExecuteAsync(
                Arg.Is <IHttpRequest>(x => x.Method == HttpMethod.Get),
                Arg.Any <CancellationToken>());
        }
Пример #13
0
        public void Updating_custom_data_with_proxy_updates_cache()
        {
            var cacheProvider   = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            // GET returns expanded request
            requestExecutor
            .Execute(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get))
            .Returns(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.AccountWithExpandedCustomData, "application/json", transportError: false));

            // Save is not an expanded request
            requestExecutor
            .Execute(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post))
            .Returns(new DefaultHttpResponse(201, "Created", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false));

            var account = this.dataStore.GetResource <IAccount>("/accounts/foobarAccount?expand=customData");

            account.CustomData.Put("isAdmin", true);
            account.CustomData.Put("writeAccess", "yes");
            account.Save();

            var customData = account.GetCustomData();

            customData["isAdmin"].ShouldBe(true);
            customData["writeAccess"].ShouldBe("yes");

            this.dataStore.RequestExecutor.Received(1).Execute(
                Arg.Is <IHttpRequest>(x => x.Method == HttpMethod.Get));
        }
Пример #14
0
        public void Instantiated_resources_contain_reference_to_client()
        {
            var fakeClient = Substitute.For <IClient>();
            var dataStore  = TestDataStore.Create(client: fakeClient);

            var account = dataStore.Instantiate <IAccount>();

            account.Client.ShouldBe(fakeClient);
        }
        public void GetValue_returns_token_value()
        {
            var dataStore = TestDataStore.Create();

            var href = "https://api.foobar.com/v1/applications/WpM9nyZ2TbaEzfbRvLk9KA/passwordResetTokens/my-token-value-here";

            var passwordResetToken = dataStore.InstantiateWithHref <IPasswordResetToken>(href);

            passwordResetToken.GetValue().ShouldBe("my-token-value-here");
        }
Пример #16
0
        public async Task Default_headers_are_applied_to_all_requests()
        {
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object);

            var account = await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None);

            // Verify the default headers
            await dataStore.RequestExecutor.Received().ExecuteAsync(
                Arg.Is <IHttpRequest>(request =>
                                      request.Headers.Accept == "application/json"),
                Arg.Any <CancellationToken>());
        }
        private static IInternalDataStore GetFakeDataStore()
        {
            var fakeApiKey = ClientApiKeys.Builder()
                             .SetId("fake_api_key")
                             .SetSecret("fake_secret")
                             .Build();

            var stubClient = Clients.Builder()
                             .SetApiKey(fakeApiKey)
                             .Build();

            var fakeDataStore = TestDataStore.Create(
                requestExecutor: new StubRequestExecutor(FakeJson.Application, fakeApiKey).Object,
                client: stubClient);

            return(fakeDataStore);
        }
Пример #18
0
        public async Task Trace_log_is_sent_to_logger()
        {
            var fakeLog    = new List <LogEntry>();
            var stubLogger = Substitute.For <ILogger>();

            stubLogger.When(x => x.Log(Arg.Any <LogEntry>())).Do(call =>
            {
                fakeLog.Add(call.Arg <LogEntry>());
            });

            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object, logger: stubLogger);

            var account = await dataStore.GetResourceAsync <IAccount>("account", CancellationToken.None);

            await account.DeleteAsync();

            fakeLog.Count.ShouldBeGreaterThanOrEqualTo(2);
        }
        public async Task When_getting_account()
        {
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object);

            var accountResult = dataStore.InstantiateWithData <IAccountResult>(
                new Dictionary <string, object>()
            {
                ["account"] = new LinkProperty("https://foo.bar/account1")
            });

            var account = await accountResult.GetAccountAsync();

            account.FullName.ShouldBe("Han Solo");

            await dataStore.RequestExecutor.Received().ExecuteAsync(
                Arg.Is <IHttpRequest>(x => x.CanonicalUri.ToString() == "https://foo.bar/account1"),
                Arg.Any <CancellationToken>());
        }
        public async Task When_getting_existing_provider_based_account()
        {
            // 200 OK indicates the account is not new
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object) as IInternalAsyncDataStore;

            dataStore.RequestExecutor
            .ExecuteAsync(Arg.Any <IHttpRequest>(), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult <IHttpResponse>(new DefaultHttpResponse(200, "OK", null, FakeJson.Account, "application/json", transportError: false)));

            var providerAccountResult = await dataStore.GetResourceAsync <IProviderAccountResult>("/providerAccount", CancellationToken.None);

            providerAccountResult.IsNewAccount.ShouldBeFalse();
            var account = providerAccountResult.Account;

            // Verify against data from FakeJson.Account
            account.Email.ShouldBe("*****@*****.**");
            account.FullName.ShouldBe("Han Solo");
        }
        public async Task Embedded_custom_data_is_cleared_after_reload()
        {
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object);

            var account = await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None);

            account.CustomData.Put("foo", 123);

            await dataStore.GetResourceAsync <IAccount>("/account", CancellationToken.None); // reload

            await account.SaveAsync();

            // Empty save, should not POST anything
            await dataStore.RequestExecutor.DidNotReceive().ExecuteAsync(
                Arg.Is <IHttpRequest>(req =>
                                      req.Method == HttpMethod.Post),
                Arg.Any <CancellationToken>());
        }
        public async Task Email_verification_result_removes_associated_account_from_cache()
        {
            var cacheProvider   = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            var emailVerificationTokenResponse = @"
{
    ""href"": ""https://api.stormpath.com/v1/accounts/foobarAccount""
}
";

            // POST returns email verification token response
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), emailVerificationTokenResponse, "application/json", transportError: false) as IHttpResponse));

            // GET returns account as unverified first,
            // then second GET returns account as verified
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any <CancellationToken>())
            .Returns(
                Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.Account.Replace(@"""status"": ""ENABLED""", @"""status"": ""UNVERIFIED"""), "application/json", transportError: false) as IHttpResponse),
                Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false) as IHttpResponse));

            var account = await this.dataStore.GetResourceAsync <IAccount>("/accounts/foobarAccount");

            account.Status.ShouldBe(AccountStatus.Unverified);

            var href          = $"/accounts/emailVerificationTokens/fooToken";
            var tokenResponse = await(this.dataStore as IInternalAsyncDataStore).CreateAsync <IResource, IEmailVerificationToken>(href, null, CancellationToken.None);

            await this.dataStore.GetResourceAsync <IAccount>(tokenResponse.Href);

            account.Status.ShouldBe(AccountStatus.Enabled);

            // Second GET should *not* hit cache
            await this.dataStore.RequestExecutor.Received(2).ExecuteAsync(
                Arg.Is <IHttpRequest>(x => x.Method == HttpMethod.Get),
                Arg.Any <CancellationToken>());
        }
        public async Task When_getting_account_and_no_account_present_throws()
        {
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object);

            var accountResult = dataStore.InstantiateWithData <IAccountResult>(
                new Dictionary <string, object>()
            {
                ["state"] = "foobar"
            });

            // TODO mono bug - should be ApplicationException
            await Should.ThrowAsync <Exception>(async() =>
            {
                var account = await accountResult.GetAccountAsync();
            });

            await dataStore.RequestExecutor.DidNotReceive().ExecuteAsync(
                Arg.Any <IHttpRequest>(),
                Arg.Any <CancellationToken>());
        }
        public async Task Only_diff_is_sent_for_updates()
        {
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.CustomData).Object);

            var customData = await dataStore.GetResourceAsync <ICustomData>("/customData", CancellationToken.None);

            customData.Count().ShouldBe(5);

            customData.Put("newprop", "foo");
            await customData.SaveAsync();

            var expectedBody = @"{""newprop"":""foo""}";

            // Sent the update as a diff
            await dataStore.RequestExecutor.Received().ExecuteAsync(
                Arg.Is <IHttpRequest>(request =>
                                      request.Method == HttpMethod.Post &&
                                      request.Body == expectedBody),
                Arg.Any <CancellationToken>());
        }
        public void Encodes_password_grant_attempt()
        {
            var dataStore = TestDataStore.Create();

            var createGrantAttempt = dataStore.Instantiate <IPasswordGrantAuthenticationAttempt>();

            createGrantAttempt.SetLogin("*****@*****.**");
            createGrantAttempt.SetPassword("Secret1");
            createGrantAttempt.SetAccountStore("https://api.stormpath.com/v1/directories/1bcd23ec1d0a8wa6");

            var properties = (createGrantAttempt as AbstractResource).GetResourceData().GetUpdatedProperties().ToDictionary();
            var result     = new FormUrlEncoder(properties)
                             .ToString()
                             .Split('&');

            result.ShouldContain("grant_type=password");
            result.ShouldContain("username=tom%40stormpath.com");
            result.ShouldContain("password=Secret1");
            result.ShouldContain("accountStore=https%3A%2F%2Fapi.stormpath.com%2Fv1%2Fdirectories%2F1bcd23ec1d0a8wa6");
        }
Пример #26
0
        public async Task When_saving_returns_empty_response_with_status_202()
        {
            // Expected behavior: Saving should always return the updated data unless we get back HTTP 202 (Accepted for Processing).
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object) as IInternalAsyncDataStore;

            dataStore.RequestExecutor
            .ExecuteAsync(Arg.Any <IHttpRequest>(), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult <IHttpResponse>(new DefaultHttpResponse(202, "Accepted", null, null, null, transportError: false)));

            var account = dataStore.Instantiate <IAccount>();

            account.SetMiddleName("Test");
            account.SetUsername("newusername");

            var result = await dataStore.CreateAsync("http://api.foo.bar/accounts", account, CancellationToken.None);

            bool isEmpty = (result as AbstractResource).GetPropertyNames().Single() == "href";

            isEmpty.ShouldBeTrue();

            result.Href.ShouldBeNullOrEmpty();
        }
Пример #27
0
        public async Task Collection_resource_data_is_deserialized_properly()
        {
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.AccountList).Object);

            IAsyncQueryable <IAccount> accounts = new CollectionResourceQueryable <IAccount>("/accounts", dataStore);
            await accounts.MoveNextAsync();

            // Verify against data from FakeJson.AccountList
            (accounts as CollectionResourceQueryable <IAccount>).Size.ShouldBe(6);
            (accounts as CollectionResourceQueryable <IAccount>).Offset.ShouldBe(0);
            (accounts as CollectionResourceQueryable <IAccount>).Limit.ShouldBe(25);
            accounts.CurrentPage.Count().ShouldBe(6);

            var account = accounts.CurrentPage.First();

            account.CreatedAt.ShouldBe(Iso8601.Parse("2015-07-21T23:50:49.078Z"));
            account.Email.ShouldBe("*****@*****.**");
            account.FullName.ShouldBe("Han Solo");
            account.GivenName.ShouldBe("Han");
            account.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1");
            account.MiddleName.ShouldBeNull();
            account.ModifiedAt.ShouldBe(Iso8601.Parse("2015-07-21T23:50:49.078Z"));
            account.Status.ShouldBe(AccountStatus.Enabled);
            account.Surname.ShouldBe("Solo");
            account.Username.ShouldBe("*****@*****.**");

            (account as DefaultAccount).AccessTokens.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/accessTokens");
            (account as DefaultAccount).ApiKeys.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/apiKeys");
            (account as DefaultAccount).Applications.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/applications");
            (account as DefaultAccount).CustomData.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/customData");
            (account as DefaultAccount).Directory.Href.ShouldBe("https://api.stormpath.com/v1/directories/directory1");
            (account as DefaultAccount).EmailVerificationToken.Href.ShouldBeNull();
            (account as DefaultAccount).GroupMemberships.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/groupMemberships");
            (account as DefaultAccount).Groups.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/groups");
            (account as DefaultAccount).ProviderData.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/providerData");
            (account as DefaultAccount).RefreshTokens.Href.ShouldBe("https://api.stormpath.com/v1/accounts/account1/refreshTokens");
            (account as DefaultAccount).Tenant.Href.ShouldBe("https://api.stormpath.com/v1/tenants/foobarTenant");
        }
        public async Task Deletes_are_performed_with_updates()
        {
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.CustomData).Object);

            var customData = await dataStore.GetResourceAsync <ICustomData>("/customData", CancellationToken.None);

            customData.Put("testingIsUseful", true);
            customData.Remove("membershipType");
            await customData.SaveAsync();

            // Delete
            await dataStore.RequestExecutor.Received().ExecuteAsync(
                Arg.Is <IHttpRequest>(request =>
                                      request.Method == HttpMethod.Delete &&
                                      request.CanonicalUri.ToString() == "https://api.stormpath.com/v1/accounts/foobarAccount/customData/membershipType"),
                Arg.Any <CancellationToken>());

            // Post
            await dataStore.RequestExecutor.Received().ExecuteAsync(
                Arg.Is <IHttpRequest>(request =>
                                      request.Method == HttpMethod.Post &&
                                      request.Body == @"{""testingIsUseful"":true}"),
                Arg.Any <CancellationToken>());
        }
        public async Task Simultaneous_delete_and_update_only_performs_update()
        {
            var dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.CustomData).Object);

            var customData = await dataStore.GetResourceAsync <ICustomData>("/customData", CancellationToken.None);

            customData.Remove("membershipType");
            customData.Put("membershipType", "unknown");
            await customData.SaveAsync();

            // Delete
            await dataStore.RequestExecutor.DidNotReceive().ExecuteAsync(
                Arg.Is <IHttpRequest>(request =>
                                      request.Method == HttpMethod.Delete &&
                                      request.CanonicalUri.ToString() == "https://api.stormpath.com/v1/accounts/foobarAccount/customData/membershipType"),
                Arg.Any <CancellationToken>());

            // Update
            await dataStore.RequestExecutor.Received().ExecuteAsync(
                Arg.Is <IHttpRequest>(request =>
                                      request.Method == HttpMethod.Post &&
                                      request.Body == @"{""membershipType"":""unknown""}"),
                Arg.Any <CancellationToken>());
        }
        private void BuildDataStore(string resourceResponse, ICacheProvider cacheProviderUnderTest)
        {
            var fakeRequestExecutor = new StubRequestExecutor(resourceResponse);

            this.dataStore = TestDataStore.Create(fakeRequestExecutor.Object, cacheProviderUnderTest);
        }