vk-ssl-auto-deploy 0.1.2 → 0.2.1

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/routes/cert.js +73 -72
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vk-ssl-auto-deploy",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "description": "SSL证书自动部署工具 - 提供HTTP API接口,支持证书文件自动上传和部署",
5
5
  "main": "app.js",
6
6
  "bin": {
package/routes/cert.js CHANGED
@@ -38,8 +38,8 @@ router.post('/deploy-cert', upload.single('file'), async (req, res, next) => {
38
38
  const clientIP = getClientIP(req);
39
39
  if (!isIPInWhitelist(clientIP, config.ipWhitelist)) {
40
40
  console.warn(`[IP白名单拦截] IP: ${clientIP} 尝试部署证书但不在白名单中`);
41
- return res.json({
42
- code: 4030,
41
+ return res.json({
42
+ code: 4030,
43
43
  msg: 'IP地址不在白名单中,访问被拒绝',
44
44
  ip: clientIP
45
45
  });
@@ -66,10 +66,11 @@ router.post('/deploy-cert', upload.single('file'), async (req, res, next) => {
66
66
  // 2. 创建cert目录和子目录
67
67
  const projectRoot = path.join(__dirname, '..');
68
68
  // 使用配置文件中的 certPath,支持绝对路径和相对路径
69
- const certBaseDir = path.isAbsolute(config.certPath)
70
- ? config.certPath
71
- : path.join(projectRoot, config.certPath);
72
- const certDir = path.resolve(certBaseDir, certName);
69
+ const certBaseDir = path.isAbsolute(config.certPath) ?
70
+ config.certPath :
71
+ path.join(projectRoot, config.certPath);
72
+ const certDir = path.resolve(certBaseDir, certName);
73
+ const userCertDir = certDir.replace(/\\/g, '/');
73
74
 
74
75
  // 确保cert根目录存在
75
76
  if (!fs.existsSync(certBaseDir)) {
@@ -91,18 +92,18 @@ router.post('/deploy-cert', upload.single('file'), async (req, res, next) => {
91
92
 
92
93
  // 统计信息
93
94
  const stats = {
94
- total: 0, // 总文件数
95
- saved: 0, // 成功保存的文件数
96
- filtered: 0, // 被过滤的文件数
97
- savedFiles: [], // 保存的文件列表
98
- filteredFiles: [] // 被过滤的文件列表(含原因)
95
+ total: 0, // 总文件数
96
+ saved: 0, // 成功保存的文件数
97
+ filtered: 0, // 被过滤的文件数
98
+ savedFiles: [], // 保存的文件列表
99
+ filteredFiles: [] // 被过滤的文件列表(含原因)
99
100
  };
100
101
 
101
102
  // 遍历并验证每个文件
102
103
  zipEntries.forEach((entry) => {
103
104
  if (!entry.isDirectory) {
104
105
  stats.total++;
105
-
106
+
106
107
  const filename = path.basename(entry.entryName);
107
108
  const entryData = entry.getData();
108
109
 
@@ -122,10 +123,10 @@ router.post('/deploy-cert', upload.single('file'), async (req, res, next) => {
122
123
 
123
124
  // 写入文件
124
125
  fs.writeFileSync(entryPath, entryData);
125
-
126
+
126
127
  stats.saved++;
127
128
  stats.savedFiles.push(entry.entryName);
128
-
129
+
129
130
  console.log(`[文件已保存] ${entry.entryName} (${entryData.length} bytes)`);
130
131
  } catch (writeError) {
131
132
  console.error(`[文件写入失败] ${entry.entryName}:`, writeError.message);
@@ -142,7 +143,7 @@ router.post('/deploy-cert', upload.single('file'), async (req, res, next) => {
142
143
  filename: entry.entryName,
143
144
  reason: validation.reason
144
145
  });
145
-
146
+
146
147
  console.warn(`[文件已过滤] ${entry.entryName}: ${validation.reason}`);
147
148
  }
148
149
  }
@@ -162,68 +163,68 @@ router.post('/deploy-cert', upload.single('file'), async (req, res, next) => {
162
163
  });
163
164
  }
164
165
 
165
- console.log(`[证书部署成功] 名称: ${certName}, 路径: ${certDir.replace(/\\/g, '/')}, 保存: ${stats.saved}个, 过滤: ${stats.filtered}个`);
166
-
167
- // 4. 执行回调命令
168
- const commandResults = [];
169
- if (config.callbackCommand && Array.isArray(config.callbackCommand) && config.callbackCommand.length > 0) {
170
- console.log(`[开始执行回调命令] 共${config.callbackCommand.length}个命令`);
171
-
172
- for (let i = 0; i < config.callbackCommand.length; i++) {
173
- const command = config.callbackCommand[i];
174
- const commandResult = {
175
- command: command,
176
- index: i + 1,
177
- success: false,
178
- output: '',
179
- error: ''
180
- };
181
-
182
- try {
183
- console.log(`[执行命令 ${i + 1}/${config.callbackCommand.length}] ${command}`);
184
- const { stdout, stderr } = await execAsync(command, {
185
- timeout: 30000, // 30秒超时
186
- maxBuffer: 1024 * 1024 // 1MB buffer
187
- });
188
-
189
- commandResult.success = true;
190
- commandResult.output = stdout ? stdout.trim() : '';
191
- if (stderr) {
192
- commandResult.error = stderr.trim();
166
+ console.log(`[证书部署成功] 名称: ${certName}, 路径: ${userCertDir}, 保存: ${stats.saved}个, 过滤: ${stats.filtered}个`);
167
+
168
+ // 4. 执行回调命令
169
+ const commandResults = [];
170
+ if (config.callbackCommand && Array.isArray(config.callbackCommand) && config.callbackCommand.length > 0) {
171
+ console.log(`[开始执行回调命令] 共${config.callbackCommand.length}个命令`);
172
+
173
+ for (let i = 0; i < config.callbackCommand.length; i++) {
174
+ const command = config.callbackCommand[i];
175
+ const commandResult = {
176
+ command: command,
177
+ index: i + 1,
178
+ success: false,
179
+ output: '',
180
+ error: ''
181
+ };
182
+
183
+ try {
184
+ console.log(`[执行命令 ${i + 1}/${config.callbackCommand.length}] ${command}`);
185
+ const { stdout, stderr } = await execAsync(command, {
186
+ timeout: 30000, // 30秒超时
187
+ maxBuffer: 1024 * 1024 // 1MB buffer
188
+ });
189
+
190
+ commandResult.success = true;
191
+ commandResult.output = stdout ? stdout.trim() : '';
192
+ if (stderr) {
193
+ commandResult.error = stderr.trim();
194
+ }
195
+
196
+ console.log(`[命令执行成功 ${i + 1}/${config.callbackCommand.length}] ${command}`);
197
+ if (stdout) console.log(`[命令输出] ${stdout.trim()}`);
198
+ if (stderr) console.warn(`[命令stderr] ${stderr.trim()}`);
199
+
200
+ } catch (cmdError) {
201
+ commandResult.success = false;
202
+ commandResult.error = cmdError.message;
203
+ if (cmdError.stdout) commandResult.output = cmdError.stdout.trim();
204
+ if (cmdError.stderr) commandResult.error += '\n' + cmdError.stderr.trim();
205
+
206
+ console.error(`[命令执行失败 ${i + 1}/${config.callbackCommand.length}] ${command}:`, cmdError.message);
193
207
  }
194
-
195
- console.log(`[命令执行成功 ${i + 1}/${config.callbackCommand.length}] ${command}`);
196
- if (stdout) console.log(`[命令输出] ${stdout.trim()}`);
197
- if (stderr) console.warn(`[命令stderr] ${stderr.trim()}`);
198
-
199
- } catch (cmdError) {
200
- commandResult.success = false;
201
- commandResult.error = cmdError.message;
202
- if (cmdError.stdout) commandResult.output = cmdError.stdout.trim();
203
- if (cmdError.stderr) commandResult.error += '\n' + cmdError.stderr.trim();
204
-
205
- console.error(`[命令执行失败 ${i + 1}/${config.callbackCommand.length}] ${command}:`, cmdError.message);
208
+
209
+ commandResults.push(commandResult);
206
210
  }
207
211
 
208
- commandResults.push(commandResult);
212
+ console.log(`[回调命令执行完成] 成功: ${commandResults.filter(r => r.success).length}个, 失败: ${commandResults.filter(r => !r.success).length}个`);
209
213
  }
210
214
 
211
- console.log(`[回调命令执行完成] 成功: ${commandResults.filter(r => r.success).length}个, 失败: ${commandResults.filter(r => !r.success).length}个`);
212
- }
213
-
214
- return res.json({
215
- code: 0,
216
- msg: '证书部署成功',
217
- path: path.join(config.certPath, certName),
218
- stats: {
219
- total: stats.total,
220
- saved: stats.saved,
221
- filtered: stats.filtered,
222
- savedFiles: stats.savedFiles,
223
- filteredFiles: stats.filteredFiles
224
- },
225
- commandResults: commandResults.length > 0 ? commandResults : undefined
226
- });
215
+ return res.json({
216
+ code: 0,
217
+ msg: '证书部署成功',
218
+ path: userCertDir,
219
+ stats: {
220
+ total: stats.total,
221
+ saved: stats.saved,
222
+ filtered: stats.filtered,
223
+ savedFiles: stats.savedFiles,
224
+ filteredFiles: stats.filteredFiles
225
+ },
226
+ commandResults: commandResults.length > 0 ? commandResults : undefined
227
+ });
227
228
 
228
229
  } catch (zipError) {
229
230
  console.error('[解压失败]', zipError);