From 8464f9f0a1fb66d58f3bc24de626252e80bcac15 Mon Sep 17 00:00:00 2001 From: Aditya Agarwal Date: Mon, 26 Aug 2024 19:33:13 +0200 Subject: [PATCH 1/3] add users batch --- src/IStreamClient.cs | 8 +++- src/IUsersBatch.cs | 13 ++++++ src/StreamClient.cs | 4 +- src/UsersBatch.cs | 64 +++++++++++++++++++++++++++ tests/UsersBatchTests.cs | 96 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 src/IUsersBatch.cs create mode 100644 src/UsersBatch.cs create mode 100644 tests/UsersBatchTests.cs diff --git a/src/IStreamClient.cs b/src/IStreamClient.cs index 3d7fc07..3cca910 100644 --- a/src/IStreamClient.cs +++ b/src/IStreamClient.cs @@ -20,6 +20,12 @@ public interface IStreamClient /// ICollections Collections { get; } + /// + /// Returns an instance that let's you interact with UsersBatch. + /// You can used the returned instance as a singleton in your application. + /// + IUsersBatch UsersBatch { get; } + /// /// Returns an instance that let's you interact with reactions. /// You can used the returned instance as a singleton in your application. @@ -77,4 +83,4 @@ public interface IStreamClient /// string CreateUserToken(string userId, IDictionary extraData = null); } -} +} \ No newline at end of file diff --git a/src/IUsersBatch.cs b/src/IUsersBatch.cs new file mode 100644 index 0000000..9e31f73 --- /dev/null +++ b/src/IUsersBatch.cs @@ -0,0 +1,13 @@ +using Stream.Models; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Stream +{ + public interface IUsersBatch + { + Task> UpsertUsersAsync(IEnumerable users, bool overrideExisting = false); + Task> GetUsersAsync(IEnumerable userIds); + Task> DeleteUsersAsync(IEnumerable userIds); + } +} \ No newline at end of file diff --git a/src/StreamClient.cs b/src/StreamClient.cs index e88a2f4..2f3f5ba 100644 --- a/src/StreamClient.cs +++ b/src/StreamClient.cs @@ -71,6 +71,7 @@ public StreamClient(string apiKey, string apiSecretOrToken, StreamClientOptions Batch = new BatchOperations(this); Collections = new Collections(this); + UsersBatch = new UsersBatch(this); Reactions = new Reactions(this); Users = new Users(this); Moderation = new Moderation(this); @@ -90,6 +91,7 @@ private StreamClient(string apiKey, IToken streamClientToken, RestClient client, public IBatchOperations Batch { get; } public ICollections Collections { get; } + public IUsersBatch UsersBatch { get; } public IReactions Reactions { get; } public IUsers Users { get; } public IPersonalization Personalization { get; } @@ -244,4 +246,4 @@ internal string JWToken(string feedId, string userId = null) return _streamClientToken.For(payload); } } -} +} \ No newline at end of file diff --git a/src/UsersBatch.cs b/src/UsersBatch.cs new file mode 100644 index 0000000..9ea1438 --- /dev/null +++ b/src/UsersBatch.cs @@ -0,0 +1,64 @@ +using Stream.Models; +using Stream.Utils; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Stream +{ + public class UsersBatch : IUsersBatch + { + private readonly StreamClient _client; + + internal UsersBatch(StreamClient client) + { + _client = client; + } + + public async Task> UpsertUsersAsync(IEnumerable users, bool overrideExisting = false) + { + var body = new Dictionary + { + { "users", users }, + { "override", overrideExisting }, + }; + var request = _client.BuildAppRequest("users/", HttpMethod.Post); + request.SetJsonBody(StreamJsonConverter.SerializeObject(body)); + + var response = await _client.MakeRequestAsync(request); + + if (response.StatusCode == HttpStatusCode.Created) + return StreamJsonConverter.DeserializeObject>(response.Content); + + throw StreamException.FromResponse(response); + } + + public async Task> GetUsersAsync(IEnumerable userIds) + { + var request = _client.BuildAppRequest("users/", HttpMethod.Get); + request.AddQueryParameter("ids", string.Join(",", userIds)); + + var response = await _client.MakeRequestAsync(request); + + if (response.StatusCode == HttpStatusCode.OK) + return StreamJsonConverter.DeserializeObject>(response.Content); + + throw StreamException.FromResponse(response); + } + + public async Task> DeleteUsersAsync(IEnumerable userIds) + { + var request = _client.BuildAppRequest("users/", HttpMethod.Delete); + request.AddQueryParameter("ids", string.Join(",", userIds)); + + var response = await _client.MakeRequestAsync(request); + + if (response.StatusCode == HttpStatusCode.OK) + return StreamJsonConverter.DeserializeObject>(response.Content); + + throw StreamException.FromResponse(response); + } + } +} \ No newline at end of file diff --git a/tests/UsersBatchTests.cs b/tests/UsersBatchTests.cs new file mode 100644 index 0000000..1553555 --- /dev/null +++ b/tests/UsersBatchTests.cs @@ -0,0 +1,96 @@ +using NUnit.Framework; +using Stream; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace StreamNetTests +{ + [TestFixture] + public class UsersBatchTests : TestBase + { + [Test] + public async Task TestAddUsersAsync() + { + var users = new List + { + new User { Id = Guid.NewGuid().ToString(), Data = new Dictionary { { "field", "value1" } } }, + new User { Id = Guid.NewGuid().ToString(), Data = new Dictionary { { "field", "value2" } } }, + }; + + var response = await Client.UsersBatch.UpsertUsersAsync(users); + + Assert.NotNull(response); + Assert.AreEqual(users.Count, response.Count()); + } + + [Test] + public async Task TestGetUsersAsync() + { + var userIds = new List { Guid.NewGuid().ToString(), Guid.NewGuid().ToString() }; + + var users = await Client.UsersBatch.GetUsersAsync(userIds); + + Assert.NotNull(users); + Assert.AreEqual(userIds.Count, users.Count()); + } + + // [Test] + // public async Task TestUpdateUsersAsync() + // { + // var users = new List + // { + // new User { Id = Guid.NewGuid().ToString(), Data = new Dictionary { { "field", "newvalue1" } } }, + // new User { Id = Guid.NewGuid().ToString(), Data = new Dictionary { { "field", "newvalue2" } } }, + // }; + // + // var response = await Client.UsersBatch.UpdateUsersAsync(users); + // + // Assert.NotNull(response); + // Assert.AreEqual(users.Count, response.Count()); + // } + [Test] + public async Task TestDeleteUsersAsync() + { + var userIds = new List { Guid.NewGuid().ToString(), Guid.NewGuid().ToString() }; + + var deletedUserIds = await Client.UsersBatch.DeleteUsersAsync(userIds); + + Assert.NotNull(deletedUserIds); + Assert.AreEqual(userIds.Count, deletedUserIds.Count()); + Assert.IsTrue(userIds.All(id => deletedUserIds.Contains(id))); + } + + [Test] + public async Task AddGetDeleteGetUsersAsync() + { + // Add users + var users = new List + { + new User { Id = Guid.NewGuid().ToString(), Data = new Dictionary { { "field", "value1" } } }, + new User { Id = Guid.NewGuid().ToString(), Data = new Dictionary { { "field", "value2" } } }, + }; + + var addResponse = await Client.UsersBatch.UpsertUsersAsync(users); + Assert.NotNull(addResponse); + Assert.AreEqual(users.Count, addResponse.Count()); + + // Get users to confirm they were added + var userIds = users.Select(u => u.Id); + var getUsersResponse = await Client.UsersBatch.GetUsersAsync(userIds); + Assert.NotNull(getUsersResponse); + Assert.AreEqual(users.Count, getUsersResponse.Count()); + + // Delete users + var deleteResponse = await Client.UsersBatch.DeleteUsersAsync(userIds); + Assert.NotNull(deleteResponse); + Assert.AreEqual(userIds.Count(), deleteResponse.Count()); + Assert.IsTrue(userIds.All(id => deleteResponse.Contains(id))); + + // Attempt to get deleted users to confirm they were deleted + var getDeletedUsersResponse = await Client.UsersBatch.GetUsersAsync(userIds); + Assert.IsEmpty(getDeletedUsersResponse); + } + } +} \ No newline at end of file From 2f593d803aa37533d9e858fd91a592dbccef1e38 Mon Sep 17 00:00:00 2001 From: Aditya Agarwal Date: Mon, 26 Aug 2024 20:28:29 +0200 Subject: [PATCH 2/3] add users batch --- src/Models/UsersBatch.cs | 73 ++++++++++++++++++++++++++++++++++++++++ src/UsersBatch.cs | 15 +++++++-- tests/UsersBatchTests.cs | 31 ++++++++--------- 3 files changed, 99 insertions(+), 20 deletions(-) create mode 100644 src/Models/UsersBatch.cs diff --git a/src/Models/UsersBatch.cs b/src/Models/UsersBatch.cs new file mode 100644 index 0000000..adc2b67 --- /dev/null +++ b/src/Models/UsersBatch.cs @@ -0,0 +1,73 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Stream.Utils; +using System; +using System.Collections.Generic; + +namespace Stream.Models +{ + public class AddUserBatchResponse + { + public IEnumerable CreatedUsers { get; set; } + } + + public class GetUserBatchResponse + { + public IEnumerable Users { get; set; } + } + +/* Unmerged change from project 'stream-net(netstandard2.0)' +Before: +// type UsersDeleteBatchResponse struct { +// BaseResponse +// DeletedUserIDs []string `json:"deleted_user_ids"` +// } +After: +// type UsersDeleteBatchResponse struct { +// BaseResponse +// DeletedUserIDs []string `json:"deleted_user_ids"` +// } +*/ + +/* Unmerged change from project 'stream-net(netstandard2.1)' +Before: +// type UsersDeleteBatchResponse struct { +// BaseResponse +// DeletedUserIDs []string `json:"deleted_user_ids"` +// } +After: +// type UsersDeleteBatchResponse struct { +// BaseResponse +// DeletedUserIDs []string `json:"deleted_user_ids"` +// } +*/ + +/* Unmerged change from project 'stream-net(net8.0)' +Before: +// type UsersDeleteBatchResponse struct { +// BaseResponse +// DeletedUserIDs []string `json:"deleted_user_ids"` +// } +After: +// type UsersDeleteBatchResponse struct { +// BaseResponse +// DeletedUserIDs []string `json:"deleted_user_ids"` +// } +*/ + // type UsersDeleteBatchResponse struct { + // BaseResponse + // DeletedUserIDs []string `json:"deleted_user_ids"` + // } + + public class DeleteUsersBatchResponse + { + public IEnumerable DeletedUserIds { get; set; } + } +} + + + + +// type UsersGetResponse struct { +// Users []*types.User `json:"data"` +// } \ No newline at end of file diff --git a/src/UsersBatch.cs b/src/UsersBatch.cs index 9ea1438..fc851b6 100644 --- a/src/UsersBatch.cs +++ b/src/UsersBatch.cs @@ -30,7 +30,10 @@ public async Task> UpsertUsersAsync(IEnumerable users, b var response = await _client.MakeRequestAsync(request); if (response.StatusCode == HttpStatusCode.Created) - return StreamJsonConverter.DeserializeObject>(response.Content); + { + var addUserBatchResponse = StreamJsonConverter.DeserializeObject(response.Content); + return addUserBatchResponse.CreatedUsers; + } throw StreamException.FromResponse(response); } @@ -43,7 +46,10 @@ public async Task> GetUsersAsync(IEnumerable userIds) var response = await _client.MakeRequestAsync(request); if (response.StatusCode == HttpStatusCode.OK) - return StreamJsonConverter.DeserializeObject>(response.Content); + { + var getUserBatchResponse = StreamJsonConverter.DeserializeObject(response.Content); + return getUserBatchResponse.Users; + } throw StreamException.FromResponse(response); } @@ -56,7 +62,10 @@ public async Task> DeleteUsersAsync(IEnumerable user var response = await _client.MakeRequestAsync(request); if (response.StatusCode == HttpStatusCode.OK) - return StreamJsonConverter.DeserializeObject>(response.Content); + { + var deleteUserBatchResponse = StreamJsonConverter.DeserializeObject(response.Content); + return deleteUserBatchResponse.DeletedUserIds; + } throw StreamException.FromResponse(response); } diff --git a/tests/UsersBatchTests.cs b/tests/UsersBatchTests.cs index 1553555..35212a7 100644 --- a/tests/UsersBatchTests.cs +++ b/tests/UsersBatchTests.cs @@ -11,31 +11,27 @@ namespace StreamNetTests public class UsersBatchTests : TestBase { [Test] - public async Task TestAddUsersAsync() + public async Task TestAddGetUsersAsync() { + var userIds = new List { Guid.NewGuid().ToString(), Guid.NewGuid().ToString() }; + var users = new List { - new User { Id = Guid.NewGuid().ToString(), Data = new Dictionary { { "field", "value1" } } }, - new User { Id = Guid.NewGuid().ToString(), Data = new Dictionary { { "field", "value2" } } }, + new User { Id = userIds[0], Data = new Dictionary { { "field", "value1" } } }, + new User { Id = userIds[1], Data = new Dictionary { { "field", "value2" } } }, }; var response = await Client.UsersBatch.UpsertUsersAsync(users); Assert.NotNull(response); Assert.AreEqual(users.Count, response.Count()); - } - [Test] - public async Task TestGetUsersAsync() - { - var userIds = new List { Guid.NewGuid().ToString(), Guid.NewGuid().ToString() }; + var usersReturned = await Client.UsersBatch.GetUsersAsync(userIds); - var users = await Client.UsersBatch.GetUsersAsync(userIds); - - Assert.NotNull(users); - Assert.AreEqual(userIds.Count, users.Count()); + Assert.NotNull(usersReturned); + Assert.AreEqual(userIds.Count, usersReturned.Count()); } - + // [Test] // public async Task TestUpdateUsersAsync() // { @@ -65,19 +61,20 @@ public async Task TestDeleteUsersAsync() [Test] public async Task AddGetDeleteGetUsersAsync() { + var userIds = new List { Guid.NewGuid().ToString(), Guid.NewGuid().ToString() }; + // Add users var users = new List { - new User { Id = Guid.NewGuid().ToString(), Data = new Dictionary { { "field", "value1" } } }, - new User { Id = Guid.NewGuid().ToString(), Data = new Dictionary { { "field", "value2" } } }, + new User { Id = userIds[0], Data = new Dictionary { { "field", "value1" } } }, + new User { Id = userIds[1], Data = new Dictionary { { "field", "value2" } } }, }; - + var addResponse = await Client.UsersBatch.UpsertUsersAsync(users); Assert.NotNull(addResponse); Assert.AreEqual(users.Count, addResponse.Count()); // Get users to confirm they were added - var userIds = users.Select(u => u.Id); var getUsersResponse = await Client.UsersBatch.GetUsersAsync(userIds); Assert.NotNull(getUsersResponse); Assert.AreEqual(users.Count, getUsersResponse.Count()); From 306dc32e380910e7e78c16b55c6ead87f2955cc3 Mon Sep 17 00:00:00 2001 From: Aditya Agarwal Date: Mon, 26 Aug 2024 20:32:50 +0200 Subject: [PATCH 3/3] remove comments --- src/Models/UsersBatch.cs | 52 +--------------------------------------- tests/UsersBatchTests.cs | 18 ++------------ 2 files changed, 3 insertions(+), 67 deletions(-) diff --git a/src/Models/UsersBatch.cs b/src/Models/UsersBatch.cs index adc2b67..841757e 100644 --- a/src/Models/UsersBatch.cs +++ b/src/Models/UsersBatch.cs @@ -15,59 +15,9 @@ public class GetUserBatchResponse { public IEnumerable Users { get; set; } } - -/* Unmerged change from project 'stream-net(netstandard2.0)' -Before: -// type UsersDeleteBatchResponse struct { -// BaseResponse -// DeletedUserIDs []string `json:"deleted_user_ids"` -// } -After: -// type UsersDeleteBatchResponse struct { -// BaseResponse -// DeletedUserIDs []string `json:"deleted_user_ids"` -// } -*/ - -/* Unmerged change from project 'stream-net(netstandard2.1)' -Before: -// type UsersDeleteBatchResponse struct { -// BaseResponse -// DeletedUserIDs []string `json:"deleted_user_ids"` -// } -After: -// type UsersDeleteBatchResponse struct { -// BaseResponse -// DeletedUserIDs []string `json:"deleted_user_ids"` -// } -*/ - -/* Unmerged change from project 'stream-net(net8.0)' -Before: -// type UsersDeleteBatchResponse struct { -// BaseResponse -// DeletedUserIDs []string `json:"deleted_user_ids"` -// } -After: -// type UsersDeleteBatchResponse struct { -// BaseResponse -// DeletedUserIDs []string `json:"deleted_user_ids"` -// } -*/ - // type UsersDeleteBatchResponse struct { - // BaseResponse - // DeletedUserIDs []string `json:"deleted_user_ids"` - // } public class DeleteUsersBatchResponse { public IEnumerable DeletedUserIds { get; set; } } -} - - - - -// type UsersGetResponse struct { -// Users []*types.User `json:"data"` -// } \ No newline at end of file +} \ No newline at end of file diff --git a/tests/UsersBatchTests.cs b/tests/UsersBatchTests.cs index 35212a7..f1a60c7 100644 --- a/tests/UsersBatchTests.cs +++ b/tests/UsersBatchTests.cs @@ -31,21 +31,7 @@ public async Task TestAddGetUsersAsync() Assert.NotNull(usersReturned); Assert.AreEqual(userIds.Count, usersReturned.Count()); } - - // [Test] - // public async Task TestUpdateUsersAsync() - // { - // var users = new List - // { - // new User { Id = Guid.NewGuid().ToString(), Data = new Dictionary { { "field", "newvalue1" } } }, - // new User { Id = Guid.NewGuid().ToString(), Data = new Dictionary { { "field", "newvalue2" } } }, - // }; - // - // var response = await Client.UsersBatch.UpdateUsersAsync(users); - // - // Assert.NotNull(response); - // Assert.AreEqual(users.Count, response.Count()); - // } + [Test] public async Task TestDeleteUsersAsync() { @@ -69,7 +55,7 @@ public async Task AddGetDeleteGetUsersAsync() new User { Id = userIds[0], Data = new Dictionary { { "field", "value1" } } }, new User { Id = userIds[1], Data = new Dictionary { { "field", "value2" } } }, }; - + var addResponse = await Client.UsersBatch.UpsertUsersAsync(users); Assert.NotNull(addResponse); Assert.AreEqual(users.Count, addResponse.Count());