long-git-cli
Version:
A CLI tool for Git tag management.
331 lines • 11 kB
JavaScript
"use strict";
/**
* 配置管理器
* 管理所有配置数据的读取、写入、验证和加密
*/
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.ConfigManager = void 0;
const storage_1 = require("./storage");
const encryption_1 = require("./encryption");
const constants_1 = require("../constants");
const path = __importStar(require("path"));
/**
* ConfigManager 类
* 负责配置的 CRUD 操作
*/
class ConfigManager {
constructor(storage) {
/** 内存缓存(用于存储明文密码,仅在运行时有效) */
this.credentialsCache = {
jenkinsTokens: new Map(),
};
this.storage = storage || new storage_1.Storage();
this.configFilename = path.basename(constants_1.CONFIG_FILE);
}
/**
* 加载配置
*/
async loadConfig() {
const config = await this.storage.read(this.configFilename);
if (!config) {
/** 返回默认配置 */
return this.getDefaultConfig();
}
return config;
}
/**
* 保存配置(不验证完整性)
* 用于部分更新配置
*/
async saveConfigWithoutValidation(config) {
await this.storage.write(this.configFilename, config);
}
/**
* 保存配置
*/
async saveConfig(config) {
/** 验证配置 */
const isValid = await this.validateConfig(config);
if (!isValid) {
throw new Error("配置验证失败");
}
await this.storage.write(this.configFilename, config);
}
/**
* 验证配置完整性
*/
async validateConfig(config) {
try {
/** 检查必需字段 */
if (!config.version) {
return false;
}
/** 检查 Bitbucket 配置 */
if (!config.bitbucket?.username) {
return false;
}
// 兼容新旧两种 token 格式
if (!config.bitbucket?.apiTokenHash && !config.bitbucket?.appPasswordHash) {
return false;
}
/** 检查至少有一个 Jenkins 实例 */
if (!config.jenkins || config.jenkins.length === 0) {
return false;
}
/** 检查每个 Jenkins 实例的配置 */
for (const jenkins of config.jenkins) {
if (!jenkins.type ||
!jenkins.url ||
!jenkins.username ||
!jenkins.apiTokenHash) {
return false;
}
}
/** 检查至少有一个项目配置 */
const projectPaths = Object.keys(config.projects || {});
if (projectPaths.length === 0) {
return false;
}
/** 检查每个项目至少有一个环境 */
for (const projectPath of projectPaths) {
const project = config.projects[projectPath];
const envs = Object.keys(project.environments || {});
if (envs.length === 0) {
return false;
}
}
return true;
}
catch {
return false;
}
}
/**
* 获取项目配置
*/
async getProjectConfig(projectPath) {
const config = await this.loadConfig();
return config.projects[projectPath] || null;
}
/**
* 更新项目配置
*/
async updateProjectConfig(projectPath, projectConfig) {
const config = await this.loadConfig();
config.projects[projectPath] = projectConfig;
// 使用不验证的保存方法,允许部分配置
await this.saveConfigWithoutValidation(config);
}
/**
* 删除项目配置
*/
async deleteProjectConfig(projectPath) {
const config = await this.loadConfig();
delete config.projects[projectPath];
// 使用不验证的保存方法,允许部分配置
await this.saveConfigWithoutValidation(config);
}
/**
* 加密 Token
*/
async encryptToken(token) {
return encryption_1.Encryption.encrypt(token);
}
/**
* 解密 Token
*/
decryptToken(encryptedToken) {
return encryption_1.Encryption.decrypt(encryptedToken);
}
/**
* 验证 Token
* @deprecated 不再需要,直接解密使用
*/
async verifyToken(token, hash) {
return encryption_1.Encryption.verify(token, hash);
}
/**
* 更新 Bitbucket 配置
* @param username Bitbucket 用户名
* @param token API Token 或 App Password(兼容旧版)
*/
async updateBitbucketConfig(username, token) {
const config = await this.loadConfig();
const tokenHash = await this.encryptToken(token);
config.bitbucket = {
username,
apiTokenHash: tokenHash,
// 保留旧字段以兼容
appPasswordHash: tokenHash,
};
/** 缓存明文 token */
this.credentialsCache.bitbucketPassword = token;
// 使用不验证的保存方法,允许部分配置
await this.saveConfigWithoutValidation(config);
}
/**
* 获取 Bitbucket 明文密码
* 优先从缓存获取,如果没有则从配置文件解密
*/
async getBitbucketPassword() {
// 先尝试从缓存获取
if (this.credentialsCache.bitbucketPassword) {
return this.credentialsCache.bitbucketPassword;
}
// 从配置文件解密
const config = await this.loadConfig();
const encryptedToken = config.bitbucket.apiTokenHash || config.bitbucket.appPasswordHash;
if (encryptedToken) {
try {
const decrypted = this.decryptToken(encryptedToken);
// 缓存到内存
this.credentialsCache.bitbucketPassword = decrypted;
return decrypted;
}
catch (error) {
console.error('解密 Bitbucket token 失败:', error);
return undefined;
}
}
return undefined;
}
/**
* 更新 Jenkins 配置
*/
async updateJenkinsConfig(jenkinsConfigs) {
const config = await this.loadConfig();
config.jenkins = jenkinsConfigs;
// 使用不验证的保存方法,允许部分配置
await this.saveConfigWithoutValidation(config);
}
/**
* 添加 Jenkins 实例
*/
async addJenkinsInstance(type, url, username, apiToken) {
const config = await this.loadConfig();
const apiTokenHash = await this.encryptToken(apiToken);
const newJenkins = {
type,
url,
username,
apiTokenHash,
};
/** 检查是否已存在相同类型的实例 */
const existingIndex = config.jenkins.findIndex((j) => j.type === type);
if (existingIndex >= 0) {
/** 更新现有实例 */
config.jenkins[existingIndex] = newJenkins;
}
else {
/** 添加新实例 */
config.jenkins.push(newJenkins);
}
/** 缓存明文 token */
this.credentialsCache.jenkinsTokens?.set(type, apiToken);
// 使用不验证的保存方法,允许部分配置
await this.saveConfigWithoutValidation(config);
}
/**
* 获取 Jenkins 明文 token
* 优先从缓存获取,如果没有则从配置文件解密
*/
async getJenkinsToken(type) {
// 先尝试从缓存获取
const cached = this.credentialsCache.jenkinsTokens?.get(type);
if (cached) {
return cached;
}
// 从配置文件解密
const config = await this.loadConfig();
const jenkinsConfig = config.jenkins.find((j) => j.type === type);
if (jenkinsConfig?.apiTokenHash) {
try {
const decrypted = this.decryptToken(jenkinsConfig.apiTokenHash);
// 缓存到内存
this.credentialsCache.jenkinsTokens?.set(type, decrypted);
return decrypted;
}
catch (error) {
console.error(`解密 Jenkins ${type} token 失败:`, error);
return undefined;
}
}
return undefined;
}
/**
* 更新部署状态
*/
async updateDeployStatus(projectPath, environment, status) {
const config = await this.loadConfig();
const project = config.projects[projectPath];
if (!project) {
throw new Error(`项目不存在: ${projectPath}`);
}
const env = project.environments[environment];
if (!env) {
throw new Error(`环境不存在: ${environment}`);
}
// 更新部署状态
env.deployStatus = {
...env.deployStatus,
...status,
lastUpdated: new Date().toISOString(),
};
await this.saveConfigWithoutValidation(config);
}
/**
* 获取默认配置
*/
getDefaultConfig() {
return {
version: constants_1.CONFIG_VERSION,
projects: {},
bitbucket: {
username: "",
apiTokenHash: "",
},
jenkins: [],
};
}
/**
* 检查配置文件是否存在
*/
async configExists() {
return this.storage.exists(this.configFilename);
}
}
exports.ConfigManager = ConfigManager;
//# sourceMappingURL=config-manager.js.map