perf: 所有授权增加测试按钮

This commit is contained in:
xiaojunnuo
2026-02-15 18:44:35 +08:00
parent 42c7ec2f75
commit 7a3e68d656
39 changed files with 1876 additions and 662 deletions
@@ -1,4 +1,6 @@
import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
import { CtyunClient } from "../lib.js";
import { HttpClient } from "@certd/basic";
@IsAccess({
name: "ctyun",
@@ -27,6 +29,37 @@ export class CtyunAccess extends BaseAccess {
helper: "",
})
securityKey = "";
@AccessInput({
title: "测试",
component: {
name: "api-test",
action: "TestRequest",
},
helper: "点击测试接口看是否正常",
})
testRequest = true;
async onTestRequest() {
await this.getCdnDomainList()
return "ok";
}
async getCdnDomainList() {
const http: HttpClient = this.ctx.http;
const client = new CtyunClient({
access:this,
http,
logger: this.ctx.logger,
});
// 008 是天翼云的CDN加速域名产品码
const all = await client.getDomainList({ productCode: "008" });
const list = all || []
return list
}
}
new CtyunAccess();
@@ -29,6 +29,40 @@ export class K8sAccess extends BaseAccess {
encrypt: false,
})
skipTLSVerify: boolean;
@AccessInput({
title: "测试",
component: {
name: "api-test",
action: "TestRequest",
},
helper: "点击测试接口看是否正常",
})
testRequest = true;
async onTestRequest() {
const k8sClient = await this.getK8sClient()
await k8sClient.getSecrets({
namespace: "default",
})
return "ok";
}
async getK8sClient() {
const sdk = await import("@certd/lib-k8s");
const K8sClient = sdk.K8sClient;
const k8sClient = new K8sClient({
kubeConfigStr: this.kubeconfig,
logger: this.ctx.logger,
skipTLSVerify: this.skipTLSVerify,
});
return k8sClient;
}
}
new K8sAccess();
@@ -30,6 +30,87 @@ export class KuocaiCdnAccess extends BaseAccess {
encrypt: true,
})
password = "";
@AccessInput({
title: "测试",
component: {
name: "api-test",
action: "TestRequest",
},
helper: "点击测试接口看是否正常",
})
testRequest = true;
async onTestRequest() {
const loginRes = await this.getLoginToken();
await this.getDomainList(loginRes);
return "ok";
}
async getLoginToken() {
const url = "https://kuocaicdn.com/login/loginUser";
const data = {
userAccount: this.username,
userPwd: this.password,
remember: true,
};
const http = this.ctx.http;
const res: any = await http.request({
url,
method: "POST",
data,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
returnOriginRes: true,
});
if (!res.data?.success) {
throw new Error(res.data?.message);
}
const jsessionId = this.ctx.utils.request.getCookie(res, "JSESSIONID");
const token = res.data?.data;
return {
jsessionId,
token,
};
}
async getDomainList(loginRes: any) {
const url = "https://kuocaicdn.com/CdnDomain/queryForDatatables";
const data = {
draw: 1,
start: 0,
length: 1000,
search: {
value: "",
regex: false,
},
};
const res = await this.doRequest(url, loginRes, data);
return res.data?.data;
}
async doRequest(url: string, loginRes: any, data: any) {
const http = this.ctx.http;
const res: any = await http.request({
url,
method: "POST",
headers: {
Cookie: `JSESSIONID=${loginRes.jsessionId};kuocai_cdn_token=${loginRes.token}`,
},
data,
});
if (!res.success) {
throw new Error(res.message);
}
return res;
}
}
new KuocaiCdnAccess();
@@ -54,7 +54,7 @@ export class KuocaiDeployToCDNPlugin extends AbstractTaskPlugin {
async onInstance() {}
async execute(): Promise<void> {
const access = await this.getAccess<KuocaiCdnAccess>(this.accessId);
const loginRes = await this.getLoginToken(access);
const loginRes = await access.getLoginToken();
const curl = "https://kuocaicdn.com/CdnDomainHttps/httpsConfiguration";
for (const domain of this.domains) {
@@ -78,71 +78,11 @@ export class KuocaiDeployToCDNPlugin extends AbstractTaskPlugin {
private_key: cert.key,
},
};
await this.doRequest(curl, loginRes, update);
await access.doRequest(curl, loginRes, update);
this.logger.info(`站点${domain}证书更新成功`);
}
}
async getLoginToken(access: KuocaiCdnAccess) {
const url = "https://kuocaicdn.com/login/loginUser";
const data = {
userAccount: access.username,
userPwd: access.password,
remember: true,
};
const http = this.ctx.http;
const res: any = await http.request({
url,
method: "POST",
data,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
returnOriginRes: true,
});
if (!res.data?.success) {
throw new Error(res.data?.message);
}
const jsessionId = this.ctx.utils.request.getCookie(res, "JSESSIONID");
const token = res.data?.data;
return {
jsessionId,
token,
};
}
async getDomainList(loginRes: any) {
const url = "https://kuocaicdn.com/CdnDomain/queryForDatatables";
const data = {
draw: 1,
start: 0,
length: 1000,
search: {
value: "",
regex: false,
},
};
const res = await this.doRequest(url, loginRes, data);
return res.data?.data;
}
private async doRequest(url: string, loginRes: any, data: any) {
const http = this.ctx.http;
const res: any = await http.request({
url,
method: "POST",
headers: {
Cookie: `JSESSIONID=${loginRes.jsessionId};kuocai_cdn_token=${loginRes.token}`,
},
data,
});
if (!res.success) {
throw new Error(res.message);
}
return res;
}
async onGetDomainList(data: any) {
if (!this.accessId) {
@@ -150,9 +90,9 @@ export class KuocaiDeployToCDNPlugin extends AbstractTaskPlugin {
}
const access = await this.getAccess<KuocaiCdnAccess>(this.accessId);
const loginRes = await this.getLoginToken(access);
const loginRes = await access.getLoginToken();
const list = await this.getDomainList(loginRes);
const list = await access.getDomainList(loginRes);
if (!list || list.length === 0) {
throw new Error("您账户下还没有站点域名,请先添加域名");
@@ -85,6 +85,90 @@ export class LeCDNAccess extends BaseAccess {
`,
})
apiToken = "";
@AccessInput({
title: "测试",
component: {
name: "api-test",
action: "TestRequest",
},
helper: "点击测试接口看是否正常",
})
testRequest = true;
_token: string;
async onTestRequest() {
await this.getCerts();
return "ok";
}
async getCerts() {
// http://cdnadmin.kxfox.com/prod-api/certificate?current_page=1&total=3&page_size=10
return await this.doRequest({
url: `/prod-api/certificate`,
method: "get",
params: {
current_page: 1,
page_size: 1000,
},
});
}
async doRequest(config: any) {
const token = await this.getToken();
const access = this;
const Authorization = access.type === "token" ? access.apiToken : `Bearer ${token}`;
const res = await this.ctx.http.request({
baseURL: access.url,
headers: {
Authorization,
},
...config,
});
this.checkRes(res);
return res.data;
}
async getToken() {
if (this.type === "token") {
return this.apiToken;
}
if (this._token){
return this._token;
}
// http://cdnadmin.kxfox.com/prod-api/login
const access = this;
const res = await this.ctx.http.request({
url: `/prod-api/login`,
baseURL: access.url,
method: "post",
data: {
//新旧版本不一样,旧版本是username,新版本是email
email: access.username,
username: access.username,
password: access.password,
},
});
this.checkRes(res);
//新旧版本不一样,旧版本是access_token,新版本是token
const token = res.data.access_token || res.data.token;
this._token = token;
return token;
}
private checkRes(res: any) {
if (res.code !== 0 && res.code !== 200) {
throw new Error(res.message || JSON.stringify(res));
}
}
}
new LeCDNAccess();
@@ -58,49 +58,15 @@ export class LeCDNUpdateCertV2 extends AbstractTaskPlugin {
async onInstance() {
this.access = await this.getAccess<LeCDNAccess>(this.accessId);
this.token = await this.getToken();
this.access.getToken();
}
async doRequest(config: any) {
const access = this.access;
const Authorization = this.access.type === "token" ? this.access.apiToken : `Bearer ${this.token}`;
const res = await this.ctx.http.request({
baseURL: access.url,
headers: {
Authorization,
},
...config,
});
this.checkRes(res);
return res.data;
}
async getToken() {
if (this.access.type === "token") {
return this.access.apiToken;
}
// http://cdnadmin.kxfox.com/prod-api/login
const access = this.access;
const res = await this.ctx.http.request({
url: `/prod-api/login`,
baseURL: access.url,
method: "post",
data: {
//新旧版本不一样,旧版本是username,新版本是email
email: access.username,
username: access.username,
password: access.password,
},
});
this.checkRes(res);
//新旧版本不一样,旧版本是access_token,新版本是token
return res.data.access_token || res.data.token;
}
async getCertInfo(id: number) {
// http://cdnadmin.kxfox.com/prod-api/certificate/9
// Bearer edGkiOiIJ8
return await this.doRequest({
return await this.access.doRequest({
url: `/prod-api/certificate/${id}`,
method: "get",
});
@@ -117,7 +83,7 @@ export class LeCDNUpdateCertV2 extends AbstractTaskPlugin {
this.logger.info(`证书名称:${certInfo.name}`);
return await this.doRequest({
return await this.access.doRequest({
url: `/prod-api/certificate/${id}`,
method: "put",
data: certInfo,
@@ -134,17 +100,13 @@ export class LeCDNUpdateCertV2 extends AbstractTaskPlugin {
this.logger.info(`更新证书完成`);
}
private checkRes(res: any) {
if (res.code !== 0 && res.code !== 200) {
throw new Error(res.message || JSON.stringify(res));
}
}
async onGetCertList(data: any) {
if (!this.accessId) {
throw new Error("请选择Access授权");
}
const res = await this.getCerts();
const res = await this.access.getCerts();
//新旧版本不一样,一个data 一个是items
const list = res.items || res.data;
if (!res || list.length === 0) {
@@ -158,18 +120,6 @@ export class LeCDNUpdateCertV2 extends AbstractTaskPlugin {
};
});
}
private async getCerts() {
// http://cdnadmin.kxfox.com/prod-api/certificate?current_page=1&total=3&page_size=10
return await this.doRequest({
url: `/prod-api/certificate`,
method: "get",
params: {
current_page: 1,
page_size: 1000,
},
});
}
}
new LeCDNUpdateCertV2();
@@ -49,6 +49,62 @@ export class LuckyAccess extends BaseAccess {
encrypt: true,
})
openToken = "";
@AccessInput({
title: "测试",
component: {
name: "api-test",
action: "TestRequest",
},
helper: "点击测试接口看是否正常",
})
testRequest = true;
async onTestRequest() {
await this.getCertList();
return "ok";
}
async doRequest(req: { urlPath: string; data: any; method?: string }) {
const { urlPath, data, method } = req;
let url = `${this.url}/${this.safePath || ""}${urlPath}?_=${Math.floor(new Date().getTime())}`;
// 从第7个字符起,将//替换成/
const protocol = url.substring(0, 7);
let suffix = url.substring(7);
suffix = suffix.replaceAll("//", "/");
suffix = suffix.replaceAll("//", "/");
url = protocol + suffix;
const headers: any = {
// Origin: access.url,
"Content-Type": "application/json",
// "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36",
};
headers["openToken"] = this.openToken;
const res = await this.ctx.http.request({
method: method || "POST",
url,
data,
headers,
skipSslVerify: true,
});
if (res.ret !== 0) {
throw new Error(`请求失败:${res.msg}`);
}
return res;
}
async getCertList() {
const res = await this.doRequest({
urlPath: "/api/ssl",
data: {},
method: "GET",
});
const list = res.list || [];
return list
}
}
new LuckyAccess();
@@ -82,8 +82,7 @@ export class LuckyUpdateCert extends AbstractPlusTaskPlugin {
throw new Error(`没有找到证书:Key=${item},请确认该证书是否存在`);
}
const remark = old.Remark;
const res = await this.doRequest({
access,
const res = await access.doRequest({
urlPath: "/api/ssl",
method: "PUT",
data: {
@@ -107,44 +106,9 @@ export class LuckyUpdateCert extends AbstractPlusTaskPlugin {
this.logger.info("部署成功");
}
async doRequest(req: { access: LuckyAccess; urlPath: string; data: any; method?: string }) {
const { access, urlPath, data, method } = req;
let url = `${access.url}/${access.safePath || ""}${urlPath}?_=${Math.floor(new Date().getTime())}`;
// 从第7个字符起,将//替换成/
const protocol = url.substring(0, 7);
let suffix = url.substring(7);
suffix = suffix.replaceAll("//", "/");
suffix = suffix.replaceAll("//", "/");
url = protocol + suffix;
const headers: any = {
// Origin: access.url,
"Content-Type": "application/json",
// "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36",
};
headers["openToken"] = access.openToken;
const res = await this.http.request({
method: method || "POST",
url,
data,
headers,
skipSslVerify: true,
});
if (res.ret !== 0) {
throw new Error(`请求失败:${res.msg}`);
}
return res;
}
async onGetCertList() {
const access: LuckyAccess = await this.getAccess<LuckyAccess>(this.accessId);
const res = await this.doRequest({
access,
urlPath: "/api/ssl",
data: {},
method: "GET",
});
const list = res.list;
const list = await access.getCertList();
if (!list || list.length === 0) {
throw new Error("没有找到证书,请先在SSL/TLS证书页面中手动上传一次证书");
}
@@ -1,4 +1,5 @@
import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
import { MaoyunClient } from "@certd/plugin-plus";
/**
*/
@@ -49,6 +50,45 @@ export class MaoyunAccess extends BaseAccess {
required: false,
})
httpProxy!: string;
@AccessInput({
title: "测试",
component: {
name: "api-test",
action: "TestRequest",
},
helper: "点击测试接口看是否正常",
})
testRequest = true;
async onTestRequest() {
await this.getCdnDomainList();
return "ok";
}
async getCdnDomainList() {
const client = new MaoyunClient({
http: this.ctx.http,
logger: this.ctx.logger,
access: this,
});
await client.login();
const res = await client.doRequest({
url: "/cdn/domain",
data: {},
params: {
channel_type: "0,1,2",
page: 1,
page_size: 1000,
},
method: "GET",
});
const list = res.data || [];
return list
}
}
new MaoyunAccess();
@@ -115,23 +115,7 @@ export class MaoyunDeployToCdn extends AbstractPlusTaskPlugin {
async onGetDomainList() {
const access: MaoyunAccess = await this.getAccess<MaoyunAccess>(this.accessId);
const client = new MaoyunClient({
http: this.ctx.http,
logger: this.logger,
access,
});
await client.login();
const res = await client.doRequest({
url: "/cdn/domain",
data: {},
params: {
channel_type: "0,1,2",
page: 1,
page_size: 1000,
},
method: "GET",
});
const list = res.data;
const list = await access.getCdnDomainList();
if (!list || list.length === 0) {
throw new Error("没有找到加速域名,请先在控制台添加加速域名");
}
@@ -1,3 +1,4 @@
import { HttpRequestConfig } from "@certd/basic";
import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
/**
@@ -40,6 +41,48 @@ export class SafelineAccess extends BaseAccess {
helper: "如果面板的url是https,且使用的是自签名证书,则需要开启此选项,其他情况可以关闭",
})
skipSslVerify = true;
@AccessInput({
title: "测试",
component: {
name: "api-test",
action: "onTestRequest",
},
helper: "点击测试接口看是否正常",
})
testRequest = true;
async onTestRequest() {
await this.getCertList();
return "ok";
}
async getCertList() {
const res = await this.doRequest({
url: "/api/open/cert",
method: "get",
data: {},
});
const nodes = res?.nodes || [];
return nodes
}
async doRequest(config: HttpRequestConfig<any>) {
config.baseURL = this.baseUrl;
config.skipSslVerify = this.skipSslVerify ?? false;
config.logRes = false;
config.logParams = false;
config.headers = {
"X-SLCE-API-TOKEN": this.apiToken,
};
const res = await this.ctx.http.request(config);
if (!res.err) {
return res.data;
}
throw new Error(res.msg);
}
}
new SafelineAccess();
@@ -1,9 +1,8 @@
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
import { HttpRequestConfig } from "@certd/basic";
import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert";
import { SafelineAccess } from "../access.js";
import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib";
import { SafelineAccess } from "../access.js";
@IsTaskPlugin({
name: "SafelineDeployToWebsitePlugin",
@@ -83,7 +82,7 @@ export class SafelineDeployToWebsitePlugin extends AbstractTaskPlugin {
data.id = parseInt(certId)
type = "更新"
}
const res = await this.doRequest({
const res = await this.access.doRequest({
url: "/api/open/cert",
method: "post",
data:data
@@ -91,25 +90,12 @@ export class SafelineDeployToWebsitePlugin extends AbstractTaskPlugin {
this.logger.info(`证书<${certId}>${type}成功,ID:${res}`);
}
async doRequest(config: HttpRequestConfig<any>) {
config.baseURL = this.access.baseUrl;
config.skipSslVerify = this.access.skipSslVerify ?? false;
config.logRes = false;
config.logParams = false;
config.headers = {
"X-SLCE-API-TOKEN": this.access.apiToken,
};
const res = await this.ctx.http.request(config);
if (!res.err) {
return res.data;
}
throw new Error(res.msg);
}
// requestHandle
async onGetCertIds() {
const res = await this.doRequest({
const res = await this.access.doRequest({
url: "/api/open/cert",
method: "get",
data: {},
@@ -34,11 +34,10 @@ export class SynologyKeepAlivePlugin extends AbstractPlusTaskPlugin {
@TaskInput({
title: "间隔天数",
helper: "多少天刷新一次,建议15天以内",
value: 15,
component: {
name: "number-input",
type: "number",
min: 1,
max: 30,
name: "a-input-number",
vModel:"value",
},
required: true,
})
@@ -51,7 +50,7 @@ export class SynologyKeepAlivePlugin extends AbstractPlusTaskPlugin {
lastRefreshTime!: number;
async onInstance() {}
async execute(): Promise<void> {
async execute(): Promise<any> {
this.logger.info("开始刷新群晖登录有效期");
const now = dayjs()
const status = this.getLastStatus();
@@ -61,18 +60,23 @@ export class SynologyKeepAlivePlugin extends AbstractPlusTaskPlugin {
this.lastRefreshTime = lastRefreshTime;
const lastTime = dayjs(lastRefreshTime);
const diffDays = now.diff(lastTime, "day");
this.logger.info(`上次刷新时间${lastTime.format("YYYY-MM-DD")}`);
if (diffDays < this.intervalDays) {
this.logger.info(`距离上次刷新有效期${diffDays.toFixed(0)}${this.intervalDays},无需刷新`);
this.logger.info(`距离上次刷新${diffDays},不足${this.intervalDays}天,无需刷新`);
this.logger.info(`下一次刷新时间${lastTime.add(this.intervalDays, "day").format("YYYY-MM-DD")}`);
return;
return "skip";
}else{
this.logger.info(`超过${this.intervalDays}天,需要刷新`);
}
}
// const access: SynologyAccess = await this.getAccess<SynologyAccess>(this.accessId);
// const client = new SynologyClient(access as any, this.ctx.http, this.ctx.logger, access.skipSslVerify);
// await client.doLogin();
// await client.getCertList();
this.lastRefreshTime = now.unix();
this.lastRefreshTime = now.valueOf();
this.logger.info("刷新群晖登录有效期成功");
}
@@ -29,6 +29,7 @@ export class UniCloudAccess extends BaseAccess {
encrypt: true,
})
password = "";
}
new UniCloudAccess();