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