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