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