Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI: create-workspace #6095

Merged
merged 1 commit into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/src/cancel_invitation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub struct CancelInvitation {
}

pub async fn cancel_invitation(cancel_invitation: CancelInvitation) -> anyhow::Result<()> {
load_device_and_run(
load_cmds_and_run(
cancel_invitation.config_dir,
cancel_invitation.device,
|cmds, _| async move {
Expand Down
44 changes: 44 additions & 0 deletions cli/src/create_workspace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS

use clap::Args;
use std::path::PathBuf;

use libparsec::{get_default_config_dir, EntryName};

use crate::utils::*;

#[derive(Args)]
pub struct CreateWorkspace {
/// Parsec config directory
#[arg(short, long, default_value_os_t = get_default_config_dir())]
config_dir: PathBuf,
/// Device slughash
#[arg(short, long)]
device: Option<String>,
/// New workspace name
#[arg(short, long)]
name: EntryName,
}

pub async fn create_workspace(create_workspace: CreateWorkspace) -> anyhow::Result<()> {
let CreateWorkspace {
config_dir,
device,
name,
} = create_workspace;

load_client_and_run(config_dir, device, |client| async move {
let handle = start_spinner("Creating workspace");

client.user_ops.create_workspace(name).await?;

handle.done();

println!("Workspace has been created");

client.stop().await;

Ok(())
})
.await
}
2 changes: 1 addition & 1 deletion cli/src/export_recovery_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub async fn export_recovery_device(
load_device_and_run(
export_recovery_device.config_dir,
export_recovery_device.device,
|_, device| async move {
|device| async move {
let handle = start_spinner("Saving recovery device file");

let passphrase = save_recovery_device(&export_recovery_device.output, &device).await?;
Expand Down
2 changes: 1 addition & 1 deletion cli/src/greet_invitation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub struct GreetInvitation {
}

pub async fn greet_invitation(greet_invitation: GreetInvitation) -> anyhow::Result<()> {
load_device_and_run(
load_cmds_and_run(
greet_invitation.config_dir,
greet_invitation.device,
|cmds, device| async move {
Expand Down
2 changes: 1 addition & 1 deletion cli/src/invite_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct InviteDevice {
}

pub async fn invite_device(invite_device: InviteDevice) -> anyhow::Result<()> {
load_device_and_run(
load_cmds_and_run(
invite_device.config_dir,
invite_device.device,
|cmds, device| async move {
Expand Down
2 changes: 1 addition & 1 deletion cli/src/invite_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub struct InviteUser {
}

pub async fn invite_user(invite_user: InviteUser) -> anyhow::Result<()> {
load_device_and_run(
load_cmds_and_run(
invite_user.config_dir,
invite_user.device,
|cmds, device| async move {
Expand Down
2 changes: 1 addition & 1 deletion cli/src/list_invitations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct ListInvitations {
}

pub async fn list_invitations(list_invitations: ListInvitations) -> anyhow::Result<()> {
load_device_and_run(
load_cmds_and_run(
list_invitations.config_dir,
list_invitations.device,
|cmds, _| async move {
Expand Down
6 changes: 6 additions & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod bootstrap_organization;
mod cancel_invitation;
mod claim_invitation;
mod create_organization;
mod create_workspace;
mod export_recovery_device;
mod greet_invitation;
mod import_recovery_device;
Expand Down Expand Up @@ -41,6 +42,8 @@ enum Command {
ClaimInvitation(claim_invitation::ClaimInvitation),
/// Create new organization
CreateOrganization(create_organization::CreateOrganization),
/// Create new workspace
CreateWorkspace(create_workspace::CreateWorkspace),
/// Export recovery device
ExportRecoveryDevice(export_recovery_device::ExportRecoveryDevice),
/// Import recovery device
Expand Down Expand Up @@ -88,6 +91,9 @@ async fn main() -> anyhow::Result<()> {
Command::CreateOrganization(create_organization) => {
create_organization::create_organization(create_organization).await
}
Command::CreateWorkspace(create_workspace) => {
create_workspace::create_workspace(create_workspace).await
}
Command::ExportRecoveryDevice(export_recovery_device) => {
export_recovery_device::export_recovery_device(export_recovery_device).await
}
Expand Down
26 changes: 26 additions & 0 deletions cli/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,32 @@ async fn list_invitations(tmp_path: TmpPath) {
)));
}

#[rstest::rstest]
#[tokio::test]
async fn create_workspace(tmp_path: TmpPath) {
let tmp_path_str = tmp_path.to_str().unwrap();
let config = get_testenv_config();
let (url, [alice, ..], _) = run_local_organization(&tmp_path, None, config)
.await
.unwrap();

set_env(&tmp_path_str, &url);

Command::cargo_bin("parsec_cli")
.unwrap()
.args([
"create-workspace",
"--device",
&alice.slughash(),
"--name",
"new-workspace",
])
.assert()
.stdout(predicates::str::contains(
"Creating workspace\nWorkspace has been created",
));
}

#[rstest::rstest]
#[tokio::test]
async fn invite_device_dance(tmp_path: TmpPath) {
Expand Down
57 changes: 46 additions & 11 deletions cli/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
use std::{future::Future, path::PathBuf, sync::Arc};

use libparsec::{
list_available_devices, load_device, AuthenticatedCmds, AvailableDevice, DeviceAccessStrategy,
DeviceFileType, DeviceLabel, HumanHandle, LocalDevice, Password, ProxyConfig, SASCode,
UserProfile,
internal::{Client, EventBus},
list_available_devices, load_device, AuthenticatedCmds, AvailableDevice, ClientConfig,
DeviceAccessStrategy, DeviceFileType, DeviceLabel, HumanHandle, LocalDevice, Password,
ProxyConfig, SASCode, UserProfile,
};
use terminal_spinners::{SpinnerBuilder, SpinnerHandle, DOTS};

Expand Down Expand Up @@ -34,7 +35,7 @@ pub async fn load_device_and_run<F, Fut>(
function: F,
) -> anyhow::Result<()>
where
F: FnOnce(AuthenticatedCmds, Arc<LocalDevice>) -> Fut,
F: FnOnce(Arc<LocalDevice>) -> Fut,
Fut: Future<Output = anyhow::Result<()>>,
{
let devices = list_available_devices(&config_dir).await;
Expand Down Expand Up @@ -86,13 +87,7 @@ where
}
};

let cmds = AuthenticatedCmds::new(
&config_dir,
device.clone(),
ProxyConfig::new_from_env()?,
)?;

function(cmds, device.clone()).await?;
function(device).await?;
}
_ => {
println!("Multiple devices found for `{device_slughash}`:");
Expand All @@ -108,6 +103,46 @@ where
Ok(())
}

pub async fn load_cmds_and_run<F, Fut>(
config_dir: PathBuf,
device_slughash: Option<String>,
function: F,
) -> anyhow::Result<()>
where
F: FnOnce(AuthenticatedCmds, Arc<LocalDevice>) -> Fut,
Fut: Future<Output = anyhow::Result<()>>,
{
load_device_and_run(config_dir.clone(), device_slughash, |device| async move {
let cmds =
AuthenticatedCmds::new(&config_dir, device.clone(), ProxyConfig::new_from_env()?)?;

function(cmds, device).await
})
.await
}

pub async fn load_client_and_run<F, Fut>(
config_dir: PathBuf,
device_slughash: Option<String>,
function: F,
) -> anyhow::Result<()>
where
F: FnOnce(Client) -> Fut,
Fut: Future<Output = anyhow::Result<()>>,
{
load_device_and_run(config_dir, device_slughash, |device| async move {
let client = Client::start(
Arc::new(ClientConfig::default().into()),
EventBus::default(),
device,
)
.await?;

function(client).await
})
.await
}

pub fn start_spinner(text: &'static str) -> SpinnerHandle {
SpinnerBuilder::new().spinner(&DOTS).text(text).start()
}
Expand Down
2 changes: 1 addition & 1 deletion libparsec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub use workspace::*;

pub mod internal {
pub use libparsec_client::{
claimer_retrieve_info, DeviceClaimFinalizeCtx, DeviceClaimInProgress1Ctx,
claimer_retrieve_info, Client, DeviceClaimFinalizeCtx, DeviceClaimInProgress1Ctx,
DeviceClaimInProgress2Ctx, DeviceClaimInProgress3Ctx, DeviceClaimInitialCtx,
DeviceGreetInProgress1Ctx, DeviceGreetInProgress2Ctx, DeviceGreetInProgress3Ctx,
DeviceGreetInProgress4Ctx, DeviceGreetInitialCtx, EventBus, UserClaimFinalizeCtx,
Expand Down
Loading