mira-app-server
Version:
Mira Server - standalone server application using mira-app-core
171 lines • 6.96 kB
JavaScript
;
/**
* 用户模块命令
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.registerUser = registerUser;
const path_1 = __importDefault(require("path"));
const client_1 = require("../client");
const format_1 = require("../format");
/**
* 交互式读取密码(隐藏输入,输出星号),回车结束。
* 仅当未通过 -p 提供密码时使用。
*/
async function promptPassword(question) {
return new Promise(resolve => {
const stdin = process.stdin;
const stdout = process.stdout;
stdout.write(question);
let value = '';
const cleanup = () => {
stdin.removeListener('data', onData);
stdin.setRawMode(false);
stdin.pause();
};
const onData = (buffer) => {
for (const byte of buffer) {
if (byte === 0x0d || byte === 0x0a) { // Enter
stdout.write('\n');
cleanup();
resolve(value.trim());
return;
}
if (byte === 0x7f || byte === 0x08) { // Backspace
if (value.length > 0) {
value = value.slice(0, -1);
stdout.write('\b \b');
}
continue;
}
if (byte === 0x03) { // Ctrl+C
stdout.write('\n');
cleanup();
process.exit(0);
}
value += String.fromCharCode(byte);
stdout.write('*');
}
};
stdin.setRawMode(true);
stdin.resume();
stdin.on('data', onData);
});
}
function registerUser(program) {
const user = program.command('user').description('用户信息管理');
user.command('info')
.description('获取当前登录用户信息')
.action(async () => {
try {
const { client } = (0, client_1.getClient)();
const info = await client.user().getInfo();
(0, format_1.output)(info, () => (0, format_1.formatKeyValue)(info));
}
catch (error) {
(0, format_1.fatal)(error);
}
});
user.command('update')
.description('更新当前用户信息')
.option('--real-name <name>', '真实姓名')
.option('--avatar <url>', '头像 URL')
.action(async (options) => {
try {
const { client } = (0, client_1.getClient)();
const data = {};
if (options.realName !== undefined)
data.realName = options.realName;
if (options.avatar !== undefined)
data.avatar = options.avatar;
const res = await client.user().updateInfo(data);
(0, format_1.success)('用户信息已更新');
(0, format_1.output)(res);
}
catch (error) {
(0, format_1.fatal)(error);
}
});
// 重置密码:直接操作本地 users.db,不经过 HTTP、不需要登录。
// 用于密码遗忘 / deploy 脚本登录失败时的恢复。会清除该用户所有会话。
user.command('reset-password')
.description('重置用户密码(直连本地 users.db,无需登录;用于密码遗忘/登录失败恢复)')
.option('-u, --username <username>', '用户名', 'admin')
.option('-p, --password <password>', '新密码(不填则交互式输入)')
.option('-d, --data-path <path>', '数据目录(含 users.db);默认取 DATA_PATH 环境变量或 ./data')
.action(async (options) => {
const dataPath = options.dataPath || process.env.DATA_PATH || path_1.default.join(process.cwd(), 'data');
let password = options.password;
if (!password) {
password = await promptPassword('新密码: ');
const confirm = await promptPassword('确认新密码: ');
if (!password) {
(0, format_1.fatal)(new Error('密码不能为空'));
}
if (password !== confirm) {
(0, format_1.fatal)(new Error('两次输入的密码不一致'));
}
}
const { UserStorage } = await Promise.resolve().then(() => __importStar(require('../../UserStorage')));
const storage = new UserStorage(dataPath);
let exitError = null;
try {
await storage.initialize();
const target = await storage.findUserByUsername(options.username);
if (!target) {
throw new Error(`用户 "${options.username}" 不存在或未激活`);
}
const updated = await storage.updateUser(target.id, { password });
if (!updated) {
throw new Error('密码更新失败(用户可能已被禁用)');
}
// 清除该用户所有会话,旧 token 立即失效
await storage.revokeAllUserSessions(target.id);
(0, format_1.output)({ ok: true, username: options.username, dataPath }, () => `已重置用户 "${options.username}" 的密码,并清除其所有登录会话`);
}
catch (error) {
exitError = error;
}
finally {
await storage.close();
if (exitError)
(0, format_1.fatal)(exitError);
}
});
}
//# sourceMappingURL=user.js.map