@nightlybuildgroup/vault 1.6.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/package.json +1 -1
- package/src/commands/add.js +5 -4
- package/src/commands/items.js +4 -4
- package/src/commands/setup.js +48 -2
- package/src/config.js +2 -0
package/README.md
CHANGED
|
@@ -20,6 +20,9 @@ nbg-pw setup
|
|
|
20
20
|
|
|
21
21
|
You'll be asked for your server URL, email, API-key client id/secret, and master
|
|
22
22
|
password. Credentials are verified against the server before anything is saved.
|
|
23
|
+
If your account belongs to an organization, setup then offers to pick a default
|
|
24
|
+
**collection** to share newly added items into (or keep them in your personal
|
|
25
|
+
vault) — you can change this any time with [`nbg-pw config`](#sharing-new-items-with-an-organization-config).
|
|
23
26
|
|
|
24
27
|
> Get your API key from your Vaultwarden web vault: **Settings → Security →
|
|
25
28
|
> Keys → API Key** (`client_id` / `client_secret`).
|
package/package.json
CHANGED
package/src/commands/add.js
CHANGED
|
@@ -75,9 +75,10 @@ async function resolveFolderId(bw, session, folderName) {
|
|
|
75
75
|
return created.id;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
// Resolves a collection given by name OR id (and an optional org name/id).
|
|
79
|
+
async function resolveCollection(bw, session, collectionRef, org) {
|
|
79
80
|
const collections = await bw.listCollections({ session });
|
|
80
|
-
let matches = collections.filter((c) => c.name ===
|
|
81
|
+
let matches = collections.filter((c) => c.name === collectionRef || c.id === collectionRef);
|
|
81
82
|
if (org) {
|
|
82
83
|
const orgs = await bw.listOrganizations({ session });
|
|
83
84
|
const match = orgs.find((o) => o.id === org || o.name === org);
|
|
@@ -85,10 +86,10 @@ async function resolveCollection(bw, session, collectionName, org) {
|
|
|
85
86
|
matches = matches.filter((c) => c.organizationId === orgId);
|
|
86
87
|
}
|
|
87
88
|
if (matches.length === 0) {
|
|
88
|
-
throw new Error(`no collection
|
|
89
|
+
throw new Error(`no collection "${collectionRef}"${org ? ` in organization "${org}"` : ''}`);
|
|
89
90
|
}
|
|
90
91
|
if (matches.length > 1) {
|
|
91
|
-
throw new Error(`multiple collections named "${
|
|
92
|
+
throw new Error(`multiple collections named "${collectionRef}"; disambiguate with --organization <name|id>`);
|
|
92
93
|
}
|
|
93
94
|
return matches[0];
|
|
94
95
|
}
|
package/src/commands/items.js
CHANGED
|
@@ -43,16 +43,16 @@ export async function runItems(args, deps) {
|
|
|
43
43
|
let folderId;
|
|
44
44
|
if (folder !== null) {
|
|
45
45
|
const folders = await bw.listFolders({ session });
|
|
46
|
-
const match = folders.find((f) => f.name === folder
|
|
47
|
-
if (!match) throw new Error(`no folder
|
|
46
|
+
const match = folders.find((f) => f.id && (f.name === folder || f.id === folder));
|
|
47
|
+
if (!match) throw new Error(`no folder "${folder}"`);
|
|
48
48
|
folderId = match.id;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
let collectionId;
|
|
52
52
|
if (collection !== null) {
|
|
53
53
|
const collections = await bw.listCollections({ session });
|
|
54
|
-
const match = collections.find((c) => c.name === collection);
|
|
55
|
-
if (!match) throw new Error(`no collection
|
|
54
|
+
const match = collections.find((c) => c.name === collection || c.id === collection);
|
|
55
|
+
if (!match) throw new Error(`no collection "${collection}"`);
|
|
56
56
|
collectionId = match.id;
|
|
57
57
|
}
|
|
58
58
|
|
package/src/commands/setup.js
CHANGED
|
@@ -15,6 +15,42 @@ export async function validateCredentials(input, deps) {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
// After credentials verify, offer to share new items into an org collection by
|
|
19
|
+
// default. Returns { defaultOrganization, defaultCollection } (by name) or {}.
|
|
20
|
+
// Stays optional: no orgs, a cancel, or "personal vault" all yield {}.
|
|
21
|
+
export async function chooseDefaultSharing(deps) {
|
|
22
|
+
const { prompts, bw, verified } = deps;
|
|
23
|
+
const session = await bw.ensureSession(verified);
|
|
24
|
+
try {
|
|
25
|
+
const orgs = await bw.listOrganizations({ session });
|
|
26
|
+
if (!orgs || orgs.length === 0) return {};
|
|
27
|
+
|
|
28
|
+
const orgChoice = await prompts.select({
|
|
29
|
+
message: 'Default: share newly added items into an organization?',
|
|
30
|
+
options: [
|
|
31
|
+
{ value: '__personal__', label: 'No — keep new items in my personal vault' },
|
|
32
|
+
...orgs.map((o) => ({ value: o.id, label: o.name })),
|
|
33
|
+
],
|
|
34
|
+
});
|
|
35
|
+
if (prompts.isCancel(orgChoice) || orgChoice === '__personal__') return {};
|
|
36
|
+
const org = orgs.find((o) => o.id === orgChoice);
|
|
37
|
+
|
|
38
|
+
const cols = (await bw.listCollections({ session })).filter((c) => c.organizationId === org.id);
|
|
39
|
+
if (cols.length === 0) return {};
|
|
40
|
+
|
|
41
|
+
const colChoice = await prompts.select({
|
|
42
|
+
message: `Which collection in "${org.name}"?`,
|
|
43
|
+
options: cols.map((c) => ({ value: c.id, label: c.name })),
|
|
44
|
+
});
|
|
45
|
+
if (prompts.isCancel(colChoice)) return {};
|
|
46
|
+
const col = cols.find((c) => c.id === colChoice);
|
|
47
|
+
|
|
48
|
+
return { defaultOrganization: org.name, defaultCollection: col.name };
|
|
49
|
+
} finally {
|
|
50
|
+
await bw.logout();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
18
54
|
export async function runSetup(deps) {
|
|
19
55
|
const { prompts, bw, keychain, buildConfig, nowIso, out } = deps;
|
|
20
56
|
|
|
@@ -74,10 +110,20 @@ export async function runSetup(deps) {
|
|
|
74
110
|
}
|
|
75
111
|
spin.stop('Credentials verified.');
|
|
76
112
|
|
|
77
|
-
|
|
113
|
+
let sharing = {};
|
|
114
|
+
try {
|
|
115
|
+
sharing = await chooseDefaultSharing({ prompts, bw, verified: input });
|
|
116
|
+
} catch {
|
|
117
|
+
out('Skipped organization setup — set a default later with "nbg-pw config set collection <name>".\n');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const config = buildConfig({ ...input, ...sharing }, nowIso);
|
|
78
121
|
await keychain.writeConfig(config);
|
|
79
122
|
|
|
80
|
-
|
|
123
|
+
const where = sharing.defaultCollection
|
|
124
|
+
? `New items will be shared into "${sharing.defaultCollection}".`
|
|
125
|
+
: 'New items go to your personal vault (configure sharing with "nbg-pw config set").';
|
|
126
|
+
prompts.outro(`Saved to your macOS Keychain. ${where} Try: nbg-pw status`);
|
|
81
127
|
return 0;
|
|
82
128
|
}
|
|
83
129
|
|
package/src/config.js
CHANGED
|
@@ -45,5 +45,7 @@ export function buildConfig(input, nowIso) {
|
|
|
45
45
|
masterPassword: input.masterPassword,
|
|
46
46
|
savedAt: nowIso,
|
|
47
47
|
};
|
|
48
|
+
if (input.defaultOrganization) c.defaultOrganization = input.defaultOrganization;
|
|
49
|
+
if (input.defaultCollection) c.defaultCollection = input.defaultCollection;
|
|
48
50
|
return c;
|
|
49
51
|
}
|