channel_tests.rs

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