pal-explorer-cli 0.4.12 → 0.4.13
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 +149 -149
- package/bin/pal.js +63 -2
- package/extensions/@palexplorer/analytics/extension.json +20 -1
- package/extensions/@palexplorer/analytics/index.js +19 -9
- package/extensions/@palexplorer/audit/extension.json +14 -0
- package/extensions/@palexplorer/auth-email/extension.json +15 -0
- package/extensions/@palexplorer/auth-oauth/extension.json +15 -0
- package/extensions/@palexplorer/chat/extension.json +14 -0
- package/extensions/@palexplorer/discovery/extension.json +17 -0
- package/extensions/@palexplorer/discovery/index.js +1 -1
- package/extensions/@palexplorer/email-notifications/extension.json +23 -0
- package/extensions/@palexplorer/groups/extension.json +15 -0
- package/extensions/@palexplorer/share-links/extension.json +15 -0
- package/extensions/@palexplorer/sync/extension.json +16 -0
- package/extensions/@palexplorer/user-mgmt/extension.json +15 -0
- package/lib/capabilities.js +24 -24
- package/lib/commands/analytics.js +175 -175
- package/lib/commands/api-keys.js +131 -131
- package/lib/commands/audit.js +235 -235
- package/lib/commands/auth.js +137 -137
- package/lib/commands/backup.js +76 -76
- package/lib/commands/billing.js +148 -148
- package/lib/commands/chat.js +217 -217
- package/lib/commands/cloud-backup.js +231 -231
- package/lib/commands/comment.js +99 -99
- package/lib/commands/completion.js +203 -203
- package/lib/commands/compliance.js +218 -218
- package/lib/commands/config.js +136 -136
- package/lib/commands/connect.js +44 -44
- package/lib/commands/dept.js +294 -294
- package/lib/commands/device.js +146 -146
- package/lib/commands/download.js +240 -226
- package/lib/commands/explorer.js +178 -178
- package/lib/commands/extension.js +1060 -970
- package/lib/commands/favorite.js +90 -90
- package/lib/commands/federation.js +270 -270
- package/lib/commands/file.js +533 -533
- package/lib/commands/group.js +271 -271
- package/lib/commands/gui-share.js +29 -29
- package/lib/commands/init.js +61 -61
- package/lib/commands/invite.js +59 -59
- package/lib/commands/list.js +58 -58
- package/lib/commands/log.js +116 -116
- package/lib/commands/nearby.js +108 -108
- package/lib/commands/network.js +251 -251
- package/lib/commands/notify.js +198 -198
- package/lib/commands/org.js +273 -273
- package/lib/commands/pal.js +403 -180
- package/lib/commands/permissions.js +216 -216
- package/lib/commands/pin.js +97 -97
- package/lib/commands/protocol.js +357 -357
- package/lib/commands/rbac.js +147 -147
- package/lib/commands/recover.js +36 -36
- package/lib/commands/register.js +171 -171
- package/lib/commands/relay.js +131 -131
- package/lib/commands/remote.js +368 -368
- package/lib/commands/revoke.js +50 -50
- package/lib/commands/scanner.js +280 -280
- package/lib/commands/schedule.js +344 -344
- package/lib/commands/scim.js +203 -203
- package/lib/commands/search.js +181 -181
- package/lib/commands/serve.js +438 -438
- package/lib/commands/server.js +350 -350
- package/lib/commands/share-link.js +199 -199
- package/lib/commands/share.js +336 -323
- package/lib/commands/sso.js +200 -200
- package/lib/commands/status.js +145 -145
- package/lib/commands/stream.js +562 -562
- package/lib/commands/su.js +187 -187
- package/lib/commands/sync.js +979 -979
- package/lib/commands/transfers.js +152 -152
- package/lib/commands/uninstall.js +188 -188
- package/lib/commands/update.js +204 -204
- package/lib/commands/user.js +276 -276
- package/lib/commands/vfs.js +84 -84
- package/lib/commands/web-login.js +79 -79
- package/lib/commands/web.js +52 -52
- package/lib/commands/webhook.js +180 -180
- package/lib/commands/whoami.js +59 -59
- package/lib/commands/workspace.js +121 -121
- package/lib/core/billing.js +16 -5
- package/lib/core/dhtDiscovery.js +9 -2
- package/lib/core/discoveryClient.js +13 -7
- package/lib/core/extensions.js +142 -1
- package/lib/core/identity.js +33 -2
- package/lib/core/imageProcessor.js +109 -0
- package/lib/core/imageTorrent.js +167 -0
- package/lib/core/permissions.js +1 -1
- package/lib/core/pro.js +11 -4
- package/lib/core/serverList.js +4 -1
- package/lib/core/shares.js +12 -1
- package/lib/core/signalingServer.js +14 -2
- package/lib/core/su.js +1 -1
- package/lib/core/users.js +1 -1
- package/lib/protocol/messages.js +12 -3
- package/lib/utils/explorer.js +1 -1
- package/lib/utils/help.js +357 -357
- package/lib/utils/torrent.js +1 -0
- package/package.json +4 -3
package/lib/commands/rbac.js
CHANGED
|
@@ -1,147 +1,147 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
|
|
3
|
-
const BUILTIN_ROLES = {
|
|
4
|
-
'org-admin': ['view', 'download', 'reshare', 'delete', 'manage', 'audit', 'assign-roles'],
|
|
5
|
-
'dept-admin': ['view', 'download', 'reshare', 'delete', 'manage'],
|
|
6
|
-
'admin': ['view', 'download', 'reshare', 'delete', 'manage'],
|
|
7
|
-
'editor': ['view', 'download', 'reshare'],
|
|
8
|
-
'viewer': ['view', 'download'],
|
|
9
|
-
'member': ['view', 'download'],
|
|
10
|
-
'restricted': ['view'],
|
|
11
|
-
'external': ['view'],
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export default function rbacCommand(program) {
|
|
15
|
-
const cmd = program
|
|
16
|
-
.command('rbac')
|
|
17
|
-
.description('enterprise role-based access control (Enterprise)')
|
|
18
|
-
.addHelpText('after', `
|
|
19
|
-
Examples:
|
|
20
|
-
$
|
|
21
|
-
$
|
|
22
|
-
$
|
|
23
|
-
$
|
|
24
|
-
$
|
|
25
|
-
`)
|
|
26
|
-
.action(() => { cmd.outputHelp(); });
|
|
27
|
-
|
|
28
|
-
cmd
|
|
29
|
-
.command('roles')
|
|
30
|
-
.description('list all roles with permissions')
|
|
31
|
-
.action(async () => {
|
|
32
|
-
try {
|
|
33
|
-
console.log('');
|
|
34
|
-
console.log(chalk.cyan.bold('Flat Roles'));
|
|
35
|
-
console.log(chalk.gray('─'.repeat(50)));
|
|
36
|
-
for (const role of ['admin', 'editor', 'viewer', 'restricted']) {
|
|
37
|
-
const perms = BUILTIN_ROLES[role];
|
|
38
|
-
console.log(` ${chalk.white(role)}`);
|
|
39
|
-
console.log(` ${chalk.gray(perms.join(', '))}`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
console.log('');
|
|
43
|
-
console.log(chalk.cyan.bold('Enterprise Hierarchical Roles'));
|
|
44
|
-
console.log(chalk.gray('─'.repeat(50)));
|
|
45
|
-
for (const role of ['org-admin', 'dept-admin', 'member', 'external']) {
|
|
46
|
-
const perms = BUILTIN_ROLES[role];
|
|
47
|
-
const scope = role === 'dept-admin' ? chalk.yellow(' (scoped to dept)') : '';
|
|
48
|
-
const note = role === 'external' ? chalk.yellow(' (limited)') : '';
|
|
49
|
-
console.log(` ${chalk.white(role)}${scope}${note}`);
|
|
50
|
-
console.log(` ${chalk.gray(perms.join(', '))}`);
|
|
51
|
-
}
|
|
52
|
-
console.log('');
|
|
53
|
-
} catch (err) {
|
|
54
|
-
console.error(chalk.red(`Failed to list roles: ${err.message}`));
|
|
55
|
-
process.exitCode = 1;
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
cmd
|
|
60
|
-
.command('assign <publicKey> <role>')
|
|
61
|
-
.description('assign role to user')
|
|
62
|
-
.option('--org <orgId>', 'scope to organization')
|
|
63
|
-
.option('--dept <deptName>', 'scope to department')
|
|
64
|
-
.action(async (publicKey, role, opts) => {
|
|
65
|
-
try {
|
|
66
|
-
if (!BUILTIN_ROLES[role]) {
|
|
67
|
-
console.error(chalk.red(`Unknown role "${role}". Valid roles: ${Object.keys(BUILTIN_ROLES).join(', ')}`));
|
|
68
|
-
process.exitCode = 1;
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const extConfig = (await import('../utils/config.js')).default;
|
|
73
|
-
const store = extConfig.get('ext_store.enterprise-rbac') || {};
|
|
74
|
-
const key = `role:${publicKey}`;
|
|
75
|
-
store[key] = {
|
|
76
|
-
role,
|
|
77
|
-
org: opts.org || null,
|
|
78
|
-
dept: opts.dept || null,
|
|
79
|
-
assignedAt: new Date().toISOString(),
|
|
80
|
-
};
|
|
81
|
-
extConfig.set('ext_store.enterprise-rbac', store);
|
|
82
|
-
|
|
83
|
-
let scope = '';
|
|
84
|
-
if (opts.org) scope += ` org=${chalk.white(opts.org)}`;
|
|
85
|
-
if (opts.dept) scope += ` dept=${chalk.white(opts.dept)}`;
|
|
86
|
-
console.log(chalk.green(`✔ Assigned role "${role}" to ${publicKey.slice(0, 16)}...${scope}`));
|
|
87
|
-
} catch (err) {
|
|
88
|
-
console.error(chalk.red(`Assign failed: ${err.message}`));
|
|
89
|
-
process.exitCode = 1;
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
cmd
|
|
94
|
-
.command('revoke <publicKey>')
|
|
95
|
-
.description('remove role assignment')
|
|
96
|
-
.action(async (publicKey) => {
|
|
97
|
-
try {
|
|
98
|
-
const extConfig = (await import('../utils/config.js')).default;
|
|
99
|
-
const store = extConfig.get('ext_store.enterprise-rbac') || {};
|
|
100
|
-
const key = `role:${publicKey}`;
|
|
101
|
-
|
|
102
|
-
if (!store[key]) {
|
|
103
|
-
console.log(chalk.yellow(`No role assignment found for ${publicKey.slice(0, 16)}...`));
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const oldRole = store[key].role;
|
|
108
|
-
delete store[key];
|
|
109
|
-
extConfig.set('ext_store.enterprise-rbac', store);
|
|
110
|
-
console.log(chalk.green(`✔ Revoked role "${oldRole}" from ${publicKey.slice(0, 16)}...`));
|
|
111
|
-
} catch (err) {
|
|
112
|
-
console.error(chalk.red(`Revoke failed: ${err.message}`));
|
|
113
|
-
process.exitCode = 1;
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
cmd
|
|
118
|
-
.command('check <publicKey> <permission>')
|
|
119
|
-
.description('check if user has specific permission')
|
|
120
|
-
.action(async (publicKey, permission) => {
|
|
121
|
-
try {
|
|
122
|
-
const extConfig = (await import('../utils/config.js')).default;
|
|
123
|
-
const store = extConfig.get('ext_store.enterprise-rbac') || {};
|
|
124
|
-
const key = `role:${publicKey}`;
|
|
125
|
-
const assignment = store[key];
|
|
126
|
-
|
|
127
|
-
if (!assignment) {
|
|
128
|
-
console.log(chalk.red(`✘ No role assigned to ${publicKey.slice(0, 16)}...`));
|
|
129
|
-
process.exitCode = 1;
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const perms = BUILTIN_ROLES[assignment.role] || [];
|
|
134
|
-
const has = perms.includes(permission);
|
|
135
|
-
|
|
136
|
-
if (has) {
|
|
137
|
-
console.log(chalk.green(`✔ ${publicKey.slice(0, 16)}... HAS "${permission}" (role: ${assignment.role})`));
|
|
138
|
-
} else {
|
|
139
|
-
console.log(chalk.red(`✘ ${publicKey.slice(0, 16)}... DOES NOT have "${permission}" (role: ${assignment.role})`));
|
|
140
|
-
process.exitCode = 1;
|
|
141
|
-
}
|
|
142
|
-
} catch (err) {
|
|
143
|
-
console.error(chalk.red(`Check failed: ${err.message}`));
|
|
144
|
-
process.exitCode = 1;
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
}
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
|
|
3
|
+
const BUILTIN_ROLES = {
|
|
4
|
+
'org-admin': ['view', 'download', 'reshare', 'delete', 'manage', 'audit', 'assign-roles'],
|
|
5
|
+
'dept-admin': ['view', 'download', 'reshare', 'delete', 'manage'],
|
|
6
|
+
'admin': ['view', 'download', 'reshare', 'delete', 'manage'],
|
|
7
|
+
'editor': ['view', 'download', 'reshare'],
|
|
8
|
+
'viewer': ['view', 'download'],
|
|
9
|
+
'member': ['view', 'download'],
|
|
10
|
+
'restricted': ['view'],
|
|
11
|
+
'external': ['view'],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default function rbacCommand(program) {
|
|
15
|
+
const cmd = program
|
|
16
|
+
.command('rbac')
|
|
17
|
+
.description('enterprise role-based access control (Enterprise)')
|
|
18
|
+
.addHelpText('after', `
|
|
19
|
+
Examples:
|
|
20
|
+
$ pal rbac roles List all roles and permissions
|
|
21
|
+
$ pal rbac assign <publicKey> admin Assign role to user
|
|
22
|
+
$ pal rbac assign <publicKey> dept-admin --org acme --dept engineering
|
|
23
|
+
$ pal rbac revoke <publicKey> Remove role assignment
|
|
24
|
+
$ pal rbac check <publicKey> delete Check if user has permission
|
|
25
|
+
`)
|
|
26
|
+
.action(() => { cmd.outputHelp(); });
|
|
27
|
+
|
|
28
|
+
cmd
|
|
29
|
+
.command('roles')
|
|
30
|
+
.description('list all roles with permissions')
|
|
31
|
+
.action(async () => {
|
|
32
|
+
try {
|
|
33
|
+
console.log('');
|
|
34
|
+
console.log(chalk.cyan.bold('Flat Roles'));
|
|
35
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
36
|
+
for (const role of ['admin', 'editor', 'viewer', 'restricted']) {
|
|
37
|
+
const perms = BUILTIN_ROLES[role];
|
|
38
|
+
console.log(` ${chalk.white(role)}`);
|
|
39
|
+
console.log(` ${chalk.gray(perms.join(', '))}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log('');
|
|
43
|
+
console.log(chalk.cyan.bold('Enterprise Hierarchical Roles'));
|
|
44
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
45
|
+
for (const role of ['org-admin', 'dept-admin', 'member', 'external']) {
|
|
46
|
+
const perms = BUILTIN_ROLES[role];
|
|
47
|
+
const scope = role === 'dept-admin' ? chalk.yellow(' (scoped to dept)') : '';
|
|
48
|
+
const note = role === 'external' ? chalk.yellow(' (limited)') : '';
|
|
49
|
+
console.log(` ${chalk.white(role)}${scope}${note}`);
|
|
50
|
+
console.log(` ${chalk.gray(perms.join(', '))}`);
|
|
51
|
+
}
|
|
52
|
+
console.log('');
|
|
53
|
+
} catch (err) {
|
|
54
|
+
console.error(chalk.red(`Failed to list roles: ${err.message}`));
|
|
55
|
+
process.exitCode = 1;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
cmd
|
|
60
|
+
.command('assign <publicKey> <role>')
|
|
61
|
+
.description('assign role to user')
|
|
62
|
+
.option('--org <orgId>', 'scope to organization')
|
|
63
|
+
.option('--dept <deptName>', 'scope to department')
|
|
64
|
+
.action(async (publicKey, role, opts) => {
|
|
65
|
+
try {
|
|
66
|
+
if (!BUILTIN_ROLES[role]) {
|
|
67
|
+
console.error(chalk.red(`Unknown role "${role}". Valid roles: ${Object.keys(BUILTIN_ROLES).join(', ')}`));
|
|
68
|
+
process.exitCode = 1;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const extConfig = (await import('../utils/config.js')).default;
|
|
73
|
+
const store = extConfig.get('ext_store.enterprise-rbac') || {};
|
|
74
|
+
const key = `role:${publicKey}`;
|
|
75
|
+
store[key] = {
|
|
76
|
+
role,
|
|
77
|
+
org: opts.org || null,
|
|
78
|
+
dept: opts.dept || null,
|
|
79
|
+
assignedAt: new Date().toISOString(),
|
|
80
|
+
};
|
|
81
|
+
extConfig.set('ext_store.enterprise-rbac', store);
|
|
82
|
+
|
|
83
|
+
let scope = '';
|
|
84
|
+
if (opts.org) scope += ` org=${chalk.white(opts.org)}`;
|
|
85
|
+
if (opts.dept) scope += ` dept=${chalk.white(opts.dept)}`;
|
|
86
|
+
console.log(chalk.green(`✔ Assigned role "${role}" to ${publicKey.slice(0, 16)}...${scope}`));
|
|
87
|
+
} catch (err) {
|
|
88
|
+
console.error(chalk.red(`Assign failed: ${err.message}`));
|
|
89
|
+
process.exitCode = 1;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
cmd
|
|
94
|
+
.command('revoke <publicKey>')
|
|
95
|
+
.description('remove role assignment')
|
|
96
|
+
.action(async (publicKey) => {
|
|
97
|
+
try {
|
|
98
|
+
const extConfig = (await import('../utils/config.js')).default;
|
|
99
|
+
const store = extConfig.get('ext_store.enterprise-rbac') || {};
|
|
100
|
+
const key = `role:${publicKey}`;
|
|
101
|
+
|
|
102
|
+
if (!store[key]) {
|
|
103
|
+
console.log(chalk.yellow(`No role assignment found for ${publicKey.slice(0, 16)}...`));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const oldRole = store[key].role;
|
|
108
|
+
delete store[key];
|
|
109
|
+
extConfig.set('ext_store.enterprise-rbac', store);
|
|
110
|
+
console.log(chalk.green(`✔ Revoked role "${oldRole}" from ${publicKey.slice(0, 16)}...`));
|
|
111
|
+
} catch (err) {
|
|
112
|
+
console.error(chalk.red(`Revoke failed: ${err.message}`));
|
|
113
|
+
process.exitCode = 1;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
cmd
|
|
118
|
+
.command('check <publicKey> <permission>')
|
|
119
|
+
.description('check if user has specific permission')
|
|
120
|
+
.action(async (publicKey, permission) => {
|
|
121
|
+
try {
|
|
122
|
+
const extConfig = (await import('../utils/config.js')).default;
|
|
123
|
+
const store = extConfig.get('ext_store.enterprise-rbac') || {};
|
|
124
|
+
const key = `role:${publicKey}`;
|
|
125
|
+
const assignment = store[key];
|
|
126
|
+
|
|
127
|
+
if (!assignment) {
|
|
128
|
+
console.log(chalk.red(`✘ No role assigned to ${publicKey.slice(0, 16)}...`));
|
|
129
|
+
process.exitCode = 1;
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const perms = BUILTIN_ROLES[assignment.role] || [];
|
|
134
|
+
const has = perms.includes(permission);
|
|
135
|
+
|
|
136
|
+
if (has) {
|
|
137
|
+
console.log(chalk.green(`✔ ${publicKey.slice(0, 16)}... HAS "${permission}" (role: ${assignment.role})`));
|
|
138
|
+
} else {
|
|
139
|
+
console.log(chalk.red(`✘ ${publicKey.slice(0, 16)}... DOES NOT have "${permission}" (role: ${assignment.role})`));
|
|
140
|
+
process.exitCode = 1;
|
|
141
|
+
}
|
|
142
|
+
} catch (err) {
|
|
143
|
+
console.error(chalk.red(`Check failed: ${err.message}`));
|
|
144
|
+
process.exitCode = 1;
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
package/lib/commands/recover.js
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import ora from 'ora';
|
|
3
|
-
import { recoverIdentity } from '../core/identity.js';
|
|
4
|
-
|
|
5
|
-
export default function recoverCommand(program) {
|
|
6
|
-
program
|
|
7
|
-
.command('recover <mnemonic...>')
|
|
8
|
-
.description('recover your identity from a BIP-39 mnemonic phrase')
|
|
9
|
-
.option('-n, --name <name>', 'Name for the recovered identity')
|
|
10
|
-
.addHelpText('after', `
|
|
11
|
-
Examples:
|
|
12
|
-
$
|
|
13
|
-
$
|
|
14
|
-
`)
|
|
15
|
-
.action(async (words, opts) => {
|
|
16
|
-
const mnemonic = words.join(' ').trim();
|
|
17
|
-
const wordCount = mnemonic.split(/\s+/).length;
|
|
18
|
-
if (wordCount !== 24) {
|
|
19
|
-
console.log(chalk.red(`Expected 24 words, got ${wordCount}.`));
|
|
20
|
-
process.exitCode = 1;
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const spinner = ora('Recovering identity...').start();
|
|
25
|
-
try {
|
|
26
|
-
const identity = await recoverIdentity(mnemonic, opts.name);
|
|
27
|
-
spinner.succeed(chalk.green('Identity recovered!'));
|
|
28
|
-
console.log(chalk.cyan(`Public Key: ${identity.publicKey}`));
|
|
29
|
-
console.log(chalk.gray('Re-register your handle with `
|
|
30
|
-
} catch (err) {
|
|
31
|
-
spinner.fail(chalk.red('Recovery failed'));
|
|
32
|
-
console.error(chalk.red(`Error: ${err.message}`));
|
|
33
|
-
process.exitCode = 1;
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { recoverIdentity } from '../core/identity.js';
|
|
4
|
+
|
|
5
|
+
export default function recoverCommand(program) {
|
|
6
|
+
program
|
|
7
|
+
.command('recover <mnemonic...>')
|
|
8
|
+
.description('recover your identity from a BIP-39 mnemonic phrase')
|
|
9
|
+
.option('-n, --name <name>', 'Name for the recovered identity')
|
|
10
|
+
.addHelpText('after', `
|
|
11
|
+
Examples:
|
|
12
|
+
$ pal recover word1 word2 ... word24 Recover from 24-word phrase
|
|
13
|
+
$ pal recover word1 word2 ... word24 -n alice Recover with name "alice"
|
|
14
|
+
`)
|
|
15
|
+
.action(async (words, opts) => {
|
|
16
|
+
const mnemonic = words.join(' ').trim();
|
|
17
|
+
const wordCount = mnemonic.split(/\s+/).length;
|
|
18
|
+
if (wordCount !== 24) {
|
|
19
|
+
console.log(chalk.red(`Expected 24 words, got ${wordCount}.`));
|
|
20
|
+
process.exitCode = 1;
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const spinner = ora('Recovering identity...').start();
|
|
25
|
+
try {
|
|
26
|
+
const identity = await recoverIdentity(mnemonic, opts.name);
|
|
27
|
+
spinner.succeed(chalk.green('Identity recovered!'));
|
|
28
|
+
console.log(chalk.cyan(`Public Key: ${identity.publicKey}`));
|
|
29
|
+
console.log(chalk.gray('Re-register your handle with `pal register <handle>` to associate it with this key.'));
|
|
30
|
+
} catch (err) {
|
|
31
|
+
spinner.fail(chalk.red('Recovery failed'));
|
|
32
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
33
|
+
process.exitCode = 1;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|