feat(cli/org): org add parity for Card/Key/Totp via shared builders
This commit is contained in:
@@ -6,12 +6,13 @@ use std::path::Path;
|
||||
use anyhow::{Context, Result};
|
||||
use relicario_core::{
|
||||
generate_org_key, wrap_org_key,
|
||||
CollectionDef, Item, ItemCore, MemberId, OrgCollections, OrgManifest, OrgMembers, OrgMeta,
|
||||
CollectionDef, Item, MemberId, OrgCollections, OrgManifest, OrgMembers, OrgMeta,
|
||||
OrgRole, OrgMember,
|
||||
encrypt_org_manifest,
|
||||
};
|
||||
|
||||
use crate::org_session::atomic_write;
|
||||
use crate::commands::item_build as ib;
|
||||
|
||||
pub fn run_init(dir: &Path, name: &str) -> Result<()> {
|
||||
// Create directory structure
|
||||
@@ -745,17 +746,20 @@ pub fn run_audit(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Item kinds `org add` supports without interactive prompts.
|
||||
/// Item kinds `org add` supports. Secrets resolve via `--*-stdin` flags or an
|
||||
/// interactive prompt inside the shared `item_build` builders.
|
||||
pub enum OrgAddKind {
|
||||
Login {
|
||||
title: String,
|
||||
username: Option<String>,
|
||||
url: Option<String>,
|
||||
password: Option<String>,
|
||||
password_stdin: bool,
|
||||
},
|
||||
SecureNote {
|
||||
title: String,
|
||||
body: String,
|
||||
body: Option<String>,
|
||||
body_stdin: bool,
|
||||
},
|
||||
Identity {
|
||||
title: String,
|
||||
@@ -763,43 +767,56 @@ pub enum OrgAddKind {
|
||||
email: Option<String>,
|
||||
phone: Option<String>,
|
||||
},
|
||||
Card {
|
||||
title: String,
|
||||
holder: Option<String>,
|
||||
expiry: Option<String>,
|
||||
kind: String,
|
||||
number_stdin: bool,
|
||||
cvv_stdin: bool,
|
||||
pin_stdin: bool,
|
||||
},
|
||||
Key {
|
||||
title: String,
|
||||
label: Option<String>,
|
||||
algorithm: Option<String>,
|
||||
public_key: Option<String>,
|
||||
material_stdin: bool,
|
||||
},
|
||||
Totp {
|
||||
title: String,
|
||||
issuer: Option<String>,
|
||||
label: Option<String>,
|
||||
secret: Option<String>,
|
||||
secret_stdin: bool,
|
||||
period: u32,
|
||||
digits: u8,
|
||||
algorithm: String,
|
||||
},
|
||||
// Document is added later by Dev-C.
|
||||
}
|
||||
|
||||
fn build_org_item(kind: OrgAddKind, tags: Vec<String>) -> Result<Item> {
|
||||
use relicario_core::item_types::{IdentityCore, LoginCore, SecureNoteCore};
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
let mut item = match kind {
|
||||
OrgAddKind::Login { title, username, url, password } => {
|
||||
let parsed_url = match url {
|
||||
Some(s) => Some(url::Url::parse(&s).with_context(|| format!("invalid URL: {s}"))?),
|
||||
None => None,
|
||||
};
|
||||
let password = password.map(Zeroizing::new);
|
||||
Item::new(title, ItemCore::Login(LoginCore {
|
||||
username,
|
||||
password,
|
||||
url: parsed_url,
|
||||
totp: None,
|
||||
}))
|
||||
fn build_org_item(kind: OrgAddKind) -> Result<Item> {
|
||||
match kind {
|
||||
OrgAddKind::Login { title, username, url, password, password_stdin } => {
|
||||
ib::build_login(title, username, url, password, password_stdin, false, None)
|
||||
}
|
||||
OrgAddKind::SecureNote { title, body } => {
|
||||
Item::new(title, ItemCore::SecureNote(SecureNoteCore {
|
||||
body: Zeroizing::new(body),
|
||||
}))
|
||||
OrgAddKind::SecureNote { title, body, body_stdin } => {
|
||||
ib::build_secure_note(title, body, body_stdin)
|
||||
}
|
||||
OrgAddKind::Identity { title, full_name, email, phone } => {
|
||||
Item::new(title, ItemCore::Identity(IdentityCore {
|
||||
full_name,
|
||||
address: None,
|
||||
phone,
|
||||
email,
|
||||
date_of_birth: None,
|
||||
}))
|
||||
ib::build_identity(title, full_name, email, phone, None)
|
||||
}
|
||||
};
|
||||
item.tags = tags;
|
||||
Ok(item)
|
||||
OrgAddKind::Card { title, holder, expiry, kind, number_stdin, cvv_stdin, pin_stdin } => {
|
||||
ib::build_card(title, holder, expiry, &kind, number_stdin, cvv_stdin, pin_stdin)
|
||||
}
|
||||
OrgAddKind::Key { title, label, algorithm, public_key, material_stdin } => {
|
||||
ib::build_key(title, label, algorithm, public_key, material_stdin)
|
||||
}
|
||||
OrgAddKind::Totp { title, issuer, label, secret, secret_stdin, period, digits, algorithm } => {
|
||||
ib::build_totp(title, issuer, label, secret, secret_stdin, period, digits, &algorithm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_add(dir: &Path, collection: &str, kind: OrgAddKind, tags: Vec<String>) -> Result<()> {
|
||||
@@ -816,7 +833,8 @@ pub fn run_add(dir: &Path, collection: &str, kind: OrgAddKind, tags: Vec<String>
|
||||
// …and the caller must hold a grant for it.
|
||||
UnlockedOrgVault::ensure_grant(&caller, collection)?;
|
||||
|
||||
let item = build_org_item(kind, tags)?;
|
||||
let mut item = build_org_item(kind)?;
|
||||
item.tags = tags;
|
||||
let item_rel = vault.save_item(collection, &item)?;
|
||||
|
||||
// Upsert the manifest entry (collection slug stored plaintext inside the
|
||||
|
||||
Reference in New Issue
Block a user