1use super::{assert_channel_tree_matches, channel_tree, new_test_user};
2use crate::test_both_dbs;
3use collab::db::{Channel, ChannelId, ChannelRole, Database, NewUserParams, RoomId, UserId};
4use rpc::{
5 ConnectionId,
6 proto::{self, reorder_channel},
7};
8use std::{collections::HashSet, sync::Arc};
9
10test_both_dbs!(test_channels, test_channels_postgres, test_channels_sqlite);
11
12async fn test_channels(db: &Arc<Database>) {
13 let a_id = new_test_user(db, "user1@example.com").await;
14 let b_id = new_test_user(db, "user2@example.com").await;
15
16 let zed_id = db.create_root_channel("zed", a_id).await.unwrap();
17
18 // Make sure that people cannot read channels they haven't been invited to
19 assert!(db.get_channel(zed_id, b_id).await.is_err());
20
21 db.invite_channel_member(zed_id, b_id, a_id, ChannelRole::Member)
22 .await
23 .unwrap();
24
25 db.respond_to_channel_invite(zed_id, b_id, true)
26 .await
27 .unwrap();
28
29 let crdb_id = db.create_sub_channel("crdb", zed_id, a_id).await.unwrap();
30 let livestreaming_id = db
31 .create_sub_channel("livestreaming", zed_id, a_id)
32 .await
33 .unwrap();
34 let replace_id = db
35 .create_sub_channel("replace", zed_id, a_id)
36 .await
37 .unwrap();
38
39 let (members, _) = db
40 .get_channel_participant_details(replace_id, "", 10, a_id)
41 .await
42 .unwrap();
43 let ids = members
44 .into_iter()
45 .map(|m| UserId::from_proto(m.user_id))
46 .collect::<Vec<_>>();
47 assert_eq!(ids, &[a_id, b_id]);
48
49 let rust_id = db.create_root_channel("rust", a_id).await.unwrap();
50 let cargo_id = db.create_sub_channel("cargo", rust_id, a_id).await.unwrap();
51
52 let cargo_ra_id = db
53 .create_sub_channel("cargo-ra", cargo_id, a_id)
54 .await
55 .unwrap();
56
57 let result = db.get_channels_for_user(a_id).await.unwrap();
58 assert_channel_tree_matches(
59 result.channels,
60 channel_tree(&[
61 (zed_id, &[], "zed"),
62 (crdb_id, &[zed_id], "crdb"),
63 (livestreaming_id, &[zed_id], "livestreaming"),
64 (replace_id, &[zed_id], "replace"),
65 (rust_id, &[], "rust"),
66 (cargo_id, &[rust_id], "cargo"),
67 (cargo_ra_id, &[rust_id, cargo_id], "cargo-ra"),
68 ]),
69 );
70
71 let result = db.get_channels_for_user(b_id).await.unwrap();
72 assert_channel_tree_matches(
73 result.channels,
74 channel_tree(&[
75 (zed_id, &[], "zed"),
76 (crdb_id, &[zed_id], "crdb"),
77 (livestreaming_id, &[zed_id], "livestreaming"),
78 (replace_id, &[zed_id], "replace"),
79 ]),
80 );
81
82 // Update member permissions
83 let set_subchannel_admin = db
84 .set_channel_member_role(crdb_id, a_id, b_id, ChannelRole::Admin)
85 .await;
86 assert!(set_subchannel_admin.is_err());
87 let set_channel_admin = db
88 .set_channel_member_role(zed_id, a_id, b_id, ChannelRole::Admin)
89 .await;
90 assert!(set_channel_admin.is_ok());
91
92 let result = db.get_channels_for_user(b_id).await.unwrap();
93 assert_channel_tree_matches(
94 result.channels,
95 channel_tree(&[
96 (zed_id, &[], "zed"),
97 (crdb_id, &[zed_id], "crdb"),
98 (livestreaming_id, &[zed_id], "livestreaming"),
99 (replace_id, &[zed_id], "replace"),
100 ]),
101 );
102
103 // Remove a single channel
104 db.delete_channel(crdb_id, a_id).await.unwrap();
105 assert!(db.get_channel(crdb_id, a_id).await.is_err());
106
107 // Remove a channel tree
108 let (_, mut channel_ids) = db.delete_channel(rust_id, a_id).await.unwrap();
109 channel_ids.sort();
110 assert_eq!(channel_ids, &[rust_id, cargo_id, cargo_ra_id]);
111
112 assert!(db.get_channel(rust_id, a_id).await.is_err());
113 assert!(db.get_channel(cargo_id, a_id).await.is_err());
114 assert!(db.get_channel(cargo_ra_id, a_id).await.is_err());
115}
116
117test_both_dbs!(
118 test_joining_channels,
119 test_joining_channels_postgres,
120 test_joining_channels_sqlite
121);
122
123async fn test_joining_channels(db: &Arc<Database>) {
124 let owner_id = db.create_server("test").await.unwrap().0 as u32;
125
126 let user_1 = new_test_user(db, "user1@example.com").await;
127 let user_2 = new_test_user(db, "user2@example.com").await;
128
129 let channel_1 = db.create_root_channel("channel_1", user_1).await.unwrap();
130
131 // can join a room with membership to its channel
132 let (joined_room, _, _) = db
133 .join_channel(channel_1, user_1, ConnectionId { owner_id, id: 1 })
134 .await
135 .unwrap();
136 assert_eq!(joined_room.room.participants.len(), 1);
137
138 let room_id = RoomId::from_proto(joined_room.room.id);
139 drop(joined_room);
140 // cannot join a room without membership to its channel
141 assert!(
142 db.join_room(room_id, user_2, ConnectionId { owner_id, id: 1 },)
143 .await
144 .is_err()
145 );
146}
147
148test_both_dbs!(
149 test_channel_invites,
150 test_channel_invites_postgres,
151 test_channel_invites_sqlite
152);
153
154async fn test_channel_invites(db: &Arc<Database>) {
155 db.create_server("test").await.unwrap();
156
157 let user_1 = new_test_user(db, "user1@example.com").await;
158 let user_2 = new_test_user(db, "user2@example.com").await;
159 let user_3 = new_test_user(db, "user3@example.com").await;
160
161 let channel_1_1 = db.create_root_channel("channel_1", user_1).await.unwrap();
162
163 let channel_1_2 = db.create_root_channel("channel_2", user_1).await.unwrap();
164
165 db.invite_channel_member(channel_1_1, user_2, user_1, ChannelRole::Member)
166 .await
167 .unwrap();
168 db.invite_channel_member(channel_1_2, user_2, user_1, ChannelRole::Member)
169 .await
170 .unwrap();
171 db.invite_channel_member(channel_1_1, user_3, user_1, ChannelRole::Admin)
172 .await
173 .unwrap();
174
175 let user_2_invites = db
176 .get_channels_for_user(user_2)
177 .await
178 .unwrap()
179 .invited_channels
180 .into_iter()
181 .map(|channel| channel.id)
182 .collect::<Vec<_>>();
183 assert_eq!(user_2_invites, &[channel_1_1, channel_1_2]);
184
185 let user_3_invites = db
186 .get_channels_for_user(user_3)
187 .await
188 .unwrap()
189 .invited_channels
190 .into_iter()
191 .map(|channel| channel.id)
192 .collect::<Vec<_>>();
193 assert_eq!(user_3_invites, &[channel_1_1]);
194
195 let (mut members, _) = db
196 .get_channel_participant_details(channel_1_1, "", 100, user_1)
197 .await
198 .unwrap();
199
200 members.sort_by_key(|member| member.user_id);
201 assert_eq!(
202 members,
203 &[
204 proto::ChannelMember {
205 user_id: user_1.to_proto(),
206 kind: proto::channel_member::Kind::Member.into(),
207 role: proto::ChannelRole::Admin.into(),
208 },
209 proto::ChannelMember {
210 user_id: user_2.to_proto(),
211 kind: proto::channel_member::Kind::Invitee.into(),
212 role: proto::ChannelRole::Member.into(),
213 },
214 proto::ChannelMember {
215 user_id: user_3.to_proto(),
216 kind: proto::channel_member::Kind::Invitee.into(),
217 role: proto::ChannelRole::Admin.into(),
218 },
219 ]
220 );
221
222 db.respond_to_channel_invite(channel_1_1, user_2, true)
223 .await
224 .unwrap();
225
226 let channel_1_3 = db
227 .create_sub_channel("channel_3", channel_1_1, user_1)
228 .await
229 .unwrap();
230
231 let (members, _) = db
232 .get_channel_participant_details(channel_1_3, "", 100, user_1)
233 .await
234 .unwrap();
235 assert_eq!(
236 members,
237 &[
238 proto::ChannelMember {
239 user_id: user_1.to_proto(),
240 kind: proto::channel_member::Kind::Member.into(),
241 role: proto::ChannelRole::Admin.into(),
242 },
243 proto::ChannelMember {
244 user_id: user_3.to_proto(),
245 kind: proto::channel_member::Kind::Invitee.into(),
246 role: proto::ChannelRole::Admin.into(),
247 },
248 proto::ChannelMember {
249 user_id: user_2.to_proto(),
250 kind: proto::channel_member::Kind::Member.into(),
251 role: proto::ChannelRole::Member.into(),
252 },
253 ]
254 );
255}
256
257test_both_dbs!(
258 test_channel_renames,
259 test_channel_renames_postgres,
260 test_channel_renames_sqlite
261);
262
263async fn test_channel_renames(db: &Arc<Database>) {
264 db.create_server("test").await.unwrap();
265
266 let user_1 = db
267 .create_user(
268 "user1@example.com",
269 None,
270 false,
271 NewUserParams {
272 github_login: "user1".into(),
273 github_user_id: 5,
274 },
275 )
276 .await
277 .unwrap()
278 .user_id;
279
280 let user_2 = db
281 .create_user(
282 "user2@example.com",
283 None,
284 false,
285 NewUserParams {
286 github_login: "user2".into(),
287 github_user_id: 6,
288 },
289 )
290 .await
291 .unwrap()
292 .user_id;
293
294 let zed_id = db.create_root_channel("zed", user_1).await.unwrap();
295
296 db.rename_channel(zed_id, user_1, "#zed-archive")
297 .await
298 .unwrap();
299
300 let channel = db.get_channel(zed_id, user_1).await.unwrap();
301 assert_eq!(channel.name, "zed-archive");
302
303 let non_permissioned_rename = db.rename_channel(zed_id, user_2, "hacked-lol").await;
304 assert!(non_permissioned_rename.is_err());
305
306 let bad_name_rename = db.rename_channel(zed_id, user_1, "#").await;
307 assert!(bad_name_rename.is_err())
308}
309
310test_both_dbs!(
311 test_db_channel_moving,
312 test_db_channel_moving_postgres,
313 test_db_channel_moving_sqlite
314);
315
316async fn test_db_channel_moving(db: &Arc<Database>) {
317 let a_id = db
318 .create_user(
319 "user1@example.com",
320 None,
321 false,
322 NewUserParams {
323 github_login: "user1".into(),
324 github_user_id: 5,
325 },
326 )
327 .await
328 .unwrap()
329 .user_id;
330
331 let zed_id = db.create_root_channel("zed", a_id).await.unwrap();
332
333 let crdb_id = db.create_sub_channel("crdb", zed_id, a_id).await.unwrap();
334
335 let gpui2_id = db.create_sub_channel("gpui2", zed_id, a_id).await.unwrap();
336
337 let livestreaming_id = db
338 .create_sub_channel("livestreaming", crdb_id, a_id)
339 .await
340 .unwrap();
341
342 let livestreaming_sub_id = db
343 .create_sub_channel("livestreaming_sub", livestreaming_id, a_id)
344 .await
345 .unwrap();
346
347 // sanity check
348 // /- gpui2
349 // zed -- crdb - livestreaming - livestreaming_sub
350 let result = db.get_channels_for_user(a_id).await.unwrap();
351 assert_channel_tree(
352 result.channels,
353 &[
354 (zed_id, &[]),
355 (crdb_id, &[zed_id]),
356 (livestreaming_id, &[zed_id, crdb_id]),
357 (livestreaming_sub_id, &[zed_id, crdb_id, livestreaming_id]),
358 (gpui2_id, &[zed_id]),
359 ],
360 );
361
362 // Check that we can do a simple leaf -> leaf move
363 db.move_channel(livestreaming_sub_id, crdb_id, a_id)
364 .await
365 .unwrap();
366
367 // /- gpui2
368 // zed -- crdb -- livestreaming
369 // \- livestreaming_sub
370 let result = db.get_channels_for_user(a_id).await.unwrap();
371 assert_channel_tree(
372 result.channels,
373 &[
374 (zed_id, &[]),
375 (crdb_id, &[zed_id]),
376 (livestreaming_id, &[zed_id, crdb_id]),
377 (livestreaming_sub_id, &[zed_id, crdb_id]),
378 (gpui2_id, &[zed_id]),
379 ],
380 );
381
382 // Check that we can move a whole subtree at once
383 db.move_channel(crdb_id, gpui2_id, a_id).await.unwrap();
384
385 // zed -- gpui2 -- crdb -- livestreaming
386 // \- livestreaming_sub
387 let result = db.get_channels_for_user(a_id).await.unwrap();
388 assert_channel_tree(
389 result.channels,
390 &[
391 (zed_id, &[]),
392 (gpui2_id, &[zed_id]),
393 (crdb_id, &[zed_id, gpui2_id]),
394 (livestreaming_id, &[zed_id, gpui2_id, crdb_id]),
395 (livestreaming_sub_id, &[zed_id, gpui2_id, crdb_id]),
396 ],
397 );
398}
399
400test_both_dbs!(
401 test_channel_reordering,
402 test_channel_reordering_postgres,
403 test_channel_reordering_sqlite
404);
405
406async fn test_channel_reordering(db: &Arc<Database>) {
407 let admin_id = db
408 .create_user(
409 "admin@example.com",
410 None,
411 false,
412 NewUserParams {
413 github_login: "admin".into(),
414 github_user_id: 1,
415 },
416 )
417 .await
418 .unwrap()
419 .user_id;
420
421 let user_id = db
422 .create_user(
423 "user@example.com",
424 None,
425 false,
426 NewUserParams {
427 github_login: "user".into(),
428 github_user_id: 2,
429 },
430 )
431 .await
432 .unwrap()
433 .user_id;
434
435 // Create a root channel with some sub-channels
436 let root_id = db.create_root_channel("root", admin_id).await.unwrap();
437
438 // Invite user to root channel so they can see the sub-channels
439 db.invite_channel_member(root_id, user_id, admin_id, ChannelRole::Member)
440 .await
441 .unwrap();
442 db.respond_to_channel_invite(root_id, user_id, true)
443 .await
444 .unwrap();
445
446 let alpha_id = db
447 .create_sub_channel("alpha", root_id, admin_id)
448 .await
449 .unwrap();
450 let beta_id = db
451 .create_sub_channel("beta", root_id, admin_id)
452 .await
453 .unwrap();
454 let gamma_id = db
455 .create_sub_channel("gamma", root_id, admin_id)
456 .await
457 .unwrap();
458
459 // Initial order should be: root, alpha (order=1), beta (order=2), gamma (order=3)
460 let result = db.get_channels_for_user(admin_id).await.unwrap();
461 assert_channel_tree_order(
462 result.channels,
463 &[
464 (root_id, &[], 1),
465 (alpha_id, &[root_id], 1),
466 (beta_id, &[root_id], 2),
467 (gamma_id, &[root_id], 3),
468 ],
469 );
470
471 // Test moving beta up (should swap with alpha)
472 let updated_channels = db
473 .reorder_channel(beta_id, reorder_channel::Direction::Up, admin_id)
474 .await
475 .unwrap();
476
477 // Verify that beta and alpha were returned as updated
478 assert_eq!(updated_channels.len(), 2);
479 let updated_ids: std::collections::HashSet<_> = updated_channels.iter().map(|c| c.id).collect();
480 assert!(updated_ids.contains(&alpha_id));
481 assert!(updated_ids.contains(&beta_id));
482
483 // Now order should be: root, beta (order=1), alpha (order=2), gamma (order=3)
484 let result = db.get_channels_for_user(admin_id).await.unwrap();
485 assert_channel_tree_order(
486 result.channels,
487 &[
488 (root_id, &[], 1),
489 (beta_id, &[root_id], 1),
490 (alpha_id, &[root_id], 2),
491 (gamma_id, &[root_id], 3),
492 ],
493 );
494
495 // Test moving gamma down (should be no-op since it's already last)
496 let updated_channels = db
497 .reorder_channel(gamma_id, reorder_channel::Direction::Down, admin_id)
498 .await
499 .unwrap();
500
501 // Should return just nothing
502 assert_eq!(updated_channels.len(), 0);
503
504 // Test moving alpha down (should swap with gamma)
505 let updated_channels = db
506 .reorder_channel(alpha_id, reorder_channel::Direction::Down, admin_id)
507 .await
508 .unwrap();
509
510 // Verify that alpha and gamma were returned as updated
511 assert_eq!(updated_channels.len(), 2);
512 let updated_ids: std::collections::HashSet<_> = updated_channels.iter().map(|c| c.id).collect();
513 assert!(updated_ids.contains(&alpha_id));
514 assert!(updated_ids.contains(&gamma_id));
515
516 // Now order should be: root, beta (order=1), gamma (order=2), alpha (order=3)
517 let result = db.get_channels_for_user(admin_id).await.unwrap();
518 assert_channel_tree_order(
519 result.channels,
520 &[
521 (root_id, &[], 1),
522 (beta_id, &[root_id], 1),
523 (gamma_id, &[root_id], 2),
524 (alpha_id, &[root_id], 3),
525 ],
526 );
527
528 // Test that non-admin cannot reorder
529 let reorder_result = db
530 .reorder_channel(beta_id, reorder_channel::Direction::Up, user_id)
531 .await;
532 assert!(reorder_result.is_err());
533
534 // Test moving beta up (should be no-op since it's already first)
535 let updated_channels = db
536 .reorder_channel(beta_id, reorder_channel::Direction::Up, admin_id)
537 .await
538 .unwrap();
539
540 // Should return nothing
541 assert_eq!(updated_channels.len(), 0);
542
543 // Adding a channel to an existing ordering should add it to the end
544 let delta_id = db
545 .create_sub_channel("delta", root_id, admin_id)
546 .await
547 .unwrap();
548
549 let result = db.get_channels_for_user(admin_id).await.unwrap();
550 assert_channel_tree_order(
551 result.channels,
552 &[
553 (root_id, &[], 1),
554 (beta_id, &[root_id], 1),
555 (gamma_id, &[root_id], 2),
556 (alpha_id, &[root_id], 3),
557 (delta_id, &[root_id], 4),
558 ],
559 );
560
561 // And moving a channel into an existing ordering should add it to the end
562 let eta_id = db
563 .create_sub_channel("eta", delta_id, admin_id)
564 .await
565 .unwrap();
566
567 let result = db.get_channels_for_user(admin_id).await.unwrap();
568 assert_channel_tree_order(
569 result.channels,
570 &[
571 (root_id, &[], 1),
572 (beta_id, &[root_id], 1),
573 (gamma_id, &[root_id], 2),
574 (alpha_id, &[root_id], 3),
575 (delta_id, &[root_id], 4),
576 (eta_id, &[root_id, delta_id], 1),
577 ],
578 );
579
580 db.move_channel(eta_id, root_id, admin_id).await.unwrap();
581 let result = db.get_channels_for_user(admin_id).await.unwrap();
582 assert_channel_tree_order(
583 result.channels,
584 &[
585 (root_id, &[], 1),
586 (beta_id, &[root_id], 1),
587 (gamma_id, &[root_id], 2),
588 (alpha_id, &[root_id], 3),
589 (delta_id, &[root_id], 4),
590 (eta_id, &[root_id], 5),
591 ],
592 );
593}
594
595test_both_dbs!(
596 test_db_channel_moving_bugs,
597 test_db_channel_moving_bugs_postgres,
598 test_db_channel_moving_bugs_sqlite
599);
600
601async fn test_db_channel_moving_bugs(db: &Arc<Database>) {
602 let user_id = db
603 .create_user(
604 "user1@example.com",
605 None,
606 false,
607 NewUserParams {
608 github_login: "user1".into(),
609 github_user_id: 5,
610 },
611 )
612 .await
613 .unwrap()
614 .user_id;
615
616 let zed_id = db.create_root_channel("zed", user_id).await.unwrap();
617
618 let projects_id = db
619 .create_sub_channel("projects", zed_id, user_id)
620 .await
621 .unwrap();
622
623 let livestreaming_id = db
624 .create_sub_channel("livestreaming", projects_id, user_id)
625 .await
626 .unwrap();
627
628 let result = db.get_channels_for_user(user_id).await.unwrap();
629 assert_channel_tree(
630 result.channels,
631 &[
632 (zed_id, &[]),
633 (projects_id, &[zed_id]),
634 (livestreaming_id, &[zed_id, projects_id]),
635 ],
636 );
637
638 // Can't move a channel into its ancestor
639 db.move_channel(projects_id, livestreaming_id, user_id)
640 .await
641 .unwrap_err();
642 let result = db.get_channels_for_user(user_id).await.unwrap();
643 assert_channel_tree(
644 result.channels,
645 &[
646 (zed_id, &[]),
647 (projects_id, &[zed_id]),
648 (livestreaming_id, &[zed_id, projects_id]),
649 ],
650 );
651
652 // Can't un-root a root channel
653 db.move_channel(zed_id, livestreaming_id, user_id)
654 .await
655 .unwrap_err();
656 let result = db.get_channels_for_user(user_id).await.unwrap();
657 assert_channel_tree(
658 result.channels,
659 &[
660 (zed_id, &[]),
661 (projects_id, &[zed_id]),
662 (livestreaming_id, &[zed_id, projects_id]),
663 ],
664 );
665}
666
667test_both_dbs!(
668 test_user_is_channel_participant,
669 test_user_is_channel_participant_postgres,
670 test_user_is_channel_participant_sqlite
671);
672
673async fn test_user_is_channel_participant(db: &Arc<Database>) {
674 let admin = new_test_user(db, "admin@example.com").await;
675 let member = new_test_user(db, "member@example.com").await;
676 let guest = new_test_user(db, "guest@example.com").await;
677
678 let zed_channel = db.create_root_channel("zed", admin).await.unwrap();
679 let internal_channel_id = db
680 .create_sub_channel("active", zed_channel, admin)
681 .await
682 .unwrap();
683 let public_channel_id = db
684 .create_sub_channel("vim", zed_channel, admin)
685 .await
686 .unwrap();
687
688 db.set_channel_visibility(zed_channel, collab::db::ChannelVisibility::Public, admin)
689 .await
690 .unwrap();
691 db.set_channel_visibility(
692 public_channel_id,
693 collab::db::ChannelVisibility::Public,
694 admin,
695 )
696 .await
697 .unwrap();
698 db.invite_channel_member(zed_channel, member, admin, ChannelRole::Member)
699 .await
700 .unwrap();
701 db.invite_channel_member(zed_channel, guest, admin, ChannelRole::Guest)
702 .await
703 .unwrap();
704
705 db.respond_to_channel_invite(zed_channel, member, true)
706 .await
707 .unwrap();
708
709 db.transaction(|tx| async move {
710 db.check_user_is_channel_participant(
711 &db.get_channel_internal(public_channel_id, &tx).await?,
712 admin,
713 &tx,
714 )
715 .await
716 })
717 .await
718 .unwrap();
719 db.transaction(|tx| async move {
720 db.check_user_is_channel_participant(
721 &db.get_channel_internal(public_channel_id, &tx).await?,
722 member,
723 &tx,
724 )
725 .await
726 })
727 .await
728 .unwrap();
729
730 let (mut members, _) = db
731 .get_channel_participant_details(public_channel_id, "", 100, admin)
732 .await
733 .unwrap();
734
735 members.sort_by_key(|member| member.user_id);
736
737 assert_eq!(
738 members,
739 &[
740 proto::ChannelMember {
741 user_id: admin.to_proto(),
742 kind: proto::channel_member::Kind::Member.into(),
743 role: proto::ChannelRole::Admin.into(),
744 },
745 proto::ChannelMember {
746 user_id: member.to_proto(),
747 kind: proto::channel_member::Kind::Member.into(),
748 role: proto::ChannelRole::Member.into(),
749 },
750 proto::ChannelMember {
751 user_id: guest.to_proto(),
752 kind: proto::channel_member::Kind::Invitee.into(),
753 role: proto::ChannelRole::Guest.into(),
754 },
755 ]
756 );
757
758 db.respond_to_channel_invite(zed_channel, guest, true)
759 .await
760 .unwrap();
761
762 db.transaction(|tx| async move {
763 db.check_user_is_channel_participant(
764 &db.get_channel_internal(public_channel_id, &tx).await?,
765 guest,
766 &tx,
767 )
768 .await
769 })
770 .await
771 .unwrap();
772
773 let channels = db.get_channels_for_user(guest).await.unwrap().channels;
774 assert_channel_tree(
775 channels,
776 &[(zed_channel, &[]), (public_channel_id, &[zed_channel])],
777 );
778 let channels = db.get_channels_for_user(member).await.unwrap().channels;
779 assert_channel_tree(
780 channels,
781 &[
782 (zed_channel, &[]),
783 (internal_channel_id, &[zed_channel]),
784 (public_channel_id, &[zed_channel]),
785 ],
786 );
787
788 db.set_channel_member_role(zed_channel, admin, guest, ChannelRole::Banned)
789 .await
790 .unwrap();
791 assert!(
792 db.transaction(|tx| async move {
793 db.check_user_is_channel_participant(
794 &db.get_channel_internal(public_channel_id, &tx)
795 .await
796 .unwrap(),
797 guest,
798 &tx,
799 )
800 .await
801 })
802 .await
803 .is_err()
804 );
805
806 let (mut members, _) = db
807 .get_channel_participant_details(public_channel_id, "", 100, admin)
808 .await
809 .unwrap();
810
811 members.sort_by_key(|member| member.user_id);
812
813 assert_eq!(
814 members,
815 &[
816 proto::ChannelMember {
817 user_id: admin.to_proto(),
818 kind: proto::channel_member::Kind::Member.into(),
819 role: proto::ChannelRole::Admin.into(),
820 },
821 proto::ChannelMember {
822 user_id: member.to_proto(),
823 kind: proto::channel_member::Kind::Member.into(),
824 role: proto::ChannelRole::Member.into(),
825 },
826 proto::ChannelMember {
827 user_id: guest.to_proto(),
828 kind: proto::channel_member::Kind::Member.into(),
829 role: proto::ChannelRole::Banned.into(),
830 },
831 ]
832 );
833
834 db.remove_channel_member(zed_channel, guest, admin)
835 .await
836 .unwrap();
837
838 db.invite_channel_member(zed_channel, guest, admin, ChannelRole::Guest)
839 .await
840 .unwrap();
841
842 // currently people invited to parent channels are not shown here
843 let (mut members, _) = db
844 .get_channel_participant_details(public_channel_id, "", 100, admin)
845 .await
846 .unwrap();
847
848 members.sort_by_key(|member| member.user_id);
849
850 assert_eq!(
851 members,
852 &[
853 proto::ChannelMember {
854 user_id: admin.to_proto(),
855 kind: proto::channel_member::Kind::Member.into(),
856 role: proto::ChannelRole::Admin.into(),
857 },
858 proto::ChannelMember {
859 user_id: member.to_proto(),
860 kind: proto::channel_member::Kind::Member.into(),
861 role: proto::ChannelRole::Member.into(),
862 },
863 proto::ChannelMember {
864 user_id: guest.to_proto(),
865 kind: proto::channel_member::Kind::Invitee.into(),
866 role: proto::ChannelRole::Guest.into(),
867 },
868 ]
869 );
870
871 db.respond_to_channel_invite(zed_channel, guest, true)
872 .await
873 .unwrap();
874
875 db.transaction(|tx| async move {
876 db.check_user_is_channel_participant(
877 &db.get_channel_internal(zed_channel, &tx).await.unwrap(),
878 guest,
879 &tx,
880 )
881 .await
882 })
883 .await
884 .unwrap();
885 assert!(
886 db.transaction(|tx| async move {
887 db.check_user_is_channel_participant(
888 &db.get_channel_internal(internal_channel_id, &tx)
889 .await
890 .unwrap(),
891 guest,
892 &tx,
893 )
894 .await
895 })
896 .await
897 .is_err(),
898 );
899
900 db.transaction(|tx| async move {
901 db.check_user_is_channel_participant(
902 &db.get_channel_internal(public_channel_id, &tx)
903 .await
904 .unwrap(),
905 guest,
906 &tx,
907 )
908 .await
909 })
910 .await
911 .unwrap();
912
913 let (mut members, _) = db
914 .get_channel_participant_details(public_channel_id, "", 100, admin)
915 .await
916 .unwrap();
917
918 members.sort_by_key(|member| member.user_id);
919
920 assert_eq!(
921 members,
922 &[
923 proto::ChannelMember {
924 user_id: admin.to_proto(),
925 kind: proto::channel_member::Kind::Member.into(),
926 role: proto::ChannelRole::Admin.into(),
927 },
928 proto::ChannelMember {
929 user_id: member.to_proto(),
930 kind: proto::channel_member::Kind::Member.into(),
931 role: proto::ChannelRole::Member.into(),
932 },
933 proto::ChannelMember {
934 user_id: guest.to_proto(),
935 kind: proto::channel_member::Kind::Member.into(),
936 role: proto::ChannelRole::Guest.into(),
937 },
938 ]
939 );
940
941 let channels = db.get_channels_for_user(guest).await.unwrap().channels;
942 assert_channel_tree(
943 channels,
944 &[(zed_channel, &[]), (public_channel_id, &[zed_channel])],
945 )
946}
947
948#[track_caller]
949fn assert_channel_tree(actual: Vec<Channel>, expected: &[(ChannelId, &[ChannelId])]) {
950 let actual = actual
951 .iter()
952 .map(|channel| (channel.id, channel.parent_path.as_slice()))
953 .collect::<HashSet<_>>();
954 let expected = expected
955 .iter()
956 .map(|(id, parents)| (*id, *parents))
957 .collect::<HashSet<_>>();
958 pretty_assertions::assert_eq!(actual, expected, "wrong channel ids and parent paths");
959}
960
961#[track_caller]
962fn assert_channel_tree_order(actual: Vec<Channel>, expected: &[(ChannelId, &[ChannelId], i32)]) {
963 let actual = actual
964 .iter()
965 .map(|channel| {
966 (
967 channel.id,
968 channel.parent_path.as_slice(),
969 channel.channel_order,
970 )
971 })
972 .collect::<HashSet<_>>();
973 let expected = expected
974 .iter()
975 .map(|(id, parents, order)| (*id, *parents, *order))
976 .collect::<HashSet<_>>();
977 pretty_assertions::assert_eq!(actual, expected, "wrong channel ids and parent paths");
978}