From 1f7f2c8971504809507db00bf5f832a8422f663c Mon Sep 17 00:00:00 2001 From: whyour Date: Mon, 13 Feb 2023 23:12:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AE=A2=E9=98=85=E7=94=9F?= =?UTF-8?q?=E6=88=90=20ssh=20=E9=85=8D=E7=BD=AE=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=B7=BB=E5=8A=A0/=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/config/subscription.ts | 43 +++++++++++++++++++ back/loaders/initTask.ts | 7 +--- back/services/sshKey.ts | 38 +++++++++++++---- back/services/subscription.ts | 78 ++++++++--------------------------- 4 files changed, 91 insertions(+), 75 deletions(-) create mode 100644 back/config/subscription.ts diff --git a/back/config/subscription.ts b/back/config/subscription.ts new file mode 100644 index 00000000..450bb75f --- /dev/null +++ b/back/config/subscription.ts @@ -0,0 +1,43 @@ +import { Subscription } from '../data/subscription'; + +export function formatUrl(doc: Subscription) { + let url = doc.url; + let host = ''; + if (doc.type === 'private-repo') { + if (doc.pull_type === 'ssh-key') { + host = doc.url!.replace(/.*\@([^\:]+)\:.*/, '$1'); + url = doc.url!.replace(host, doc.alias); + } else { + host = doc.url!.replace(/.*\:\/\/([^\/]+)\/.*/, '$1'); + const { username, password } = doc.pull_option as any; + url = doc.url!.replace(host, `${username}:${password}@${host}`); + } + } + return { url, host }; +} + +export function formatCommand(doc: Subscription, url?: string) { + let command = 'ql '; + let _url = url || formatUrl(doc).url; + const { + type, + whitelist, + blacklist, + dependences, + branch, + extensions, + proxy, + autoAddCron, + autoDelCron, + } = doc; + if (type === 'file') { + command += `raw "${_url}"`; + } else { + command += `repo "${_url}" "${whitelist || ''}" "${blacklist || ''}" "${ + dependences || '' + }" "${branch || ''}" "${extensions || ''}" "${proxy || ''}" "${ + Boolean(autoAddCron) ?? '' + }" "${Boolean(autoDelCron) ?? ''}"`; + } + return command; +} diff --git a/back/loaders/initTask.ts b/back/loaders/initTask.ts index c185b916..7587acc6 100644 --- a/back/loaders/initTask.ts +++ b/back/loaders/initTask.ts @@ -41,11 +41,6 @@ export default async () => { // 运行所有订阅 const subs = await subscriptionService.list(); for (const sub of subs) { - await subscriptionService.handleTask( - sub, - !sub.is_disabled, - true, - !sub.is_disabled, - ); + subscriptionService.handleTask(sub, !sub.is_disabled, !sub.is_disabled); } }; diff --git a/back/services/sshKey.ts b/back/services/sshKey.ts index 2a71d896..7db49654 100644 --- a/back/services/sshKey.ts +++ b/back/services/sshKey.ts @@ -1,8 +1,10 @@ import { Service, Inject } from 'typedi'; import winston from 'winston'; -import fs from 'fs'; +import fs, { existsSync } from 'fs'; import os from 'os'; import path from 'path'; +import { Subscription } from '../data/subscription'; +import { formatUrl } from '../config/subscription'; @Service() export default class SshKeyService { @@ -32,7 +34,10 @@ export default class SshKeyService { private removePrivateKeyFile(alias: string): void { try { - fs.unlinkSync(`${this.sshPath}/${alias}`); + const filePath = path.join(this.sshPath, alias); + if (existsSync(filePath)) { + fs.unlinkSync(`${this.sshPath}/${alias}`); + } } catch (error) { this.logger.error('删除私钥文件失败', error); } @@ -47,16 +52,14 @@ export default class SshKeyService { host = `ssh.github.com\n Port 443\n HostkeyAlgorithms +ssh-rsa\n PubkeyAcceptedAlgorithms +ssh-rsa`; } const proxyStr = proxy ? ` ProxyCommand nc -v -x ${proxy} %h %p\n` : ''; - return `\nHost ${alias}\n Hostname ${host}\n IdentityFile ${this.sshPath}/${alias}\n StrictHostKeyChecking no\n${proxyStr}`; + return `Host ${alias}\n Hostname ${host}\n IdentityFile ${this.sshPath}/${alias}\n StrictHostKeyChecking no\n${proxyStr}`; } private generateSshConfig(configs: string[]) { try { - for (const config of configs) { - fs.appendFileSync(this.sshConfigFilePath, config, { - encoding: 'utf8', - }); - } + fs.writeFileSync(this.sshConfigFilePath, configs.join('\n'), { + encoding: 'utf8', + }); } catch (error) { this.logger.error('写入ssh配置文件失败', error); } @@ -94,4 +97,23 @@ export default class SshKeyService { const config = this.generateSingleSshConfig(alias, host, proxy); this.removeSshConfig(config); } + + public setSshConfig(docs: Subscription[]) { + let result = []; + for (const doc of docs) { + if (doc.type === 'private-repo' && doc.pull_type === 'ssh-key') { + const { alias, proxy } = doc; + const { host } = formatUrl(doc); + this.removePrivateKeyFile(alias); + this.generatePrivateKeyFile( + alias, + (doc.pull_option as any).private_key, + ); + const config = this.generateSingleSshConfig(alias, host, proxy); + console.log(config); + result.push(config); + } + } + this.generateSshConfig(result); + } } diff --git a/back/services/subscription.ts b/back/services/subscription.ts index cc57926d..091fb403 100644 --- a/back/services/subscription.ts +++ b/back/services/subscription.ts @@ -29,6 +29,7 @@ import SockService from './sock'; import SshKeyService from './sshKey'; import dayjs from 'dayjs'; import { LOG_END_SYMBOL } from '../config/const'; +import { formatCommand, formatUrl } from '../config/subscription'; @Service() export default class SubscriptionService { @@ -73,69 +74,14 @@ export default class SubscriptionService { } } - private formatCommand(doc: Subscription, url?: string) { - let command = 'ql '; - let _url = url || this.formatUrl(doc).url; - const { - type, - whitelist, - blacklist, - dependences, - branch, - extensions, - proxy, - autoAddCron, - autoDelCron, - } = doc; - if (type === 'file') { - command += `raw "${_url}"`; - } else { - command += `repo "${_url}" "${whitelist || ''}" "${blacklist || ''}" "${ - dependences || '' - }" "${branch || ''}" "${extensions || ''}" "${proxy || ''}" "${ - Boolean(autoAddCron) || '' - }" "${Boolean(autoDelCron) || ''}"`; - } - return command; - } - - private formatUrl(doc: Subscription) { - let url = doc.url; - let host = ''; - if (doc.type === 'private-repo') { - if (doc.pull_type === 'ssh-key') { - host = doc.url!.replace(/.*\@([^\:]+)\:.*/, '$1'); - url = doc.url!.replace(host, doc.alias); - } else { - host = doc.url!.replace(/.*\:\/\/([^\/]+)\/.*/, '$1'); - const { username, password } = doc.pull_option as any; - url = doc.url!.replace(host, `${username}:${password}@${host}`); - } - } - return { url, host }; - } - public async handleTask( doc: Subscription, needCreate = true, - needAddKey = true, runImmediately = false, ) { - const { url, host } = this.formatUrl(doc); - if (doc.type === 'private-repo' && doc.pull_type === 'ssh-key') { - if (needAddKey) { - this.sshKeyService.addSSHKey( - (doc.pull_option as any).private_key, - doc.alias, - host, - doc.proxy, - ); - } else { - this.sshKeyService.removeSSHKey(doc.alias, host, doc.proxy); - } - } + const { url } = formatUrl(doc); - doc.command = this.formatCommand(doc, url as string); + doc.command = formatCommand(doc, url as string); if (doc.schedule_type === 'crontab') { this.scheduleService.cancelCronTask(doc as any); @@ -158,6 +104,11 @@ export default class SubscriptionService { } } + private async setSshConfig() { + const docs = await SubscriptionModel.findAll(); + this.sshKeyService.setSshConfig(docs); + } + private async promiseExec(command: string): Promise { return new Promise((resolve, reject) => { exec( @@ -276,6 +227,7 @@ export default class SubscriptionService { const tab = new Subscription(payload); const doc = await this.insert(tab); await this.handleTask(doc); + await this.setSshConfig(); return doc; } @@ -287,6 +239,7 @@ export default class SubscriptionService { const tab = new Subscription(payload); const newDoc = await this.updateDb(tab); await this.handleTask(newDoc, !newDoc.is_disabled); + await this.setSshConfig(); return newDoc; } @@ -329,9 +282,10 @@ export default class SubscriptionService { public async remove(ids: number[]) { const docs = await SubscriptionModel.findAll({ where: { id: ids } }); for (const doc of docs) { - await this.handleTask(doc, false, false); + await this.handleTask(doc, false); } await SubscriptionModel.destroy({ where: { id: ids } }); + await this.setSshConfig(); } public async getDb(query: any): Promise { @@ -382,7 +336,7 @@ export default class SubscriptionService { return; } - const command = this.formatCommand(subscription); + const command = formatCommand(subscription); await this.scheduleService.runTask( command, @@ -391,19 +345,21 @@ export default class SubscriptionService { } public async disabled(ids: number[]) { + await SubscriptionModel.update({ is_disabled: 1 }, { where: { id: ids } }); const docs = await SubscriptionModel.findAll({ where: { id: ids } }); + await this.setSshConfig(); for (const doc of docs) { await this.handleTask(doc, false); } - await SubscriptionModel.update({ is_disabled: 1 }, { where: { id: ids } }); } public async enabled(ids: number[]) { + await SubscriptionModel.update({ is_disabled: 0 }, { where: { id: ids } }); const docs = await SubscriptionModel.findAll({ where: { id: ids } }); + await this.setSshConfig(); for (const doc of docs) { await this.handleTask(doc); } - await SubscriptionModel.update({ is_disabled: 0 }, { where: { id: ids } }); } public async log(id: number) {