Skip to content

Commit

Permalink
Fix invite list command crashing when having more than one entry (#…
Browse files Browse the repository at this point in the history
…9175)

This is a parcially cherry-pick of commit `100152ac72a262790468ceac444256ac25399c93`

Closes #9176
  • Loading branch information
FirelightFlagboy authored Dec 12, 2024
1 parent d68303c commit 9369534
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 34 deletions.
22 changes: 7 additions & 15 deletions cli/src/commands/invite/list.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS

use libparsec::{
authenticated_cmds::latest::invite_list::{self, InviteListItem, InviteListRep},
InvitationStatus,
};
use libparsec::{authenticated_cmds::latest::invite_list::InviteListItem, InvitationStatus};

use crate::utils::*;

Expand All @@ -24,23 +21,18 @@ pub async fn main(args: Args) -> anyhow::Result<()> {
device.as_deref().unwrap_or("N/A")
);

let (cmds, _) = load_cmds(&config_dir, device, password_stdin).await?;
let client = load_client(&config_dir, device, password_stdin).await?;
let mut handle = start_spinner("Listing invitations".into());

let rep = cmds.send(invite_list::Req).await?;
let invitations = client.list_invitations().await?;

let invitations = match rep {
InviteListRep::Ok { invitations } => invitations,
rep => {
return Err(anyhow::anyhow!(
"Server error while listing invitations: {rep:?}"
));
}
};
client.stop().await;
drop(client);

if invitations.is_empty() {
handle.stop_with_message("No invitation.".into());
} else {
handle.stop_with_message(format!("{} invitations found.", invitations.len()));
for invitation in invitations {
let (token, status, display_type) = match invitation {
InviteListItem::User {
Expand All @@ -61,7 +53,7 @@ pub async fn main(args: Args) -> anyhow::Result<()> {
InvitationStatus::Finished => format!("{GREEN}finished{RESET}"),
};

handle.stop_with_message(format!("{token}\t{display_status}\t{display_type}"))
println!("{token}\t{display_status}\t{display_type}");
}
}

Expand Down
70 changes: 51 additions & 19 deletions cli/tests/integration/invitations/list.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
use libparsec::{
authenticated_cmds::v4::invite_new_device, get_default_config_dir, tmp_path, AuthenticatedCmds,
InvitationType, ParsecInvitationAddr, ProxyConfig, TmpPath,
InvitationToken, ProxyConfig, TmpPath,
};
use predicates::prelude::PredicateBooleanExt;

use crate::{
integration_tests::bootstrap_cli_test,
testenv_utils::{TestOrganization, DEFAULT_DEVICE_PASSWORD},
utils::{RESET, YELLOW},
};

async fn invite_device(cmds: &AuthenticatedCmds) -> InvitationToken {
let rep = cmds
.send(invite_new_device::Req { send_email: false })
.await
.unwrap();

match rep {
invite_new_device::InviteNewDeviceRep::Ok { token, .. } => token,
rep => {
panic!("Server refused to create device invitation: {rep:?}");
}
}
}

#[rstest::rstest]
#[tokio::test]
async fn list_invitations(tmp_path: TmpPath) {
Expand All @@ -21,24 +36,7 @@ async fn list_invitations(tmp_path: TmpPath) {
)
.unwrap();

let rep = cmds
.send(invite_new_device::Req { send_email: false })
.await
.unwrap();

let invitation_addr = match rep {
invite_new_device::InviteNewDeviceRep::Ok { token, .. } => ParsecInvitationAddr::new(
alice.organization_addr.clone(),
alice.organization_id().clone(),
InvitationType::Device,
token,
),
rep => {
panic!("Server refused to create device invitation: {rep:?}");
}
};

let token = invitation_addr.token();
let token = invite_device(&cmds).await;

crate::assert_cmd_success!(
with_password = DEFAULT_DEVICE_PASSWORD,
Expand All @@ -53,6 +51,40 @@ async fn list_invitations(tmp_path: TmpPath) {
)));
}

#[rstest::rstest]
#[tokio::test]
async fn issue_9176_list_more_than_one_invitations(tmp_path: TmpPath) {
let (_, TestOrganization { alice, .. }, _) = bootstrap_cli_test(&tmp_path).await.unwrap();

let cmds = AuthenticatedCmds::new(
&get_default_config_dir(),
alice.clone(),
ProxyConfig::new_from_env().unwrap(),
)
.unwrap();

let token1 = invite_device(&cmds).await;
let token2 = invite_device(&cmds).await;
let token3 = invite_device(&cmds).await;

let contains_invite = |token: InvitationToken| {
predicates::str::contains(format!("{token}\t{YELLOW}idle{RESET}\tdevice"))
};

crate::assert_cmd_success!(
with_password = DEFAULT_DEVICE_PASSWORD,
"invite",
"list",
"--device",
&alice.device_id.hex()
)
.stdout(
contains_invite(token1)
.and(contains_invite(token2))
.and(contains_invite(token3)),
);
}

#[rstest::rstest]
#[tokio::test]
async fn no_invitations(tmp_path: TmpPath) {
Expand Down
1 change: 1 addition & 0 deletions newsfragments/9176.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix CLI command ``invite list`` crashing when listing more than one entry

0 comments on commit 9369534

Please sign in to comment.