Skip to content

Commit e9ee670

Browse files
totalimmersionclaudeadityaalifn
authored
[CHA-1703] Add Future Channel Bans support (#229)
* feat: [CHA-1699] add Future Channel Bans support - Add banFromFutureChannels field to UserBanRequestData - Add removeFutureChannelsBan method and parameter to UserUnbanRequest - Add FutureChannelBan class for query response - Add UserQueryFutureChannelBansRequest and UserQueryFutureChannelBansResponse - Add queryFutureChannelBans factory method and service endpoint * fix: apply spotless formatting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add targetUserId to UserQueryFutureChannelBansRequestData Add target_user_id parameter to allow filtering future channel bans by target user, especially for client-side requests. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add QueryFutureChannelBans test with target_user_id filter Test the new targetUserId parameter for filtering future channel bans. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix lint * Fix tests --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Aditya Alif Nugraha <aditya.nugraha@getstream.io>
1 parent fc13f5c commit e9ee670

File tree

3 files changed

+186
-2
lines changed

3 files changed

+186
-2
lines changed

src/main/java/io/getstream/chat/java/models/User.java

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import io.getstream.chat.java.models.User.UserMuteRequestData.UserMuteRequest;
1616
import io.getstream.chat.java.models.User.UserPartialUpdateRequestData.UserPartialUpdateRequest;
1717
import io.getstream.chat.java.models.User.UserQueryBannedRequestData.UserQueryBannedRequest;
18+
import io.getstream.chat.java.models.User.UserQueryFutureChannelBansRequestData.UserQueryFutureChannelBansRequest;
1819
import io.getstream.chat.java.models.User.UserReactivateRequestData.UserReactivateRequest;
1920
import io.getstream.chat.java.models.User.UserUnmuteRequestData.UserUnmuteRequest;
2021
import io.getstream.chat.java.models.User.UserUpsertRequestData.UserUpsertRequest;
@@ -214,6 +215,34 @@ public static class Ban {
214215
private Date createdAt;
215216
}
216217

218+
@Data
219+
@NoArgsConstructor
220+
public static class FutureChannelBan {
221+
@Nullable
222+
@JsonProperty("user")
223+
private User user;
224+
225+
@Nullable
226+
@JsonProperty("banned_by")
227+
private User bannedBy;
228+
229+
@Nullable
230+
@JsonProperty("expires")
231+
private Date expires;
232+
233+
@Nullable
234+
@JsonProperty("reason")
235+
private String reason;
236+
237+
@Nullable
238+
@JsonProperty("shadow")
239+
private Boolean shadow;
240+
241+
@NotNull
242+
@JsonProperty("created_at")
243+
private Date createdAt;
244+
}
245+
217246
@Data
218247
@NoArgsConstructor
219248
public static class OwnUser {
@@ -799,6 +828,14 @@ public static class UserBanRequestData {
799828
@JsonProperty("user")
800829
private UserRequestObject user;
801830

831+
@Nullable
832+
@JsonProperty("ban_from_future_channels")
833+
private Boolean banFromFutureChannels;
834+
835+
@Nullable
836+
@JsonProperty("channel_cid")
837+
private String channelCid;
838+
802839
public static class UserBanRequest extends StreamRequest<StreamResponseObject> {
803840
@Override
804841
protected Call<StreamResponseObject> generateCall(Client client) {
@@ -1078,6 +1115,10 @@ public static class UserUnbanRequest extends StreamRequest<StreamResponseObject>
10781115

10791116
@Nullable private Boolean shadow;
10801117

1118+
@Nullable private Boolean removeFutureChannelsBan;
1119+
1120+
@Nullable private String createdBy;
1121+
10811122
@NotNull
10821123
public UserUnbanRequest type(@NotNull String type) {
10831124
this.type = type;
@@ -1096,9 +1137,23 @@ public UserUnbanRequest shadow(@NotNull Boolean shadow) {
10961137
return this;
10971138
}
10981139

1140+
@NotNull
1141+
public UserUnbanRequest removeFutureChannelsBan(@NotNull Boolean removeFutureChannelsBan) {
1142+
this.removeFutureChannelsBan = removeFutureChannelsBan;
1143+
return this;
1144+
}
1145+
1146+
@NotNull
1147+
public UserUnbanRequest createdBy(@NotNull String createdBy) {
1148+
this.createdBy = createdBy;
1149+
return this;
1150+
}
1151+
10991152
@Override
11001153
protected Call<StreamResponseObject> generateCall(Client client) {
1101-
return client.create(UserService.class).unban(targetUserId, type, id, shadow);
1154+
return client
1155+
.create(UserService.class)
1156+
.unban(targetUserId, type, id, shadow, removeFutureChannelsBan, createdBy);
11021157
}
11031158
}
11041159

@@ -1171,6 +1226,51 @@ public static class UserQueryBannedResponse extends StreamResponseObject {
11711226
private List<Ban> bans;
11721227
}
11731228

1229+
@Builder(
1230+
builderClassName = "UserQueryFutureChannelBansRequest",
1231+
builderMethodName = "",
1232+
buildMethodName = "internalBuild")
1233+
@Getter
1234+
@EqualsAndHashCode
1235+
public static class UserQueryFutureChannelBansRequestData {
1236+
@Nullable
1237+
@JsonProperty("user_id")
1238+
private String userId;
1239+
1240+
@Nullable
1241+
@JsonProperty("target_user_id")
1242+
private String targetUserId;
1243+
1244+
@Nullable
1245+
@JsonProperty("exclude_expired_bans")
1246+
private Boolean excludeExpiredBans;
1247+
1248+
@Nullable
1249+
@JsonProperty("limit")
1250+
private Integer limit;
1251+
1252+
@Nullable
1253+
@JsonProperty("offset")
1254+
private Integer offset;
1255+
1256+
public static class UserQueryFutureChannelBansRequest
1257+
extends StreamRequest<UserQueryFutureChannelBansResponse> {
1258+
@Override
1259+
protected Call<UserQueryFutureChannelBansResponse> generateCall(Client client) {
1260+
return client.create(UserService.class).queryFutureChannelBans(this.internalBuild());
1261+
}
1262+
}
1263+
}
1264+
1265+
@Data
1266+
@NoArgsConstructor
1267+
@EqualsAndHashCode(callSuper = true)
1268+
public static class UserQueryFutureChannelBansResponse extends StreamResponseObject {
1269+
@NotNull
1270+
@JsonProperty("bans")
1271+
private List<FutureChannelBan> bans;
1272+
}
1273+
11741274
@Data
11751275
@NoArgsConstructor
11761276
@EqualsAndHashCode(callSuper = true)
@@ -1305,6 +1405,16 @@ public static UserQueryBannedRequest queryBanned() {
13051405
return new UserQueryBannedRequest();
13061406
}
13071407

1408+
/**
1409+
* Creates a query future channel bans request
1410+
*
1411+
* @return the created request
1412+
*/
1413+
@NotNull
1414+
public static UserQueryFutureChannelBansRequest queryFutureChannelBans() {
1415+
return new UserQueryFutureChannelBansRequest();
1416+
}
1417+
13081418
/**
13091419
* Creates a deactivate request
13101420
*

src/main/java/io/getstream/chat/java/services/UserService.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,11 @@ Call<StreamResponseObject> unban(
6565
@NotNull @Query("target_user_id") String targetUserId,
6666
@Nullable @Query("type") String channelType,
6767
@Nullable @Query("id") String channelId,
68-
@Nullable @Query("shadow") Boolean shadow);
68+
@Nullable @Query("shadow") Boolean shadow,
69+
@Nullable @Query("remove_future_channels_ban") Boolean removeFutureChannelsBan,
70+
@Nullable @Query("created_by") String createdBy);
71+
72+
@GET("query_future_channel_bans")
73+
Call<UserQueryFutureChannelBansResponse> queryFutureChannelBans(
74+
@NotNull @ToJson @Query("payload") UserQueryFutureChannelBansRequestData requestData);
6975
}

src/test/java/io/getstream/chat/java/UserTest.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,4 +506,72 @@ void whenGeneratingUserToken_thenNoException() {
506506

507507
Assertions.assertEquals(197, token.length());
508508
}
509+
510+
@DisplayName("Can query future channel bans with target_user_id filter")
511+
@Test
512+
void whenQueryingFutureChannelBansWithTargetUserId_thenFiltersCorrectly() {
513+
String creatorId = RandomStringUtils.randomAlphabetic(10);
514+
String targetId1 = RandomStringUtils.randomAlphabetic(10);
515+
String targetId2 = RandomStringUtils.randomAlphabetic(10);
516+
517+
// Create users
518+
UserUpsertRequest usersUpsertRequest = User.upsert();
519+
usersUpsertRequest.user(UserRequestObject.builder().id(creatorId).name("Creator").build());
520+
usersUpsertRequest.user(UserRequestObject.builder().id(targetId1).name("Target 1").build());
521+
usersUpsertRequest.user(UserRequestObject.builder().id(targetId2).name("Target 2").build());
522+
Assertions.assertDoesNotThrow(() -> usersUpsertRequest.request());
523+
524+
// Use the test channel's CID for banning from future channels
525+
String channelCid = testChannel.getType() + ":" + testChannel.getId();
526+
527+
// Ban both targets from future channels created by creator
528+
Assertions.assertDoesNotThrow(
529+
() ->
530+
User.ban()
531+
.userId(creatorId)
532+
.targetUserId(targetId1)
533+
.channelCid(channelCid)
534+
.banFromFutureChannels(true)
535+
.reason("test ban 1")
536+
.request());
537+
538+
Assertions.assertDoesNotThrow(
539+
() ->
540+
User.ban()
541+
.userId(creatorId)
542+
.targetUserId(targetId2)
543+
.channelCid(channelCid)
544+
.banFromFutureChannels(true)
545+
.reason("test ban 2")
546+
.request());
547+
548+
// Query with target_user_id filter - should only return the specific target
549+
var response =
550+
Assertions.assertDoesNotThrow(
551+
() ->
552+
User.queryFutureChannelBans().userId(creatorId).targetUserId(targetId1).request());
553+
Assertions.assertEquals(1, response.getBans().size());
554+
// For future channel bans, banned_by contains the creator (userId)
555+
Assertions.assertEquals(creatorId, response.getBans().get(0).getBannedBy().getId());
556+
557+
// Query for the other target
558+
response =
559+
Assertions.assertDoesNotThrow(
560+
() ->
561+
User.queryFutureChannelBans().userId(creatorId).targetUserId(targetId2).request());
562+
Assertions.assertEquals(1, response.getBans().size());
563+
Assertions.assertEquals(creatorId, response.getBans().get(0).getBannedBy().getId());
564+
565+
// Query all future channel bans by creator (without target filter)
566+
response =
567+
Assertions.assertDoesNotThrow(
568+
() -> User.queryFutureChannelBans().userId(creatorId).request());
569+
Assertions.assertTrue(response.getBans().size() >= 2);
570+
571+
// Cleanup - unban both users (createdBy is required when removing future channel bans)
572+
Assertions.assertDoesNotThrow(
573+
() -> User.unban(targetId1).removeFutureChannelsBan(true).createdBy(creatorId).request());
574+
Assertions.assertDoesNotThrow(
575+
() -> User.unban(targetId2).removeFutureChannelsBan(true).createdBy(creatorId).request());
576+
}
509577
}

0 commit comments

Comments
 (0)