polyv-live-cli
Version:
CLI tool for managing PolyV live streaming services.
362 lines • 13.7 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;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.AccountConfigManager = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const os = __importStar(require("os"));
const account_types_1 = require("../types/account.types");
const account_crypto_1 = require("./account-crypto");
const DEFAULT_CONFIG = {
version: '1.0.0',
configDir: '.polyv',
configFileName: 'accounts.json',
filePermissions: 0o600
};
class AccountConfigManager {
constructor(configPath, masterKey) {
if (configPath) {
if (configPath.endsWith('.json')) {
this.configPath = configPath;
}
else {
this.configPath = path.join(configPath, DEFAULT_CONFIG.configFileName);
}
}
else {
this.configPath = this.getDefaultConfigPath();
}
this.crypto = new account_crypto_1.AccountCrypto(masterKey);
}
getDefaultConfigPath() {
const homeDir = process.env['HOME'] || os.homedir();
const configDir = path.join(homeDir, DEFAULT_CONFIG.configDir);
return path.join(configDir, DEFAULT_CONFIG.configFileName);
}
ensureConfigDir() {
const configDir = path.dirname(this.configPath);
if (!fs.existsSync(configDir)) {
fs.mkdirSync(configDir, { recursive: true, mode: 0o700 });
}
}
setSecurePermissions(filePath) {
try {
fs.chmodSync(filePath, DEFAULT_CONFIG.filePermissions);
}
catch (error) {
console.warn(`Warning: Could not set file permissions for ${filePath}`);
}
}
validateAccountConfig(config) {
const { name, appId, appSecret } = config;
if (!name || typeof name !== 'string') {
throw new Error('Account name is required and must be a string');
}
if (!account_types_1.AccountConfigValidation.name.pattern.test(name)) {
throw new Error('Account name can only contain letters, numbers, underscores, and hyphens');
}
if (name.length > account_types_1.AccountConfigValidation.name.maxLength) {
throw new Error(`Account name must be ${account_types_1.AccountConfigValidation.name.maxLength} characters or less`);
}
if (!appId || typeof appId !== 'string') {
throw new Error('App ID is required and must be a string');
}
if (!account_types_1.AccountConfigValidation.appId.pattern.test(appId)) {
throw new Error('App ID can only contain letters and numbers');
}
if (appId.length < account_types_1.AccountConfigValidation.appId.minLength ||
appId.length > account_types_1.AccountConfigValidation.appId.maxLength) {
throw new Error(`App ID must be between ${account_types_1.AccountConfigValidation.appId.minLength} and ${account_types_1.AccountConfigValidation.appId.maxLength} characters`);
}
if (!appSecret || typeof appSecret !== 'string') {
throw new Error('App Secret is required and must be a string');
}
if (appSecret.length < account_types_1.AccountConfigValidation.appSecret.minLength ||
appSecret.length > account_types_1.AccountConfigValidation.appSecret.maxLength) {
throw new Error(`App Secret must be between ${account_types_1.AccountConfigValidation.appSecret.minLength} and ${account_types_1.AccountConfigValidation.appSecret.maxLength} characters`);
}
}
loadAccountsStore() {
try {
if (!fs.existsSync(this.configPath)) {
return this.createEmptyStore();
}
const fileContent = fs.readFileSync(this.configPath, 'utf8');
const store = JSON.parse(fileContent);
if (!store.version || !store.accounts || !store.metadata) {
throw new Error('Invalid accounts store format');
}
return store;
}
catch (error) {
if (error instanceof SyntaxError) {
throw new Error(`Invalid JSON in accounts configuration file: ${error.message}`);
}
throw new Error(`Failed to load accounts configuration: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
saveAccountsStore(store) {
try {
this.ensureConfigDir();
store.metadata.updatedAt = new Date().toISOString();
const tempPath = `${this.configPath}.tmp`;
fs.writeFileSync(tempPath, JSON.stringify(store, null, 2), 'utf8');
this.setSecurePermissions(tempPath);
fs.renameSync(tempPath, this.configPath);
}
catch (error) {
throw new Error(`Failed to save accounts configuration: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
createEmptyStore() {
const now = new Date().toISOString();
return {
version: DEFAULT_CONFIG.version,
accounts: {},
metadata: {
createdAt: now,
updatedAt: now
}
};
}
addAccount(name, appId, appSecret, userId, environment, baseUrl) {
try {
this.validateAccountConfig({ name, appId, appSecret });
const store = this.loadAccountsStore();
if (store.accounts[name]) {
return {
success: false,
message: `Account '${name}' already exists. Use a different name or remove the existing account first.`
};
}
const encryptedSecret = this.crypto.encryptSimple(appSecret);
const now = new Date().toISOString();
const accountConfig = {
name,
appId,
appSecret: encryptedSecret,
...(userId && { userId }),
...(environment && { environment: environment }),
...(baseUrl && { baseUrl }),
createdAt: now,
updatedAt: now
};
store.accounts[name] = accountConfig;
this.saveAccountsStore(store);
return {
success: true,
message: `Account '${name}' added successfully.`,
account: { ...accountConfig, appSecret: '[encrypted]' }
};
}
catch (error) {
return {
success: false,
message: error instanceof Error ? error.message : 'Unknown error occurred'
};
}
}
removeAccount(name) {
try {
const store = this.loadAccountsStore();
if (!store.accounts[name]) {
return {
success: false,
message: `Account '${name}' not found.`
};
}
delete store.accounts[name];
this.saveAccountsStore(store);
return {
success: true,
message: `Account '${name}' removed successfully.`
};
}
catch (error) {
return {
success: false,
message: error instanceof Error ? error.message : 'Unknown error occurred'
};
}
}
getAccount(name) {
try {
const store = this.loadAccountsStore();
const account = store.accounts[name];
if (!account) {
return null;
}
const decryptedSecret = this.crypto.decryptSimple(account.appSecret);
return {
...account,
appSecret: decryptedSecret
};
}
catch (error) {
throw new Error(`Failed to get account '${name}': ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
listAccounts() {
try {
const store = this.loadAccountsStore();
return Object.values(store.accounts).map(account => ({
name: account.name,
appId: account.appId,
...(account.userId && { userId: account.userId }),
...(account.environment && { environment: account.environment }),
...(account.baseUrl && { baseUrl: account.baseUrl }),
createdAt: account.createdAt,
updatedAt: account.updatedAt
}));
}
catch (error) {
throw new Error(`Failed to list accounts: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
accountExists(name) {
try {
const store = this.loadAccountsStore();
return name in store.accounts;
}
catch {
return false;
}
}
getConfigPath() {
return this.configPath;
}
backupConfig(backupPath) {
const backup = backupPath || `${this.configPath}.backup.${Date.now()}`;
if (fs.existsSync(this.configPath)) {
fs.copyFileSync(this.configPath, backup);
this.setSecurePermissions(backup);
}
return backup;
}
restoreConfig(backupPath) {
if (!fs.existsSync(backupPath)) {
throw new Error(`Backup file not found: ${backupPath}`);
}
this.ensureConfigDir();
fs.copyFileSync(backupPath, this.configPath);
this.setSecurePermissions(this.configPath);
}
validateConfig() {
try {
const store = this.loadAccountsStore();
for (const account of Object.values(store.accounts)) {
this.crypto.decryptSimple(account.appSecret);
}
return true;
}
catch {
return false;
}
}
setDefaultAccount(accountName) {
try {
const store = this.loadAccountsStore();
if (!store.accounts[accountName]) {
const availableAccounts = Object.keys(store.accounts);
const suggestion = availableAccounts.length > 0
? `\n\n可用账号: ${availableAccounts.join(', ')}`
: '\n\n当前没有配置任何账号。使用 \'polyv-cli account add <account-name>\' 添加账号。';
return {
success: false,
message: `账号 '${accountName}' 不存在。${suggestion}`
};
}
store.defaultAccount = accountName;
this.saveAccountsStore(store);
return {
success: true,
message: `已将账号 '${accountName}' 设置为默认账号。`
};
}
catch (error) {
return {
success: false,
message: error instanceof Error ? error.message : '设置默认账号时发生未知错误'
};
}
}
unsetDefaultAccount() {
try {
const store = this.loadAccountsStore();
if (!store.defaultAccount) {
return {
success: false,
message: '当前没有设置默认账号。'
};
}
const previousDefault = store.defaultAccount;
delete store.defaultAccount;
this.saveAccountsStore(store);
return {
success: true,
message: `已取消 '${previousDefault}' 的默认账号设置。`
};
}
catch (error) {
return {
success: false,
message: error instanceof Error ? error.message : '取消默认账号时发生未知错误'
};
}
}
getDefaultAccount() {
try {
const store = this.loadAccountsStore();
return store.defaultAccount || null;
}
catch {
return null;
}
}
getDefaultAccountConfig() {
try {
const defaultAccountName = this.getDefaultAccount();
if (!defaultAccountName) {
return null;
}
return this.getAccount(defaultAccountName);
}
catch {
return null;
}
}
}
exports.AccountConfigManager = AccountConfigManager;
//# sourceMappingURL=account-config.js.map