1use crate::{
2 db::{
3 tests::{channel_tree, new_test_connection, new_test_user, TEST_RELEASE_CHANNEL},
4 Channel, ChannelId, ChannelRole, Database, NewUserParams, RoomId,
5 },
6 test_both_dbs,
7};
8use rpc::{
9 proto::{self},
10 ConnectionId,
11};
12use std::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 mut members = db
44 .transaction(|tx| async move {
45 let channel = db.get_channel_internal(replace_id, &*tx).await?;
46 Ok(db.get_channel_participants(&channel, &*tx).await?)
47 })
48 .await
49 .unwrap();
50 members.sort();
51 assert_eq!(members, &[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_eq!(
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_eq!(
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_eq!(
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, user_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 assert_eq!(user_ids, &[a_id]);
116
117 assert!(db.get_channel(rust_id, a_id).await.is_err());
118 assert!(db.get_channel(cargo_id, a_id).await.is_err());
119 assert!(db.get_channel(cargo_ra_id, a_id).await.is_err());
120}
121
122test_both_dbs!(
123 test_joining_channels,
124 test_joining_channels_postgres,
125 test_joining_channels_sqlite
126);
127
128async fn test_joining_channels(db: &Arc<Database>) {
129 let owner_id = db.create_server("test").await.unwrap().0 as u32;
130
131 let user_1 = new_test_user(db, "user1@example.com").await;
132 let user_2 = new_test_user(db, "user2@example.com").await;
133
134 let channel_1 = db.create_root_channel("channel_1", user_1).await.unwrap();
135
136 // can join a room with membership to its channel
137 let (joined_room, _, _) = db
138 .join_channel(
139 channel_1,
140 user_1,
141 ConnectionId { owner_id, id: 1 },
142 TEST_RELEASE_CHANNEL,
143 )
144 .await
145 .unwrap();
146 assert_eq!(joined_room.room.participants.len(), 1);
147
148 let room_id = RoomId::from_proto(joined_room.room.id);
149 drop(joined_room);
150 // cannot join a room without membership to its channel
151 assert!(db
152 .join_room(
153 room_id,
154 user_2,
155 ConnectionId { owner_id, id: 1 },
156 TEST_RELEASE_CHANNEL
157 )
158 .await
159 .is_err());
160}
161
162test_both_dbs!(
163 test_channel_invites,
164 test_channel_invites_postgres,
165 test_channel_invites_sqlite
166);
167
168async fn test_channel_invites(db: &Arc<Database>) {
169 db.create_server("test").await.unwrap();
170
171 let user_1 = new_test_user(db, "user1@example.com").await;
172 let user_2 = new_test_user(db, "user2@example.com").await;
173 let user_3 = new_test_user(db, "user3@example.com").await;
174
175 let channel_1_1 = db.create_root_channel("channel_1", user_1).await.unwrap();
176
177 let channel_1_2 = db.create_root_channel("channel_2", user_1).await.unwrap();
178
179 db.invite_channel_member(channel_1_1, user_2, user_1, ChannelRole::Member)
180 .await
181 .unwrap();
182 db.invite_channel_member(channel_1_2, user_2, user_1, ChannelRole::Member)
183 .await
184 .unwrap();
185 db.invite_channel_member(channel_1_1, user_3, user_1, ChannelRole::Admin)
186 .await
187 .unwrap();
188
189 let user_2_invites = db
190 .get_channel_invites_for_user(user_2) // -> [channel_1_1, channel_1_2]
191 .await
192 .unwrap()
193 .into_iter()
194 .map(|channel| channel.id)
195 .collect::<Vec<_>>();
196
197 assert_eq!(user_2_invites, &[channel_1_1, channel_1_2]);
198
199 let user_3_invites = db
200 .get_channel_invites_for_user(user_3) // -> [channel_1_1]
201 .await
202 .unwrap()
203 .into_iter()
204 .map(|channel| channel.id)
205 .collect::<Vec<_>>();
206
207 assert_eq!(user_3_invites, &[channel_1_1]);
208
209 let mut members = db
210 .get_channel_participant_details(channel_1_1, user_1)
211 .await
212 .unwrap();
213
214 members.sort_by_key(|member| member.user_id);
215 assert_eq!(
216 members,
217 &[
218 proto::ChannelMember {
219 user_id: user_1.to_proto(),
220 kind: proto::channel_member::Kind::Member.into(),
221 role: proto::ChannelRole::Admin.into(),
222 },
223 proto::ChannelMember {
224 user_id: user_2.to_proto(),
225 kind: proto::channel_member::Kind::Invitee.into(),
226 role: proto::ChannelRole::Member.into(),
227 },
228 proto::ChannelMember {
229 user_id: user_3.to_proto(),
230 kind: proto::channel_member::Kind::Invitee.into(),
231 role: proto::ChannelRole::Admin.into(),
232 },
233 ]
234 );
235
236 db.respond_to_channel_invite(channel_1_1, user_2, true)
237 .await
238 .unwrap();
239
240 let channel_1_3 = db
241 .create_sub_channel("channel_3", channel_1_1, user_1)
242 .await
243 .unwrap();
244
245 let members = db
246 .get_channel_participant_details(channel_1_3, user_1)
247 .await
248 .unwrap();
249 assert_eq!(
250 members,
251 &[
252 proto::ChannelMember {
253 user_id: user_1.to_proto(),
254 kind: proto::channel_member::Kind::Member.into(),
255 role: proto::ChannelRole::Admin.into(),
256 },
257 proto::ChannelMember {
258 user_id: user_2.to_proto(),
259 kind: proto::channel_member::Kind::Member.into(),
260 role: proto::ChannelRole::Member.into(),
261 },
262 proto::ChannelMember {
263 user_id: user_3.to_proto(),
264 kind: proto::channel_member::Kind::Invitee.into(),
265 role: proto::ChannelRole::Admin.into(),
266 },
267 ]
268 );
269}
270
271test_both_dbs!(
272 test_channel_renames,
273 test_channel_renames_postgres,
274 test_channel_renames_sqlite
275);
276
277async fn test_channel_renames(db: &Arc<Database>) {
278 db.create_server("test").await.unwrap();
279
280 let user_1 = db
281 .create_user(
282 "user1@example.com",
283 false,
284 NewUserParams {
285 github_login: "user1".into(),
286 github_user_id: 5,
287 },
288 )
289 .await
290 .unwrap()
291 .user_id;
292
293 let user_2 = db
294 .create_user(
295 "user2@example.com",
296 false,
297 NewUserParams {
298 github_login: "user2".into(),
299 github_user_id: 6,
300 },
301 )
302 .await
303 .unwrap()
304 .user_id;
305
306 let zed_id = db.create_root_channel("zed", user_1).await.unwrap();
307
308 db.rename_channel(zed_id, user_1, "#zed-archive")
309 .await
310 .unwrap();
311
312 let channel = db.get_channel(zed_id, user_1).await.unwrap();
313 assert_eq!(channel.name, "zed-archive");
314
315 let non_permissioned_rename = db.rename_channel(zed_id, user_2, "hacked-lol").await;
316 assert!(non_permissioned_rename.is_err());
317
318 let bad_name_rename = db.rename_channel(zed_id, user_1, "#").await;
319 assert!(bad_name_rename.is_err())
320}
321
322test_both_dbs!(
323 test_db_channel_moving,
324 test_channels_moving_postgres,
325 test_channels_moving_sqlite
326);
327
328async fn test_db_channel_moving(db: &Arc<Database>) {
329 let a_id = db
330 .create_user(
331 "user1@example.com",
332 false,
333 NewUserParams {
334 github_login: "user1".into(),
335 github_user_id: 5,
336 },
337 )
338 .await
339 .unwrap()
340 .user_id;
341
342 let zed_id = db.create_root_channel("zed", a_id).await.unwrap();
343
344 let crdb_id = db.create_sub_channel("crdb", zed_id, a_id).await.unwrap();
345
346 let gpui2_id = db.create_sub_channel("gpui2", zed_id, a_id).await.unwrap();
347
348 let livestreaming_id = db
349 .create_sub_channel("livestreaming", crdb_id, a_id)
350 .await
351 .unwrap();
352
353 let livestreaming_dag_id = db
354 .create_sub_channel("livestreaming_dag", livestreaming_id, a_id)
355 .await
356 .unwrap();
357
358 // ========================================================================
359 // sanity check
360 // Initial DAG:
361 // /- gpui2
362 // zed -- crdb - livestreaming - livestreaming_dag
363 let result = db.get_channels_for_user(a_id).await.unwrap();
364 assert_channel_tree(
365 result.channels,
366 &[
367 (zed_id, &[]),
368 (crdb_id, &[zed_id]),
369 (livestreaming_id, &[zed_id, crdb_id]),
370 (livestreaming_dag_id, &[zed_id, crdb_id, livestreaming_id]),
371 (gpui2_id, &[zed_id]),
372 ],
373 );
374}
375
376test_both_dbs!(
377 test_db_channel_moving_bugs,
378 test_db_channel_moving_bugs_postgres,
379 test_db_channel_moving_bugs_sqlite
380);
381
382async fn test_db_channel_moving_bugs(db: &Arc<Database>) {
383 let user_id = db
384 .create_user(
385 "user1@example.com",
386 false,
387 NewUserParams {
388 github_login: "user1".into(),
389 github_user_id: 5,
390 },
391 )
392 .await
393 .unwrap()
394 .user_id;
395
396 let zed_id = db.create_root_channel("zed", user_id).await.unwrap();
397
398 let projects_id = db
399 .create_sub_channel("projects", zed_id, user_id)
400 .await
401 .unwrap();
402
403 let livestreaming_id = db
404 .create_sub_channel("livestreaming", projects_id, user_id)
405 .await
406 .unwrap();
407
408 let result = db.get_channels_for_user(user_id).await.unwrap();
409 assert_channel_tree(
410 result.channels,
411 &[
412 (zed_id, &[]),
413 (projects_id, &[zed_id]),
414 (livestreaming_id, &[zed_id, projects_id]),
415 ],
416 );
417
418 // Can't move a channel into its ancestor
419 db.move_channel(projects_id, livestreaming_id, user_id)
420 .await
421 .unwrap_err();
422 let result = db.get_channels_for_user(user_id).await.unwrap();
423 assert_channel_tree(
424 result.channels,
425 &[
426 (zed_id, &[]),
427 (projects_id, &[zed_id]),
428 (livestreaming_id, &[zed_id, projects_id]),
429 ],
430 );
431}
432
433test_both_dbs!(
434 test_user_is_channel_participant,
435 test_user_is_channel_participant_postgres,
436 test_user_is_channel_participant_sqlite
437);
438
439async fn test_user_is_channel_participant(db: &Arc<Database>) {
440 let admin = new_test_user(db, "admin@example.com").await;
441 let member = new_test_user(db, "member@example.com").await;
442 let guest = new_test_user(db, "guest@example.com").await;
443
444 let zed_channel = db.create_root_channel("zed", admin).await.unwrap();
445 let internal_channel_id = db
446 .create_sub_channel("active", zed_channel, admin)
447 .await
448 .unwrap();
449 let public_channel_id = db
450 .create_sub_channel("vim", zed_channel, admin)
451 .await
452 .unwrap();
453
454 db.set_channel_visibility(zed_channel, crate::db::ChannelVisibility::Public, admin)
455 .await
456 .unwrap();
457 db.set_channel_visibility(
458 public_channel_id,
459 crate::db::ChannelVisibility::Public,
460 admin,
461 )
462 .await
463 .unwrap();
464 db.invite_channel_member(zed_channel, member, admin, ChannelRole::Member)
465 .await
466 .unwrap();
467 db.invite_channel_member(zed_channel, guest, admin, ChannelRole::Guest)
468 .await
469 .unwrap();
470
471 db.respond_to_channel_invite(zed_channel, member, true)
472 .await
473 .unwrap();
474
475 db.transaction(|tx| async move {
476 db.check_user_is_channel_participant(
477 &db.get_channel_internal(public_channel_id, &*tx).await?,
478 admin,
479 &*tx,
480 )
481 .await
482 })
483 .await
484 .unwrap();
485 db.transaction(|tx| async move {
486 db.check_user_is_channel_participant(
487 &db.get_channel_internal(public_channel_id, &*tx).await?,
488 member,
489 &*tx,
490 )
491 .await
492 })
493 .await
494 .unwrap();
495
496 let mut members = db
497 .get_channel_participant_details(public_channel_id, admin)
498 .await
499 .unwrap();
500
501 members.sort_by_key(|member| member.user_id);
502
503 assert_eq!(
504 members,
505 &[
506 proto::ChannelMember {
507 user_id: admin.to_proto(),
508 kind: proto::channel_member::Kind::Member.into(),
509 role: proto::ChannelRole::Admin.into(),
510 },
511 proto::ChannelMember {
512 user_id: member.to_proto(),
513 kind: proto::channel_member::Kind::Member.into(),
514 role: proto::ChannelRole::Member.into(),
515 },
516 proto::ChannelMember {
517 user_id: guest.to_proto(),
518 kind: proto::channel_member::Kind::Invitee.into(),
519 role: proto::ChannelRole::Guest.into(),
520 },
521 ]
522 );
523
524 db.respond_to_channel_invite(zed_channel, guest, true)
525 .await
526 .unwrap();
527
528 db.transaction(|tx| async move {
529 db.check_user_is_channel_participant(
530 &db.get_channel_internal(public_channel_id, &*tx).await?,
531 guest,
532 &*tx,
533 )
534 .await
535 })
536 .await
537 .unwrap();
538
539 let channels = db.get_channels_for_user(guest).await.unwrap().channels;
540 assert_channel_tree(
541 channels,
542 &[(zed_channel, &[]), (public_channel_id, &[zed_channel])],
543 );
544 let channels = db.get_channels_for_user(member).await.unwrap().channels;
545 assert_channel_tree(
546 channels,
547 &[
548 (zed_channel, &[]),
549 (internal_channel_id, &[zed_channel]),
550 (public_channel_id, &[zed_channel]),
551 ],
552 );
553
554 db.set_channel_member_role(zed_channel, admin, guest, ChannelRole::Banned)
555 .await
556 .unwrap();
557 assert!(db
558 .transaction(|tx| async move {
559 db.check_user_is_channel_participant(
560 &db.get_channel_internal(public_channel_id, &*tx)
561 .await
562 .unwrap(),
563 guest,
564 &*tx,
565 )
566 .await
567 })
568 .await
569 .is_err());
570
571 let mut members = db
572 .get_channel_participant_details(public_channel_id, admin)
573 .await
574 .unwrap();
575
576 members.sort_by_key(|member| member.user_id);
577
578 assert_eq!(
579 members,
580 &[
581 proto::ChannelMember {
582 user_id: admin.to_proto(),
583 kind: proto::channel_member::Kind::Member.into(),
584 role: proto::ChannelRole::Admin.into(),
585 },
586 proto::ChannelMember {
587 user_id: member.to_proto(),
588 kind: proto::channel_member::Kind::Member.into(),
589 role: proto::ChannelRole::Member.into(),
590 },
591 proto::ChannelMember {
592 user_id: guest.to_proto(),
593 kind: proto::channel_member::Kind::Member.into(),
594 role: proto::ChannelRole::Banned.into(),
595 },
596 ]
597 );
598
599 db.remove_channel_member(zed_channel, guest, admin)
600 .await
601 .unwrap();
602
603 db.invite_channel_member(zed_channel, guest, admin, ChannelRole::Guest)
604 .await
605 .unwrap();
606
607 // currently people invited to parent channels are not shown here
608 let mut members = db
609 .get_channel_participant_details(public_channel_id, admin)
610 .await
611 .unwrap();
612
613 members.sort_by_key(|member| member.user_id);
614
615 assert_eq!(
616 members,
617 &[
618 proto::ChannelMember {
619 user_id: admin.to_proto(),
620 kind: proto::channel_member::Kind::Member.into(),
621 role: proto::ChannelRole::Admin.into(),
622 },
623 proto::ChannelMember {
624 user_id: member.to_proto(),
625 kind: proto::channel_member::Kind::Member.into(),
626 role: proto::ChannelRole::Member.into(),
627 },
628 proto::ChannelMember {
629 user_id: guest.to_proto(),
630 kind: proto::channel_member::Kind::Invitee.into(),
631 role: proto::ChannelRole::Guest.into(),
632 },
633 ]
634 );
635
636 db.respond_to_channel_invite(zed_channel, guest, true)
637 .await
638 .unwrap();
639
640 db.transaction(|tx| async move {
641 db.check_user_is_channel_participant(
642 &db.get_channel_internal(zed_channel, &*tx).await.unwrap(),
643 guest,
644 &*tx,
645 )
646 .await
647 })
648 .await
649 .unwrap();
650 assert!(db
651 .transaction(|tx| async move {
652 db.check_user_is_channel_participant(
653 &db.get_channel_internal(internal_channel_id, &*tx)
654 .await
655 .unwrap(),
656 guest,
657 &*tx,
658 )
659 .await
660 })
661 .await
662 .is_err(),);
663
664 db.transaction(|tx| async move {
665 db.check_user_is_channel_participant(
666 &db.get_channel_internal(public_channel_id, &*tx)
667 .await
668 .unwrap(),
669 guest,
670 &*tx,
671 )
672 .await
673 })
674 .await
675 .unwrap();
676
677 let mut members = db
678 .get_channel_participant_details(public_channel_id, admin)
679 .await
680 .unwrap();
681
682 members.sort_by_key(|member| member.user_id);
683
684 assert_eq!(
685 members,
686 &[
687 proto::ChannelMember {
688 user_id: admin.to_proto(),
689 kind: proto::channel_member::Kind::Member.into(),
690 role: proto::ChannelRole::Admin.into(),
691 },
692 proto::ChannelMember {
693 user_id: member.to_proto(),
694 kind: proto::channel_member::Kind::Member.into(),
695 role: proto::ChannelRole::Member.into(),
696 },
697 proto::ChannelMember {
698 user_id: guest.to_proto(),
699 kind: proto::channel_member::Kind::Member.into(),
700 role: proto::ChannelRole::Guest.into(),
701 },
702 ]
703 );
704
705 let channels = db.get_channels_for_user(guest).await.unwrap().channels;
706 assert_channel_tree(
707 channels,
708 &[(zed_channel, &[]), (public_channel_id, &[zed_channel])],
709 )
710}
711
712test_both_dbs!(
713 test_guest_access,
714 test_guest_access_postgres,
715 test_guest_access_sqlite
716);
717
718async fn test_guest_access(db: &Arc<Database>) {
719 let server = db.create_server("test").await.unwrap();
720
721 let admin = new_test_user(db, "admin@example.com").await;
722 let guest = new_test_user(db, "guest@example.com").await;
723 let guest_connection = new_test_connection(server);
724
725 let zed_channel = db.create_root_channel("zed", admin).await.unwrap();
726 db.set_channel_visibility(zed_channel, crate::db::ChannelVisibility::Public, admin)
727 .await
728 .unwrap();
729
730 assert!(db
731 .join_channel_chat(zed_channel, guest_connection, guest)
732 .await
733 .is_err());
734
735 db.join_channel(zed_channel, guest, guest_connection, TEST_RELEASE_CHANNEL)
736 .await
737 .unwrap();
738
739 assert!(db
740 .join_channel_chat(zed_channel, guest_connection, guest)
741 .await
742 .is_ok())
743}
744
745#[track_caller]
746fn assert_channel_tree(actual: Vec<Channel>, expected: &[(ChannelId, &[ChannelId])]) {
747 let actual = actual
748 .iter()
749 .map(|channel| (channel.id, channel.parent_path.as_slice()))
750 .collect::<Vec<_>>();
751 pretty_assertions::assert_eq!(
752 actual,
753 expected.to_vec(),
754 "wrong channel ids and parent paths"
755 );
756}