javascript-solid-server 0.0.143 → 0.0.144
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/bin/jss.js +58 -31
- package/package.json +1 -1
package/bin/jss.js
CHANGED
|
@@ -13,6 +13,7 @@ import { Command } from 'commander';
|
|
|
13
13
|
import { createServer } from '../src/server.js';
|
|
14
14
|
import { loadConfig, saveConfig, printConfig, defaults } from '../src/config.js';
|
|
15
15
|
import { createInvite, listInvites, revokeInvite } from '../src/idp/invites.js';
|
|
16
|
+
import { findByUsername, updatePassword, deleteAccount } from '../src/idp/accounts.js';
|
|
16
17
|
import { setQuotaLimit, getQuotaInfo, reconcileQuota, formatBytes } from '../src/storage/quota.js';
|
|
17
18
|
import { parseSize } from '../src/config.js';
|
|
18
19
|
import crypto from 'crypto';
|
|
@@ -637,32 +638,12 @@ program
|
|
|
637
638
|
process.env.DATA_ROOT = path.resolve(options.root);
|
|
638
639
|
}
|
|
639
640
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
const accountsDir = path.join(dataRoot, '.idp', 'accounts');
|
|
643
|
-
const indexPath = path.join(accountsDir, '_username_index.json');
|
|
644
|
-
|
|
645
|
-
let usernameIndex;
|
|
646
|
-
try {
|
|
647
|
-
usernameIndex = await fs.readJson(indexPath);
|
|
648
|
-
} catch (err) {
|
|
649
|
-
if (err.code === 'ENOENT') {
|
|
650
|
-
console.error(`Error: No accounts found (missing ${indexPath})`);
|
|
651
|
-
process.exit(1);
|
|
652
|
-
}
|
|
653
|
-
throw err;
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
const normalizedUsername = username.toLowerCase().trim();
|
|
657
|
-
const accountId = usernameIndex[normalizedUsername];
|
|
658
|
-
if (!accountId) {
|
|
641
|
+
const account = await findByUsername(username);
|
|
642
|
+
if (!account) {
|
|
659
643
|
console.error(`Error: User not found: ${username}`);
|
|
660
644
|
process.exit(1);
|
|
661
645
|
}
|
|
662
646
|
|
|
663
|
-
const accountPath = path.join(accountsDir, `${accountId}.json`);
|
|
664
|
-
const account = await fs.readJson(accountPath);
|
|
665
|
-
|
|
666
647
|
// Determine new password
|
|
667
648
|
let newPassword;
|
|
668
649
|
|
|
@@ -673,8 +654,8 @@ program
|
|
|
673
654
|
} else {
|
|
674
655
|
// Interactive prompt
|
|
675
656
|
newPassword = await promptPassword('New password: ');
|
|
676
|
-
const
|
|
677
|
-
if (newPassword !==
|
|
657
|
+
const confirmation = await promptPassword('Confirm password: ');
|
|
658
|
+
if (newPassword !== confirmation) {
|
|
678
659
|
console.error('Error: Passwords do not match');
|
|
679
660
|
process.exit(1);
|
|
680
661
|
}
|
|
@@ -685,17 +666,63 @@ program
|
|
|
685
666
|
process.exit(1);
|
|
686
667
|
}
|
|
687
668
|
|
|
688
|
-
|
|
689
|
-
const bcrypt = await import('bcryptjs').then(m => m.default);
|
|
690
|
-
account.passwordHash = await bcrypt.hash(newPassword, 10);
|
|
691
|
-
account.passwordChangedAt = new Date().toISOString();
|
|
692
|
-
await fs.writeJson(accountPath, account, { spaces: 2 });
|
|
669
|
+
await updatePassword(account.id, newPassword);
|
|
693
670
|
|
|
694
671
|
if (options.generate) {
|
|
695
|
-
console.log(`\nPassword updated for ${
|
|
672
|
+
console.log(`\nPassword updated for ${account.username}`);
|
|
696
673
|
console.log(`Generated password: ${newPassword}\n`);
|
|
697
674
|
} else {
|
|
698
|
-
console.log(`\nPassword updated for ${
|
|
675
|
+
console.log(`\nPassword updated for ${account.username}\n`);
|
|
676
|
+
}
|
|
677
|
+
} catch (err) {
|
|
678
|
+
console.error(`Error: ${err.message}`);
|
|
679
|
+
process.exit(1);
|
|
680
|
+
}
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* Account commands - manage user accounts
|
|
685
|
+
*/
|
|
686
|
+
const accountCmd = program
|
|
687
|
+
.command('account')
|
|
688
|
+
.description('Manage user accounts');
|
|
689
|
+
|
|
690
|
+
accountCmd
|
|
691
|
+
.command('delete <username>')
|
|
692
|
+
.description('Delete a user account from the IdP')
|
|
693
|
+
.option('-r, --root <path>', 'Data directory')
|
|
694
|
+
.option('-y, --yes', 'Skip the confirmation prompt')
|
|
695
|
+
.option('--purge', 'Also delete pod data at <dataRoot>/<username>/')
|
|
696
|
+
.action(async (username, options) => {
|
|
697
|
+
try {
|
|
698
|
+
if (options.root) {
|
|
699
|
+
process.env.DATA_ROOT = path.resolve(options.root);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
const account = await findByUsername(username);
|
|
703
|
+
if (!account) {
|
|
704
|
+
console.error(`Error: User not found: ${username}`);
|
|
705
|
+
process.exit(1);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
if (!options.yes) {
|
|
709
|
+
const summary = `Delete account '${account.username}' (${account.webId})${options.purge ? ' AND purge pod data' : ''}?`;
|
|
710
|
+
const ok = await confirm(summary, false);
|
|
711
|
+
if (!ok) {
|
|
712
|
+
console.log('Cancelled.');
|
|
713
|
+
process.exit(0);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
await deleteAccount(account.id);
|
|
718
|
+
|
|
719
|
+
if (options.purge) {
|
|
720
|
+
const dataRoot = process.env.DATA_ROOT || './data';
|
|
721
|
+
const podPath = path.join(dataRoot, account.username);
|
|
722
|
+
await fs.remove(podPath);
|
|
723
|
+
console.log(`\nDeleted account ${account.username}. Pod data removed from ${podPath}.\n`);
|
|
724
|
+
} else {
|
|
725
|
+
console.log(`\nDeleted account ${account.username}. Pod data preserved at <dataRoot>/${account.username}/ (use --purge to remove).\n`);
|
|
699
726
|
}
|
|
700
727
|
} catch (err) {
|
|
701
728
|
console.error(`Error: ${err.message}`);
|