channel_tests.rs

   1use crate::{
   2    db::{
   3        Channel, ChannelId, ChannelRole, Database, NewUserParams, RoomId, UserId,
   4        tests::{assert_channel_tree_matches, channel_tree, new_test_connection, new_test_user},
   5    },
   6    test_both_dbs,
   7};
   8use rpc::{
   9    ConnectionId,
  10    proto::{self, reorder_channel},
  11};
  12use std::{collections::HashSet, 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_channel_tree_matches(
  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_channel_tree_matches(
  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_channel_tree_matches(
  98        result.channels,
  99        channel_tree(&[
 100            (zed_id, &[], "zed"),
 101            (crdb_id, &[zed_id], "crdb"),
 102            (livestreaming_id, &[zed_id], "livestreaming"),
 103            (replace_id, &[zed_id], "replace"),
 104        ]),
 105    );
 106
 107    // Remove a single channel
 108    db.delete_channel(crdb_id, a_id).await.unwrap();
 109    assert!(db.get_channel(crdb_id, a_id).await.is_err());
 110
 111    // Remove a channel tree
 112    let (_, mut channel_ids) = db.delete_channel(rust_id, a_id).await.unwrap();
 113    channel_ids.sort();
 114    assert_eq!(channel_ids, &[rust_id, cargo_id, cargo_ra_id]);
 115
 116    assert!(db.get_channel(rust_id, a_id).await.is_err());
 117    assert!(db.get_channel(cargo_id, a_id).await.is_err());
 118    assert!(db.get_channel(cargo_ra_id, a_id).await.is_err());
 119}
 120
 121test_both_dbs!(
 122    test_joining_channels,
 123    test_joining_channels_postgres,
 124    test_joining_channels_sqlite
 125);
 126
 127async fn test_joining_channels(db: &Arc<Database>) {
 128    let owner_id = db.create_server("test").await.unwrap().0 as u32;
 129
 130    let user_1 = new_test_user(db, "user1@example.com").await;
 131    let user_2 = new_test_user(db, "user2@example.com").await;
 132
 133    let channel_1 = db.create_root_channel("channel_1", user_1).await.unwrap();
 134
 135    // can join a room with membership to its channel
 136    let (joined_room, _, _) = db
 137        .join_channel(channel_1, user_1, ConnectionId { owner_id, id: 1 })
 138        .await
 139        .unwrap();
 140    assert_eq!(joined_room.room.participants.len(), 1);
 141
 142    let room_id = RoomId::from_proto(joined_room.room.id);
 143    drop(joined_room);
 144    // cannot join a room without membership to its channel
 145    assert!(
 146        db.join_room(room_id, user_2, ConnectionId { owner_id, id: 1 },)
 147            .await
 148            .is_err()
 149    );
 150}
 151
 152test_both_dbs!(
 153    test_channel_invites,
 154    test_channel_invites_postgres,
 155    test_channel_invites_sqlite
 156);
 157
 158async fn test_channel_invites(db: &Arc<Database>) {
 159    db.create_server("test").await.unwrap();
 160
 161    let user_1 = new_test_user(db, "user1@example.com").await;
 162    let user_2 = new_test_user(db, "user2@example.com").await;
 163    let user_3 = new_test_user(db, "user3@example.com").await;
 164
 165    let channel_1_1 = db.create_root_channel("channel_1", user_1).await.unwrap();
 166
 167    let channel_1_2 = db.create_root_channel("channel_2", user_1).await.unwrap();
 168
 169    db.invite_channel_member(channel_1_1, user_2, user_1, ChannelRole::Member)
 170        .await
 171        .unwrap();
 172    db.invite_channel_member(channel_1_2, user_2, user_1, ChannelRole::Member)
 173        .await
 174        .unwrap();
 175    db.invite_channel_member(channel_1_1, user_3, user_1, ChannelRole::Admin)
 176        .await
 177        .unwrap();
 178
 179    let user_2_invites = db
 180        .get_channels_for_user(user_2)
 181        .await
 182        .unwrap()
 183        .invited_channels
 184        .into_iter()
 185        .map(|channel| channel.id)
 186        .collect::<Vec<_>>();
 187    assert_eq!(user_2_invites, &[channel_1_1, channel_1_2]);
 188
 189    let user_3_invites = db
 190        .get_channels_for_user(user_3)
 191        .await
 192        .unwrap()
 193        .invited_channels
 194        .into_iter()
 195        .map(|channel| channel.id)
 196        .collect::<Vec<_>>();
 197    assert_eq!(user_3_invites, &[channel_1_1]);
 198
 199    let (mut members, _) = db
 200        .get_channel_participant_details(channel_1_1, "", 100, user_1)
 201        .await
 202        .unwrap();
 203
 204    members.sort_by_key(|member| member.user_id);
 205    assert_eq!(
 206        members,
 207        &[
 208            proto::ChannelMember {
 209                user_id: user_1.to_proto(),
 210                kind: proto::channel_member::Kind::Member.into(),
 211                role: proto::ChannelRole::Admin.into(),
 212            },
 213            proto::ChannelMember {
 214                user_id: user_2.to_proto(),
 215                kind: proto::channel_member::Kind::Invitee.into(),
 216                role: proto::ChannelRole::Member.into(),
 217            },
 218            proto::ChannelMember {
 219                user_id: user_3.to_proto(),
 220                kind: proto::channel_member::Kind::Invitee.into(),
 221                role: proto::ChannelRole::Admin.into(),
 222            },
 223        ]
 224    );
 225
 226    db.respond_to_channel_invite(channel_1_1, user_2, true)
 227        .await
 228        .unwrap();
 229
 230    let channel_1_3 = db
 231        .create_sub_channel("channel_3", channel_1_1, user_1)
 232        .await
 233        .unwrap();
 234
 235    let (members, _) = db
 236        .get_channel_participant_details(channel_1_3, "", 100, user_1)
 237        .await
 238        .unwrap();
 239    assert_eq!(
 240        members,
 241        &[
 242            proto::ChannelMember {
 243                user_id: user_1.to_proto(),
 244                kind: proto::channel_member::Kind::Member.into(),
 245                role: proto::ChannelRole::Admin.into(),
 246            },
 247            proto::ChannelMember {
 248                user_id: user_3.to_proto(),
 249                kind: proto::channel_member::Kind::Invitee.into(),
 250                role: proto::ChannelRole::Admin.into(),
 251            },
 252            proto::ChannelMember {
 253                user_id: user_2.to_proto(),
 254                kind: proto::channel_member::Kind::Member.into(),
 255                role: proto::ChannelRole::Member.into(),
 256            },
 257        ]
 258    );
 259}
 260
 261test_both_dbs!(
 262    test_channel_renames,
 263    test_channel_renames_postgres,
 264    test_channel_renames_sqlite
 265);
 266
 267async fn test_channel_renames(db: &Arc<Database>) {
 268    db.create_server("test").await.unwrap();
 269
 270    let user_1 = db
 271        .create_user(
 272            "user1@example.com",
 273            None,
 274            false,
 275            NewUserParams {
 276                github_login: "user1".into(),
 277                github_user_id: 5,
 278            },
 279        )
 280        .await
 281        .unwrap()
 282        .user_id;
 283
 284    let user_2 = db
 285        .create_user(
 286            "user2@example.com",
 287            None,
 288            false,
 289            NewUserParams {
 290                github_login: "user2".into(),
 291                github_user_id: 6,
 292            },
 293        )
 294        .await
 295        .unwrap()
 296        .user_id;
 297
 298    let zed_id = db.create_root_channel("zed", user_1).await.unwrap();
 299
 300    db.rename_channel(zed_id, user_1, "#zed-archive")
 301        .await
 302        .unwrap();
 303
 304    let channel = db.get_channel(zed_id, user_1).await.unwrap();
 305    assert_eq!(channel.name, "zed-archive");
 306
 307    let non_permissioned_rename = db.rename_channel(zed_id, user_2, "hacked-lol").await;
 308    assert!(non_permissioned_rename.is_err());
 309
 310    let bad_name_rename = db.rename_channel(zed_id, user_1, "#").await;
 311    assert!(bad_name_rename.is_err())
 312}
 313
 314test_both_dbs!(
 315    test_db_channel_moving,
 316    test_db_channel_moving_postgres,
 317    test_db_channel_moving_sqlite
 318);
 319
 320async fn test_db_channel_moving(db: &Arc<Database>) {
 321    let a_id = db
 322        .create_user(
 323            "user1@example.com",
 324            None,
 325            false,
 326            NewUserParams {
 327                github_login: "user1".into(),
 328                github_user_id: 5,
 329            },
 330        )
 331        .await
 332        .unwrap()
 333        .user_id;
 334
 335    let zed_id = db.create_root_channel("zed", a_id).await.unwrap();
 336
 337    let crdb_id = db.create_sub_channel("crdb", zed_id, a_id).await.unwrap();
 338
 339    let gpui2_id = db.create_sub_channel("gpui2", zed_id, a_id).await.unwrap();
 340
 341    let livestreaming_id = db
 342        .create_sub_channel("livestreaming", crdb_id, a_id)
 343        .await
 344        .unwrap();
 345
 346    let livestreaming_sub_id = db
 347        .create_sub_channel("livestreaming_sub", livestreaming_id, a_id)
 348        .await
 349        .unwrap();
 350
 351    // sanity check
 352    //     /- gpui2
 353    // zed -- crdb - livestreaming - livestreaming_sub
 354    let result = db.get_channels_for_user(a_id).await.unwrap();
 355    assert_channel_tree(
 356        result.channels,
 357        &[
 358            (zed_id, &[]),
 359            (crdb_id, &[zed_id]),
 360            (livestreaming_id, &[zed_id, crdb_id]),
 361            (livestreaming_sub_id, &[zed_id, crdb_id, livestreaming_id]),
 362            (gpui2_id, &[zed_id]),
 363        ],
 364    );
 365
 366    // Check that we can do a simple leaf -> leaf move
 367    db.move_channel(livestreaming_sub_id, crdb_id, a_id)
 368        .await
 369        .unwrap();
 370
 371    //     /- gpui2
 372    // zed -- crdb -- livestreaming
 373    //             \- livestreaming_sub
 374    let result = db.get_channels_for_user(a_id).await.unwrap();
 375    assert_channel_tree(
 376        result.channels,
 377        &[
 378            (zed_id, &[]),
 379            (crdb_id, &[zed_id]),
 380            (livestreaming_id, &[zed_id, crdb_id]),
 381            (livestreaming_sub_id, &[zed_id, crdb_id]),
 382            (gpui2_id, &[zed_id]),
 383        ],
 384    );
 385
 386    // Check that we can move a whole subtree at once
 387    db.move_channel(crdb_id, gpui2_id, a_id).await.unwrap();
 388
 389    // zed -- gpui2 -- crdb -- livestreaming
 390    //                      \- livestreaming_sub
 391    let result = db.get_channels_for_user(a_id).await.unwrap();
 392    assert_channel_tree(
 393        result.channels,
 394        &[
 395            (zed_id, &[]),
 396            (gpui2_id, &[zed_id]),
 397            (crdb_id, &[zed_id, gpui2_id]),
 398            (livestreaming_id, &[zed_id, gpui2_id, crdb_id]),
 399            (livestreaming_sub_id, &[zed_id, gpui2_id, crdb_id]),
 400        ],
 401    );
 402}
 403
 404test_both_dbs!(
 405    test_channel_reordering,
 406    test_channel_reordering_postgres,
 407    test_channel_reordering_sqlite
 408);
 409
 410async fn test_channel_reordering(db: &Arc<Database>) {
 411    let admin_id = db
 412        .create_user(
 413            "admin@example.com",
 414            None,
 415            false,
 416            NewUserParams {
 417                github_login: "admin".into(),
 418                github_user_id: 1,
 419            },
 420        )
 421        .await
 422        .unwrap()
 423        .user_id;
 424
 425    let user_id = db
 426        .create_user(
 427            "user@example.com",
 428            None,
 429            false,
 430            NewUserParams {
 431                github_login: "user".into(),
 432                github_user_id: 2,
 433            },
 434        )
 435        .await
 436        .unwrap()
 437        .user_id;
 438
 439    // Create a root channel with some sub-channels
 440    let root_id = db.create_root_channel("root", admin_id).await.unwrap();
 441
 442    // Invite user to root channel so they can see the sub-channels
 443    db.invite_channel_member(root_id, user_id, admin_id, ChannelRole::Member)
 444        .await
 445        .unwrap();
 446    db.respond_to_channel_invite(root_id, user_id, true)
 447        .await
 448        .unwrap();
 449
 450    let alpha_id = db
 451        .create_sub_channel("alpha", root_id, admin_id)
 452        .await
 453        .unwrap();
 454    let beta_id = db
 455        .create_sub_channel("beta", root_id, admin_id)
 456        .await
 457        .unwrap();
 458    let gamma_id = db
 459        .create_sub_channel("gamma", root_id, admin_id)
 460        .await
 461        .unwrap();
 462
 463    // Initial order should be: root, alpha (order=1), beta (order=2), gamma (order=3)
 464    let result = db.get_channels_for_user(admin_id).await.unwrap();
 465    assert_channel_tree_order(
 466        result.channels,
 467        &[
 468            (root_id, &[], 1),
 469            (alpha_id, &[root_id], 1),
 470            (beta_id, &[root_id], 2),
 471            (gamma_id, &[root_id], 3),
 472        ],
 473    );
 474
 475    // Test moving beta up (should swap with alpha)
 476    let updated_channels = db
 477        .reorder_channel(beta_id, reorder_channel::Direction::Up, admin_id)
 478        .await
 479        .unwrap();
 480
 481    // Verify that beta and alpha were returned as updated
 482    assert_eq!(updated_channels.len(), 2);
 483    let updated_ids: std::collections::HashSet<_> = updated_channels.iter().map(|c| c.id).collect();
 484    assert!(updated_ids.contains(&alpha_id));
 485    assert!(updated_ids.contains(&beta_id));
 486
 487    // Now order should be: root, beta (order=1), alpha (order=2), gamma (order=3)
 488    let result = db.get_channels_for_user(admin_id).await.unwrap();
 489    assert_channel_tree_order(
 490        result.channels,
 491        &[
 492            (root_id, &[], 1),
 493            (beta_id, &[root_id], 1),
 494            (alpha_id, &[root_id], 2),
 495            (gamma_id, &[root_id], 3),
 496        ],
 497    );
 498
 499    // Test moving gamma down (should be no-op since it's already last)
 500    let updated_channels = db
 501        .reorder_channel(gamma_id, reorder_channel::Direction::Down, admin_id)
 502        .await
 503        .unwrap();
 504
 505    // Should return just nothing
 506    assert_eq!(updated_channels.len(), 0);
 507
 508    // Test moving alpha down (should swap with gamma)
 509    let updated_channels = db
 510        .reorder_channel(alpha_id, reorder_channel::Direction::Down, admin_id)
 511        .await
 512        .unwrap();
 513
 514    // Verify that alpha and gamma were returned as updated
 515    assert_eq!(updated_channels.len(), 2);
 516    let updated_ids: std::collections::HashSet<_> = updated_channels.iter().map(|c| c.id).collect();
 517    assert!(updated_ids.contains(&alpha_id));
 518    assert!(updated_ids.contains(&gamma_id));
 519
 520    // Now order should be: root, beta (order=1), gamma (order=2), alpha (order=3)
 521    let result = db.get_channels_for_user(admin_id).await.unwrap();
 522    assert_channel_tree_order(
 523        result.channels,
 524        &[
 525            (root_id, &[], 1),
 526            (beta_id, &[root_id], 1),
 527            (gamma_id, &[root_id], 2),
 528            (alpha_id, &[root_id], 3),
 529        ],
 530    );
 531
 532    // Test that non-admin cannot reorder
 533    let reorder_result = db
 534        .reorder_channel(beta_id, reorder_channel::Direction::Up, user_id)
 535        .await;
 536    assert!(reorder_result.is_err());
 537
 538    // Test moving beta up (should be no-op since it's already first)
 539    let updated_channels = db
 540        .reorder_channel(beta_id, reorder_channel::Direction::Up, admin_id)
 541        .await
 542        .unwrap();
 543
 544    // Should return nothing
 545    assert_eq!(updated_channels.len(), 0);
 546
 547    // Adding a channel to an existing ordering should add it to the end
 548    let delta_id = db
 549        .create_sub_channel("delta", root_id, admin_id)
 550        .await
 551        .unwrap();
 552
 553    let result = db.get_channels_for_user(admin_id).await.unwrap();
 554    assert_channel_tree_order(
 555        result.channels,
 556        &[
 557            (root_id, &[], 1),
 558            (beta_id, &[root_id], 1),
 559            (gamma_id, &[root_id], 2),
 560            (alpha_id, &[root_id], 3),
 561            (delta_id, &[root_id], 4),
 562        ],
 563    );
 564
 565    // And moving a channel into an existing ordering should add it to the end
 566    let eta_id = db
 567        .create_sub_channel("eta", delta_id, admin_id)
 568        .await
 569        .unwrap();
 570
 571    let result = db.get_channels_for_user(admin_id).await.unwrap();
 572    assert_channel_tree_order(
 573        result.channels,
 574        &[
 575            (root_id, &[], 1),
 576            (beta_id, &[root_id], 1),
 577            (gamma_id, &[root_id], 2),
 578            (alpha_id, &[root_id], 3),
 579            (delta_id, &[root_id], 4),
 580            (eta_id, &[root_id, delta_id], 1),
 581        ],
 582    );
 583
 584    db.move_channel(eta_id, root_id, admin_id).await.unwrap();
 585    let result = db.get_channels_for_user(admin_id).await.unwrap();
 586    assert_channel_tree_order(
 587        result.channels,
 588        &[
 589            (root_id, &[], 1),
 590            (beta_id, &[root_id], 1),
 591            (gamma_id, &[root_id], 2),
 592            (alpha_id, &[root_id], 3),
 593            (delta_id, &[root_id], 4),
 594            (eta_id, &[root_id], 5),
 595        ],
 596    );
 597}
 598
 599test_both_dbs!(
 600    test_db_channel_moving_bugs,
 601    test_db_channel_moving_bugs_postgres,
 602    test_db_channel_moving_bugs_sqlite
 603);
 604
 605async fn test_db_channel_moving_bugs(db: &Arc<Database>) {
 606    let user_id = db
 607        .create_user(
 608            "user1@example.com",
 609            None,
 610            false,
 611            NewUserParams {
 612                github_login: "user1".into(),
 613                github_user_id: 5,
 614            },
 615        )
 616        .await
 617        .unwrap()
 618        .user_id;
 619
 620    let zed_id = db.create_root_channel("zed", user_id).await.unwrap();
 621
 622    let projects_id = db
 623        .create_sub_channel("projects", zed_id, user_id)
 624        .await
 625        .unwrap();
 626
 627    let livestreaming_id = db
 628        .create_sub_channel("livestreaming", projects_id, user_id)
 629        .await
 630        .unwrap();
 631
 632    let result = db.get_channels_for_user(user_id).await.unwrap();
 633    assert_channel_tree(
 634        result.channels,
 635        &[
 636            (zed_id, &[]),
 637            (projects_id, &[zed_id]),
 638            (livestreaming_id, &[zed_id, projects_id]),
 639        ],
 640    );
 641
 642    // Can't move a channel into its ancestor
 643    db.move_channel(projects_id, livestreaming_id, user_id)
 644        .await
 645        .unwrap_err();
 646    let result = db.get_channels_for_user(user_id).await.unwrap();
 647    assert_channel_tree(
 648        result.channels,
 649        &[
 650            (zed_id, &[]),
 651            (projects_id, &[zed_id]),
 652            (livestreaming_id, &[zed_id, projects_id]),
 653        ],
 654    );
 655
 656    // Can't un-root a root channel
 657    db.move_channel(zed_id, livestreaming_id, user_id)
 658        .await
 659        .unwrap_err();
 660    let result = db.get_channels_for_user(user_id).await.unwrap();
 661    assert_channel_tree(
 662        result.channels,
 663        &[
 664            (zed_id, &[]),
 665            (projects_id, &[zed_id]),
 666            (livestreaming_id, &[zed_id, projects_id]),
 667        ],
 668    );
 669}
 670
 671test_both_dbs!(
 672    test_user_is_channel_participant,
 673    test_user_is_channel_participant_postgres,
 674    test_user_is_channel_participant_sqlite
 675);
 676
 677async fn test_user_is_channel_participant(db: &Arc<Database>) {
 678    let admin = new_test_user(db, "admin@example.com").await;
 679    let member = new_test_user(db, "member@example.com").await;
 680    let guest = new_test_user(db, "guest@example.com").await;
 681
 682    let zed_channel = db.create_root_channel("zed", admin).await.unwrap();
 683    let internal_channel_id = db
 684        .create_sub_channel("active", zed_channel, admin)
 685        .await
 686        .unwrap();
 687    let public_channel_id = db
 688        .create_sub_channel("vim", zed_channel, admin)
 689        .await
 690        .unwrap();
 691
 692    db.set_channel_visibility(zed_channel, crate::db::ChannelVisibility::Public, admin)
 693        .await
 694        .unwrap();
 695    db.set_channel_visibility(
 696        public_channel_id,
 697        crate::db::ChannelVisibility::Public,
 698        admin,
 699    )
 700    .await
 701    .unwrap();
 702    db.invite_channel_member(zed_channel, member, admin, ChannelRole::Member)
 703        .await
 704        .unwrap();
 705    db.invite_channel_member(zed_channel, guest, admin, ChannelRole::Guest)
 706        .await
 707        .unwrap();
 708
 709    db.respond_to_channel_invite(zed_channel, member, true)
 710        .await
 711        .unwrap();
 712
 713    db.transaction(|tx| async move {
 714        db.check_user_is_channel_participant(
 715            &db.get_channel_internal(public_channel_id, &tx).await?,
 716            admin,
 717            &tx,
 718        )
 719        .await
 720    })
 721    .await
 722    .unwrap();
 723    db.transaction(|tx| async move {
 724        db.check_user_is_channel_participant(
 725            &db.get_channel_internal(public_channel_id, &tx).await?,
 726            member,
 727            &tx,
 728        )
 729        .await
 730    })
 731    .await
 732    .unwrap();
 733
 734    let (mut members, _) = db
 735        .get_channel_participant_details(public_channel_id, "", 100, admin)
 736        .await
 737        .unwrap();
 738
 739    members.sort_by_key(|member| member.user_id);
 740
 741    assert_eq!(
 742        members,
 743        &[
 744            proto::ChannelMember {
 745                user_id: admin.to_proto(),
 746                kind: proto::channel_member::Kind::Member.into(),
 747                role: proto::ChannelRole::Admin.into(),
 748            },
 749            proto::ChannelMember {
 750                user_id: member.to_proto(),
 751                kind: proto::channel_member::Kind::Member.into(),
 752                role: proto::ChannelRole::Member.into(),
 753            },
 754            proto::ChannelMember {
 755                user_id: guest.to_proto(),
 756                kind: proto::channel_member::Kind::Invitee.into(),
 757                role: proto::ChannelRole::Guest.into(),
 758            },
 759        ]
 760    );
 761
 762    db.respond_to_channel_invite(zed_channel, guest, true)
 763        .await
 764        .unwrap();
 765
 766    db.transaction(|tx| async move {
 767        db.check_user_is_channel_participant(
 768            &db.get_channel_internal(public_channel_id, &tx).await?,
 769            guest,
 770            &tx,
 771        )
 772        .await
 773    })
 774    .await
 775    .unwrap();
 776
 777    let channels = db.get_channels_for_user(guest).await.unwrap().channels;
 778    assert_channel_tree(
 779        channels,
 780        &[(zed_channel, &[]), (public_channel_id, &[zed_channel])],
 781    );
 782    let channels = db.get_channels_for_user(member).await.unwrap().channels;
 783    assert_channel_tree(
 784        channels,
 785        &[
 786            (zed_channel, &[]),
 787            (internal_channel_id, &[zed_channel]),
 788            (public_channel_id, &[zed_channel]),
 789        ],
 790    );
 791
 792    db.set_channel_member_role(zed_channel, admin, guest, ChannelRole::Banned)
 793        .await
 794        .unwrap();
 795    assert!(
 796        db.transaction(|tx| async move {
 797            db.check_user_is_channel_participant(
 798                &db.get_channel_internal(public_channel_id, &tx)
 799                    .await
 800                    .unwrap(),
 801                guest,
 802                &tx,
 803            )
 804            .await
 805        })
 806        .await
 807        .is_err()
 808    );
 809
 810    let (mut members, _) = db
 811        .get_channel_participant_details(public_channel_id, "", 100, admin)
 812        .await
 813        .unwrap();
 814
 815    members.sort_by_key(|member| member.user_id);
 816
 817    assert_eq!(
 818        members,
 819        &[
 820            proto::ChannelMember {
 821                user_id: admin.to_proto(),
 822                kind: proto::channel_member::Kind::Member.into(),
 823                role: proto::ChannelRole::Admin.into(),
 824            },
 825            proto::ChannelMember {
 826                user_id: member.to_proto(),
 827                kind: proto::channel_member::Kind::Member.into(),
 828                role: proto::ChannelRole::Member.into(),
 829            },
 830            proto::ChannelMember {
 831                user_id: guest.to_proto(),
 832                kind: proto::channel_member::Kind::Member.into(),
 833                role: proto::ChannelRole::Banned.into(),
 834            },
 835        ]
 836    );
 837
 838    db.remove_channel_member(zed_channel, guest, admin)
 839        .await
 840        .unwrap();
 841
 842    db.invite_channel_member(zed_channel, guest, admin, ChannelRole::Guest)
 843        .await
 844        .unwrap();
 845
 846    // currently people invited to parent channels are not shown here
 847    let (mut members, _) = db
 848        .get_channel_participant_details(public_channel_id, "", 100, admin)
 849        .await
 850        .unwrap();
 851
 852    members.sort_by_key(|member| member.user_id);
 853
 854    assert_eq!(
 855        members,
 856        &[
 857            proto::ChannelMember {
 858                user_id: admin.to_proto(),
 859                kind: proto::channel_member::Kind::Member.into(),
 860                role: proto::ChannelRole::Admin.into(),
 861            },
 862            proto::ChannelMember {
 863                user_id: member.to_proto(),
 864                kind: proto::channel_member::Kind::Member.into(),
 865                role: proto::ChannelRole::Member.into(),
 866            },
 867            proto::ChannelMember {
 868                user_id: guest.to_proto(),
 869                kind: proto::channel_member::Kind::Invitee.into(),
 870                role: proto::ChannelRole::Guest.into(),
 871            },
 872        ]
 873    );
 874
 875    db.respond_to_channel_invite(zed_channel, guest, true)
 876        .await
 877        .unwrap();
 878
 879    db.transaction(|tx| async move {
 880        db.check_user_is_channel_participant(
 881            &db.get_channel_internal(zed_channel, &tx).await.unwrap(),
 882            guest,
 883            &tx,
 884        )
 885        .await
 886    })
 887    .await
 888    .unwrap();
 889    assert!(
 890        db.transaction(|tx| async move {
 891            db.check_user_is_channel_participant(
 892                &db.get_channel_internal(internal_channel_id, &tx)
 893                    .await
 894                    .unwrap(),
 895                guest,
 896                &tx,
 897            )
 898            .await
 899        })
 900        .await
 901        .is_err(),
 902    );
 903
 904    db.transaction(|tx| async move {
 905        db.check_user_is_channel_participant(
 906            &db.get_channel_internal(public_channel_id, &tx)
 907                .await
 908                .unwrap(),
 909            guest,
 910            &tx,
 911        )
 912        .await
 913    })
 914    .await
 915    .unwrap();
 916
 917    let (mut members, _) = db
 918        .get_channel_participant_details(public_channel_id, "", 100, admin)
 919        .await
 920        .unwrap();
 921
 922    members.sort_by_key(|member| member.user_id);
 923
 924    assert_eq!(
 925        members,
 926        &[
 927            proto::ChannelMember {
 928                user_id: admin.to_proto(),
 929                kind: proto::channel_member::Kind::Member.into(),
 930                role: proto::ChannelRole::Admin.into(),
 931            },
 932            proto::ChannelMember {
 933                user_id: member.to_proto(),
 934                kind: proto::channel_member::Kind::Member.into(),
 935                role: proto::ChannelRole::Member.into(),
 936            },
 937            proto::ChannelMember {
 938                user_id: guest.to_proto(),
 939                kind: proto::channel_member::Kind::Member.into(),
 940                role: proto::ChannelRole::Guest.into(),
 941            },
 942        ]
 943    );
 944
 945    let channels = db.get_channels_for_user(guest).await.unwrap().channels;
 946    assert_channel_tree(
 947        channels,
 948        &[(zed_channel, &[]), (public_channel_id, &[zed_channel])],
 949    )
 950}
 951
 952test_both_dbs!(
 953    test_guest_access,
 954    test_guest_access_postgres,
 955    test_guest_access_sqlite
 956);
 957
 958async fn test_guest_access(db: &Arc<Database>) {
 959    let server = db.create_server("test").await.unwrap();
 960
 961    let admin = new_test_user(db, "admin@example.com").await;
 962    let guest = new_test_user(db, "guest@example.com").await;
 963    let guest_connection = new_test_connection(server);
 964
 965    let zed_channel = db.create_root_channel("zed", admin).await.unwrap();
 966    db.set_channel_visibility(zed_channel, crate::db::ChannelVisibility::Public, admin)
 967        .await
 968        .unwrap();
 969
 970    assert!(
 971        db.join_channel_chat(zed_channel, guest_connection, guest)
 972            .await
 973            .is_err()
 974    );
 975
 976    db.join_channel(zed_channel, guest, guest_connection)
 977        .await
 978        .unwrap();
 979
 980    assert!(
 981        db.join_channel_chat(zed_channel, guest_connection, guest)
 982            .await
 983            .is_ok()
 984    )
 985}
 986
 987#[track_caller]
 988fn assert_channel_tree(actual: Vec<Channel>, expected: &[(ChannelId, &[ChannelId])]) {
 989    let actual = actual
 990        .iter()
 991        .map(|channel| (channel.id, channel.parent_path.as_slice()))
 992        .collect::<HashSet<_>>();
 993    let expected = expected
 994        .iter()
 995        .map(|(id, parents)| (*id, *parents))
 996        .collect::<HashSet<_>>();
 997    pretty_assertions::assert_eq!(actual, expected, "wrong channel ids and parent paths");
 998}
 999
1000#[track_caller]
1001fn assert_channel_tree_order(actual: Vec<Channel>, expected: &[(ChannelId, &[ChannelId], i32)]) {
1002    let actual = actual
1003        .iter()
1004        .map(|channel| {
1005            (
1006                channel.id,
1007                channel.parent_path.as_slice(),
1008                channel.channel_order,
1009            )
1010        })
1011        .collect::<HashSet<_>>();
1012    let expected = expected
1013        .iter()
1014        .map(|(id, parents, order)| (*id, *parents, *order))
1015        .collect::<HashSet<_>>();
1016    pretty_assertions::assert_eq!(actual, expected, "wrong channel ids and parent paths");
1017}