channel_tests.rs

  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}