channel_tests.rs

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