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