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 share workspace #6099

Merged
merged 1 commit into from
Jan 9, 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
4 changes: 2 additions & 2 deletions cli/src/create_workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ pub async fn create_workspace(create_workspace: CreateWorkspace) -> anyhow::Resu
load_client_and_run(config_dir, device, |client| async move {
let handle = start_spinner("Creating workspace");

client.user_ops.create_workspace(name).await?;
let id = client.user_ops.create_workspace(name).await?.simple();

handle.done();

println!("Workspace has been created");
println!("Workspace has been created with id: {YELLOW}{id}{RESET}");

client.stop().await;

Expand Down
1 change: 0 additions & 1 deletion cli/src/list_users.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ pub async fn list_users(list_users: ListUsers) -> anyhow::Result<()> {
} = list_users;

load_client_and_run(config_dir, device, |client| async move {
client.user_ops.sync().await?;
let users = client.certificates_ops.list_users(skip_revoked, None, None).await?;

if users.is_empty() {
Expand Down
6 changes: 6 additions & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod list_workspaces;
mod remove_device;
#[cfg(feature = "testenv")]
mod run_testenv;
mod share_workspace;
mod stats_organization;
mod stats_server;
mod status_organization;
Expand Down Expand Up @@ -72,6 +73,8 @@ enum Command {
/// This command creates three users, `Alice`, `Bob` and `Toto`,
/// To run testenv, see the script run_testenv in the current directory.
RunTestenv(run_testenv::RunTestenv),
/// Share workspace
ShareWorkspace(share_workspace::ShareWorkspace),
/// Get data & user statistics on organization
StatsOrganization(stats_organization::StatsOrganization),
/// Get a per-organization report of server usage
Expand Down Expand Up @@ -122,6 +125,9 @@ async fn main() -> anyhow::Result<()> {
Command::RemoveDevice(remove_device) => remove_device::remove_device(remove_device).await,
#[cfg(feature = "testenv")]
Command::RunTestenv(run_testenv) => run_testenv::run_testenv(run_testenv).await,
Command::ShareWorkspace(share_workspace) => {
share_workspace::share_workspace(share_workspace).await
}
Command::StatsOrganization(stats_organization) => {
stats_organization::stats_organization(stats_organization).await
}
Expand Down
55 changes: 55 additions & 0 deletions cli/src/share_workspace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 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, RealmRole, UserID, VlobID};

use crate::utils::*;

#[derive(Args)]
pub struct ShareWorkspace {
/// 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>,
/// Workspace id
#[arg(short, long, value_parser = VlobID::from_hex)]
workspace_id: VlobID,
/// Recipient id
#[arg(short, long)]
user_id: UserID,
/// Role (owner/manager/contributor/reader)
#[arg(short, long)]
role: RealmRole,
}

pub async fn share_workspace(share_workspace: ShareWorkspace) -> anyhow::Result<()> {
let ShareWorkspace {
config_dir,
device,
workspace_id,
user_id,
role,
} = share_workspace;

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

client
.user_ops
.share_workspace(workspace_id, user_id, Some(role))
.await?;

handle.done();

println!("Workspace has been shared");

client.stop().await;

Ok(())
})
.await
}
66 changes: 64 additions & 2 deletions cli/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use std::{
use libparsec::{
authenticated_cmds::latest::invite_new::{self, InviteNewRep, UserOrDevice},
get_default_config_dir, tmp_path, AuthenticatedCmds, BackendAddr, BackendInvitationAddr,
BackendOrganizationBootstrapAddr, ClientConfig, InvitationType, LocalDevice, OrganizationID,
ProxyConfig, TmpPath, PARSEC_CONFIG_DIR, PARSEC_DATA_DIR, PARSEC_HOME_DIR,
BackendOrganizationBootstrapAddr, ClientConfig, HumanHandle, InvitationType, LocalDevice,
OrganizationID, ProxyConfig, TmpPath, PARSEC_CONFIG_DIR, PARSEC_DATA_DIR, PARSEC_HOME_DIR,
};

use crate::{
Expand Down Expand Up @@ -588,6 +588,68 @@ async fn list_users(tmp_path: TmpPath) {
);
}

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

set_env(&tmp_path_str, &url);

load_client_and_run(
get_default_config_dir(),
Some(alice.slughash()),
|client| async move {
let wid = client
.user_ops
.create_workspace("new-workspace".parse().unwrap())
.await?;

let users = client
.certificates_ops
.list_users(false, None, None)
.await
.unwrap();
let bob_id = &users
.iter()
.find(|x| x.human_handle == HumanHandle::new("[email protected]", "Bob").unwrap())
.unwrap()
.id;

Command::cargo_bin("parsec_cli")
.unwrap()
.args([
"share-workspace",
"--device",
&alice.slughash(),
"--workspace-id",
&wid.simple().to_string(),
"--user-id",
&bob_id.to_string(),
"--role",
"contributor",
])
.assert()
.stdout(predicates::str::contains(
"Sharing workspace\nWorkspace has been shared",
));

Ok(())
},
)
.await
.unwrap();

Command::cargo_bin("parsec_cli")
.unwrap()
.args(["list-workspaces", "--device", &bob.slughash()])
.assert()
.stdout(predicates::str::contains("new-workspace"));
}

#[rstest::rstest]
#[tokio::test]
async fn invite_device_dance(tmp_path: TmpPath) {
Expand Down
2 changes: 2 additions & 0 deletions cli/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ where
)
.await?;

client.user_ops.sync().await?;

function(client).await
})
.await
Expand Down
14 changes: 14 additions & 0 deletions libparsec/crates/types/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,20 @@ impl RealmRole {
}
}

impl std::str::FromStr for RealmRole {
type Err = &'static str;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"owner" => Ok(Self::Owner),
"manager" => Ok(Self::Manager),
"contributor" => Ok(Self::Contributor),
"reader" => Ok(Self::Reader),
_ => Err("Failed to parse RealmRole"),
}
}
}

/*
* WorkspaceEntry
*/
Expand Down
Loading