Compare commits

...

3 Commits

Author SHA1 Message Date
xiaojunnuo 60c8ace443 perf: 支持部署到华为elb 2026-01-29 23:39:57 +08:00
xiaojunnuo 933aaeaf25 chore: cfTurnstile 2026-01-29 22:10:27 +08:00
xiaojunnuo ca43c77525 perf: 验证码支持 Cloudflare Turnstile ,谨慎启用,国内被墙了 2026-01-29 17:21:39 +08:00
22 changed files with 498 additions and 104 deletions
+26 -19
View File
@@ -177,39 +177,40 @@ export function createAxiosService({ logger }: { logger: ILogger }) {
},
(error: any) => {
const status = error.response?.status;
let message = "";
switch (status) {
case 400:
error.message = "请求错误";
message = "请求错误";
break;
case 401:
error.message = "认证/登录失败";
message = "认证/登录失败";
break;
case 403:
error.message = "拒绝访问";
message = "拒绝访问";
break;
case 404:
error.message = `请求地址出错`;
message = `请求地址出错`;
break;
case 408:
error.message = "请求超时";
message = "请求超时";
break;
case 500:
error.message = "服务器内部错误";
message = "服务器内部错误";
break;
case 501:
error.message = "服务未实现";
message = "服务未实现";
break;
case 502:
error.message = "网关错误";
message = "网关错误";
break;
case 503:
error.message = "服务不可用";
message = "服务不可用";
break;
case 504:
error.message = "网关超时";
message = "网关超时";
break;
case 505:
error.message = "HTTP版本不受支持";
message = "HTTP版本不受支持";
break;
case 302:
//重定向
@@ -217,9 +218,12 @@ export function createAxiosService({ logger }: { logger: ILogger }) {
default:
break;
}
if (status) {
message += ` [${status}] `;
}
const errorCode = error.code;
let errorMessage = null;
let errorMessage = "";
if (errorCode === "ECONNABORTED") {
errorMessage = "请求连接终止";
} else if (errorCode === "ETIMEDOUT") {
@@ -231,14 +235,17 @@ export function createAxiosService({ logger }: { logger: ILogger }) {
} else if (errorCode === "ENOTFOUND") {
errorMessage = "请求地址不存在";
}
if (errorMessage) {
if (error.message) {
errorMessage += `,${error.message}`;
}
error.message = errorMessage;
if (errorCode) {
errorMessage += ` [${errorCode}] `;
}
logger.error(`请求出错:${errorMessage} status:${error.response?.status || error.code},statusText:${error.response?.statusText || error.code},url:${error.config?.url},method:${error.config?.method}`);
if (message) {
errorMessage += `,${message}`;
}
if (error.message) {
errorMessage += `(${error.message})`;
}
error.message = errorMessage;
logger.error(`请求出错:${errorMessage} status:${status},statusText:${error.response?.statusText || error.code},url:${error.config?.url},method:${error.config?.method}`);
logger.error("返回数据:", JSON.stringify(error.response?.data));
if (error.response?.data) {
const message = error.response.data.message || error.response.data.msg || error.response.data.error;
@@ -0,0 +1,97 @@
<template>
<div class="cf-turnstile">
<div id="turnstile-container" class="cf-turnstile-container" :data-sitekey="siteKeyRef"></div>
</div>
</template>
<script setup lang="ts">
import { nextTick, onMounted, onUnmounted, ref, watch } from "vue";
import { loadScript } from "vue-plugin-load-script";
const loaded = ref(false);
async function loadCaptchaScript() {
await loadScript("https://challenges.cloudflare.com/turnstile/v0/api.js");
loaded.value = true;
}
defineOptions({
name: "CfTurnstileCaptcha",
});
const emit = defineEmits(["update:modelValue", "change"]);
const props = defineProps<{
modelValue: any;
captchaGet: () => Promise<any>;
}>();
const captchaRef = ref(null);
const siteKeyRef = ref("");
const widgetIdRef = ref(null);
onMounted(async () => {
await loadCaptchaScript();
await nextTick();
const { siteKey } = await props.captchaGet();
siteKeyRef.value = siteKey; //这里确定是string类型
//@ts-ignore
const widgetId = turnstile.render("#turnstile-container", {
sitekey: siteKey,
size: "flexible",
callback: function (token: string) {
console.log("turnstile success:", token);
emitChange({
token: token,
});
},
});
widgetIdRef.value = widgetId;
});
onUnmounted(() => {
//@ts-ignore
if (turnstile && widgetIdRef.value) {
//@ts-ignore
turnstile.remove(widgetIdRef.value);
}
});
function checkExpired() {
//@ts-ignore
if (turnstile && widgetIdRef.value) {
//@ts-ignore
return turnstile.isExpired(widgetIdRef.value);
}
}
function emitChange(value: any) {
emit("update:modelValue", value);
emit("change", value);
}
function reset() {
// 重置验证码
//@ts-ignore
if (turnstile && widgetIdRef.value) {
//@ts-ignore
turnstile.reset(widgetIdRef.value);
}
}
watch(
() => {
return props.modelValue;
},
value => {
if (value == null) {
reset();
}
}
);
defineExpose({
reset,
});
</script>
<style lang="less">
.cf-turnstile-container {
iframe {
width: 100% !important;
}
}
</style>
@@ -11,8 +11,7 @@
</div>
</template>
<script setup lang="ts">
import { defineEmits, defineExpose, defineProps, ref, watch } from "vue";
import { nanoid } from "nanoid";
import { ref, watch } from "vue";
const props = defineProps<{
modelValue: any;
@@ -11,8 +11,8 @@
</div>
</template>
<script setup lang="ts">
import { onMounted, defineProps, defineEmits, ref, onUnmounted, Ref, watch } from "vue";
import { notification } from "ant-design-vue";
import { ref, Ref, watch } from "vue";
import { loadScript } from "vue-plugin-load-script";
const loaded = ref(false);
@@ -455,4 +455,10 @@ h6 {
background: #ffecb3;
color: #f57c00;
}
}
.ant-tag{
.fs-icon{
margin-right: 5px;
}
}
@@ -9,9 +9,11 @@
<addon-selector v-model:model-value="formState.public.captchaAddonId" addon-type="captcha" from="sys" @selected-change="onAddonChanged" />
</a-form-item>
<a-form-item v-if="formState.public.captchaType === settingsStore.sysPublic.captchaType" :label="t('certd.sys.setting.captchaTest')">
<div class="flex">
<CaptchaInput v-model:model-value="captchaTestForm.captcha" class="w-50%"></CaptchaInput>
<a-button class="ml-2" type="primary" @click="doCaptchaValidate">后端验证</a-button>
<div class="flex items-center">
<CaptchaInput v-model:model-value="captchaTestForm.captcha" class="w-60%"></CaptchaInput>
<a-button class="ml-2 mr-2" type="primary" @click="doCaptchaValidate">后端验证</a-button>
<a-tag v-if="captchaTestForm.pass" color="green" class="flex items-center"> <fs-icon icon="material-symbols:check-circle-rounded"></fs-icon> 校验通过</a-tag>
<a-tag v-else class="flex items-center"> <fs-icon icon="material-symbols:info-rounded"></fs-icon> 请先点击验证</a-tag>
</div>
</a-form-item>
+1 -1
View File
@@ -87,7 +87,7 @@ export default ({ command, mode }) => {
host: "0.0.0.0",
port: 3008,
fs: devServerFs,
allowedHosts: ["localhost", "127.0.0.1", "yfy.docmirror.cn"],
allowedHosts: ["localhost", "127.0.0.1", "yfy.docmirror.cn", "docmirror.top", "*"],
proxy: {
// with options
"/api": {
+4 -2
View File
@@ -63,8 +63,10 @@
"@certd/plugin-plus": "^1.38.3",
"@certd/plus-core": "^1.38.3",
"@google-cloud/publicca": "^1.3.0",
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.120",
"@huaweicloud/huaweicloud-sdk-core": "^3.1.120",
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.185",
"@huaweicloud/huaweicloud-sdk-core": "^3.1.185",
"@huaweicloud/huaweicloud-sdk-elb": "^3.1.185",
"@huaweicloud/huaweicloud-sdk-iam": "^3.1.185",
"@koa/cors": "^5.0.0",
"@midwayjs/bootstrap": "3.20.11",
"@midwayjs/cache": "3.14.0",
@@ -1,5 +1,5 @@
import { BaseController, Constants, SysSettingsService } from "@certd/lib-server";
import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core";
import { ALL, Body, Controller, Inject, Post, Provide, Query, RequestIP } from "@midwayjs/core";
import { Rule, RuleType } from "@midwayjs/validate";
import { CaptchaService } from "../../modules/basic/service/captcha-service.js";
import { CodeService } from "../../modules/basic/service/code-service.js";
@@ -62,7 +62,8 @@ export class BasicController extends BaseController {
@Post('/sendSmsCode', { summary: Constants.per.guest })
public async sendSmsCode(
@Body(ALL)
body: SmsCodeReq
body: SmsCodeReq,
@RequestIP() remoteIp: string
) {
const opts = {
verificationType: body.verificationType,
@@ -74,7 +75,7 @@ export class BasicController extends BaseController {
// opts.verificationCodeLength = 6; //部分厂商这里会设置参数长度这里就不改了
}
await this.codeService.checkCaptcha(body.captcha);
await this.codeService.checkCaptcha(body.captcha,{remoteIp});
await this.codeService.sendSmsCode(body.phoneCode, body.mobile, opts);
return this.ok(null);
}
@@ -82,7 +83,8 @@ export class BasicController extends BaseController {
@Post('/sendEmailCode', { summary: Constants.per.guest })
public async sendEmailCode(
@Body(ALL)
body: EmailCodeReq
body: EmailCodeReq,
@RequestIP() remoteIp: string
) {
const opts = {
verificationType: body.verificationType,
@@ -99,7 +101,7 @@ export class BasicController extends BaseController {
}
await this.codeService.checkCaptcha(body.captcha);
await this.codeService.checkCaptcha(body.captcha,{remoteIp});
await this.codeService.sendEmailCode(body.email, opts);
// 设置缓存内容
return this.ok(null);
@@ -1,4 +1,4 @@
import { ALL, Body, Controller, Inject, Post, Provide } from "@midwayjs/core";
import { ALL, Body, Controller, Inject, Post, Provide, RequestIP } from "@midwayjs/core";
import { LoginService } from "../../../modules/login/service/login-service.js";
import { AddonService, BaseController, Constants, SysPublicSettings, SysSettingsService } from "@certd/lib-server";
import { CodeService } from "../../../modules/basic/service/code-service.js";
@@ -26,11 +26,13 @@ export class LoginController extends BaseController {
@Post('/login', { summary: Constants.per.guest })
public async login(
@Body(ALL)
body: any
body: any,
@RequestIP()
remoteIp: string
) {
const settings = await this.sysSettingsService.getPublicSettings()
if (settings.captchaEnabled === true) {
await this.captchaService.doValidate({form:body.captcha,must:false,captchaAddonId:settings.captchaAddonId})
await this.captchaService.doValidate({form:body.captcha,must:false,captchaAddonId:settings.captchaAddonId,req:{remoteIp}})
}
const token = await this.loginService.loginByPassword(body);
this.writeTokenCookie(token);
@@ -1,4 +1,4 @@
import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core';
import { ALL, Body, Controller, Inject, Post, Provide, RequestIP } from '@midwayjs/core';
import { BaseController, Constants, SysSettingsService } from '@certd/lib-server';
import { RegisterType, UserService } from '../../../modules/sys/authority/service/user-service.js';
import { CodeService } from '../../../modules/basic/service/code-service.js';
@@ -32,7 +32,8 @@ export class RegisterController extends BaseController {
@Post('/register', { summary: Constants.per.guest })
public async register(
@Body(ALL)
body: RegisterReq
body: RegisterReq,
@RequestIP() remoteIp: string
) {
const sysPublicSettings = await this.sysSettingsService.getPublicSettings();
if (sysPublicSettings.registerEnabled === false) {
@@ -51,7 +52,7 @@ export class RegisterController extends BaseController {
throw new Error('用户名不能为空');
}
await this.codeService.checkCaptcha(body.captcha);
await this.codeService.checkCaptcha(body.captcha,{remoteIp});
const newUser = await this.userService.register(body.type, {
username: body.username,
password: body.password,
@@ -1,4 +1,4 @@
import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core";
import { ALL, Body, Controller, Inject, Post, Provide, Query, RequestIP } from "@midwayjs/core";
import {
addonRegistry,
AddonService,
@@ -218,8 +218,8 @@ export class SysSettingsController extends CrudController<SysSettingsService> {
@Post("/captchaTest", { summary: "sys:settings:edit" })
async captchaTest(@Body(ALL) body: any) {
await this.codeService.checkCaptcha(body)
async captchaTest(@Body(ALL) body: any,@RequestIP() remoteIp: string) {
await this.codeService.checkCaptcha(body,{remoteIp});
return this.ok({});
}
@@ -1,7 +1,7 @@
import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core";
import { SysSettingsService } from "@certd/lib-server";
import { logger } from "@certd/basic";
import { ICaptchaAddon } from "../../../plugins/plugin-captcha/api.js";
import { CaptchaRequest, ICaptchaAddon } from "../../../plugins/plugin-captcha/api.js";
import { AddonGetterService } from "../../pipeline/service/addon-getter-service.js";
@Provide()
@@ -29,7 +29,7 @@ export class CaptchaService {
}
async doValidate(opts: { form: any, must?: boolean, captchaAddonId?: number }) {
async doValidate(opts: { form: any, must?: boolean, captchaAddonId?: number,req:CaptchaRequest }) {
if (!opts.captchaAddonId) {
const settings = await this.sysSettingsService.getPublicSettings();
opts.captchaAddonId = settings.captchaAddonId ?? 0;
@@ -46,7 +46,7 @@ export class CaptchaService {
if (!opts.form) {
throw new Error("请输入验证码");
}
const res = await addon.onValidate(opts.form);
const res = await addon.onValidate(opts.form,opts.req);
if (!res) {
throw new Error("验证码错误");
}
@@ -5,6 +5,7 @@ import { ISmsService } from '../sms/api.js';
import { SmsServiceFactory } from '../sms/factory.js';
import { CaptchaService } from "./captcha-service.js";
import { EmailService } from './email-service.js';
import { CaptchaRequest } from '../../../plugins/plugin-captcha/api.js';
// {data: '<svg.../svg>', text: 'abcd'}
/**
@@ -25,8 +26,8 @@ export class CodeService {
async checkCaptcha(body:any) {
return await this.captchaService.doValidate({form:body})
async checkCaptcha(body:any,req:CaptchaRequest) {
return await this.captchaService.doValidate({form:body,req});
}
/**
*/
@@ -11,4 +11,5 @@ export * from './deploy-to-esa/index.js';
export * from './deploy-to-vod/index.js';
export * from './deploy-to-apigateway/index.js';
export * from './deploy-to-apig/index.js';
export * from './deploy-to-ack/index.js';
export * from './deploy-to-ack/index.js';
export * from './deploy-to-all/index.js';
@@ -1,4 +1,7 @@
export type CaptchaRequest = {
remoteIp: string,
}
export interface ICaptchaAddon{
onValidate(data?:any):Promise<any>;
onValidate(data?:any,req?:CaptchaRequest):Promise<any>;
getCaptcha():Promise<any>;
}
@@ -0,0 +1,71 @@
import { AddonInput, BaseAddon, IsAddon } from "@certd/lib-server";
import { CaptchaRequest, ICaptchaAddon } from "../api.js";
@IsAddon({
addonType: "captcha",
name: "cfTurnstile",
title: "Cloudflare Turnstile",
desc: "谨慎使用,国内被墙了",
showTest: false,
})
export class CfTurnstileCaptcha extends BaseAddon implements ICaptchaAddon {
@AddonInput({
title: "站点密钥",
component: {
placeholder: "SiteKey",
},
helper: "[Cloudflare Turnstile](https://www.cloudflare.com/zh-cn/application-services/products/turnstile/) -> 添加小组件",
required: true,
})
siteKey = "";
@AddonInput({
title: "密钥",
component: {
placeholder: "SecretKey",
},
required: true,
})
secretKey = "";
async onValidate(data?: any, req?: CaptchaRequest) {
if (!data) {
return false;
}
const { token } = data;
const { remoteIp } = req;
const formData = new FormData();
formData.append('secret', this.secretKey);
formData.append('response', token);
formData.append('remoteip', remoteIp);
const res = await this.http.request({
url: 'https://challenges.cloudflare.com/turnstile/v0/siteverify',
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
data: formData
})
if (res.success) {
// Token is valid - process the form
return true;
} else {
// Token is invalid - reject the submission
const errorMessage = 'Cloudflare Turnstile 校验失败:' + res['error-codes'].join(', ')
this.logger.error(errorMessage);
throw new Error(errorMessage);
}
}
async getCaptcha(): Promise<any> {
return {
siteKey: this.siteKey,
};
}
}
@@ -1,3 +1,4 @@
export * from './geetest/index.js';
export * from './image/index.js';
export * from './tencent/index.js';
export * from './cf-turnstile/index.js';
@@ -1,3 +1,4 @@
import { resetLogConfigure } from '@certd/basic';
import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline';
@IsAccess({
@@ -26,6 +27,26 @@ export class HuaweiAccess extends BaseAccess {
encrypt: true,
})
accessKeySecret = '';
async getProjectList() {
const endpoint = "https://iam.cn-north-4.myhuaweicloud.com";
const { BasicCredentials } = await import('@huaweicloud/huaweicloud-sdk-core');
const iam = await import('@huaweicloud/huaweicloud-sdk-iam/v3/public-api.js');
//恢复华为云把log4j的config改了的问题
resetLogConfigure();
const credentials: any = new BasicCredentials().withAk(this.accessKeyId).withSk(this.accessKeySecret)
const client = iam.IamClient.newBuilder()
.withCredential(credentials)
.withEndpoint(endpoint)
.build();
const request = new iam.KeystoneListAuthProjectsRequest();
const result = await client.keystoneListAuthProjects(request);
return result.projects;
}
}
new HuaweiAccess();
@@ -0,0 +1,151 @@
import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
import { HuaweiAccess } from '../../access/index.js';
import { CertInfo } from '@certd/plugin-cert';
import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from '@certd/plugin-lib';
import { resetLogConfigure } from '@certd/basic';
import { CertApplyPluginNames } from '@certd/plugin-cert';
@IsTaskPlugin({
name: 'HauweiDeployCertToELB',
title: '华为云-部署证书至ELB负载均衡',
icon: 'svg:icon-huawei',
group: pluginGroups.huawei.key,
desc: '',
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
})
export class HauweiDeployCertToELB extends AbstractTaskPlugin {
@TaskInput({
title: '域名证书',
helper: '请选择前置任务输出的域名证书\n如果你选择使用ccm证书ID,则需要在[域名管理页面右上角开启SCM授权](https://console.huaweicloud.com/cdn/#/cdn/domain)',
component: {
name: 'output-selector',
from: [...CertApplyPluginNames],
},
required: true,
})
cert!: CertInfo;
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: 'Access授权',
helper: '华为云授权AccessKeyId、AccessKeySecret',
component: {
name: 'access-selector',
type: 'huawei',
},
required: true,
})
accessId!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: '项目ID',
helper: '请选择项目',
typeName: 'HauweiDeployCertToELB',
action: HauweiDeployCertToELB.prototype.onGetProjectList.name,
multi:false
})
)
projectId!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: 'ELB已有证书',
helper: '请选择域名或输入域名',
typeName: 'HauweiDeployCertToELB',
action: HauweiDeployCertToELB.prototype.onGetCertList.name,
search: true,
})
)
certIds!: string[];
async execute(): Promise<void> {
if (!this.cert) {
throw new Error('域名证书不能为空');
}
this.logger.info('开始部署证书到华为云ELB');
const { elb, client } = await this.getElbClient();
for (const certId of this.certIds) {
this.logger.info('开始更新ELB证书,证书ID' + certId);
let request = new elb.UpdateCertificateRequest(certId);
const certificate = new elb.UpdateCertificateOption()
.withCertificate(this.cert.crt)
.withPrivateKey(this.cert.key);
const body = new elb.UpdateCertificateRequestBody()
.withCertificate(certificate);
request.withBody(body);
await client.updateCertificate(request);
this.logger.info('更新ELB证书完成,证书ID' + certId );
await this.ctx.utils.sleep(2000);
}
this.logger.info('更新ELB证书完成');
}
async onGetProjectList() {
const access = await this.getAccess<HuaweiAccess>(this.accessId);
const projects = await access.getProjectList();
return projects.map(project => {
return {
value: project.id+"_"+project.name,
label: `${project.name}(${project.id})`,
};
});
}
async getElbClient() {
if (!this.projectId) {
throw new Error('项目ID不能为空');
}
const access = await this.getAccess<HuaweiAccess>(this.accessId);
const { BasicCredentials } = await import('@huaweicloud/huaweicloud-sdk-core');
const elb = await import('@huaweicloud/huaweicloud-sdk-elb/v3/public-api.js');
//恢复华为云把log4j的config改了的问题
resetLogConfigure();
const projectArr = this.projectId.split("_");
const projectId = projectArr[0];
const region = projectArr[1];
const credentials: any = new BasicCredentials().withAk(access.accessKeyId).withSk(access.accessKeySecret).withProjectId(projectId);
const client = elb.ElbClient.newBuilder().withCredential(credentials).withEndpoint('https://elb.'+region+'.myhuaweicloud.com').build();
return {
client,
elb,
};
}
async onGetCertList(data: PageSearch) {
const { client, elb } = await this.getElbClient();
const request = new elb.ListCertificatesRequest();
request.limit = 1000;
if (data.searchKey) {
request.withDomain([data.searchKey]);
}
const result = await client.listCertificates(request);
if (!result || !result.certificates || result.certificates.length === 0) {
throw new Error('未找到ELB证书,您可以手动输入');
}
const certs = result.certificates.map(cert => {
return {
value: cert.id,
//@ts-ignore
label: cert.id + '(' + cert.common_name + ')',
domain: cert.domain.split(','),
};
});
return this.ctx.utils.options.buildGroupOptions(certs, this.certDomains);
}
}
new HauweiDeployCertToELB();
@@ -1,3 +1,4 @@
export * from './deploy-to-cdn/index.js'
export * from './upload-to-ccm/index.js'
export * from './deploy-to-obs/index.js'
export * from './deploy-to-elb/index.js'
+81 -55
View File
@@ -49,7 +49,7 @@ importers:
packages/core/acme-client:
dependencies:
'@certd/basic':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../basic
'@peculiar/x509':
specifier: ^1.11.0
@@ -213,10 +213,10 @@ importers:
packages/core/pipeline:
dependencies:
'@certd/basic':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../basic
'@certd/plus-core':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../pro/plus-core
dayjs:
specifier: ^1.11.7
@@ -412,7 +412,7 @@ importers:
packages/libs/lib-k8s:
dependencies:
'@certd/basic':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/basic
'@kubernetes/client-node':
specifier: 0.21.0
@@ -452,19 +452,19 @@ importers:
packages/libs/lib-server:
dependencies:
'@certd/acme-client':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/acme-client
'@certd/basic':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/basic
'@certd/pipeline':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/pipeline
'@certd/plugin-lib':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../plugins/plugin-lib
'@certd/plus-core':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../pro/plus-core
'@midwayjs/cache':
specifier: 3.14.0
@@ -610,16 +610,16 @@ importers:
packages/plugins/plugin-cert:
dependencies:
'@certd/acme-client':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/acme-client
'@certd/basic':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/basic
'@certd/pipeline':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/pipeline
'@certd/plugin-lib':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../plugin-lib
psl:
specifier: ^1.9.0
@@ -683,16 +683,16 @@ importers:
specifier: ^3.964.0
version: 3.964.0(aws-crt@1.26.2)
'@certd/acme-client':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/acme-client
'@certd/basic':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/basic
'@certd/pipeline':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/pipeline
'@certd/plus-core':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../pro/plus-core
'@kubernetes/client-node':
specifier: 0.21.0
@@ -783,16 +783,16 @@ importers:
packages/pro/commercial-core:
dependencies:
'@certd/basic':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/basic
'@certd/lib-server':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../libs/lib-server
'@certd/pipeline':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/pipeline
'@certd/plus-core':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../plus-core
'@midwayjs/core':
specifier: 3.20.11
@@ -865,16 +865,16 @@ importers:
packages/pro/plugin-plus:
dependencies:
'@certd/basic':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/basic
'@certd/pipeline':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/pipeline
'@certd/plugin-lib':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../plugins/plugin-lib
'@certd/plus-core':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../plus-core
crypto-js:
specifier: ^4.2.0
@@ -950,7 +950,7 @@ importers:
packages/pro/plus-core:
dependencies:
'@certd/basic':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/basic
dayjs:
specifier: ^1.11.7
@@ -1246,10 +1246,10 @@ importers:
version: 0.1.3(zod@3.24.4)
devDependencies:
'@certd/lib-iframe':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../libs/lib-iframe
'@certd/pipeline':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/pipeline
'@rollup/plugin-commonjs':
specifier: ^25.0.7
@@ -1438,56 +1438,62 @@ importers:
specifier: ^3.964.0
version: 3.964.0(aws-crt@1.26.2)
'@certd/acme-client':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/acme-client
'@certd/basic':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/basic
'@certd/commercial-core':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../pro/commercial-core
'@certd/cv4pve-api-javascript':
specifier: ^8.4.2
version: 8.4.2
'@certd/jdcloud':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../libs/lib-jdcloud
'@certd/lib-huawei':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../libs/lib-huawei
'@certd/lib-k8s':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../libs/lib-k8s
'@certd/lib-server':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../libs/lib-server
'@certd/midway-flyway-js':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../libs/midway-flyway-js
'@certd/pipeline':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../core/pipeline
'@certd/plugin-cert':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../plugins/plugin-cert
'@certd/plugin-lib':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../plugins/plugin-lib
'@certd/plugin-plus':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../pro/plugin-plus
'@certd/plus-core':
specifier: ^1.38.1
specifier: ^1.38.3
version: link:../../pro/plus-core
'@google-cloud/publicca':
specifier: ^1.3.0
version: 1.3.0(encoding@0.1.13)
'@huaweicloud/huaweicloud-sdk-cdn':
specifier: ^3.1.120
version: 3.1.149
specifier: ^3.1.185
version: 3.1.185
'@huaweicloud/huaweicloud-sdk-core':
specifier: ^3.1.120
version: 3.1.149
specifier: ^3.1.185
version: 3.1.185
'@huaweicloud/huaweicloud-sdk-elb':
specifier: ^3.1.185
version: 3.1.185
'@huaweicloud/huaweicloud-sdk-iam':
specifier: ^3.1.185
version: 3.1.185
'@koa/cors':
specifier: ^5.0.0
version: 5.0.0
@@ -3407,11 +3413,17 @@ packages:
'@httptoolkit/websocket-stream@6.0.1':
resolution: {integrity: sha512-A0NOZI+Glp3Xgcz6Na7i7o09+/+xm2m0UCU8gdtM2nIv6/cjLmhMZMqehSpTlgbx9omtLmV8LVqOskPEyWnmZQ==}
'@huaweicloud/huaweicloud-sdk-cdn@3.1.149':
resolution: {integrity: sha512-orvtJRgJA/KKCmu6jLKxjMLhdxuKEOyeAakQCi3kwgWcbbeQUbRbr+2iMKLqXdM4lCrbOlfe06uqEtC/AG9ZRA==}
'@huaweicloud/huaweicloud-sdk-cdn@3.1.185':
resolution: {integrity: sha512-n4X0TDXpBFUbLFNkHbHbADETT4CG1Z8GgxDyQQrZHVMR3cUS2FnB8IJV1h34MToIB2D68u9ftOBrIjpnfgxIcg==}
'@huaweicloud/huaweicloud-sdk-core@3.1.149':
resolution: {integrity: sha512-5fY87f/z46L4jzB6YPpc3Qq6gt49C4J0//0AV7ELuOfmtstzbuS0O5UmBuTurTtAtsbPgW+08jn42N8Aqa2gGw==}
'@huaweicloud/huaweicloud-sdk-core@3.1.185':
resolution: {integrity: sha512-gSrJ5lFR0mqm5lQxTpSJ+ZIQTI5fzmM7a80ot4zvZ5Ll8T4HfcpcvEgDb/Q6VyZfPEApHo70CsreUe4PHGe8jQ==}
'@huaweicloud/huaweicloud-sdk-elb@3.1.185':
resolution: {integrity: sha512-GKtB/cntti5coam7WBgjhNPzhpr9WdZz5EB2NZO5mFtdQ106ztQa8uIxt04PumFC71nQaC0LbAlAK7JrHVGjrw==}
'@huaweicloud/huaweicloud-sdk-iam@3.1.185':
resolution: {integrity: sha512-uZFsGyFCVYET5RxBW6nwM53ooKmggdkZAOFu8ZHvuVl3chOxPAt35jrEpznvUk7iApIn5XSC62t4DAKIslPFcg==}
'@humanwhocodes/config-array@0.11.14':
resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
@@ -15137,14 +15149,14 @@ snapshots:
- bufferutil
- utf-8-validate
'@huaweicloud/huaweicloud-sdk-cdn@3.1.149':
'@huaweicloud/huaweicloud-sdk-cdn@3.1.185':
dependencies:
'@huaweicloud/huaweicloud-sdk-core': 3.1.149
'@huaweicloud/huaweicloud-sdk-core': 3.1.185
transitivePeerDependencies:
- debug
- supports-color
'@huaweicloud/huaweicloud-sdk-core@3.1.149':
'@huaweicloud/huaweicloud-sdk-core@3.1.185':
dependencies:
axios: 1.9.0(debug@4.4.3)
form-data: 4.0.2
@@ -15159,6 +15171,20 @@ snapshots:
- debug
- supports-color
'@huaweicloud/huaweicloud-sdk-elb@3.1.185':
dependencies:
'@huaweicloud/huaweicloud-sdk-core': 3.1.185
transitivePeerDependencies:
- debug
- supports-color
'@huaweicloud/huaweicloud-sdk-iam@3.1.185':
dependencies:
'@huaweicloud/huaweicloud-sdk-core': 3.1.185
transitivePeerDependencies:
- debug
- supports-color
'@humanwhocodes/config-array@0.11.14':
dependencies:
'@humanwhocodes/object-schema': 2.0.3
@@ -19945,13 +19971,13 @@ snapshots:
resolve: 1.22.10
semver: 6.3.1
eslint-plugin-prettier@3.4.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@7.32.0)(prettier@2.8.8):
eslint-plugin-prettier@3.4.1(eslint-config-prettier@8.10.0(eslint@7.32.0))(eslint@7.32.0)(prettier@2.8.8):
dependencies:
eslint: 7.32.0
prettier: 2.8.8
prettier-linter-helpers: 1.0.0
optionalDependencies:
eslint-config-prettier: 8.10.0(eslint@8.57.0)
eslint-config-prettier: 8.10.0(eslint@7.32.0)
eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8):
dependencies:
@@ -22351,7 +22377,7 @@ snapshots:
eslint: 7.32.0
eslint-config-prettier: 8.10.0(eslint@7.32.0)
eslint-plugin-node: 11.1.0(eslint@7.32.0)
eslint-plugin-prettier: 3.4.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@7.32.0)(prettier@2.8.8)
eslint-plugin-prettier: 3.4.1(eslint-config-prettier@8.10.0(eslint@7.32.0))(eslint@7.32.0)(prettier@2.8.8)
execa: 5.1.1
inquirer: 7.3.3
json5: 2.2.3