mirror of
https://github.com/certd/certd.git
synced 2026-06-10 10:37:34 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a5eff6581 |
@@ -179,10 +179,7 @@ https://certd.handfree.work/
|
||||
2. 您的需求我们将优先实现,并且可能将作为专业版功能提供
|
||||
3. 获得专业版功能
|
||||
|
||||
|
||||
> [50元专业版优惠券限时领取](https://app.handfree.work/subject/#/app/certd/product) https://app.handfree.work/subject/#/app/certd/product
|
||||
> handfree.work是Certd官方激活码购买平台
|
||||
|
||||
[50元专业版优惠券限时领取](https://app.handfree.work/subject/#/app/certd/product)
|
||||
|
||||
专业版、商业版特权对比
|
||||
|
||||
|
||||
@@ -263,4 +263,4 @@ export function createChallengeFn(opts = {}) {
|
||||
|
||||
|
||||
|
||||
// createChallengeFn({logger:{info:console.log}}).walkDnsChallengeRecord("handfree.work")
|
||||
// createChallengeFn({logger:{info:console.log}}).walkDnsChallengeRecord("handsfree.work")
|
||||
|
||||
@@ -4,8 +4,8 @@ VITE_APP_PM_ENABLED=true
|
||||
VITE_APP_TITLE=Certd
|
||||
VITE_APP_SLOGAN=让你的证书永不过期
|
||||
VITE_APP_COPYRIGHT_YEAR=2021-2026
|
||||
VITE_APP_COPYRIGHT_NAME=handfree.work
|
||||
VITE_APP_COPYRIGHT_URL=https://certd.handfree.work
|
||||
VITE_APP_COPYRIGHT_NAME=handsfree.work
|
||||
VITE_APP_COPYRIGHT_URL=https://certd.handsfree.work
|
||||
VITE_APP_LOGO=static/images/logo/logo.svg
|
||||
VITE_APP_LOGIN_LOGO=static/images/logo/rect-black.svg
|
||||
VITE_APP_PROJECT_PATH=https://github.com/certd/certd
|
||||
|
||||
+3
-7
@@ -14,7 +14,7 @@ export default {
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue", "selected-change", "change"],
|
||||
emits: ["update:modelValue", "selected-change"],
|
||||
setup(props: any, ctx: any) {
|
||||
const options = ref<any[]>([]);
|
||||
|
||||
@@ -33,8 +33,7 @@ export default {
|
||||
// if (props.modelValue == null && options.value.length > 0) {
|
||||
// ctx.emit("update:modelValue", options.value[0].value);
|
||||
// }
|
||||
//这里需要一个第一次的selected-change事件,外部表单字段有情况会用到选中的option
|
||||
onSelectedChange(props.modelValue, true);
|
||||
onSelectedChange(props.modelValue);
|
||||
}
|
||||
onCreate();
|
||||
|
||||
@@ -42,12 +41,9 @@ export default {
|
||||
ctx.emit("update:modelValue", value);
|
||||
onSelectedChange(value);
|
||||
}
|
||||
function onSelectedChange(value: any, isFirst: boolean = false) {
|
||||
function onSelectedChange(value: any) {
|
||||
if (value) {
|
||||
const option = options.value.find(item => item.value == value);
|
||||
if (!isFirst) {
|
||||
ctx.emit("change", value);
|
||||
}
|
||||
if (option) {
|
||||
ctx.emit("selected-change", option);
|
||||
return;
|
||||
|
||||
@@ -4,7 +4,7 @@ export default {
|
||||
"The domain name configured here serves as a proxy for verifying other domains. When other domains apply for certificates, they map to this domain via CNAME for ownership verification. The advantage is that any domain can apply for a certificate this way without providing an AccessSecret.",
|
||||
cnameLinkText: "CNAME principle and usage instructions",
|
||||
cnameDomain: "CNAME Domain",
|
||||
cnameDomainPlaceholder: "cname.handfree.work",
|
||||
cnameDomainPlaceholder: "cname.handsfree.work",
|
||||
cnameDomainHelper:
|
||||
"Requires a domain registered with a DNS provider on the right (or you can transfer other domain DNS servers here).\nOnce the CNAME domain is set, it cannot be changed. It is recommended to use a first-level subdomain.",
|
||||
cnameDomainPattern: "Domain name cannot contain *",
|
||||
|
||||
@@ -3,7 +3,7 @@ export default {
|
||||
cnameDescription: "此处配置的域名作为其他域名校验的代理,当别的域名需要申请证书时,通过CNAME映射到此域名上来验证所有权。好处是任何域名都可以通过此方式申请证书,也无需填写AccessSecret。",
|
||||
cnameLinkText: "CNAME功能原理及使用说明",
|
||||
cnameDomain: "CNAME域名",
|
||||
cnameDomainPlaceholder: "cname.handfree.work",
|
||||
cnameDomainPlaceholder: "cname.handsfree.work",
|
||||
cnameDomainHelper: "需要一个右边DNS提供商注册的域名(也可以将其他域名的dns服务器转移到这几家来)。\nCNAME域名一旦确定不可修改,建议使用一级子域名",
|
||||
cnameDomainPattern: "域名不能使用星号",
|
||||
cnameProviderSubdomain: "托管子域名",
|
||||
|
||||
+2
-2
@@ -172,9 +172,9 @@ function useStepForm() {
|
||||
|
||||
const stepTypeSelected = (item: any) => {
|
||||
if (item.needPlus && !settingStore.isPlus) {
|
||||
message.warn("此插件需要开通Certd专业版才能使用");
|
||||
message.warn("此插件需要开通专业版才能使用");
|
||||
mitter.emit("openVipModal");
|
||||
throw new Error("此插件需要开通Certd专业版才能使用");
|
||||
throw new Error("此插件需要开通专业版才能使用");
|
||||
}
|
||||
currentStep.value.type = item.name;
|
||||
currentStep.value.title = item.title;
|
||||
|
||||
@@ -13,7 +13,7 @@ typeorm:
|
||||
|
||||
#plus:
|
||||
# server:
|
||||
# baseUrl: 'https://api.ai.handfree.work'
|
||||
# baseUrl: 'https://api.ai.handsfree.work'
|
||||
|
||||
plus:
|
||||
server:
|
||||
|
||||
@@ -14,7 +14,7 @@ typeorm:
|
||||
|
||||
#plus:
|
||||
# server:
|
||||
# baseUrl: 'https://api.ai.handfree.work'
|
||||
# baseUrl: 'https://api.ai.handsfree.work'
|
||||
|
||||
plus:
|
||||
server:
|
||||
|
||||
@@ -71,7 +71,7 @@ input:
|
||||
},
|
||||
}
|
||||
|
||||
helper: 你在七牛云上配置的CDN加速域名,比如:certd.handfree.work
|
||||
helper: 你在七牛云上配置的CDN加速域名,比如:certd.handsfree.work
|
||||
order: 0
|
||||
output: {}
|
||||
pluginType: deploy
|
||||
|
||||
@@ -10,7 +10,7 @@ desc: 自动部署域名证书至七牛云KODO,注意是自定义源站域名
|
||||
input:
|
||||
domainName:
|
||||
title: 自定义源站域名
|
||||
helper: 你在七牛云上配置的OSS域名,比如:certd.handfree.work
|
||||
helper: 你在七牛云上配置的OSS域名,比如:certd.handsfree.work
|
||||
required: true
|
||||
order: 0
|
||||
cert:
|
||||
|
||||
@@ -60,7 +60,7 @@ export class SysPlusController extends BaseController {
|
||||
// const bindUrl = 'http://127.0.0.1:7001/';
|
||||
// const service = new PlusRequestService({
|
||||
// subjectId: subjectId,
|
||||
// plusServerBaseUrls: ['https://api.ai.handfree.work'],
|
||||
// plusServerBaseUrls: ['https://api.ai.handsfree.work'],
|
||||
// });
|
||||
// const body = { subjectId, appKey: 'kQth6FHM71IPV3qdWc', url: bindUrl };
|
||||
//
|
||||
|
||||
@@ -11,7 +11,7 @@ import { PipelineEntity } from "../../../modules/pipeline/entity/pipeline.js";
|
||||
const pipelineExample = `
|
||||
// 流水线配置示例,实际传送时要去掉注释
|
||||
{
|
||||
"title": "handfree.work证书自动化", //标题
|
||||
"title": "handsfree.work证书自动化", //标题
|
||||
"runnableType": "pipeline", //类型,固定为pipeline
|
||||
"projectId": 1, // 项目ID, 未开启企业模式,无需传递
|
||||
"type": "cert", // 流水线类型,cert:证书自动化, custom :自定义流水线
|
||||
|
||||
+2
-2
@@ -28,12 +28,12 @@ describe("DnsPersistRecordService", () => {
|
||||
const service = new DnsPersistRecordService();
|
||||
|
||||
const record = await service.buildRecord({
|
||||
domain: "aaa.handfree.work",
|
||||
domain: "aaa.handsfree.work",
|
||||
accountUri: "https://example.com/acct/1",
|
||||
});
|
||||
|
||||
assert.equal(record.hostRecord, "_validation-persist.aaa");
|
||||
assert.equal(record.mainDomain, "handfree.work");
|
||||
assert.equal(record.mainDomain, "handsfree.work");
|
||||
assert.equal(record.recordValue, "letsencrypt.org; accounturi=https://example.com/acct/1; policy=wildcard");
|
||||
});
|
||||
|
||||
|
||||
@@ -160,13 +160,9 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||
onSelectedChange: ctx.compute(({form})=>{
|
||||
return ($event)=>{
|
||||
form.dnsProviderAccessType = $event.accessType
|
||||
form.dnsProviderAccess = null
|
||||
}
|
||||
}),
|
||||
onChange: ctx.compute(({form})=>{
|
||||
return ($event)=>{
|
||||
form.dnsProviderAccess = null
|
||||
}
|
||||
}),
|
||||
})
|
||||
},
|
||||
}
|
||||
`,
|
||||
|
||||
@@ -32,7 +32,7 @@ export class CertApplyLegoPlugin extends CertApplyBasePlugin {
|
||||
// vModel: "value",
|
||||
// options: [
|
||||
// { value: "https://acme-v02.api.letsencrypt.org/directory", label: "Let's Encrypt" },
|
||||
// { value: "https://letsencrypt.proxy.handfree.work/directory", label: "Let's Encrypt代理,letsencrypt.org无法访问时使用" },
|
||||
// { value: "https://letsencrypt.proxy.handsfree.work/directory", label: "Let's Encrypt代理,letsencrypt.org无法访问时使用" },
|
||||
// ],
|
||||
// },
|
||||
// required: true,
|
||||
|
||||
@@ -47,53 +47,7 @@ export class HipmDnsmgrAccess extends BaseAccess {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取域名 ID(双层查询策略)
|
||||
* 方案1: 使用 keyword 参数直接查询(高效)
|
||||
* 方案2: 列表匹配作为冗余(兼容旧版本 API)
|
||||
*/
|
||||
async getDomainId(domainName: string): Promise<string> {
|
||||
this.ctx.logger.info(`[HiPM DNSMgr] 尝试通过keyword查询域名: ${domainName}`);
|
||||
|
||||
// 方案1: 使用 keyword 参数直接查询
|
||||
try {
|
||||
const resp = await this.doRequest({
|
||||
method: 'GET',
|
||||
path: '/domains',
|
||||
params: {
|
||||
page: 1,
|
||||
pageSize: 1,
|
||||
keyword: domainName,
|
||||
},
|
||||
});
|
||||
|
||||
// 检查是否找到精确匹配的域名
|
||||
if (resp && Array.isArray(resp) && resp.length > 0) {
|
||||
const domain = resp.find((item: any) => item.name === domainName);
|
||||
if (domain) {
|
||||
this.ctx.logger.info(`[HiPM DNSMgr] 通过keyword查询成功: domain=${domainName}, id=${domain.id}`);
|
||||
return String(domain.id);
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
this.ctx.logger.warn(`[HiPM DNSMgr] keyword查询失败,尝试列表匹配: ${error.message}`);
|
||||
}
|
||||
|
||||
// 方案2: 如果 keyword 查询未找到,使用列表匹配作为冗余
|
||||
this.ctx.logger.info(`[HiPM DNSMgr] keyword查询未找到,尝试列表匹配: ${domainName}`);
|
||||
|
||||
const domainList = await this.getDomainList();
|
||||
const domainInfo = domainList.find((item: any) => item.domain === domainName);
|
||||
|
||||
if (!domainInfo) {
|
||||
throw new Error(`[HiPM DNSMgr] 未找到域名:${domainName}`);
|
||||
}
|
||||
|
||||
this.ctx.logger.info(`[HiPM DNSMgr] 通过列表匹配成功: domain=${domainName}, id=${domainInfo.id}`);
|
||||
return String(domainInfo.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取域名列表(保留用于向后兼容)
|
||||
* 获取域名列表
|
||||
*/
|
||||
async getDomainList() {
|
||||
this.ctx.logger.info(`[HiPM DNSMgr] 获取域名列表`);
|
||||
|
||||
-3
@@ -27,9 +27,6 @@ export class HipmDnsmgrDnsProvider extends AbstractDnsProvider<{ domainId: strin
|
||||
const { fullRecord, hostRecord, value, type, domain } = options;
|
||||
this.logger.info("[HiPM DNSMgr] 添加域名解析:", fullRecord, value, type, domain);
|
||||
|
||||
// 1. 获取域名 ID(双层查询策略)
|
||||
const domainId = await this.access.getDomainId(domain);
|
||||
this.logger.debug('[HiPM DNSMgr] 找到域名:', domain, 'ID:', domainId);
|
||||
// 1. 获取域名列表,找到对应的域名 ID
|
||||
const domainList = await this.access.getDomainList();
|
||||
const domainInfo = domainList.find((item: any) => item.domain === domain);
|
||||
|
||||
@@ -132,7 +132,7 @@ export class HostDeployToIIS extends AbstractPlusTaskPlugin {
|
||||
*
|
||||
* SiteName HttpsBindings
|
||||
* -------- -------------
|
||||
* first *:443:first.handfree.work
|
||||
* first *:443:first.handsfree.work
|
||||
*/
|
||||
// 解析获取网站名称
|
||||
const siteOptions = [];
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ export class CtyunDeployToCDN extends AbstractTaskPlugin {
|
||||
const domain_details = res.domain_details;
|
||||
const errorMessage = "";
|
||||
for (const domainDetail of domain_details) {
|
||||
// "code":200002,"domain":"ctyun.handfree.work","message":"参数cert_name只在https_status为on时才有效"}
|
||||
// "code":200002,"domain":"ctyun.handsfree.work","message":"参数cert_name只在https_status为on时才有效"}
|
||||
if (domainDetail.code !== 100000) {
|
||||
const thisMessage = `部署失败[${domainDetail.code}]:${domainDetail.domain}:${domainDetail.message}`;
|
||||
if (thisMessage.includes("已有进行中的工单") || errorMessage.includes("域名正在操作中")) {
|
||||
|
||||
@@ -47,7 +47,7 @@ export class QiniuDeployCertToCDN extends AbstractTaskPlugin {
|
||||
@TaskInput(
|
||||
createRemoteSelectInputDefine({
|
||||
title: "CDN加速域名",
|
||||
helper: "你在七牛云上配置的CDN加速域名,比如:certd.handfree.work",
|
||||
helper: "你在七牛云上配置的CDN加速域名,比如:certd.handsfree.work",
|
||||
rules: [{ type: "domains", allowDotStart: true }],
|
||||
action: QiniuDeployCertToCDN.prototype.onGetDomainList.name,
|
||||
required: true,
|
||||
|
||||
@@ -17,7 +17,7 @@ import { QiniuAccess, QiniuClient } from "../../plugin-lib/qiniu/index.js";
|
||||
export class QiniuDeployCertToOSS extends AbstractTaskPlugin {
|
||||
@TaskInput({
|
||||
title: "自定义源站域名",
|
||||
helper: "你在七牛云上配置的OSS域名,比如:certd.handfree.work",
|
||||
helper: "你在七牛云上配置的OSS域名,比如:certd.handsfree.work",
|
||||
required: true,
|
||||
})
|
||||
domainName!: string;
|
||||
|
||||
@@ -157,7 +157,7 @@ export class UCloudDeployToCDN extends AbstractTaskPlugin {
|
||||
}
|
||||
|
||||
/**
|
||||
* "Domain": "ucloud.certd.handfree.work",
|
||||
* "Domain": "ucloud.certd.handsfree.work",
|
||||
"DomainId": "ucdn-1kwdtph5ygbb"
|
||||
*/
|
||||
const options = list.map((item: any) => {
|
||||
|
||||
@@ -119,7 +119,7 @@ export class UCloudDeployToWaf extends AbstractTaskPlugin {
|
||||
}
|
||||
|
||||
/**
|
||||
* "Domain": "ucloud.certd.handfree.work",
|
||||
* "Domain": "ucloud.certd.handsfree.work",
|
||||
"DomainId": "ucdn-1kwdtph5ygbb"
|
||||
*/
|
||||
const options = list.map((item: any) => {
|
||||
|
||||
@@ -112,7 +112,7 @@ certificateKey
|
||||
}
|
||||
|
||||
/**
|
||||
* "Domain": "ucloud.certd.handfree.work",
|
||||
* "Domain": "ucloud.certd.handsfree.work",
|
||||
"DomainId": "ucdn-1kwdtph5ygbb"
|
||||
*/
|
||||
const options = list.map((item: any) => {
|
||||
|
||||
Reference in New Issue
Block a user