channel_tests.rs

  1use crate::{
  2    db::{
  3        tests::{channel_tree, new_test_connection, new_test_user},
  4        Channel, ChannelId, ChannelRole, Database, NewUserParams, RoomId,
  5    },
  6    test_both_dbs,
  7};
  8use rpc::{
  9    proto::{self},
 10    ConnectionId,
 11};
 12use std::sync::Arc;
 13
 14test_both_dbs!(test_channels, test_channels_postgres, test_channels_sqlite);
 15
 16async fn test_channels(db: &Arc<Database>) {
 17    let a_id = new_test_user(db, "user1@example.com").await;
 18    let b_id = new_test_user(db, "user2@example.com").await;
 19
 20    let zed_id = db.create_root_channel("zed", a_id).await.unwrap();
 21
 22    // Make sure that people cannot read channels they haven't been invited to
 23    assert!(db.get_channel(zed_id, b_id).await.is_err());
 24
 25    db.invite_channel_member(zed_id, b_id, a_id, ChannelRole::Member)
 26        .await
 27        .unwrap();
 28
 29    db.respond_to_channel_invite(zed_id, b_id, true)
 30        .await
 31        .unwrap();
 32
 33    let crdb_id = db.create_sub_channel("crdb", zed_id, a_id).await.unwrap();
 34    let livestreaming_id = db
 35        .create_sub_channel("livestreaming", zed_id, a_id)
 36        .await
 37        .unwrap();
 38    let replace_id = db
 39        .create_sub_channel("replace", zed_id, a_id)
 40        .await
 41        .unwrap();
 42
 43    let mut members = db
 44        .transaction(|tx| async move {
 45            let channel = db.get_channel_internal(replace_id, &tx).await?;
 46            db.get_channel_participants(&channel, &tx).await
 47        })
 48        .await
 49        .unwrap();
 50    members.sort();
 51    assert_eq!(members, &[a_id, b_id]);
 52
 53    let rust_id = db.create_root_channel("rust", a_id).await.unwrap();
 54    let cargo_id = db.create_sub_channel("cargo", rust_id, a_id).await.unwrap();
 55
 56    let cargo_ra_id = db
 57        .create_sub_channel("cargo-ra", cargo_id, a_id)
 58        .await
 59        .unwrap();
 60
 61    let result = db.get_channels_for_user(a_id).await.unwrap();
 62    assert_eq!(
 63        result.channels,
 64        channel_tree(&[
 65            (zed_id, &[], "zed"),
 66            (crdb_id, &[zed_id], "crdb"),
 67            (livestreaming_id, &[zed_id], "livestreaming",),
 68            (replace_id, &[zed_id], "replace"),
 69            (rust_id, &[], "rust"),
 70            (cargo_id, &[rust_id], "cargo"),
 71            (cargo_ra_id, &[rust_id, cargo_id], "cargo-ra",)
 72        ],)
 73    );
 74
 75    let result = db.get_channels_for_user(b_id).await.unwrap();
 76    assert_eq!(
 77        result.channels,
 78        channel_tree(&[
 79            (zed_id, &[], "zed"),
 80            (crdb_id, &[zed_id], "crdb"),
 81            (livestreaming_id, &[zed_id], "livestreaming",),
 82            (replace_id, &[zed_id], "replace")
 83        ],)
 84    );
 85
 86    // Update member permissions
 87    let set_subchannel_admin = db
 88        .set_channel_member_role(crdb_id, a_id, b_id, ChannelRole::Admin)
 89        .await;
 90    assert!(set_subchannel_admin.is_err());
 91    let set_channel_admin = db
 92        .set_channel_member_role(zed_id, a_id, b_id, ChannelRole::Admin)
 93        .await;
 94    assert!(set_channel_admin.is_ok());
 95
 96    let result = db.get_channels_for_user(b_id).await.unwrap();
 97    assert_eq!(
 98        result.channels,
 99        channel_tree(&[
100            (zed_id, &[], "zed"),
101            (crdb_id, &[zed_id], "crdb"),
102            (livestreaming_id, &[zed_id], "livestreaming",),
103            (replace_id, &[zed_id], "replace")
104        ],)
105    );
106
107    // Remove a single channel
108    db.delete_channel(crdb_id, a_id).await.unwrap();
109    assert!(db.get_channel(crdb_id, a_id).await.is_err());
110
111    // Remove a channel tree
112    let (mut channel_ids, user_ids) = db.delete_channel(rust_id, a_id).await.unwrap();
113    channel_ids.sort();
114    assert_eq!(channel_ids, &[rust_id, cargo_id, cargo_ra_id]);
115    assert_eq!(user_ids, &[a_id]);
116
117    assert!(db.get_channel(rust_id, a_id).await.is_err());
118    assert!(db.get_channel(cargo_id, a_id).await.is_err());
119    assert!(db.get_channel(cargo_ra_id, a_id).await.is_err());
120}
121
122test_both_dbs!(
123    test_joining_channels,
124    test_joining_channels_postgres,
125    test_joining_channels_sqlite
126);
127
128async fn test_joining_channels(db: &Arc<Database>) {
129    let owner_id = db.create_server("test").await.unwrap().0 as u32;
130
131    let user_1 = new_test_user(db, "user1@example.com").await;
132    let user_2 = new_test_user(db, "user2@example.com").await;
133
134    let channel_1 = db.create_root_channel("channel_1", user_1).await.unwrap();
135
136    // can join a room with membership to its channel
137    let (joined_room, _, _) = db
138        .join_channel(channel_1, user_1, ConnectionId { owner_id, id: 1 })
139        .await
140        .unwrap();
141    assert_eq!(joined_room.room.participants.len(), 1);
142
143    let room_id = RoomId::from_proto(joined_room.room.id);
144    drop(joined_room);
145    // cannot join a room without membership to its channel
146    assert!(db
147        .join_room(room_id, user_2, ConnectionId { owner_id, id: 1 },)
148        .await
149        .is_err());
150}
151
152test_both_dbs!(
153    test_channel_invites,
154    test_channel_invites_postgres,
155    test_channel_invites_sqlite
156);
157
158async fn test_channel_invites(db: &Arc<Database>) {
159    db.create_server("test").await.unwrap();
160
161    let user_1 = new_test_user(db, "user1@example.com").await;
162    let user_2 = new_test_user(db, "user2@example.com").await;
163    let user_3 = new_test_user(db, "user3@example.com").await;
164
165    let channel_1_1 = db.create_root_channel("channel_1", user_1).await.unwrap();
166
167    let channel_1_2 = db.create_root_channel("channel_2", user_1).await.unwrap();
168
169    db.invite_channel_member(channel_1_1, user_2, user_1, ChannelRole::Member)
170        .await
171        .unwrap();
172    db.invite_channel_member(channel_1_2, user_2, user_1, ChannelRole::Member)
173        .await
174        .unwrap();
175    db.invite_channel_member(channel_1_1, user_3, user_1, ChannelRole::Admin)
176        .await
177        .unwrap();
178
179    let user_2_invites = db
180        .get_channel_invites_for_user(user_2) // -> [channel_1_1, channel_1_2]
181        .await
182        .unwrap()
183        .into_iter()
184        .map(|channel| channel.id)
185        .collect::<Vec<_>>();
186
187    assert_eq!(user_2_invites, &[channel_1_1, channel_1_2]);
188
189    let user_3_invites = db
190        .get_channel_invites_for_user(user_3) // -> [channel_1_1]
191        .await
192        .unwrap()
193        .into_iter()
194        .map(|channel| channel.id)
195        .collect::<Vec<_>>();
196
197    assert_eq!(user_3_invites, &[channel_1_1]);
198
199    let mut members = db
200        .get_channel_participant_details(channel_1_1, user_1)
201        .await
202        .unwrap();
203
204    members.sort_by_key(|member| member.user_id);
205    assert_eq!(
206        members,
207        &[
208            proto::ChannelMember {
209                user_id: user_1.to_proto(),
210                kind: proto::channel_member::Kind::Member.into(),
211                role: proto::ChannelRole::Admin.into(),
212            },
213            proto::ChannelMember {
214                user_id: user_2.to_proto(),
215                kind: proto::channel_member::Kind::Invitee.into(),
216                role: proto::ChannelRole::Member.into(),
217            },
218            proto::ChannelMember {
219                user_id: user_3.to_proto(),
220                kind: proto::channel_member::Kind::Invitee.into(),
221                role: proto::ChannelRole::Admin.into(),
222            },
223        ]
224    );
225
226    db.respond_to_channel_invite(channel_1_1, user_2, true)
227        .await
228        .unwrap();
229
230    let channel_1_3 = db
231        .create_sub_channel("channel_3", channel_1_1, user_1)
232        .await
233        .unwrap();
234
235    let members = db
236        .get_channel_participant_details(channel_1_3, user_1)
237        .await
238        .unwrap();
239    assert_eq!(
240        members,
241        &[
242            proto::ChannelMember {
243                user_id: user_1.to_proto(),
244                kind: proto::channel_member::Kind::Member.into(),
245                role: proto::ChannelRole::Admin.into(),
246            },
247            proto::ChannelMember {
248                user_id: user_2.to_proto(),
249                kind: proto::channel_member::Kind::Member.into(),
250                role: proto::ChannelRole::Member.into(),
251            },
252            proto::ChannelMember {
253                user_id: user_3.to_proto(),
254                kind: proto::channel_member::Kind::Invitee.into(),
255                role: proto::ChannelRole::Admin.into(),
256            },
257        ]
258    );
259}
260
261test_both_dbs!(
262    test_channel_renames,
263    test_channel_renames_postgres,
264    test_channel_renames_sqlite
265);
266
267async fn test_channel_renames(db: &Arc<Database>) {
268    db.create_server("test").await.unwrap();
269
270    let user_1 = db
271        .create_user(
272            "user1@example.com",
273            false,
274            NewUserParams {
275                github_login: "user1".into(),
276                github_user_id: 5,
277            },
278        )
279        .await
280        .unwrap()
281        .user_id;
282
283    let user_2 = db
284        .create_user(
285            "user2@example.com",
286            false,
287            NewUserParams {
288                github_login: "user2".into(),
289                github_user_id: 6,
290            },
291        )
292        .await
293        .unwrap()
294        .user_id;
295
296    let zed_id = db.create_root_channel("zed", user_1).await.unwrap();
297
298    db.rename_channel(zed_id, user_1, "#zed-archive")
299        .await
300        .unwrap();
301
302    let channel = db.get_channel(zed_id, user_1).await.unwrap();
303    assert_eq!(channel.name, "zed-archive");
304
305    let non_permissioned_rename = db.rename_channel(zed_id, user_2, "hacked-lol").await;
306    assert!(non_permissioned_rename.is_err());
307
308    let bad_name_rename = db.rename_channel(zed_id, user_1, "#").await;
309    assert!(bad_name_rename.is_err())
310}
311
312test_both_dbs!(
313    test_db_channel_moving,
314    test_channels_moving_postgres,
315    test_channels_moving_sqlite
316);
317
318async fn test_db_channel_moving(db: &Arc<Database>) {
319    let a_id = db
320        .create_user(
321            "user1@example.com",
322            false,
323            NewUserParams {
324                github_login: "user1".into(),
325                github_user_id: 5,
326            },
327        )
328        .await
329        .unwrap()
330        .user_id;
331
332    let zed_id = db.create_root_channel("zed", a_id).await.unwrap();
333
334    let crdb_id = db.create_sub_channel("crdb", zed_id, a_id).await.unwrap();
335
336    let gpui2_id = db.create_sub_channel("gpui2", zed_id, a_id).await.unwrap();
337
338    let livestreaming_id = db
339        .create_sub_channel("livestreaming", crdb_id, a_id)
340        .await
341        .unwrap();
342
343    let livestreaming_dag_id = db
344        .create_sub_channel("livestreaming_dag", livestreaming_id, a_id)
345        .await
346        .unwrap();
347
348    // ========================================================================
349    // sanity check
350    // Initial DAG:
351    //     /- gpui2
352    // zed -- crdb - livestreaming - livestreaming_dag
353    let result = db.get_channels_for_user(a_id).await.unwrap();
354    assert_channel_tree(
355        result.channels,
356        &[
357            (zed_id, &[]),
358            (crdb_id, &[zed_id]),
359            (livestreaming_id, &[zed_id, crdb_id]),
360            (livestreaming_dag_id, &[zed_id, crdb_id, livestreaming_id]),
361            (gpui2_id, &[zed_id]),
362        ],
363    );
364}
365
366test_both_dbs!(
367    test_db_channel_moving_bugs,
368    test_db_channel_moving_bugs_postgres,
369    test_db_channel_moving_bugs_sqlite
370);
371
372async fn test_db_channel_moving_bugs(db: &Arc<Database>) {
373    let user_id = db
374        .create_user(
375            "user1@example.com",
376            false,
377            NewUserParams {
378                github_login: "user1".into(),
379                github_user_id: 5,
380            },
381        )
382        .await
383        .unwrap()
384        .user_id;
385
386    let zed_id = db.create_root_channel("zed", user_id).await.unwrap();
387
388    let projects_id = db
389        .create_sub_channel("projects", zed_id, user_id)
390        .await
391        .unwrap();
392
393    let livestreaming_id = db
394        .create_sub_channel("livestreaming", projects_id, user_id)
395        .await
396        .unwrap();
397
398    let result = db.get_channels_for_user(user_id).await.unwrap();
399    assert_channel_tree(
400        result.channels,
401        &[
402            (zed_id, &[]),
403            (projects_id, &[zed_id]),
404            (livestreaming_id, &[zed_id, projects_id]),
405        ],
406    );
407
408    // Can't move a channel into its ancestor
409    db.move_channel(projects_id, livestreaming_id, user_id)
410        .await
411        .unwrap_err();
412    let result = db.get_channels_for_user(user_id).await.unwrap();
413    assert_channel_tree(
414        result.channels,
415        &[
416            (zed_id, &[]),
417            (projects_id, &[zed_id]),
418            (livestreaming_id, &[zed_id, projects_id]),
419        ],
420    );
421}
422
423test_both_dbs!(
424    test_user_is_channel_participant,
425    test_user_is_channel_participant_postgres,
426    test_user_is_channel_participant_sqlite
427);
428
429async fn test_user_is_channel_participant(db: &Arc<Database>) {
430    let admin = new_test_user(db, "admin@example.com").await;
431    let member = new_test_user(db, "member@example.com").await;
432    let guest = new_test_user(db, "guest@example.com").await;
433
434    let zed_channel = db.create_root_channel("zed", admin).await.unwrap();
435    let internal_channel_id = db
436        .create_sub_channel("active", zed_channel, admin)
437        .await
438        .unwrap();
439    let public_channel_id = db
440        .create_sub_channel("vim", zed_channel, admin)
441        .await
442        .unwrap();
443
444    db.set_channel_visibility(zed_channel, crate::db::ChannelVisibility::Public, admin)
445        .await
446        .unwrap();
447    db.set_channel_visibility(
448        public_channel_id,
449        crate::db::ChannelVisibility::Public,
450        admin,
451    )
452    .await
453    .unwrap();
454    db.invite_channel_member(zed_channel, member, admin, ChannelRole::Member)
455        .await
456        .unwrap();
457    db.invite_channel_member(zed_channel, guest, admin, ChannelRole::Guest)
458        .await
459        .unwrap();
460
461    db.respond_to_channel_invite(zed_channel, member, true)
462        .await
463        .unwrap();
464
465    db.transaction(|tx| async move {
466        db.check_user_is_channel_participant(
467            &db.get_channel_internal(public_channel_id, &tx).await?,
468            admin,
469            &tx,
470        )
471        .await
472    })
473    .await
474    .unwrap();
475    db.transaction(|tx| async move {
476        db.check_user_is_channel_participant(
477            &db.get_channel_internal(public_channel_id, &tx).await?,
478            member,
479            &tx,
480        )
481        .await
482    })
483    .await
484    .unwrap();
485
486    let mut members = db
487        .get_channel_participant_details(public_channel_id, admin)
488        .await
489        .unwrap();
490
491    members.sort_by_key(|member| member.user_id);
492
493    assert_eq!(
494        members,
495        &[
496            proto::ChannelMember {
497                user_id: admin.to_proto(),
498                kind: proto::channel_member::Kind::Member.into(),
499                role: proto::ChannelRole::Admin.into(),
500            },
501            proto::ChannelMember {
502                user_id: member.to_proto(),
503                kind: proto::channel_member::Kind::Member.into(),
504                role: proto::ChannelRole::Member.into(),
505            },
506            proto::ChannelMember {
507                user_id: guest.to_proto(),
508                kind: proto::channel_member::Kind::Invitee.into(),
509                role: proto::ChannelRole::Guest.into(),
510            },
511        ]
512    );
513
514    db.respond_to_channel_invite(zed_channel, guest, true)
515        .await
516        .unwrap();
517
518    db.transaction(|tx| async move {
519        db.check_user_is_channel_participant(
520            &db.get_channel_internal(public_channel_id, &tx).await?,
521            guest,
522            &tx,
523        )
524        .await
525    })
526    .await
527    .unwrap();
528
529    let channels = db.get_channels_for_user(guest).await.unwrap().channels;
530    assert_channel_tree(
531        channels,
532        &[(zed_channel, &[]), (public_channel_id, &[zed_channel])],
533    );
534    let channels = db.get_channels_for_user(member).await.unwrap().channels;
535    assert_channel_tree(
536        channels,
537        &[
538            (zed_channel, &[]),
539            (internal_channel_id, &[zed_channel]),
540            (public_channel_id, &[zed_channel]),
541        ],
542    );
543
544    db.set_channel_member_role(zed_channel, admin, guest, ChannelRole::Banned)
545        .await
546        .unwrap();
547    assert!(db
548        .transaction(|tx| async move {
549            db.check_user_is_channel_participant(
550                &db.get_channel_internal(public_channel_id, &tx)
551                    .await
552                    .unwrap(),
553                guest,
554                &tx,
555            )
556            .await
557        })
558        .await
559        .is_err());
560
561    let mut members = db
562        .get_channel_participant_details(public_channel_id, admin)
563        .await
564        .unwrap();
565
566    members.sort_by_key(|member| member.user_id);
567
568    assert_eq!(
569        members,
570        &[
571            proto::ChannelMember {
572                user_id: admin.to_proto(),
573                kind: proto::channel_member::Kind::Member.into(),
574                role: proto::ChannelRole::Admin.into(),
575            },
576            proto::ChannelMember {
577                user_id: member.to_proto(),
578                kind: proto::channel_member::Kind::Member.into(),
579                role: proto::ChannelRole::Member.into(),
580            },
581            proto::ChannelMember {
582                user_id: guest.to_proto(),
583                kind: proto::channel_member::Kind::Member.into(),
584                role: proto::ChannelRole::Banned.into(),
585            },
586        ]
587    );
588
589    db.remove_channel_member(zed_channel, guest, admin)
590        .await
591        .unwrap();
592
593    db.invite_channel_member(zed_channel, guest, admin, ChannelRole::Guest)
594        .await
595        .unwrap();
596
597    // currently people invited to parent channels are not shown here
598    let mut members = db
599        .get_channel_participant_details(public_channel_id, admin)
600        .await
601        .unwrap();
602
603    members.sort_by_key(|member| member.user_id);
604
605    assert_eq!(
606        members,
607        &[
608            proto::ChannelMember {
609                user_id: admin.to_proto(),
610                kind: proto::channel_member::Kind::Member.into(),
611                role: proto::ChannelRole::Admin.into(),
612            },
613            proto::ChannelMember {
614                user_id: member.to_proto(),
615                kind: proto::channel_member::Kind::Member.into(),
616                role: proto::ChannelRole::Member.into(),
617            },
618            proto::ChannelMember {
619                user_id: guest.to_proto(),
620                kind: proto::channel_member::Kind::Invitee.into(),
621                role: proto::ChannelRole::Guest.into(),
622            },
623        ]
624    );
625
626    db.respond_to_channel_invite(zed_channel, guest, true)
627        .await
628        .unwrap();
629
630    db.transaction(|tx| async move {
631        db.check_user_is_channel_participant(
632            &db.get_channel_internal(zed_channel, &tx).await.unwrap(),
633            guest,
634            &tx,
635        )
636        .await
637    })
638    .await
639    .unwrap();
640    assert!(db
641        .transaction(|tx| async move {
642            db.check_user_is_channel_participant(
643                &db.get_channel_internal(internal_channel_id, &tx)
644                    .await
645                    .unwrap(),
646                guest,
647                &tx,
648            )
649            .await
650        })
651        .await
652        .is_err(),);
653
654    db.transaction(|tx| async move {
655        db.check_user_is_channel_participant(
656            &db.get_channel_internal(public_channel_id, &tx)
657                .await
658                .unwrap(),
659            guest,
660            &tx,
661        )
662        .await
663    })
664    .await
665    .unwrap();
666
667    let mut members = db
668        .get_channel_participant_details(public_channel_id, admin)
669        .await
670        .unwrap();
671
672    members.sort_by_key(|member| member.user_id);
673
674    assert_eq!(
675        members,
676        &[
677            proto::ChannelMember {
678                user_id: admin.to_proto(),
679                kind: proto::channel_member::Kind::Member.into(),
680                role: proto::ChannelRole::Admin.into(),
681            },
682            proto::ChannelMember {
683                user_id: member.to_proto(),
684                kind: proto::channel_member::Kind::Member.into(),
685                role: proto::ChannelRole::Member.into(),
686            },
687            proto::ChannelMember {
688                user_id: guest.to_proto(),
689                kind: proto::channel_member::Kind::Member.into(),
690                role: proto::ChannelRole::Guest.into(),
691            },
692        ]
693    );
694
695    let channels = db.get_channels_for_user(guest).await.unwrap().channels;
696    assert_channel_tree(
697        channels,
698        &[(zed_channel, &[]), (public_channel_id, &[zed_channel])],
699    )
700}
701
702test_both_dbs!(
703    test_guest_access,
704    test_guest_access_postgres,
705    test_guest_access_sqlite
706);
707
708async fn test_guest_access(db: &Arc<Database>) {
709    let server = db.create_server("test").await.unwrap();
710
711    let admin = new_test_user(db, "admin@example.com").await;
712    let guest = new_test_user(db, "guest@example.com").await;
713    let guest_connection = new_test_connection(server);
714
715    let zed_channel = db.create_root_channel("zed", admin).await.unwrap();
716    db.set_channel_visibility(zed_channel, crate::db::ChannelVisibility::Public, admin)
717        .await
718        .unwrap();
719
720    assert!(db
721        .join_channel_chat(zed_channel, guest_connection, guest)
722        .await
723        .is_err());
724
725    db.join_channel(zed_channel, guest, guest_connection)
726        .await
727        .unwrap();
728
729    assert!(db
730        .join_channel_chat(zed_channel, guest_connection, guest)
731        .await
732        .is_ok())
733}
734
735#[track_caller]
736fn assert_channel_tree(actual: Vec<Channel>, expected: &[(ChannelId, &[ChannelId])]) {
737    let actual = actual
738        .iter()
739        .map(|channel| (channel.id, channel.parent_path.as_slice()))
740        .collect::<Vec<_>>();
741    pretty_assertions::assert_eq!(
742        actual,
743        expected.to_vec(),
744        "wrong channel ids and parent paths"
745    );
746}