perf: 文件名特殊字符限制输入

pull/229/head
xiaojunnuo 2024-10-25 22:49:05 +08:00
parent a90d1e68ee
commit c4164c66e2
4 changed files with 65 additions and 11 deletions

View File

@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
import { isDomain } from "/@/plugin/validator"; import { isDomain, isFilePath } from "/@/plugin/validator";
describe("domain_validator", () => { describe("domain_validator", () => {
it("ok", () => { it("ok", () => {
@ -41,4 +41,35 @@ describe("domain_validator", () => {
value = [".cc.com"]; value = [".cc.com"];
expect(test).to.throw(Error, "域名有误:.cc.com请输入正确的域名"); expect(test).to.throw(Error, "域名有误:.cc.com请输入正确的域名");
}); });
it("isFilePath", () => {
let value = "/a/$/bc";
function test() {
return isFilePath({}, value);
}
expect(test()).to.be.true;
value = "/a/&/bc";
expect(test()).to.be.true;
//*?“<>|等特殊字符
value = "/a/&/b>c.txt";
const errorMessage = '文件名不能包含*?"<>|等特殊字符';
expect(test).to.throw(Error, errorMessage);
value = "/a/&/b<c.txt";
expect(test).to.throw(Error, errorMessage);
value = "/a/&/b|c.txt";
expect(test).to.throw(Error, errorMessage);
value = "/a/&/b?c.txt";
expect(test).to.throw(Error, errorMessage);
value = "/a/&/b*c.txt";
expect(test).to.throw(Error, errorMessage);
});
}); });

View File

@ -21,5 +21,18 @@ export function isDomain(rule: any, value: any) {
} }
return true; return true;
} }
// 注册自定义验证器 // 注册自定义验证器
Validator.register("domains", isDomain); Validator.register("domains", isDomain);
export function isFilePath(rule: any, value: any) {
if (value == null) {
return true;
}
// 文件名不能用*?"<>|等特殊符号
if (!/^[^*?"<>|]*$/.test(value)) {
throw new Error(`文件名不能包含*?"<>|等特殊字符`);
}
return true;
}
Validator.register("filepath", isFilePath);

View File

@ -19,46 +19,51 @@ import path from 'path';
export class CopyCertToLocalPlugin extends AbstractTaskPlugin { export class CopyCertToLocalPlugin extends AbstractTaskPlugin {
@TaskInput({ @TaskInput({
title: '证书保存路径', title: '证书保存路径',
helper: '全链证书,路径要包含文件名,文件名不能用*?!等特殊符号' + '\n推荐使用相对路径将写入与数据库同级目录无需映射例如./tmp/cert.pem', helper: '全链证书,路径要包含文件名' + '\n推荐使用相对路径将写入与数据库同级目录无需映射例如./tmp/cert.pem',
component: { component: {
placeholder: './tmp/full_chain.pem', placeholder: './tmp/full_chain.pem',
}, },
rules: [{ type: 'filepath' }],
}) })
crtPath!: string; crtPath!: string;
@TaskInput({ @TaskInput({
title: '私钥保存路径', title: '私钥保存路径',
helper: '路径要包含文件名,文件名不能用*?!等特殊符号\n推荐使用相对路径将写入与数据库同级目录无需映射例如./tmp/cert.key', helper: '路径要包含文件名\n推荐使用相对路径将写入与数据库同级目录无需映射例如./tmp/cert.key',
component: { component: {
placeholder: './tmp/cert.key', placeholder: './tmp/cert.key',
}, },
rules: [{ type: 'filepath' }],
}) })
keyPath!: string; keyPath!: string;
@TaskInput({ @TaskInput({
title: '中间证书保存路径', title: '中间证书保存路径',
helper: '一般情况传上面两个文件就行了,极少数情况需要这个中间证书', helper: '路径要包含文件名,一般情况传上面两个文件就行了,极少数情况需要这个中间证书',
component: { component: {
placeholder: '/root/deploy/nginx/intermediate.pem', placeholder: '/root/deploy/nginx/intermediate.pem',
}, },
rules: [{ type: 'filepath' }],
}) })
icPath!: string; icPath!: string;
@TaskInput({ @TaskInput({
title: 'PFX证书保存路径', title: 'PFX证书保存路径',
helper: '用于IIS证书部署路径要包含文件名,文件名不能用*?!等特殊符号\n推荐使用相对路径将写入与数据库同级目录无需映射例如./tmp/cert.pfx', helper: '用于IIS证书部署路径要包含文件名\n推荐使用相对路径将写入与数据库同级目录无需映射例如./tmp/cert.pfx',
component: { component: {
placeholder: './tmp/cert.pfx', placeholder: './tmp/cert.pfx',
}, },
rules: [{ type: 'filepath' }],
}) })
pfxPath!: string; pfxPath!: string;
@TaskInput({ @TaskInput({
title: 'DER证书保存路径', title: 'DER证书保存路径',
helper: helper:
'用户Apache证书部署路径要包含文件名文件名不能用*?!等特殊符号\n推荐使用相对路径将写入与数据库同级目录无需映射例如./tmp/cert.der\n.der和.cer是相同的东西改个后缀名即可', '用于Apache证书部署路径要包含文件名\n推荐使用相对路径将写入与数据库同级目录无需映射例如./tmp/cert.der\n.der和.cer是相同的东西改个后缀名即可',
component: { component: {
placeholder: './tmp/cert.der 或 ./tmp/cert.cer', placeholder: './tmp/cert.der 或 ./tmp/cert.cer',
}, },
rules: [{ type: 'filepath' }],
}) })
derPath!: string; derPath!: string;

View File

@ -20,45 +20,50 @@ import dayjs from 'dayjs';
export class UploadCertToHostPlugin extends AbstractTaskPlugin { export class UploadCertToHostPlugin extends AbstractTaskPlugin {
@TaskInput({ @TaskInput({
title: '证书保存路径', title: '证书保存路径',
helper: '全链证书,需要有写入权限,路径要包含证书文件名,文件名不能用*?!等特殊符号,例如:/tmp/cert.pem', helper: '全链证书,需要有写入权限,路径要包含证书文件名,例如:/tmp/cert.pem',
component: { component: {
placeholder: '/root/deploy/nginx/full_chain.pem', placeholder: '/root/deploy/nginx/full_chain.pem',
}, },
rules: [{ type: 'filepath' }],
}) })
crtPath!: string; crtPath!: string;
@TaskInput({ @TaskInput({
title: '私钥保存路径', title: '私钥保存路径',
helper: '需要有写入权限,路径要包含私钥文件名,文件名不能用*?!等特殊符号,例如:/tmp/cert.key', helper: '需要有写入权限,路径要包含私钥文件名,例如:/tmp/cert.key',
component: { component: {
placeholder: '/root/deploy/nginx/cert.key', placeholder: '/root/deploy/nginx/cert.key',
}, },
rules: [{ type: 'filepath' }],
}) })
keyPath!: string; keyPath!: string;
@TaskInput({ @TaskInput({
title: '中间证书保存路径', title: '中间证书保存路径',
helper: '一般情况传上面两个文件即可,极少数情况需要这个中间证书', helper: '路径要包含文件名,一般情况传上面两个文件即可,极少数情况需要这个中间证书',
component: { component: {
placeholder: '/root/deploy/nginx/intermediate.pem', placeholder: '/root/deploy/nginx/intermediate.pem',
}, },
rules: [{ type: 'filepath' }],
}) })
icPath!: string; icPath!: string;
@TaskInput({ @TaskInput({
title: 'PFX证书保存路径', title: 'PFX证书保存路径',
helper: '用于IIS证书部署需要有写入权限路径要包含私钥文件名,文件名不能用*?!等特殊符号,例如:/tmp/cert.pfx', helper: '用于IIS证书部署需要有写入权限路径要包含证书文件名,例如:/tmp/cert.pfx',
component: { component: {
placeholder: '/root/deploy/nginx/cert.pfx', placeholder: '/root/deploy/nginx/cert.pfx',
}, },
rules: [{ type: 'filepath' }],
}) })
pfxPath!: string; pfxPath!: string;
@TaskInput({ @TaskInput({
title: 'DER证书保存路径', title: 'DER证书保存路径',
helper: '用于Apache证书部署需要有写入权限路径要包含私钥文件名,文件名不能用*?!等特殊符号,例如:/tmp/cert.der', helper: '用于Apache证书部署需要有写入权限路径要包含证书文件名,例如:/tmp/cert.der',
component: { component: {
placeholder: '/root/deploy/nginx/cert.der', placeholder: '/root/deploy/nginx/cert.der',
}, },
rules: [{ type: 'filepath' }],
}) })
derPath!: string; derPath!: string;