mirror of https://github.com/certd/certd
chore:
parent
14cdb54212
commit
d6b3142a02
|
@ -2,8 +2,8 @@ import crypto from 'crypto';
|
|||
|
||||
export class Encryptor {
|
||||
secretKey: Buffer;
|
||||
constructor(encryptSecret: string) {
|
||||
this.secretKey = Buffer.from(encryptSecret, 'base64');
|
||||
constructor(encryptSecret: string, encoding: BufferEncoding = 'base64') {
|
||||
this.secretKey = Buffer.from(encryptSecret, encoding);
|
||||
}
|
||||
// 加密函数
|
||||
encrypt(text: string) {
|
||||
|
|
|
@ -40,6 +40,17 @@ export const certdResources = [
|
|||
cache: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "证书仓库",
|
||||
name: "CertStore",
|
||||
path: "/certd/monitor/cert",
|
||||
component: "/certd/monitor/cert/index.vue",
|
||||
meta: {
|
||||
icon: "ion:shield-checkmark-outline",
|
||||
auth: true,
|
||||
isMenu: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "站点证书监控",
|
||||
name: "SiteCertMonitor",
|
||||
|
@ -80,21 +91,6 @@ export const certdResources = [
|
|||
auth: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "证书仓库",
|
||||
name: "CertStore",
|
||||
path: "/certd/monitor/cert",
|
||||
component: "/certd/monitor/cert/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isPlus;
|
||||
},
|
||||
icon: "ion:shield-checkmark-outline",
|
||||
auth: true,
|
||||
isMenu: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "授权管理",
|
||||
name: "AccessManager",
|
||||
|
@ -106,6 +102,17 @@ export const certdResources = [
|
|||
cache: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "OpenKey",
|
||||
name: "OpenKey",
|
||||
path: "/certd/open/openkey",
|
||||
component: "/certd/open/openkey/index.vue",
|
||||
meta: {
|
||||
icon: "ion:disc-outline",
|
||||
auth: true,
|
||||
cache: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "通知设置",
|
||||
name: "NotificationManager",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { request } from "/src/api/service";
|
||||
|
||||
export function createApi() {
|
||||
const apiPrefix = "/open/cert";
|
||||
const apiPrefix = "/open/key";
|
||||
return {
|
||||
async GetList(query: any) {
|
||||
return await request({
|
||||
|
|
|
@ -3,6 +3,7 @@ import { useI18n } from "vue-i18n";
|
|||
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||
import { pipelineGroupApi } from "./api";
|
||||
import dayjs from "dayjs";
|
||||
import { Modal } from "ant-design-vue";
|
||||
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const { t } = useI18n();
|
||||
|
@ -35,6 +36,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
editRequest,
|
||||
delRequest
|
||||
},
|
||||
search: {
|
||||
show: false
|
||||
},
|
||||
form: {
|
||||
labelCol: {
|
||||
//固定label宽度
|
||||
|
@ -50,15 +54,31 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
width: 600
|
||||
}
|
||||
},
|
||||
actionbar: { show: false },
|
||||
actionbar: {
|
||||
buttons: {
|
||||
add: {
|
||||
text: "生成新的Key",
|
||||
click() {
|
||||
Modal.confirm({
|
||||
title: "确认",
|
||||
content: "确定要生成新的Key?",
|
||||
async onOk() {
|
||||
await api.AddObj({});
|
||||
await crudExpose.doRefresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
rowHandle: {
|
||||
width: 200,
|
||||
fixed: "right",
|
||||
buttons: {
|
||||
view: { show: false },
|
||||
view: { show: true },
|
||||
copy: { show: false },
|
||||
edit: { show: false },
|
||||
remove: { show: false }
|
||||
remove: { show: true }
|
||||
}
|
||||
},
|
||||
columns: {
|
||||
|
@ -79,125 +99,39 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
show: false
|
||||
}
|
||||
},
|
||||
// domain: {
|
||||
// title: "主域名",
|
||||
// search: {
|
||||
// show: true
|
||||
// },
|
||||
// type: "text",
|
||||
// form: {
|
||||
// show: false
|
||||
// },
|
||||
// column: {
|
||||
// width: 180,
|
||||
// sorter: true,
|
||||
// component: {
|
||||
// name: "fs-values-format"
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
domains: {
|
||||
title: "全部域名",
|
||||
keyId: {
|
||||
title: "KeyId",
|
||||
search: {
|
||||
show: false
|
||||
},
|
||||
form: {
|
||||
show: false
|
||||
},
|
||||
type: "text",
|
||||
form: {
|
||||
rules: [{ required: true, message: "请输入域名" }]
|
||||
},
|
||||
column: {
|
||||
width: 450,
|
||||
sorter: true,
|
||||
component: {
|
||||
name: "fs-values-format",
|
||||
color: "auto"
|
||||
}
|
||||
width: 200,
|
||||
sorter: true
|
||||
}
|
||||
},
|
||||
domainCount: {
|
||||
title: "域名数量",
|
||||
type: "number",
|
||||
keySecret: {
|
||||
title: "KeySecret",
|
||||
type: "text",
|
||||
form: {
|
||||
show: false
|
||||
},
|
||||
column: {
|
||||
width: 120,
|
||||
sorter: true,
|
||||
show: false
|
||||
width: 550,
|
||||
sorter: true
|
||||
}
|
||||
},
|
||||
"pipeline.title": {
|
||||
title: "已关联流水线",
|
||||
search: { show: false },
|
||||
type: "link",
|
||||
form: {
|
||||
show: false
|
||||
},
|
||||
column: {
|
||||
width: 280,
|
||||
sorter: true,
|
||||
component: {}
|
||||
}
|
||||
},
|
||||
applyTime: {
|
||||
title: "申请时间",
|
||||
search: {
|
||||
show: false
|
||||
},
|
||||
createTime: {
|
||||
title: "创建时间",
|
||||
type: "datetime",
|
||||
form: {
|
||||
search: {
|
||||
show: false
|
||||
},
|
||||
column: {
|
||||
sorter: true
|
||||
}
|
||||
},
|
||||
expiresTime: {
|
||||
title: "过期时间",
|
||||
search: {
|
||||
show: true
|
||||
},
|
||||
type: "date",
|
||||
form: {
|
||||
show: false
|
||||
},
|
||||
column: {
|
||||
sorter: true,
|
||||
cellRender({ value }) {
|
||||
if (!value) {
|
||||
return "-";
|
||||
}
|
||||
const expireDate = dayjs(value).format("YYYY-MM-DD");
|
||||
const leftDays = dayjs(value).diff(dayjs(), "day");
|
||||
const color = leftDays < 20 ? "red" : "#389e0d";
|
||||
const percent = (leftDays / 90) * 100;
|
||||
return <a-progress title={expireDate + "过期"} percent={percent} strokeColor={color} format={(percent: number) => `${leftDays}天`} />;
|
||||
}
|
||||
}
|
||||
},
|
||||
fromType: {
|
||||
title: "来源",
|
||||
search: {
|
||||
show: true
|
||||
},
|
||||
type: "text",
|
||||
form: { show: false },
|
||||
column: {
|
||||
width: 100,
|
||||
sorter: true
|
||||
}
|
||||
},
|
||||
certProvider: {
|
||||
title: "证书颁发机构",
|
||||
search: {
|
||||
show: true
|
||||
},
|
||||
type: "text",
|
||||
form: {
|
||||
show: false
|
||||
},
|
||||
column: {
|
||||
width: 400
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
<template>
|
||||
<fs-page>
|
||||
<template #header>
|
||||
<div class="title">
|
||||
证书仓库
|
||||
<span class="sub">从流水线生成的证书,后续将支持手动上传证书并部署</span>
|
||||
</div>
|
||||
<div class="title">开放接口密钥管理</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
||||
</fs-page>
|
||||
|
@ -16,7 +13,7 @@ import { useFs } from "@fast-crud/fast-crud";
|
|||
import createCrudOptions from "./crud";
|
||||
import { createApi } from "./api";
|
||||
defineOptions({
|
||||
name: "CertStore"
|
||||
name: "OpenKey"
|
||||
});
|
||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: {} });
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ export class BaseOpenController extends BaseController {
|
|||
const openKey: OpenKey = this.ctx.openKey;
|
||||
if (openKey.encrypt) {
|
||||
const data = JSON.stringify(res);
|
||||
const encryptor = new Encryptor(openKey.keySecret);
|
||||
const encryptor = new Encryptor(openKey.keySecret, 'hex');
|
||||
const encrypted = encryptor.encrypt(data);
|
||||
return this.ok(encrypted);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,8 @@ export class OpenKeyController extends CrudController<OpenKeyService> {
|
|||
}
|
||||
|
||||
@Post('/add', { summary: Constants.per.authOnly })
|
||||
async add(@Body(ALL) bean: any) {
|
||||
async add() {
|
||||
const bean: any = {};
|
||||
bean.userId = this.getUserId();
|
||||
const res = await this.service.add(bean);
|
||||
return this.ok(res);
|
||||
|
|
|
@ -27,30 +27,20 @@ export class OpenKeyService extends BaseService<OpenKeyEntity> {
|
|||
return await super.page(pageReq);
|
||||
}
|
||||
|
||||
async getKey(userId: number) {
|
||||
let entity = await this.getByUserId(userId);
|
||||
if (entity) {
|
||||
return {
|
||||
keyId: entity.keyId,
|
||||
keySecret: entity.keySecret,
|
||||
};
|
||||
}
|
||||
const keyId = utils.id.simpleNanoId(12) + '_key';
|
||||
async add(bean: OpenKeyEntity) {
|
||||
return await this.generate(bean.userId);
|
||||
}
|
||||
|
||||
async generate(userId: number) {
|
||||
const keyId = utils.id.simpleNanoId(18) + '_key';
|
||||
const secretKey = crypto.randomBytes(32);
|
||||
const keySecret = secretKey.toString('base64');
|
||||
entity = new OpenKeyEntity();
|
||||
const keySecret = Buffer.from(secretKey).toString('hex');
|
||||
const entity = new OpenKeyEntity();
|
||||
entity.userId = userId;
|
||||
entity.keyId = keyId;
|
||||
entity.keySecret = keySecret;
|
||||
await this.repository.save(entity);
|
||||
return {
|
||||
keyId: entity.keyId,
|
||||
keySecret: entity.keySecret,
|
||||
};
|
||||
}
|
||||
|
||||
private getByUserId(userId: number) {
|
||||
return this.repository.findOne({ where: { userId } });
|
||||
return entity;
|
||||
}
|
||||
|
||||
async getByKeyId(keyId: string) {
|
||||
|
|
Loading…
Reference in New Issue