From aa90750cfa6f1f0ff18be4b16b082b4efc465eec Mon Sep 17 00:00:00 2001 From: Slava Bobik Date: Wed, 12 Nov 2025 14:46:26 +0100 Subject: [PATCH] Added include_deactivated_users property --- src/Clients/UserClient.cs | 1 + src/Models/QueryOptions.cs | 7 ++++++ tests/UserClientTests.cs | 44 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/Clients/UserClient.cs b/src/Clients/UserClient.cs index d5f9838..cae8b08 100644 --- a/src/Clients/UserClient.cs +++ b/src/Clients/UserClient.cs @@ -229,6 +229,7 @@ public async Task QueryAsync(QueryUserOptions opts) offset = opts.Offset, limit = opts.Limit, presence = opts.Presence, + include_deactivated_users = opts.IncludeDeactivatedUsers, filter_conditions = opts.Filter, sort = opts.Sort, }; diff --git a/src/Models/QueryOptions.cs b/src/Models/QueryOptions.cs index 0222b73..d1ebe7a 100644 --- a/src/Models/QueryOptions.cs +++ b/src/Models/QueryOptions.cs @@ -26,6 +26,7 @@ public class QueryUserOptions public int Offset { get; set; } = DefaultOffset; public int Limit { get; set; } = DefaultLimit; public bool Presence { get; set; } = false; + public bool IncludeDeactivatedUsers { get; set; } = false; public List Sort { get; set; } = new List(); public Dictionary Filter { get; set; } = new Dictionary(); @@ -47,6 +48,12 @@ public QueryUserOptions WithPresence() return this; } + public QueryUserOptions WithIncludeDeactivatedUsers() + { + IncludeDeactivatedUsers = true; + return this; + } + public QueryUserOptions WithSortBy(SortParameter param) { Sort.Add(param); diff --git a/tests/UserClientTests.cs b/tests/UserClientTests.cs index b126796..ba5b1ad 100644 --- a/tests/UserClientTests.cs +++ b/tests/UserClientTests.cs @@ -25,18 +25,19 @@ public class UserClientTests : TestBase private ChannelWithConfig _channel; private UserRequest _user1; private UserRequest _user2; + private UserRequest _user3; [SetUp] public async Task SetupAsync() { - (_user1, _user2) = (await UpsertNewUserAsync(), await UpsertNewUserAsync()); + (_user1, _user2, _user3) = (await UpsertNewUserAsync(), await UpsertNewUserAsync(), await UpsertNewUserAsync()); _channel = await CreateChannelAsync(createdByUserId: _user1.Id, members: new[] { _user1.Id, _user2.Id }); } [TearDown] public async Task TeardownAsync() { - await TryDeleteUsersAsync(_user1.Id, _user2.Id); + await TryDeleteUsersAsync(_user1.Id, _user2.Id, _user3.Id); } [Test] @@ -180,6 +181,45 @@ public async Task TestQueryUsersAsync() resp.Users.Should().NotBeEmpty(); } + [Test] + public async Task TestQueryUsersWithIncludeDeactivatedUsersAsync() + { + // Deactivate user3 + await _userClient.DeactivateAsync(_user3.Id); + + // Query without including deactivated users + var respWithoutDeactivated = await _userClient.QueryAsync(QueryUserOptions.Default.WithFilter(new Dictionary + { + { "id", new Dictionary { { "$in", new[] { _user1.Id, _user3.Id } } } }, + })); + + // Should only find user1 (user3 is deactivated) + respWithoutDeactivated.Users.Should().NotBeEmpty(); + respWithoutDeactivated.Users.Should().HaveCount(1); + respWithoutDeactivated.Users[0].Id.Should().Be(_user1.Id); + + // Query with including deactivated users + var respWithDeactivated = await _userClient.QueryAsync(QueryUserOptions.Default + .WithIncludeDeactivatedUsers() + .WithFilter(new Dictionary + { + { "id", new Dictionary { { "$in", new[] { _user1.Id, _user3.Id } } } }, + })); + + // Should find both users + respWithDeactivated.Users.Should().NotBeEmpty(); + respWithDeactivated.Users.Should().HaveCount(2); + respWithDeactivated.Users.Should().Contain(u => u.Id == _user1.Id); + respWithDeactivated.Users.Should().Contain(u => u.Id == _user3.Id); + + // Verify user3 is deactivated + var user3 = respWithDeactivated.Users.First(u => u.Id == _user3.Id); + user3.DeactivatedAt.Should().NotBeNull(); + + // Reactivate user3 for cleanup + await _userClient.ReactivateAsync(_user3.Id); + } + [Test] public async Task TestDeactivateUserAsync() {