channel_tests.rs

  1use crate::{
  2    db::{
  3        Channel, ChannelId, ChannelRole, Database, NewUserParams, RoomId, UserId,
  4        tests::{channel_tree, new_test_connection, new_test_user},
  5    },
  6    test_both_dbs,
  7};
  8use rpc::{
  9    ConnectionId,
 10    proto::{self},
 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!(
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_channels_moving_postgres,
317    test_channels_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_dag_id = db
347        .create_sub_channel("livestreaming_dag", livestreaming_id, a_id)
348        .await
349        .unwrap();
350
351    // ========================================================================
352    // sanity check
353    // Initial DAG:
354    //     /- gpui2
355    // zed -- crdb - livestreaming - livestreaming_dag
356    let result = db.get_channels_for_user(a_id).await.unwrap();
357    assert_channel_tree(
358        result.channels,
359        &[
360            (zed_id, &[]),
361            (crdb_id, &[zed_id]),
362            (livestreaming_id, &[zed_id, crdb_id]),
363            (livestreaming_dag_id, &[zed_id, crdb_id, livestreaming_id]),
364            (gpui2_id, &[zed_id]),
365        ],
366    );
367}
368
369test_both_dbs!(
370    test_db_channel_moving_bugs,
371    test_db_channel_moving_bugs_postgres,
372    test_db_channel_moving_bugs_sqlite
373);
374
375async fn test_db_channel_moving_bugs(db: &Arc<Database>) {
376    let user_id = db
377        .create_user(
378            "user1@example.com",
379            None,
380            false,
381            NewUserParams {
382                github_login: "user1".into(),
383                github_user_id: 5,
384            },
385        )
386        .await
387        .unwrap()
388        .user_id;
389
390    let zed_id = db.create_root_channel("zed", user_id).await.unwrap();
391
392    let projects_id = db
393        .create_sub_channel("projects", zed_id, user_id)
394        .await
395        .unwrap();
396
397    let livestreaming_id = db
398        .create_sub_channel("livestreaming", projects_id, user_id)
399        .await
400        .unwrap();
401
402    let result = db.get_channels_for_user(user_id).await.unwrap();
403    assert_channel_tree(
404        result.channels,
405        &[
406            (zed_id, &[]),
407            (projects_id, &[zed_id]),
408            (livestreaming_id, &[zed_id, projects_id]),
409        ],
410    );
411
412    // Can't move a channel into its ancestor
413    db.move_channel(projects_id, livestreaming_id, user_id)
414        .await
415        .unwrap_err();
416    let result = db.get_channels_for_user(user_id).await.unwrap();
417    assert_channel_tree(
418        result.channels,
419        &[
420            (zed_id, &[]),
421            (projects_id, &[zed_id]),
422            (livestreaming_id, &[zed_id, projects_id]),
423        ],
424    );
425}
426
427test_both_dbs!(
428    test_user_is_channel_participant,
429    test_user_is_channel_participant_postgres,
430    test_user_is_channel_participant_sqlite
431);
432
433async fn test_user_is_channel_participant(db: &Arc<Database>) {
434    let admin = new_test_user(db, "admin@example.com").await;
435    let member = new_test_user(db, "member@example.com").await;
436    let guest = new_test_user(db, "guest@example.com").await;
437
438    let zed_channel = db.create_root_channel("zed", admin).await.unwrap();
439    let internal_channel_id = db
440        .create_sub_channel("active", zed_channel, admin)
441        .await
442        .unwrap();
443    let public_channel_id = db
444        .create_sub_channel("vim", zed_channel, admin)
445        .await
446        .unwrap();
447
448    db.set_channel_visibility(zed_channel, crate::db::ChannelVisibility::Public, admin)
449        .await
450        .unwrap();
451    db.set_channel_visibility(
452        public_channel_id,
453        crate::db::ChannelVisibility::Public,
454        admin,
455    )
456    .await
457    .unwrap();
458    db.invite_channel_member(zed_channel, member, admin, ChannelRole::Member)
459        .await
460        .unwrap();
461    db.invite_channel_member(zed_channel, guest, admin, ChannelRole::Guest)
462        .await
463        .unwrap();
464
465    db.respond_to_channel_invite(zed_channel, member, true)
466        .await
467        .unwrap();
468
469    db.transaction(|tx| async move {
470        db.check_user_is_channel_participant(
471            &db.get_channel_internal(public_channel_id, &tx).await?,
472            admin,
473            &tx,
474        )
475        .await
476    })
477    .await
478    .unwrap();
479    db.transaction(|tx| async move {
480        db.check_user_is_channel_participant(
481            &db.get_channel_internal(public_channel_id, &tx).await?,
482            member,
483            &tx,
484        )
485        .await
486    })
487    .await
488    .unwrap();
489
490    let (mut members, _) = db
491        .get_channel_participant_details(public_channel_id, "", 100, admin)
492        .await
493        .unwrap();
494
495    members.sort_by_key(|member| member.user_id);
496
497    assert_eq!(
498        members,
499        &[
500            proto::ChannelMember {
501                user_id: admin.to_proto(),
502                kind: proto::channel_member::Kind::Member.into(),
503                role: proto::ChannelRole::Admin.into(),
504            },
505            proto::ChannelMember {
506                user_id: member.to_proto(),
507                kind: proto::channel_member::Kind::Member.into(),
508                role: proto::ChannelRole::Member.into(),
509            },
510            proto::ChannelMember {
511                user_id: guest.to_proto(),
512                kind: proto::channel_member::Kind::Invitee.into(),
513                role: proto::ChannelRole::Guest.into(),
514            },
515        ]
516    );
517
518    db.respond_to_channel_invite(zed_channel, guest, true)
519        .await
520        .unwrap();
521
522    db.transaction(|tx| async move {
523        db.check_user_is_channel_participant(
524            &db.get_channel_internal(public_channel_id, &tx).await?,
525            guest,
526            &tx,
527        )
528        .await
529    })
530    .await
531    .unwrap();
532
533    let channels = db.get_channels_for_user(guest).await.unwrap().channels;
534    assert_channel_tree(
535        channels,
536        &[(zed_channel, &[]), (public_channel_id, &[zed_channel])],
537    );
538    let channels = db.get_channels_for_user(member).await.unwrap().channels;
539    assert_channel_tree(
540        channels,
541        &[
542            (zed_channel, &[]),
543            (internal_channel_id, &[zed_channel]),
544            (public_channel_id, &[zed_channel]),
545        ],
546    );
547
548    db.set_channel_member_role(zed_channel, admin, guest, ChannelRole::Banned)
549        .await
550        .unwrap();
551    assert!(
552        db.transaction(|tx| async move {
553            db.check_user_is_channel_participant(
554                &db.get_channel_internal(public_channel_id, &tx)
555                    .await
556                    .unwrap(),
557                guest,
558                &tx,
559            )
560            .await
561        })
562        .await
563        .is_err()
564    );
565
566    let (mut members, _) = db
567        .get_channel_participant_details(public_channel_id, "", 100, admin)
568        .await
569        .unwrap();
570
571    members.sort_by_key(|member| member.user_id);
572
573    assert_eq!(
574        members,
575        &[
576            proto::ChannelMember {
577                user_id: admin.to_proto(),
578                kind: proto::channel_member::Kind::Member.into(),
579                role: proto::ChannelRole::Admin.into(),
580            },
581            proto::ChannelMember {
582                user_id: member.to_proto(),
583                kind: proto::channel_member::Kind::Member.into(),
584                role: proto::ChannelRole::Member.into(),
585            },
586            proto::ChannelMember {
587                user_id: guest.to_proto(),
588                kind: proto::channel_member::Kind::Member.into(),
589                role: proto::ChannelRole::Banned.into(),
590            },
591        ]
592    );
593
594    db.remove_channel_member(zed_channel, guest, admin)
595        .await
596        .unwrap();
597
598    db.invite_channel_member(zed_channel, guest, admin, ChannelRole::Guest)
599        .await
600        .unwrap();
601
602    // currently people invited to parent channels are not shown here
603    let (mut members, _) = db
604        .get_channel_participant_details(public_channel_id, "", 100, admin)
605        .await
606        .unwrap();
607
608    members.sort_by_key(|member| member.user_id);
609
610    assert_eq!(
611        members,
612        &[
613            proto::ChannelMember {
614                user_id: admin.to_proto(),
615                kind: proto::channel_member::Kind::Member.into(),
616                role: proto::ChannelRole::Admin.into(),
617            },
618            proto::ChannelMember {
619                user_id: member.to_proto(),
620                kind: proto::channel_member::Kind::Member.into(),
621                role: proto::ChannelRole::Member.into(),
622            },
623            proto::ChannelMember {
624                user_id: guest.to_proto(),
625                kind: proto::channel_member::Kind::Invitee.into(),
626                role: proto::ChannelRole::Guest.into(),
627            },
628        ]
629    );
630
631    db.respond_to_channel_invite(zed_channel, guest, true)
632        .await
633        .unwrap();
634
635    db.transaction(|tx| async move {
636        db.check_user_is_channel_participant(
637            &db.get_channel_internal(zed_channel, &tx).await.unwrap(),
638            guest,
639            &tx,
640        )
641        .await
642    })
643    .await
644    .unwrap();
645    assert!(
646        db.transaction(|tx| async move {
647            db.check_user_is_channel_participant(
648                &db.get_channel_internal(internal_channel_id, &tx)
649                    .await
650                    .unwrap(),
651                guest,
652                &tx,
653            )
654            .await
655        })
656        .await
657        .is_err(),
658    );
659
660    db.transaction(|tx| async move {
661        db.check_user_is_channel_participant(
662            &db.get_channel_internal(public_channel_id, &tx)
663                .await
664                .unwrap(),
665            guest,
666            &tx,
667        )
668        .await
669    })
670    .await
671    .unwrap();
672
673    let (mut members, _) = db
674        .get_channel_participant_details(public_channel_id, "", 100, admin)
675        .await
676        .unwrap();
677
678    members.sort_by_key(|member| member.user_id);
679
680    assert_eq!(
681        members,
682        &[
683            proto::ChannelMember {
684                user_id: admin.to_proto(),
685                kind: proto::channel_member::Kind::Member.into(),
686                role: proto::ChannelRole::Admin.into(),
687            },
688            proto::ChannelMember {
689                user_id: member.to_proto(),
690                kind: proto::channel_member::Kind::Member.into(),
691                role: proto::ChannelRole::Member.into(),
692            },
693            proto::ChannelMember {
694                user_id: guest.to_proto(),
695                kind: proto::channel_member::Kind::Member.into(),
696                role: proto::ChannelRole::Guest.into(),
697            },
698        ]
699    );
700
701    let channels = db.get_channels_for_user(guest).await.unwrap().channels;
702    assert_channel_tree(
703        channels,
704        &[(zed_channel, &[]), (public_channel_id, &[zed_channel])],
705    )
706}
707
708test_both_dbs!(
709    test_guest_access,
710    test_guest_access_postgres,
711    test_guest_access_sqlite
712);
713
714async fn test_guest_access(db: &Arc<Database>) {
715    let server = db.create_server("test").await.unwrap();
716
717    let admin = new_test_user(db, "admin@example.com").await;
718    let guest = new_test_user(db, "guest@example.com").await;
719    let guest_connection = new_test_connection(server);
720
721    let zed_channel = db.create_root_channel("zed", admin).await.unwrap();
722    db.set_channel_visibility(zed_channel, crate::db::ChannelVisibility::Public, admin)
723        .await
724        .unwrap();
725
726    assert!(
727        db.join_channel_chat(zed_channel, guest_connection, guest)
728            .await
729            .is_err()
730    );
731
732    db.join_channel(zed_channel, guest, guest_connection)
733        .await
734        .unwrap();
735
736    assert!(
737        db.join_channel_chat(zed_channel, guest_connection, guest)
738            .await
739            .is_ok()
740    )
741}
742
743#[track_caller]
744fn assert_channel_tree(actual: Vec<Channel>, expected: &[(ChannelId, &[ChannelId])]) {
745    let actual = actual
746        .iter()
747        .map(|channel| (channel.id, channel.parent_path.as_slice()))
748        .collect::<Vec<_>>();
749    pretty_assertions::assert_eq!(
750        actual,
751        expected.to_vec(),
752        "wrong channel ids and parent paths"
753    );
754}