mirror of
https://github.com/whyour/qinglong.git
synced 2025-05-23 23:06:06 +08:00
修复订阅生成 ssh 配置逻辑,自动添加/删除任务
This commit is contained in:
parent
437a849c2a
commit
1f7f2c8971
43
back/config/subscription.ts
Normal file
43
back/config/subscription.ts
Normal file
|
@ -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;
|
||||||
|
}
|
|
@ -41,11 +41,6 @@ export default async () => {
|
||||||
// 运行所有订阅
|
// 运行所有订阅
|
||||||
const subs = await subscriptionService.list();
|
const subs = await subscriptionService.list();
|
||||||
for (const sub of subs) {
|
for (const sub of subs) {
|
||||||
await subscriptionService.handleTask(
|
subscriptionService.handleTask(sub, !sub.is_disabled, !sub.is_disabled);
|
||||||
sub,
|
|
||||||
!sub.is_disabled,
|
|
||||||
true,
|
|
||||||
!sub.is_disabled,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import { Service, Inject } from 'typedi';
|
import { Service, Inject } from 'typedi';
|
||||||
import winston from 'winston';
|
import winston from 'winston';
|
||||||
import fs from 'fs';
|
import fs, { existsSync } from 'fs';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import { Subscription } from '../data/subscription';
|
||||||
|
import { formatUrl } from '../config/subscription';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class SshKeyService {
|
export default class SshKeyService {
|
||||||
|
@ -32,7 +34,10 @@ export default class SshKeyService {
|
||||||
|
|
||||||
private removePrivateKeyFile(alias: string): void {
|
private removePrivateKeyFile(alias: string): void {
|
||||||
try {
|
try {
|
||||||
fs.unlinkSync(`${this.sshPath}/${alias}`);
|
const filePath = path.join(this.sshPath, alias);
|
||||||
|
if (existsSync(filePath)) {
|
||||||
|
fs.unlinkSync(`${this.sshPath}/${alias}`);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error('删除私钥文件失败', 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`;
|
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` : '';
|
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[]) {
|
private generateSshConfig(configs: string[]) {
|
||||||
try {
|
try {
|
||||||
for (const config of configs) {
|
fs.writeFileSync(this.sshConfigFilePath, configs.join('\n'), {
|
||||||
fs.appendFileSync(this.sshConfigFilePath, config, {
|
encoding: 'utf8',
|
||||||
encoding: 'utf8',
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error('写入ssh配置文件失败', error);
|
this.logger.error('写入ssh配置文件失败', error);
|
||||||
}
|
}
|
||||||
|
@ -94,4 +97,23 @@ export default class SshKeyService {
|
||||||
const config = this.generateSingleSshConfig(alias, host, proxy);
|
const config = this.generateSingleSshConfig(alias, host, proxy);
|
||||||
this.removeSshConfig(config);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import SockService from './sock';
|
||||||
import SshKeyService from './sshKey';
|
import SshKeyService from './sshKey';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { LOG_END_SYMBOL } from '../config/const';
|
import { LOG_END_SYMBOL } from '../config/const';
|
||||||
|
import { formatCommand, formatUrl } from '../config/subscription';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class SubscriptionService {
|
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(
|
public async handleTask(
|
||||||
doc: Subscription,
|
doc: Subscription,
|
||||||
needCreate = true,
|
needCreate = true,
|
||||||
needAddKey = true,
|
|
||||||
runImmediately = false,
|
runImmediately = false,
|
||||||
) {
|
) {
|
||||||
const { url, host } = this.formatUrl(doc);
|
const { url } = 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doc.command = this.formatCommand(doc, url as string);
|
doc.command = formatCommand(doc, url as string);
|
||||||
|
|
||||||
if (doc.schedule_type === 'crontab') {
|
if (doc.schedule_type === 'crontab') {
|
||||||
this.scheduleService.cancelCronTask(doc as any);
|
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<string> {
|
private async promiseExec(command: string): Promise<string> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
exec(
|
exec(
|
||||||
|
@ -276,6 +227,7 @@ export default class SubscriptionService {
|
||||||
const tab = new Subscription(payload);
|
const tab = new Subscription(payload);
|
||||||
const doc = await this.insert(tab);
|
const doc = await this.insert(tab);
|
||||||
await this.handleTask(doc);
|
await this.handleTask(doc);
|
||||||
|
await this.setSshConfig();
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,6 +239,7 @@ export default class SubscriptionService {
|
||||||
const tab = new Subscription(payload);
|
const tab = new Subscription(payload);
|
||||||
const newDoc = await this.updateDb(tab);
|
const newDoc = await this.updateDb(tab);
|
||||||
await this.handleTask(newDoc, !newDoc.is_disabled);
|
await this.handleTask(newDoc, !newDoc.is_disabled);
|
||||||
|
await this.setSshConfig();
|
||||||
return newDoc;
|
return newDoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,9 +282,10 @@ export default class SubscriptionService {
|
||||||
public async remove(ids: number[]) {
|
public async remove(ids: number[]) {
|
||||||
const docs = await SubscriptionModel.findAll({ where: { id: ids } });
|
const docs = await SubscriptionModel.findAll({ where: { id: ids } });
|
||||||
for (const doc of docs) {
|
for (const doc of docs) {
|
||||||
await this.handleTask(doc, false, false);
|
await this.handleTask(doc, false);
|
||||||
}
|
}
|
||||||
await SubscriptionModel.destroy({ where: { id: ids } });
|
await SubscriptionModel.destroy({ where: { id: ids } });
|
||||||
|
await this.setSshConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getDb(query: any): Promise<Subscription> {
|
public async getDb(query: any): Promise<Subscription> {
|
||||||
|
@ -382,7 +336,7 @@ export default class SubscriptionService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const command = this.formatCommand(subscription);
|
const command = formatCommand(subscription);
|
||||||
|
|
||||||
await this.scheduleService.runTask(
|
await this.scheduleService.runTask(
|
||||||
command,
|
command,
|
||||||
|
@ -391,19 +345,21 @@ export default class SubscriptionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async disabled(ids: number[]) {
|
public async disabled(ids: number[]) {
|
||||||
|
await SubscriptionModel.update({ is_disabled: 1 }, { where: { id: ids } });
|
||||||
const docs = await SubscriptionModel.findAll({ where: { id: ids } });
|
const docs = await SubscriptionModel.findAll({ where: { id: ids } });
|
||||||
|
await this.setSshConfig();
|
||||||
for (const doc of docs) {
|
for (const doc of docs) {
|
||||||
await this.handleTask(doc, false);
|
await this.handleTask(doc, false);
|
||||||
}
|
}
|
||||||
await SubscriptionModel.update({ is_disabled: 1 }, { where: { id: ids } });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async enabled(ids: number[]) {
|
public async enabled(ids: number[]) {
|
||||||
|
await SubscriptionModel.update({ is_disabled: 0 }, { where: { id: ids } });
|
||||||
const docs = await SubscriptionModel.findAll({ where: { id: ids } });
|
const docs = await SubscriptionModel.findAll({ where: { id: ids } });
|
||||||
|
await this.setSshConfig();
|
||||||
for (const doc of docs) {
|
for (const doc of docs) {
|
||||||
await this.handleTask(doc);
|
await this.handleTask(doc);
|
||||||
}
|
}
|
||||||
await SubscriptionModel.update({ is_disabled: 0 }, { where: { id: ids } });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async log(id: number) {
|
public async log(id: number) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user