mirror of
https://github.com/certd/certd.git
synced 2026-04-24 04:17:25 +08:00
perf: 所有授权增加测试按钮
This commit is contained in:
@@ -299,6 +299,14 @@ export abstract class AbstractTaskPlugin implements ITaskPlugin {
|
|||||||
buildDomainGroupOptions(options: any[], domains: string[]) {
|
buildDomainGroupOptions(options: any[], domains: string[]) {
|
||||||
return utils.options.buildGroupOptions(options, domains);
|
return utils.options.buildGroupOptions(options, domains);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getLastStatus(): Runnable {
|
||||||
|
return this.ctx.lastStatus || ({} as any);
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastOutput(key: string) {
|
||||||
|
return this.getLastStatus().status?.output?.[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type OutputVO = {
|
export type OutputVO = {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export function getCronNextTimes(cron: string, count: number = 1) {
|
|||||||
const interval = parser.parseExpression(cron);
|
const interval = parser.parseExpression(cron);
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
const next = interval.next().getTime();
|
const next = interval.next().getTime();
|
||||||
nextTimes.push(dayjs(next).valueOf());
|
nextTimes.push(dayjs(next).format("YYYY-MM-DD HH:mm:ss"));
|
||||||
}
|
}
|
||||||
return nextTimes;
|
return nextTimes;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,10 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
|
|||||||
set(form, key, column.value);
|
set(form, key, column.value);
|
||||||
}
|
}
|
||||||
//字段配置赋值
|
//字段配置赋值
|
||||||
columnsRef.value[key] = column;
|
if (columnsRef.value) {
|
||||||
|
columnsRef.value[key] = column;
|
||||||
|
}
|
||||||
|
|
||||||
console.log("form", columnsRef.value);
|
console.log("form", columnsRef.value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"@alicloud/openapi-client": "^0.4.12",
|
"@alicloud/openapi-client": "^0.4.12",
|
||||||
"@alicloud/openapi-util": "^0.3.2",
|
"@alicloud/openapi-util": "^0.3.2",
|
||||||
"@alicloud/pop-core": "^1.7.10",
|
"@alicloud/pop-core": "^1.7.10",
|
||||||
|
"@alicloud/sts-sdk": "^1.0.2",
|
||||||
"@alicloud/tea-typescript": "^1.8.0",
|
"@alicloud/tea-typescript": "^1.8.0",
|
||||||
"@alicloud/tea-util": "^1.4.10",
|
"@alicloud/tea-util": "^1.4.10",
|
||||||
"@aws-sdk/client-acm": "^3.964.0",
|
"@aws-sdk/client-acm": "^3.964.0",
|
||||||
@@ -48,6 +49,7 @@
|
|||||||
"@aws-sdk/client-iam": "^3.964.0",
|
"@aws-sdk/client-iam": "^3.964.0",
|
||||||
"@aws-sdk/client-route-53": "^3.964.0",
|
"@aws-sdk/client-route-53": "^3.964.0",
|
||||||
"@aws-sdk/client-s3": "^3.964.0",
|
"@aws-sdk/client-s3": "^3.964.0",
|
||||||
|
"@aws-sdk/client-sts": "^3.990.0",
|
||||||
"@certd/acme-client": "^1.38.9",
|
"@certd/acme-client": "^1.38.9",
|
||||||
"@certd/basic": "^1.38.9",
|
"@certd/basic": "^1.38.9",
|
||||||
"@certd/commercial-core": "^1.38.9",
|
"@certd/commercial-core": "^1.38.9",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline';
|
import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline';
|
||||||
|
import { Dns51Client } from './client.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 这个注解将注册一个授权配置
|
* 这个注解将注册一个授权配置
|
||||||
@@ -27,14 +28,38 @@ export class Dns51Access extends BaseAccess {
|
|||||||
@AccessInput({
|
@AccessInput({
|
||||||
title: '登录密码',
|
title: '登录密码',
|
||||||
component: {
|
component: {
|
||||||
name:"a-input-password",
|
name: "a-input-password",
|
||||||
vModel:"value",
|
vModel: "value",
|
||||||
placeholder: '密码',
|
placeholder: '密码',
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
encrypt: true,
|
encrypt: true,
|
||||||
})
|
})
|
||||||
password = '';
|
password = '';
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "测试授权是否正确"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
|
||||||
|
const client = new Dns51Client({
|
||||||
|
logger: this.ctx.logger,
|
||||||
|
access: this,
|
||||||
|
});
|
||||||
|
|
||||||
|
await client.login();
|
||||||
|
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new Dns51Access();
|
new Dns51Access();
|
||||||
|
|||||||
+5
-38
@@ -1,6 +1,6 @@
|
|||||||
import { IAccessService, Pager, PageRes, PageSearch } from '@certd/pipeline';
|
import { PageRes, PageSearch } from '@certd/pipeline';
|
||||||
import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert';
|
import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert';
|
||||||
import { AliesaAccess, AliyunAccess } from '../../plugin-lib/aliyun/index.js';
|
import { AliesaAccess } from '../../plugin-lib/aliyun/index.js';
|
||||||
import { AliyunClientV2 } from '../../plugin-lib/aliyun/lib/aliyun-client-v2.js';
|
import { AliyunClientV2 } from '../../plugin-lib/aliyun/lib/aliyun-client-v2.js';
|
||||||
|
|
||||||
|
|
||||||
@@ -17,11 +17,8 @@ export class AliesaDnsProvider extends AbstractDnsProvider {
|
|||||||
|
|
||||||
client: AliyunClientV2
|
client: AliyunClientV2
|
||||||
async onInstance() {
|
async onInstance() {
|
||||||
const access: AliesaAccess = this.ctx.access as AliesaAccess
|
const access : AliesaAccess = this.ctx.access as AliesaAccess
|
||||||
const accessGetter = await this.ctx.serviceGetter.get("accessService") as IAccessService
|
this.client = await access.getEsaClient()
|
||||||
const aliAccess = await accessGetter.getById(access.accessId) as AliyunAccess
|
|
||||||
const endpoint = `esa.${access.region}.aliyuncs.com`
|
|
||||||
this.client = aliAccess.getClient(endpoint)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -103,37 +100,7 @@ export class AliesaDnsProvider extends AbstractDnsProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
||||||
const pager = new Pager(req)
|
return await this.ctx.access.getDomainListPage(req)
|
||||||
const ret = await this.client.doRequest({
|
|
||||||
// 接口名称
|
|
||||||
action: "ListSites",
|
|
||||||
// 接口版本
|
|
||||||
version: "2024-09-10",
|
|
||||||
// 接口协议
|
|
||||||
protocol: "HTTPS",
|
|
||||||
// 接口 HTTP 方法
|
|
||||||
method: "GET",
|
|
||||||
authType: "AK",
|
|
||||||
style: "RPC",
|
|
||||||
data: {
|
|
||||||
query: {
|
|
||||||
SiteName: req.searchKey,
|
|
||||||
// ["SiteSearchType"] = "exact";
|
|
||||||
SiteSearchType: "fuzzy",
|
|
||||||
AccessType: "NS",
|
|
||||||
PageSize: pager.pageSize,
|
|
||||||
PageNumber: pager.pageNo,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const list = ret.Sites?.map(item => ({
|
|
||||||
domain: item.SiteName,
|
|
||||||
id: item.SiteId,
|
|
||||||
}))
|
|
||||||
return {
|
|
||||||
list: list || [],
|
|
||||||
total: ret.TotalCount,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline';
|
import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline';
|
||||||
import { AwsRegions } from './constants.js';
|
import { AwsRegions } from './constants.js';
|
||||||
|
import { AwsClient } from './libs/aws-client.js';
|
||||||
|
|
||||||
@IsAccess({
|
@IsAccess({
|
||||||
name: 'aws',
|
name: 'aws',
|
||||||
@@ -33,7 +34,7 @@ export class AwsAccess extends BaseAccess {
|
|||||||
@AccessInput({
|
@AccessInput({
|
||||||
title: 'region',
|
title: 'region',
|
||||||
component: {
|
component: {
|
||||||
name:"a-select",
|
name: "a-select",
|
||||||
options: AwsRegions,
|
options: AwsRegions,
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
@@ -41,6 +42,25 @@ export class AwsAccess extends BaseAccess {
|
|||||||
options: AwsRegions,
|
options: AwsRegions,
|
||||||
})
|
})
|
||||||
region = '';
|
region = '';
|
||||||
|
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "测试授权是否正确"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
|
||||||
|
const client = new AwsClient({ access: this, logger: this.ctx.logger, region: this.region || 'us-east-1' });
|
||||||
|
await client.getCallerIdentity();
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new AwsAccess();
|
new AwsAccess();
|
||||||
|
|||||||
@@ -45,6 +45,26 @@ export class AwsClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async getCallerIdentity() {
|
||||||
|
const { STSClient, GetCallerIdentityCommand } = await import ("@aws-sdk/client-sts");
|
||||||
|
|
||||||
|
const client = new STSClient({
|
||||||
|
region: this.access.region || 'us-east-1',
|
||||||
|
credentials: {
|
||||||
|
accessKeyId: this.access.accessKeyId, // 从环境变量中读取
|
||||||
|
secretAccessKey: this.access.secretAccessKey,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const command = new GetCallerIdentityCommand({});
|
||||||
|
const response = await client.send(command);
|
||||||
|
this.logger.info(` 账户ID: ${response.Account}`);
|
||||||
|
this.logger.info(` ARN: ${response.Arn}`);
|
||||||
|
this.logger.info(` 用户ID: ${response.UserId}`);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async route53ClientGet() {
|
async route53ClientGet() {
|
||||||
const { Route53Client } = await import('@aws-sdk/client-route-53');
|
const { Route53Client } = await import('@aws-sdk/client-route-53');
|
||||||
return new Route53Client({
|
return new Route53Client({
|
||||||
@@ -85,7 +105,7 @@ export class AwsClient {
|
|||||||
const { ListHostedZonesByNameCommand } = await import("@aws-sdk/client-route-53"); // ES Modules import
|
const { ListHostedZonesByNameCommand } = await import("@aws-sdk/client-route-53"); // ES Modules import
|
||||||
|
|
||||||
const client = await this.route53ClientGet();
|
const client = await this.route53ClientGet();
|
||||||
const input:any = { // ListHostedZonesByNameRequest
|
const input: any = { // ListHostedZonesByNameRequest
|
||||||
MaxItems: req.pageSize,
|
MaxItems: req.pageSize,
|
||||||
};
|
};
|
||||||
if (req.searchKey) {
|
if (req.searchKey) {
|
||||||
@@ -93,7 +113,7 @@ export class AwsClient {
|
|||||||
}
|
}
|
||||||
const command = new ListHostedZonesByNameCommand(input);
|
const command = new ListHostedZonesByNameCommand(input);
|
||||||
const response = await this.doRequest(() => client.send(command));
|
const response = await this.doRequest(() => client.send(command));
|
||||||
let list :any[]= response.HostedZones || [];
|
let list: any[] = response.HostedZones || [];
|
||||||
list = list.map((item: any) => ({
|
list = list.map((item: any) => ({
|
||||||
id: item.Id.replace('/hostedzone/', ''),
|
id: item.Id.replace('/hostedzone/', ''),
|
||||||
domain: item.Name,
|
domain: item.Name,
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline';
|
|||||||
icon: 'clarity:plugin-line',
|
icon: 'clarity:plugin-line',
|
||||||
})
|
})
|
||||||
export class CacheflyAccess extends BaseAccess {
|
export class CacheflyAccess extends BaseAccess {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@AccessInput({
|
@AccessInput({
|
||||||
title: 'username',
|
title: 'username',
|
||||||
component: {
|
component: {
|
||||||
@@ -32,6 +35,62 @@ export class CacheflyAccess extends BaseAccess {
|
|||||||
encrypt: true,
|
encrypt: true,
|
||||||
})
|
})
|
||||||
otpkey = '';
|
otpkey = '';
|
||||||
|
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "测试授权是否正确"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
await this.login();
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async login(){
|
||||||
|
let otp = null;
|
||||||
|
if (this.otpkey) {
|
||||||
|
const response = await this.ctx.http.request<any, any>({
|
||||||
|
url: `https://cn-api.my-api.cn/api/totp/?key=${this.otpkey}`,
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
otp = response;
|
||||||
|
this.ctx.logger.info('获取到otp:', otp);
|
||||||
|
}
|
||||||
|
const loginResponse = await this.doRequestApi(`/api/2.6/auth/login`, {
|
||||||
|
username: this.username,
|
||||||
|
password: this.password,
|
||||||
|
...(otp && { otp }),
|
||||||
|
});
|
||||||
|
const token = loginResponse.token;
|
||||||
|
this.ctx.logger.info('Token 获取成功');
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
async doRequestApi(url: string, data: any = null, method = 'post', token: string | null = null) {
|
||||||
|
|
||||||
|
const baseApi = 'https://api.cachefly.com';
|
||||||
|
|
||||||
|
const headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
...(token ? { 'x-cf-authorization': `Bearer ${token}` } : {}),
|
||||||
|
};
|
||||||
|
const res = await this.ctx.http.request<any, any>({
|
||||||
|
url,
|
||||||
|
baseURL: baseApi,
|
||||||
|
method,
|
||||||
|
data,
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new CacheflyAccess();
|
new CacheflyAccess();
|
||||||
|
|||||||
+7
-33
@@ -35,47 +35,21 @@ export class CacheFlyPlugin extends AbstractTaskPlugin {
|
|||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
accessId!: string;
|
accessId!: string;
|
||||||
private readonly baseApi = 'https://api.cachefly.com';
|
|
||||||
|
|
||||||
async onInstance() {}
|
async onInstance() {}
|
||||||
|
|
||||||
private async doRequestApi(url: string, data: any = null, method = 'post', token: string | null = null) {
|
|
||||||
const headers = {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
...(token ? { 'x-cf-authorization': `Bearer ${token}` } : {}),
|
|
||||||
};
|
|
||||||
const res = await this.http.request<any, any>({
|
|
||||||
url,
|
|
||||||
method,
|
|
||||||
data,
|
|
||||||
headers,
|
|
||||||
});
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async execute(): Promise<void> {
|
async execute(): Promise<void> {
|
||||||
const { cert, accessId } = this;
|
const { cert, accessId } = this;
|
||||||
const access = (await this.getAccess(accessId)) as CacheflyAccess;
|
const access = (await this.getAccess(accessId)) as CacheflyAccess;
|
||||||
let otp = null;
|
|
||||||
if (access.otpkey) {
|
const token = await access.login();
|
||||||
const response = await this.http.request<any, any>({
|
|
||||||
url: `https://cn-api.my-api.cn/api/totp/?key=${access.otpkey}`,
|
|
||||||
method: 'get',
|
|
||||||
});
|
|
||||||
otp = response;
|
|
||||||
this.logger.info('获取到otp:', otp);
|
|
||||||
}
|
|
||||||
const loginResponse = await this.doRequestApi(`${this.baseApi}/api/2.6/auth/login`, {
|
|
||||||
username: access.username,
|
|
||||||
password: access.password,
|
|
||||||
...(otp && { otp }),
|
|
||||||
});
|
|
||||||
const token = loginResponse.token;
|
|
||||||
this.logger.info('Token 获取成功');
|
|
||||||
// 更新证书
|
// 更新证书
|
||||||
await this.doRequestApi(
|
await access.doRequestApi(
|
||||||
`${this.baseApi}/api/2.6/certificates`,
|
`/api/2.6/certificates`,
|
||||||
{
|
{
|
||||||
certificate: cert.crt,
|
certificate: cert.crt,
|
||||||
certificateKey: cert.key,
|
certificateKey: cert.key,
|
||||||
|
|||||||
@@ -37,6 +37,58 @@ export class CloudflareAccess extends BaseAccess {
|
|||||||
encrypt: false,
|
encrypt: false,
|
||||||
})
|
})
|
||||||
proxy = '';
|
proxy = '';
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "测试授权是否正确"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
await this.getZoneList();
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async getZoneList() {
|
||||||
|
const url = `https://api.cloudflare.com/client/v4/zones`;
|
||||||
|
const res = await this.doRequestApi(url, null, 'get');
|
||||||
|
return res.result
|
||||||
|
}
|
||||||
|
|
||||||
|
async doRequestApi(url: string, data: any = null, method = 'post') {
|
||||||
|
try {
|
||||||
|
const res = await this.ctx.http.request<any, any>({
|
||||||
|
url,
|
||||||
|
method,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Bearer ${this.apiToken}`,
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
httpProxy: this.proxy,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.success) {
|
||||||
|
throw new Error(`${JSON.stringify(res.errors)}`);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
} catch (e: any) {
|
||||||
|
const data = e.response?.data;
|
||||||
|
if (data && data.success === false && data.errors && data.errors.length > 0) {
|
||||||
|
if (data.errors[0].code === 81058) {
|
||||||
|
this.ctx.logger.info('dns解析记录重复');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new CloudflareAccess();
|
new CloudflareAccess();
|
||||||
|
|||||||
@@ -41,41 +41,14 @@ export class CloudflareDnsProvider extends AbstractDnsProvider<CloudflareRecord>
|
|||||||
async getZoneId(domain: string) {
|
async getZoneId(domain: string) {
|
||||||
this.logger.info('获取zoneId:', domain);
|
this.logger.info('获取zoneId:', domain);
|
||||||
const url = `https://api.cloudflare.com/client/v4/zones?name=${domain}`;
|
const url = `https://api.cloudflare.com/client/v4/zones?name=${domain}`;
|
||||||
const res = await this.doRequestApi(url, null, 'get');
|
const res = await this.access.doRequestApi(url, null, 'get');
|
||||||
if (res.result.length === 0) {
|
if (res.result.length === 0) {
|
||||||
throw new Error(`未找到域名${domain}的zoneId`);
|
throw new Error(`未找到域名${domain}的zoneId`);
|
||||||
}
|
}
|
||||||
return res.result[0].id;
|
return res.result[0].id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async doRequestApi(url: string, data: any = null, method = 'post') {
|
|
||||||
try {
|
|
||||||
const res = await this.http.request<any, any>({
|
|
||||||
url,
|
|
||||||
method,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
Authorization: `Bearer ${this.access.apiToken}`,
|
|
||||||
},
|
|
||||||
data,
|
|
||||||
httpProxy: this.access.proxy,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!res.success) {
|
|
||||||
throw new Error(`${JSON.stringify(res.errors)}`);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
} catch (e: any) {
|
|
||||||
const data = e.response?.data;
|
|
||||||
if (data && data.success === false && data.errors && data.errors.length > 0) {
|
|
||||||
if (data.errors[0].code === 81058) {
|
|
||||||
this.logger.info('dns解析记录重复');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建dns解析记录,用于验证域名所有权
|
* 创建dns解析记录,用于验证域名所有权
|
||||||
@@ -95,7 +68,7 @@ export class CloudflareDnsProvider extends AbstractDnsProvider<CloudflareRecord>
|
|||||||
|
|
||||||
// 给domain下创建txt类型的dns解析记录,fullRecord
|
// 给domain下创建txt类型的dns解析记录,fullRecord
|
||||||
const url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records`;
|
const url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records`;
|
||||||
const res = await this.doRequestApi(url, {
|
const res = await this.access.doRequestApi(url, {
|
||||||
content: value,
|
content: value,
|
||||||
name: fullRecord,
|
name: fullRecord,
|
||||||
type: type,
|
type: type,
|
||||||
@@ -119,7 +92,7 @@ export class CloudflareDnsProvider extends AbstractDnsProvider<CloudflareRecord>
|
|||||||
async findRecord(zoneId: string, options: CreateRecordOptions): Promise<CloudflareRecord | null> {
|
async findRecord(zoneId: string, options: CreateRecordOptions): Promise<CloudflareRecord | null> {
|
||||||
const { fullRecord, value } = options;
|
const { fullRecord, value } = options;
|
||||||
const url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records?type=TXT&name=${fullRecord}&content=${value}`;
|
const url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records?type=TXT&name=${fullRecord}&content=${value}`;
|
||||||
const res = await this.doRequestApi(url, null, 'get');
|
const res = await this.access.doRequestApi(url, null, 'get');
|
||||||
if (res.result.length === 0) {
|
if (res.result.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -142,7 +115,7 @@ export class CloudflareDnsProvider extends AbstractDnsProvider<CloudflareRecord>
|
|||||||
const zoneId = record.zone_id;
|
const zoneId = record.zone_id;
|
||||||
const recordId = record.id;
|
const recordId = record.id;
|
||||||
const url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records/${recordId}`;
|
const url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records/${recordId}`;
|
||||||
await this.doRequestApi(url, null, 'delete');
|
await this.access.doRequestApi(url, null, 'delete');
|
||||||
this.logger.info(`删除域名解析成功:fullRecord=${fullRecord},value=${value}`);
|
this.logger.info(`删除域名解析成功:fullRecord=${fullRecord},value=${value}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +126,7 @@ export class CloudflareDnsProvider extends AbstractDnsProvider<CloudflareRecord>
|
|||||||
if (req.searchKey) {
|
if (req.searchKey) {
|
||||||
url += `&name=${req.searchKey}`;
|
url += `&name=${req.searchKey}`;
|
||||||
}
|
}
|
||||||
const ret = await this.doRequestApi(url, null, 'get');
|
const ret = await this.access.doRequestApi(url, null, 'get');
|
||||||
|
|
||||||
let list = ret.result || []
|
let list = ret.result || []
|
||||||
list = list.map((item: any) => ({
|
list = list.map((item: any) => ({
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline';
|
import { IsAccess, AccessInput, BaseAccess, PageSearch, PageRes, Pager } from '@certd/pipeline';
|
||||||
|
import { DomainRecord } from '@certd/plugin-lib';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 这个注解将注册一个授权配置
|
* 这个注解将注册一个授权配置
|
||||||
@@ -19,7 +20,7 @@ export class DnslaAccess extends BaseAccess {
|
|||||||
component: {
|
component: {
|
||||||
placeholder: 'APIID',
|
placeholder: 'APIID',
|
||||||
},
|
},
|
||||||
helper:"从我的账户->API密钥中获取 APIID APISecret",
|
helper: "从我的账户->API密钥中获取 APIID APISecret",
|
||||||
required: true,
|
required: true,
|
||||||
encrypt: false,
|
encrypt: false,
|
||||||
})
|
})
|
||||||
@@ -36,6 +37,83 @@ export class DnslaAccess extends BaseAccess {
|
|||||||
encrypt: true,
|
encrypt: true,
|
||||||
})
|
})
|
||||||
apiSecret = '';
|
apiSecret = '';
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "测试授权是否正确"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
await this.getDomainListPage({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 1,
|
||||||
|
});
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
||||||
|
const pager = new Pager(req);
|
||||||
|
const url = `/api/domainList?pageIndex=${pager.pageNo}&pageSize=${pager.pageSize}`;
|
||||||
|
const ret = await this.doRequestApi(url, null, 'get');
|
||||||
|
|
||||||
|
let list = ret.data.results || []
|
||||||
|
list = list.map((item: any) => ({
|
||||||
|
id: item.id,
|
||||||
|
domain: item.domain,
|
||||||
|
}));
|
||||||
|
const total = ret.data.total || list.length;
|
||||||
|
return {
|
||||||
|
total,
|
||||||
|
list,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async doRequestApi(url: string, data: any = null, method = 'post') {
|
||||||
|
/**
|
||||||
|
* Basic 认证
|
||||||
|
* 我的账户 API 密钥 中获取 APIID APISecret
|
||||||
|
* APIID=myApiId
|
||||||
|
* APISecret=mySecret
|
||||||
|
* 生成 Basic 令牌
|
||||||
|
* # 用冒号连接 APIID APISecret
|
||||||
|
* str = "myApiId:mySecret"
|
||||||
|
* token = base64Encode(str)
|
||||||
|
* 在请求头中添加 Basic 认证令牌
|
||||||
|
* Authorization: Basic {token}
|
||||||
|
* 响应示例
|
||||||
|
* application/json
|
||||||
|
* {
|
||||||
|
* "code":200,
|
||||||
|
* "msg":"",
|
||||||
|
* "data":{}
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
const token = Buffer.from(`${this.apiId}:${this.apiSecret}`).toString('base64');
|
||||||
|
const res = await this.ctx.http.request<any, any>({
|
||||||
|
url: "https://api.dns.la" + url,
|
||||||
|
method,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Basic ${token}`,
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.code !== 200) {
|
||||||
|
throw new Error(res.msg);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new DnslaAccess();
|
new DnslaAccess();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert";
|
import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert";
|
||||||
|
|
||||||
|
import { PageRes, PageSearch } from "@certd/pipeline";
|
||||||
import { DnslaAccess } from "./access.js";
|
import { DnslaAccess } from "./access.js";
|
||||||
import { Pager, PageRes, PageSearch } from "@certd/pipeline";
|
|
||||||
|
|
||||||
export type DnslaRecord = {
|
export type DnslaRecord = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -25,43 +25,6 @@ export class DnslaDnsProvider extends AbstractDnsProvider<DnslaRecord> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async doRequestApi(url: string, data: any = null, method = 'post') {
|
|
||||||
/**
|
|
||||||
* Basic 认证
|
|
||||||
* 我的账户 API 密钥 中获取 APIID APISecret
|
|
||||||
* APIID=myApiId
|
|
||||||
* APISecret=mySecret
|
|
||||||
* 生成 Basic 令牌
|
|
||||||
* # 用冒号连接 APIID APISecret
|
|
||||||
* str = "myApiId:mySecret"
|
|
||||||
* token = base64Encode(str)
|
|
||||||
* 在请求头中添加 Basic 认证令牌
|
|
||||||
* Authorization: Basic {token}
|
|
||||||
* 响应示例
|
|
||||||
* application/json
|
|
||||||
* {
|
|
||||||
* "code":200,
|
|
||||||
* "msg":"",
|
|
||||||
* "data":{}
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
const token = Buffer.from(`${this.access.apiId}:${this.access.apiSecret}`).toString('base64');
|
|
||||||
const res = await this.http.request<any, any>({
|
|
||||||
url:"https://api.dns.la"+url,
|
|
||||||
method,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
Authorization: `Basic ${token}`,
|
|
||||||
},
|
|
||||||
data,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res.code !== 200) {
|
|
||||||
throw new Error(res.msg);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
async getDomainDetail(domain:string){
|
async getDomainDetail(domain:string){
|
||||||
/**
|
/**
|
||||||
@@ -88,7 +51,7 @@ export class DnslaDnsProvider extends AbstractDnsProvider<DnslaRecord> {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const url = `/api/domain?domain=${domain}`;
|
const url = `/api/domain?domain=${domain}`;
|
||||||
const res = await this.doRequestApi(url, null, 'get');
|
const res = await this.access.doRequestApi(url, null, 'get');
|
||||||
return res.data
|
return res.data
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +104,7 @@ export class DnslaDnsProvider extends AbstractDnsProvider<DnslaRecord> {
|
|||||||
* CAA 257
|
* CAA 257
|
||||||
* URL转发 256
|
* URL转发 256
|
||||||
*/
|
*/
|
||||||
const res = await this.doRequestApi(url, {
|
const res = await this.access.doRequestApi(url, {
|
||||||
domainId: domainId,
|
domainId: domainId,
|
||||||
type: 16,
|
type: 16,
|
||||||
host: fullRecord.replace(`.${domain}`, ''),
|
host: fullRecord.replace(`.${domain}`, ''),
|
||||||
@@ -174,27 +137,14 @@ export class DnslaDnsProvider extends AbstractDnsProvider<DnslaRecord> {
|
|||||||
*/
|
*/
|
||||||
const recordId = record.id;
|
const recordId = record.id;
|
||||||
const url = `/api/record?id=${recordId}`;
|
const url = `/api/record?id=${recordId}`;
|
||||||
await this.doRequestApi(url, null, 'delete');
|
await this.access.doRequestApi(url, null, 'delete');
|
||||||
this.logger.info(`删除域名解析成功:fullRecord=${fullRecord},value=${value}`);
|
this.logger.info(`删除域名解析成功:fullRecord=${fullRecord},value=${value}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
||||||
const pager = new Pager(req);
|
return await this.access.getDomainListPage(req);
|
||||||
const url = `/api/domain?pageIndex=${pager.pageNo}&pageSize=${pager.pageSize}`;
|
|
||||||
const ret = await this.doRequestApi(url, null, 'get');
|
|
||||||
|
|
||||||
|
|
||||||
let list = ret.data.results || []
|
|
||||||
list = list.map((item: any) => ({
|
|
||||||
id: item.id,
|
|
||||||
domain: item.domain,
|
|
||||||
}));
|
|
||||||
const total = ret.data.total || list.length;
|
|
||||||
return {
|
|
||||||
total,
|
|
||||||
list,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//实例化这个provider,将其自动注册到系统中
|
//实例化这个provider,将其自动注册到系统中
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline';
|
import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline';
|
||||||
|
import { DogeClient } from './lib/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 这个注解将注册一个授权配置
|
* 这个注解将注册一个授权配置
|
||||||
@@ -35,6 +36,25 @@ export class DogeCloudAccess extends BaseAccess {
|
|||||||
encrypt: true,
|
encrypt: true,
|
||||||
})
|
})
|
||||||
secretKey = '';
|
secretKey = '';
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "测试授权是否正确"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
const dogeClient = new DogeClient(this, this.ctx.http, this.ctx.logger);
|
||||||
|
await dogeClient.request(
|
||||||
|
'/cdn/domain/list.json',
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new DogeCloudAccess();
|
new DogeCloudAccess();
|
||||||
|
|||||||
@@ -32,6 +32,60 @@ export class GcoreAccess extends BaseAccess {
|
|||||||
encrypt: true,
|
encrypt: true,
|
||||||
})
|
})
|
||||||
otpkey = '';
|
otpkey = '';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "点击测试接口是否正常"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
await this.login();
|
||||||
|
return "ok"
|
||||||
|
}
|
||||||
|
|
||||||
|
async login() {
|
||||||
|
let otp = null;
|
||||||
|
if (this.otpkey) {
|
||||||
|
const response = await this.ctx.http.request<any, any>({
|
||||||
|
url: `https://cn-api.my-api.cn/api/totp/?key=${this.otpkey}`,
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
otp = response;
|
||||||
|
this.ctx.logger.info('获取到otp:', otp);
|
||||||
|
}
|
||||||
|
const loginResponse = await this.doRequestApi(`/iam/auth/jwt/login`, {
|
||||||
|
username: this.username,
|
||||||
|
password: this.password,
|
||||||
|
...(otp && { otp }),
|
||||||
|
});
|
||||||
|
const token = loginResponse.access;
|
||||||
|
this.ctx.logger.info('Token 获取成功');
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
async doRequestApi(url: string, data: any = null, method = 'post', token: string | null = null) {
|
||||||
|
const baseApi = 'https://api.gcore.com';
|
||||||
|
const headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
...(token ? { authorization: `Bearer ${token}` } : {}),
|
||||||
|
};
|
||||||
|
const res = await this.ctx.http.request<any, any>({
|
||||||
|
url,
|
||||||
|
baseURL: baseApi,
|
||||||
|
method,
|
||||||
|
data,
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new GcoreAccess();
|
new GcoreAccess();
|
||||||
|
|||||||
@@ -41,47 +41,20 @@ export class GcoreuploadPlugin extends AbstractTaskPlugin {
|
|||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
accessId!: string;
|
accessId!: string;
|
||||||
private readonly baseApi = 'https://api.gcore.com';
|
|
||||||
|
|
||||||
async onInstance() {}
|
async onInstance() {}
|
||||||
|
|
||||||
private async doRequestApi(url: string, data: any = null, method = 'post', token: string | null = null) {
|
|
||||||
const headers = {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
...(token ? { authorization: `Bearer ${token}` } : {}),
|
|
||||||
};
|
|
||||||
const res = await this.http.request<any, any>({
|
|
||||||
url,
|
|
||||||
method,
|
|
||||||
data,
|
|
||||||
headers,
|
|
||||||
});
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async execute(): Promise<void> {
|
async execute(): Promise<void> {
|
||||||
const { cert, accessId } = this;
|
const { cert, accessId } = this;
|
||||||
const access = (await this.getAccess(accessId)) as GcoreAccess;
|
const access = (await this.getAccess(accessId)) as GcoreAccess;
|
||||||
let otp = null;
|
|
||||||
if (access.otpkey) {
|
const token = await access.login();
|
||||||
const response = await this.http.request<any, any>({
|
|
||||||
url: `https://cn-api.my-api.cn/api/totp/?key=${access.otpkey}`,
|
|
||||||
method: 'get',
|
|
||||||
});
|
|
||||||
otp = response;
|
|
||||||
this.logger.info('获取到otp:', otp);
|
|
||||||
}
|
|
||||||
const loginResponse = await this.doRequestApi(`${this.baseApi}/iam/auth/jwt/login`, {
|
|
||||||
username: access.username,
|
|
||||||
password: access.password,
|
|
||||||
...(otp && { otp }),
|
|
||||||
});
|
|
||||||
const token = loginResponse.access;
|
|
||||||
this.logger.info('Token 获取成功');
|
this.logger.info('Token 获取成功');
|
||||||
this.logger.info('开始上传证书');
|
this.logger.info('开始上传证书');
|
||||||
await this.doRequestApi(
|
await access.doRequestApi(
|
||||||
`${this.baseApi}/cdn/sslData`,
|
`/cdn/sslData`,
|
||||||
{
|
{
|
||||||
name: this.certName,
|
name: this.certName,
|
||||||
sslCertificate: cert.crt,
|
sslCertificate: cert.crt,
|
||||||
|
|||||||
@@ -29,6 +29,25 @@ export class HuaweiAccess extends BaseAccess {
|
|||||||
accessKeySecret = '';
|
accessKeySecret = '';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "点击测试接口是否正常"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
accessToken: { expiresAt: number, token: string }
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
await this.getProjectList();
|
||||||
|
return "ok"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async getProjectList() {
|
async getProjectList() {
|
||||||
const endpoint = "https://iam.cn-north-4.myhuaweicloud.com";
|
const endpoint = "https://iam.cn-north-4.myhuaweicloud.com";
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {AccessInput, BaseAccess, IsAccess} from '@certd/pipeline';
|
import {AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch} from '@certd/pipeline';
|
||||||
|
import { DomainRecord } from '@certd/plugin-lib';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 这个注解将注册一个授权配置
|
* 这个注解将注册一个授权配置
|
||||||
@@ -32,6 +33,59 @@ export class JDCloudAccess extends BaseAccess {
|
|||||||
})
|
})
|
||||||
secretAccessKey = '';
|
secretAccessKey = '';
|
||||||
|
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "点击测试接口是否正常"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
accessToken: { expiresAt: number, token: string }
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
await this.getDomainListPage({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 1,
|
||||||
|
});
|
||||||
|
return "ok"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async getJDDomainService() {
|
||||||
|
const {JDDomainService} = await import("@certd/jdcloud")
|
||||||
|
const service = new JDDomainService({
|
||||||
|
credentials: {
|
||||||
|
accessKeyId: this.accessKeyId,
|
||||||
|
secretAccessKey: this.secretAccessKey
|
||||||
|
},
|
||||||
|
regionId: "cn-north-1" //地域信息,某个api调用可以单独传参regionId,如果不传则会使用此配置中的regionId
|
||||||
|
});
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
||||||
|
const pager = new Pager(req);
|
||||||
|
const service = await this.getJDDomainService();
|
||||||
|
const domainRes = await service.describeDomains({
|
||||||
|
domainName: req.searchKey,
|
||||||
|
pageNumber: pager.pageNo,
|
||||||
|
pageSize: pager.pageSize,
|
||||||
|
})
|
||||||
|
let list = domainRes.result?.dataList || []
|
||||||
|
list = list.map((item: any) => ({
|
||||||
|
id: item.domainId,
|
||||||
|
domain: item.domainName,
|
||||||
|
}));
|
||||||
|
return {
|
||||||
|
total:domainRes.result.totalCount || list.length,
|
||||||
|
list,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new JDCloudAccess();
|
new JDCloudAccess();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { PageRes, PageSearch } from "@certd/pipeline";
|
||||||
import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert";
|
import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert";
|
||||||
import { JDCloudAccess } from "./access.js";
|
import { JDCloudAccess } from "./access.js";
|
||||||
import { Pager, PageRes, PageSearch } from "@certd/pipeline";
|
|
||||||
|
|
||||||
@IsDnsProvider({
|
@IsDnsProvider({
|
||||||
name: "jdcloud",
|
name: "jdcloud",
|
||||||
@@ -85,34 +85,11 @@ export class JDCloudDnsProvider extends AbstractDnsProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getJDDomainService() {
|
private async getJDDomainService() {
|
||||||
const {JDDomainService} = await import("@certd/jdcloud")
|
return await this.access.getJDDomainService();
|
||||||
const service = new JDDomainService({
|
|
||||||
credentials: {
|
|
||||||
accessKeyId: this.access.accessKeyId,
|
|
||||||
secretAccessKey: this.access.secretAccessKey
|
|
||||||
},
|
|
||||||
regionId: "cn-north-1" //地域信息,某个api调用可以单独传参regionId,如果不传则会使用此配置中的regionId
|
|
||||||
});
|
|
||||||
return service;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
||||||
const pager = new Pager(req);
|
return await this.access.getDomainListPage(req);
|
||||||
const service = await this.getJDDomainService();
|
|
||||||
const domainRes = await service.describeDomains({
|
|
||||||
domainName: req.searchKey,
|
|
||||||
pageNumber: pager.pageNo,
|
|
||||||
pageSize: pager.pageSize,
|
|
||||||
})
|
|
||||||
let list = domainRes.result?.dataList || []
|
|
||||||
list = list.map((item: any) => ({
|
|
||||||
id: item.domainId,
|
|
||||||
domain: item.domainName,
|
|
||||||
}));
|
|
||||||
return {
|
|
||||||
total:domainRes.result.totalCount || list.length,
|
|
||||||
list,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline";
|
import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from "@certd/pipeline";
|
||||||
|
import { DomainRecord } from "@certd/plugin-lib";
|
||||||
|
import { AliyunAccess } from "./aliyun-access.js";
|
||||||
|
|
||||||
@IsAccess({
|
@IsAccess({
|
||||||
name: "aliesa",
|
name: "aliesa",
|
||||||
@@ -40,6 +42,68 @@ export class AliesaAccess extends BaseAccess {
|
|||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
region = "";
|
region = "";
|
||||||
|
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "点击测试接口是否正常"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
await this.getDomainListPage({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 1,
|
||||||
|
});
|
||||||
|
return "ok"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async getEsaClient(){
|
||||||
|
const access: AliesaAccess = this
|
||||||
|
const aliAccess = await this.ctx.accessService.getById(access.accessId) as AliyunAccess
|
||||||
|
const endpoint = `esa.${access.region}.aliyuncs.com`
|
||||||
|
return aliAccess.getClient(endpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
||||||
|
const pager = new Pager(req)
|
||||||
|
const client = await this.getEsaClient()
|
||||||
|
const ret = await client.doRequest({
|
||||||
|
// 接口名称
|
||||||
|
action: "ListSites",
|
||||||
|
// 接口版本
|
||||||
|
version: "2024-09-10",
|
||||||
|
// 接口协议
|
||||||
|
protocol: "HTTPS",
|
||||||
|
// 接口 HTTP 方法
|
||||||
|
method: "GET",
|
||||||
|
authType: "AK",
|
||||||
|
style: "RPC",
|
||||||
|
data: {
|
||||||
|
query: {
|
||||||
|
SiteName: req.searchKey,
|
||||||
|
// ["SiteSearchType"] = "exact";
|
||||||
|
SiteSearchType: "fuzzy",
|
||||||
|
AccessType: "NS",
|
||||||
|
PageSize: pager.pageSize,
|
||||||
|
PageNumber: pager.pageNo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const list = ret.Sites?.map(item => ({
|
||||||
|
domain: item.SiteName,
|
||||||
|
id: item.SiteId,
|
||||||
|
}))
|
||||||
|
return {
|
||||||
|
list: list || [],
|
||||||
|
total: ret.TotalCount,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new AliesaAccess();
|
new AliesaAccess();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline";
|
import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline";
|
||||||
import { AliyunClientV2 } from "../lib/aliyun-client-v2.js";
|
import { AliyunClientV2 } from "../lib/aliyun-client-v2.js";
|
||||||
|
import { AliyunSslClient } from "../lib/ssl-client.js";
|
||||||
@IsAccess({
|
@IsAccess({
|
||||||
name: "aliyun",
|
name: "aliyun",
|
||||||
title: "阿里云授权",
|
title: "阿里云授权",
|
||||||
@@ -28,6 +29,67 @@ export class AliyunAccess extends BaseAccess {
|
|||||||
})
|
})
|
||||||
accessKeySecret = "";
|
accessKeySecret = "";
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "点击测试接口是否正常"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
await this.getCallerIdentity();
|
||||||
|
return "ok"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async getStsClient() {
|
||||||
|
const StsClient = await import('@alicloud/sts-sdk');
|
||||||
|
|
||||||
|
// 配置凭证
|
||||||
|
const sts = new StsClient.default({
|
||||||
|
endpoint: 'sts.aliyuncs.com',
|
||||||
|
accessKeyId: this.accessKeyId,
|
||||||
|
accessKeySecret: this.accessKeySecret,
|
||||||
|
});
|
||||||
|
|
||||||
|
return sts
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async getCallerIdentity() {
|
||||||
|
|
||||||
|
const sts = await this.getStsClient();
|
||||||
|
// 调用 GetCallerIdentity 接口
|
||||||
|
const result = await sts.getCallerIdentity();
|
||||||
|
|
||||||
|
this.ctx.logger.log("✅ 密钥有效!");
|
||||||
|
this.ctx.logger.log(` 账户ID: ${result.AccountId}`);
|
||||||
|
this.ctx.logger.log(` ARN: ${result.Arn}`);
|
||||||
|
this.ctx.logger.log(` 用户ID: ${result.UserId}`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: true,
|
||||||
|
accountId: result.AccountId,
|
||||||
|
arn: result.Arn,
|
||||||
|
userId: result.UserId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getSslClient({ endpoint }: { endpoint: string }) {
|
||||||
|
const client = new AliyunSslClient({
|
||||||
|
access: this,
|
||||||
|
logger: this.ctx.logger,
|
||||||
|
endpoint,
|
||||||
|
});
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
getClient(endpoint: string) {
|
getClient(endpoint: string) {
|
||||||
return new AliyunClientV2({
|
return new AliyunClientV2({
|
||||||
access: this,
|
access: this,
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline';
|
import { IsAccess, AccessInput, BaseAccess, PageSearch, PageRes, Pager } from '@certd/pipeline';
|
||||||
|
import { DomainRecord } from '@certd/plugin-lib';
|
||||||
|
import { merge } from 'lodash-es';
|
||||||
|
import qs from 'qs';
|
||||||
/**
|
/**
|
||||||
* 这个注解将注册一个授权配置
|
* 这个注解将注册一个授权配置
|
||||||
* 在certd的后台管理系统中,用户可以选择添加此类型的授权
|
* 在certd的后台管理系统中,用户可以选择添加此类型的授权
|
||||||
@@ -25,6 +27,74 @@ export class NamesiloAccess extends BaseAccess {
|
|||||||
encrypt: true,
|
encrypt: true,
|
||||||
})
|
})
|
||||||
apiKey = '';
|
apiKey = '';
|
||||||
|
|
||||||
|
|
||||||
|
@AccessInput({
|
||||||
|
title: "测试",
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
helper: "点击测试接口是否正常"
|
||||||
|
})
|
||||||
|
testRequest = true;
|
||||||
|
|
||||||
|
async onTestRequest() {
|
||||||
|
await this.getDomainListPage({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 1,
|
||||||
|
});
|
||||||
|
return "ok"
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
||||||
|
|
||||||
|
const pager = new Pager(req);
|
||||||
|
const ret =await this.doRequest('/api/listDomains', {
|
||||||
|
key:req.searchKey,
|
||||||
|
page: pager.pageNo,
|
||||||
|
pageSize: pager.pageSize,
|
||||||
|
});
|
||||||
|
let list = ret.domains ||[]
|
||||||
|
// this.logger.info("获取域名列表成功:", ret);
|
||||||
|
list = list.map((item: any) => ({
|
||||||
|
id: item.domain,
|
||||||
|
domain: item.domain,
|
||||||
|
}));
|
||||||
|
return {
|
||||||
|
total:ret.pager?.total || list.length,
|
||||||
|
list,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async doRequest(url: string, params: any = null) {
|
||||||
|
params = merge(
|
||||||
|
{
|
||||||
|
version: 1,
|
||||||
|
type: 'json',
|
||||||
|
key: this.apiKey,
|
||||||
|
},
|
||||||
|
params
|
||||||
|
);
|
||||||
|
const qsString = qs.stringify(params);
|
||||||
|
url = `${url}?${qsString}`;
|
||||||
|
const res = await this.ctx.http.request<any, any>({
|
||||||
|
url,
|
||||||
|
baseURL: 'https://www.namesilo.com',
|
||||||
|
method: 'get',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.reply?.code !== '300' && res.reply?.code !== 300 && res.reply?.detail!=="success") {
|
||||||
|
throw new Error(`${JSON.stringify(res.reply.detail)}`);
|
||||||
|
}
|
||||||
|
return res.reply;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new NamesiloAccess();
|
new NamesiloAccess();
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
|
import { PageRes, PageSearch } from '@certd/pipeline';
|
||||||
import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert';
|
import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert';
|
||||||
import qs from 'qs';
|
|
||||||
import { NamesiloAccess } from './access.js';
|
import { NamesiloAccess } from './access.js';
|
||||||
import { merge } from 'lodash-es';
|
|
||||||
import { Pager, PageRes, PageSearch } from '@certd/pipeline';
|
|
||||||
|
|
||||||
export type NamesiloRecord = {
|
export type NamesiloRecord = {
|
||||||
record_id: string;
|
record_id: string;
|
||||||
@@ -30,31 +28,6 @@ export class NamesiloDnsProvider extends AbstractDnsProvider<NamesiloRecord> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async doRequest(url: string, params: any = null) {
|
|
||||||
params = merge(
|
|
||||||
{
|
|
||||||
version: 1,
|
|
||||||
type: 'json',
|
|
||||||
key: this.access.apiKey,
|
|
||||||
},
|
|
||||||
params
|
|
||||||
);
|
|
||||||
const qsString = qs.stringify(params);
|
|
||||||
url = `${url}?${qsString}`;
|
|
||||||
const res = await this.http.request<any, any>({
|
|
||||||
url,
|
|
||||||
baseURL: 'https://www.namesilo.com',
|
|
||||||
method: 'get',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res.reply?.code !== '300' && res.reply?.code !== 300 && res.reply?.detail!=="success") {
|
|
||||||
throw new Error(`${JSON.stringify(res.reply.detail)}`);
|
|
||||||
}
|
|
||||||
return res.reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建dns解析记录,用于验证域名所有权
|
* 创建dns解析记录,用于验证域名所有权
|
||||||
@@ -70,7 +43,7 @@ export class NamesiloDnsProvider extends AbstractDnsProvider<NamesiloRecord> {
|
|||||||
this.logger.info('添加域名解析:', fullRecord, value, type, domain);
|
this.logger.info('添加域名解析:', fullRecord, value, type, domain);
|
||||||
|
|
||||||
//domain=namesilo.com&rrtype=A&rrhost=test&rrvalue=55.55.55.55&rrttl=7207
|
//domain=namesilo.com&rrtype=A&rrhost=test&rrvalue=55.55.55.55&rrttl=7207
|
||||||
const record: any = await this.doRequest('/api/dnsAddRecord', {
|
const record: any = await this.access.doRequest('/api/dnsAddRecord', {
|
||||||
domain,
|
domain,
|
||||||
rrtype: type,
|
rrtype: type,
|
||||||
rrhost: hostRecord,
|
rrhost: hostRecord,
|
||||||
@@ -97,7 +70,7 @@ export class NamesiloDnsProvider extends AbstractDnsProvider<NamesiloRecord> {
|
|||||||
//这里调用删除txt dns解析记录接口
|
//这里调用删除txt dns解析记录接口
|
||||||
|
|
||||||
const recordId = record.record_id;
|
const recordId = record.record_id;
|
||||||
await this.doRequest('/api/dnsDeleteRecord', {
|
await this.access.doRequest('/api/dnsDeleteRecord', {
|
||||||
domain: options.recordReq.domain,
|
domain: options.recordReq.domain,
|
||||||
rrid: recordId,
|
rrid: recordId,
|
||||||
});
|
});
|
||||||
@@ -105,22 +78,7 @@ export class NamesiloDnsProvider extends AbstractDnsProvider<NamesiloRecord> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
||||||
|
return await this.access.getDomainListPage(req);
|
||||||
const pager = new Pager(req);
|
|
||||||
const ret =await this.doRequest('/api/listDomains', {
|
|
||||||
key:req.searchKey,
|
|
||||||
page: pager.pageNo,
|
|
||||||
pageSize: pager.pageSize,
|
|
||||||
});
|
|
||||||
// this.logger.info("获取域名列表成功:", ret);
|
|
||||||
const list = ret.domains.map((item: any) => ({
|
|
||||||
id: item.domain,
|
|
||||||
domain: item.domain,
|
|
||||||
}));
|
|
||||||
return {
|
|
||||||
total:ret.pager?.total || list.length,
|
|
||||||
list,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
|
import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
|
||||||
|
import { CtyunClient } from "../lib.js";
|
||||||
|
import { HttpClient } from "@certd/basic";
|
||||||
|
|
||||||
@IsAccess({
|
@IsAccess({
|
||||||
name: "ctyun",
|
name: "ctyun",
|
||||||
@@ -27,6 +29,37 @@ export class CtyunAccess extends BaseAccess {
|
|||||||
helper: "",
|
helper: "",
|
||||||
})
|
})
|
||||||
securityKey = "";
|
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();
|
new CtyunAccess();
|
||||||
|
|||||||
@@ -29,6 +29,40 @@ export class K8sAccess extends BaseAccess {
|
|||||||
encrypt: false,
|
encrypt: false,
|
||||||
})
|
})
|
||||||
skipTLSVerify: boolean;
|
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();
|
new K8sAccess();
|
||||||
|
|||||||
@@ -30,6 +30,87 @@ export class KuocaiCdnAccess extends BaseAccess {
|
|||||||
encrypt: true,
|
encrypt: true,
|
||||||
})
|
})
|
||||||
password = "";
|
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();
|
new KuocaiCdnAccess();
|
||||||
|
|||||||
+4
-64
@@ -54,7 +54,7 @@ export class KuocaiDeployToCDNPlugin extends AbstractTaskPlugin {
|
|||||||
async onInstance() {}
|
async onInstance() {}
|
||||||
async execute(): Promise<void> {
|
async execute(): Promise<void> {
|
||||||
const access = await this.getAccess<KuocaiCdnAccess>(this.accessId);
|
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";
|
const curl = "https://kuocaicdn.com/CdnDomainHttps/httpsConfiguration";
|
||||||
for (const domain of this.domains) {
|
for (const domain of this.domains) {
|
||||||
@@ -78,71 +78,11 @@ export class KuocaiDeployToCDNPlugin extends AbstractTaskPlugin {
|
|||||||
private_key: cert.key,
|
private_key: cert.key,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
await this.doRequest(curl, loginRes, update);
|
await access.doRequest(curl, loginRes, update);
|
||||||
this.logger.info(`站点${domain}证书更新成功`);
|
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) {
|
async onGetDomainList(data: any) {
|
||||||
if (!this.accessId) {
|
if (!this.accessId) {
|
||||||
@@ -150,9 +90,9 @@ export class KuocaiDeployToCDNPlugin extends AbstractTaskPlugin {
|
|||||||
}
|
}
|
||||||
const access = await this.getAccess<KuocaiCdnAccess>(this.accessId);
|
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) {
|
if (!list || list.length === 0) {
|
||||||
throw new Error("您账户下还没有站点域名,请先添加域名");
|
throw new Error("您账户下还没有站点域名,请先添加域名");
|
||||||
|
|||||||
@@ -85,6 +85,90 @@ export class LeCDNAccess extends BaseAccess {
|
|||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
apiToken = "";
|
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();
|
new LeCDNAccess();
|
||||||
|
|||||||
+5
-55
@@ -58,49 +58,15 @@ export class LeCDNUpdateCertV2 extends AbstractTaskPlugin {
|
|||||||
|
|
||||||
async onInstance() {
|
async onInstance() {
|
||||||
this.access = await this.getAccess<LeCDNAccess>(this.accessId);
|
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) {
|
async getCertInfo(id: number) {
|
||||||
// http://cdnadmin.kxfox.com/prod-api/certificate/9
|
// http://cdnadmin.kxfox.com/prod-api/certificate/9
|
||||||
// Bearer edGkiOiIJ8
|
// Bearer edGkiOiIJ8
|
||||||
return await this.doRequest({
|
return await this.access.doRequest({
|
||||||
url: `/prod-api/certificate/${id}`,
|
url: `/prod-api/certificate/${id}`,
|
||||||
method: "get",
|
method: "get",
|
||||||
});
|
});
|
||||||
@@ -117,7 +83,7 @@ export class LeCDNUpdateCertV2 extends AbstractTaskPlugin {
|
|||||||
|
|
||||||
this.logger.info(`证书名称:${certInfo.name}`);
|
this.logger.info(`证书名称:${certInfo.name}`);
|
||||||
|
|
||||||
return await this.doRequest({
|
return await this.access.doRequest({
|
||||||
url: `/prod-api/certificate/${id}`,
|
url: `/prod-api/certificate/${id}`,
|
||||||
method: "put",
|
method: "put",
|
||||||
data: certInfo,
|
data: certInfo,
|
||||||
@@ -134,17 +100,13 @@ export class LeCDNUpdateCertV2 extends AbstractTaskPlugin {
|
|||||||
this.logger.info(`更新证书完成`);
|
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) {
|
async onGetCertList(data: any) {
|
||||||
if (!this.accessId) {
|
if (!this.accessId) {
|
||||||
throw new Error("请选择Access授权");
|
throw new Error("请选择Access授权");
|
||||||
}
|
}
|
||||||
const res = await this.getCerts();
|
const res = await this.access.getCerts();
|
||||||
//新旧版本不一样,一个data 一个是items
|
//新旧版本不一样,一个data 一个是items
|
||||||
const list = res.items || res.data;
|
const list = res.items || res.data;
|
||||||
if (!res || list.length === 0) {
|
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();
|
new LeCDNUpdateCertV2();
|
||||||
|
|||||||
@@ -49,6 +49,62 @@ export class LuckyAccess extends BaseAccess {
|
|||||||
encrypt: true,
|
encrypt: true,
|
||||||
})
|
})
|
||||||
openToken = "";
|
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();
|
new LuckyAccess();
|
||||||
|
|||||||
@@ -82,8 +82,7 @@ export class LuckyUpdateCert extends AbstractPlusTaskPlugin {
|
|||||||
throw new Error(`没有找到证书:Key=${item},请确认该证书是否存在`);
|
throw new Error(`没有找到证书:Key=${item},请确认该证书是否存在`);
|
||||||
}
|
}
|
||||||
const remark = old.Remark;
|
const remark = old.Remark;
|
||||||
const res = await this.doRequest({
|
const res = await access.doRequest({
|
||||||
access,
|
|
||||||
urlPath: "/api/ssl",
|
urlPath: "/api/ssl",
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
data: {
|
data: {
|
||||||
@@ -107,44 +106,9 @@ export class LuckyUpdateCert extends AbstractPlusTaskPlugin {
|
|||||||
this.logger.info("部署成功");
|
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() {
|
async onGetCertList() {
|
||||||
const access: LuckyAccess = await this.getAccess<LuckyAccess>(this.accessId);
|
const access: LuckyAccess = await this.getAccess<LuckyAccess>(this.accessId);
|
||||||
const res = await this.doRequest({
|
const list = await access.getCertList();
|
||||||
access,
|
|
||||||
urlPath: "/api/ssl",
|
|
||||||
data: {},
|
|
||||||
method: "GET",
|
|
||||||
});
|
|
||||||
const list = res.list;
|
|
||||||
if (!list || list.length === 0) {
|
if (!list || list.length === 0) {
|
||||||
throw new Error("没有找到证书,请先在SSL/TLS证书页面中手动上传一次证书");
|
throw new Error("没有找到证书,请先在SSL/TLS证书页面中手动上传一次证书");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
|
import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
|
||||||
|
import { MaoyunClient } from "@certd/plugin-plus";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@@ -49,6 +50,45 @@ export class MaoyunAccess extends BaseAccess {
|
|||||||
required: false,
|
required: false,
|
||||||
})
|
})
|
||||||
httpProxy!: string;
|
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();
|
new MaoyunAccess();
|
||||||
|
|||||||
+1
-17
@@ -115,23 +115,7 @@ export class MaoyunDeployToCdn extends AbstractPlusTaskPlugin {
|
|||||||
|
|
||||||
async onGetDomainList() {
|
async onGetDomainList() {
|
||||||
const access: MaoyunAccess = await this.getAccess<MaoyunAccess>(this.accessId);
|
const access: MaoyunAccess = await this.getAccess<MaoyunAccess>(this.accessId);
|
||||||
const client = new MaoyunClient({
|
const list = await access.getCdnDomainList();
|
||||||
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;
|
|
||||||
if (!list || list.length === 0) {
|
if (!list || list.length === 0) {
|
||||||
throw new Error("没有找到加速域名,请先在控制台添加加速域名");
|
throw new Error("没有找到加速域名,请先在控制台添加加速域名");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { HttpRequestConfig } from "@certd/basic";
|
||||||
import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
|
import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,6 +41,48 @@ export class SafelineAccess extends BaseAccess {
|
|||||||
helper: "如果面板的url是https,且使用的是自签名证书,则需要开启此选项,其他情况可以关闭",
|
helper: "如果面板的url是https,且使用的是自签名证书,则需要开启此选项,其他情况可以关闭",
|
||||||
})
|
})
|
||||||
skipSslVerify = true;
|
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();
|
new SafelineAccess();
|
||||||
|
|||||||
+4
-18
@@ -1,9 +1,8 @@
|
|||||||
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
|
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
|
||||||
import { HttpRequestConfig } from "@certd/basic";
|
|
||||||
|
|
||||||
import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert";
|
import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert";
|
||||||
import { SafelineAccess } from "../access.js";
|
|
||||||
import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib";
|
import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib";
|
||||||
|
import { SafelineAccess } from "../access.js";
|
||||||
|
|
||||||
@IsTaskPlugin({
|
@IsTaskPlugin({
|
||||||
name: "SafelineDeployToWebsitePlugin",
|
name: "SafelineDeployToWebsitePlugin",
|
||||||
@@ -83,7 +82,7 @@ export class SafelineDeployToWebsitePlugin extends AbstractTaskPlugin {
|
|||||||
data.id = parseInt(certId)
|
data.id = parseInt(certId)
|
||||||
type = "更新"
|
type = "更新"
|
||||||
}
|
}
|
||||||
const res = await this.doRequest({
|
const res = await this.access.doRequest({
|
||||||
url: "/api/open/cert",
|
url: "/api/open/cert",
|
||||||
method: "post",
|
method: "post",
|
||||||
data:data
|
data:data
|
||||||
@@ -91,25 +90,12 @@ export class SafelineDeployToWebsitePlugin extends AbstractTaskPlugin {
|
|||||||
this.logger.info(`证书<${certId}>${type}成功,ID:${res}`);
|
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
|
// requestHandle
|
||||||
|
|
||||||
async onGetCertIds() {
|
async onGetCertIds() {
|
||||||
const res = await this.doRequest({
|
const res = await this.access.doRequest({
|
||||||
url: "/api/open/cert",
|
url: "/api/open/cert",
|
||||||
method: "get",
|
method: "get",
|
||||||
data: {},
|
data: {},
|
||||||
|
|||||||
+12
-8
@@ -34,11 +34,10 @@ export class SynologyKeepAlivePlugin extends AbstractPlusTaskPlugin {
|
|||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: "间隔天数",
|
title: "间隔天数",
|
||||||
helper: "多少天刷新一次,建议15天以内",
|
helper: "多少天刷新一次,建议15天以内",
|
||||||
|
value: 15,
|
||||||
component: {
|
component: {
|
||||||
name: "number-input",
|
name: "a-input-number",
|
||||||
type: "number",
|
vModel:"value",
|
||||||
min: 1,
|
|
||||||
max: 30,
|
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
@@ -51,7 +50,7 @@ export class SynologyKeepAlivePlugin extends AbstractPlusTaskPlugin {
|
|||||||
lastRefreshTime!: number;
|
lastRefreshTime!: number;
|
||||||
|
|
||||||
async onInstance() {}
|
async onInstance() {}
|
||||||
async execute(): Promise<void> {
|
async execute(): Promise<any> {
|
||||||
this.logger.info("开始刷新群晖登录有效期");
|
this.logger.info("开始刷新群晖登录有效期");
|
||||||
const now = dayjs()
|
const now = dayjs()
|
||||||
const status = this.getLastStatus();
|
const status = this.getLastStatus();
|
||||||
@@ -61,18 +60,23 @@ export class SynologyKeepAlivePlugin extends AbstractPlusTaskPlugin {
|
|||||||
this.lastRefreshTime = lastRefreshTime;
|
this.lastRefreshTime = lastRefreshTime;
|
||||||
const lastTime = dayjs(lastRefreshTime);
|
const lastTime = dayjs(lastRefreshTime);
|
||||||
const diffDays = now.diff(lastTime, "day");
|
const diffDays = now.diff(lastTime, "day");
|
||||||
|
|
||||||
|
this.logger.info(`上次刷新时间${lastTime.format("YYYY-MM-DD")}`);
|
||||||
if (diffDays < this.intervalDays) {
|
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")}`);
|
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 access: SynologyAccess = await this.getAccess<SynologyAccess>(this.accessId);
|
||||||
// const client = new SynologyClient(access as any, this.ctx.http, this.ctx.logger, access.skipSslVerify);
|
// const client = new SynologyClient(access as any, this.ctx.http, this.ctx.logger, access.skipSslVerify);
|
||||||
// await client.doLogin();
|
// await client.doLogin();
|
||||||
// await client.getCertList();
|
// await client.getCertList();
|
||||||
this.lastRefreshTime = now.unix();
|
this.lastRefreshTime = now.valueOf();
|
||||||
this.logger.info("刷新群晖登录有效期成功");
|
this.logger.info("刷新群晖登录有效期成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export class UniCloudAccess extends BaseAccess {
|
|||||||
encrypt: true,
|
encrypt: true,
|
||||||
})
|
})
|
||||||
password = "";
|
password = "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new UniCloudAccess();
|
new UniCloudAccess();
|
||||||
|
|||||||
Generated
+819
-187
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user