mirror of https://github.com/certd/certd
chore:
parent
6877b865a7
commit
87620b9072
|
@ -72,19 +72,19 @@ export const Constants = {
|
||||||
},
|
},
|
||||||
openKeyError: {
|
openKeyError: {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
message: 'openKey错误',
|
message: 'ApiToken错误',
|
||||||
},
|
},
|
||||||
openKeySignError: {
|
openKeySignError: {
|
||||||
code: 20001,
|
code: 20001,
|
||||||
message: 'openKey签名错误',
|
message: 'ApiToken签名错误',
|
||||||
},
|
},
|
||||||
openKeyExpiresError: {
|
openKeyExpiresError: {
|
||||||
code: 20002,
|
code: 20002,
|
||||||
message: 'openKey时间戳错误',
|
message: 'ApiToken时间戳错误',
|
||||||
},
|
},
|
||||||
openKeySignTypeError: {
|
openKeySignTypeError: {
|
||||||
code: 20003,
|
code: 20003,
|
||||||
message: 'openKey签名类型不支持',
|
message: 'ApiToken签名类型不支持',
|
||||||
},
|
},
|
||||||
openParamError: {
|
openParamError: {
|
||||||
code: 20010,
|
code: 20010,
|
||||||
|
@ -94,5 +94,9 @@ export const Constants = {
|
||||||
code: 20011,
|
code: 20011,
|
||||||
message: '证书不存在',
|
message: '证书不存在',
|
||||||
},
|
},
|
||||||
|
openCertNotReady: {
|
||||||
|
code: 20012,
|
||||||
|
message: '证书还未生成',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
* 异常基类
|
* 异常基类
|
||||||
*/
|
*/
|
||||||
export class BaseException extends Error {
|
export class BaseException extends Error {
|
||||||
status: number;
|
code: number;
|
||||||
constructor(name, code, message) {
|
constructor(name, code, message) {
|
||||||
super(message);
|
super(message);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.status = code;
|
this.code = code;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ export class Result<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
static error(code = 1, msg) {
|
static error(code = 1, msg) {
|
||||||
return new Result(code, msg, null);
|
return new Result(code, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static success(msg, data?) {
|
static success(msg, data?) {
|
||||||
|
|
|
@ -126,32 +126,6 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
show: false
|
show: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pipeline.title": {
|
|
||||||
title: "已关联流水线",
|
|
||||||
search: { show: false },
|
|
||||||
type: "link",
|
|
||||||
form: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
column: {
|
|
||||||
width: 280,
|
|
||||||
sorter: true,
|
|
||||||
component: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
applyTime: {
|
|
||||||
title: "申请时间",
|
|
||||||
search: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
type: "datetime",
|
|
||||||
form: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
column: {
|
|
||||||
sorter: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
expiresTime: {
|
expiresTime: {
|
||||||
title: "过期时间",
|
title: "过期时间",
|
||||||
search: {
|
search: {
|
||||||
|
@ -175,18 +149,6 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fromType: {
|
|
||||||
title: "来源",
|
|
||||||
search: {
|
|
||||||
show: true
|
|
||||||
},
|
|
||||||
type: "text",
|
|
||||||
form: { show: false },
|
|
||||||
column: {
|
|
||||||
width: 100,
|
|
||||||
sorter: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
certProvider: {
|
certProvider: {
|
||||||
title: "证书颁发机构",
|
title: "证书颁发机构",
|
||||||
search: {
|
search: {
|
||||||
|
@ -197,7 +159,33 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 400
|
width: 200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
applyTime: {
|
||||||
|
title: "申请时间",
|
||||||
|
search: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
type: "datetime",
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
sorter: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pipeline.title": {
|
||||||
|
title: "已关联流水线",
|
||||||
|
search: { show: false },
|
||||||
|
type: "link",
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 350,
|
||||||
|
sorter: true,
|
||||||
|
component: {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,10 +42,11 @@ export function createApi() {
|
||||||
params: { id }
|
params: { id }
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async ListAll() {
|
async GetApiToken(id: number) {
|
||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/all",
|
url: apiPrefix + "/getApiToken",
|
||||||
method: "post"
|
method: "post",
|
||||||
|
data: { id }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,13 +72,30 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
rowHandle: {
|
rowHandle: {
|
||||||
width: 200,
|
width: 300,
|
||||||
fixed: "right",
|
fixed: "right",
|
||||||
buttons: {
|
buttons: {
|
||||||
view: { show: true },
|
view: { show: true },
|
||||||
copy: { show: false },
|
copy: { show: false },
|
||||||
edit: { show: false },
|
edit: { show: false },
|
||||||
remove: { show: true }
|
remove: { show: true },
|
||||||
|
gen: {
|
||||||
|
text: "测试ApiToken",
|
||||||
|
async click({ row }) {
|
||||||
|
const apiToken = await api.GetApiToken(row.id);
|
||||||
|
Modal.info({
|
||||||
|
title: "ApiToken",
|
||||||
|
content: () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>测试ApiKey如下,您可以在3分钟内使用它进行开放接口请求测试</div>
|
||||||
|
<div>{apiToken}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
columns: {
|
columns: {
|
||||||
|
|
|
@ -19,7 +19,6 @@ import * as libServer from '@certd/lib-server';
|
||||||
import * as commercial from '@certd/commercial-core';
|
import * as commercial from '@certd/commercial-core';
|
||||||
import * as upload from '@midwayjs/upload';
|
import * as upload from '@midwayjs/upload';
|
||||||
import { setLogger } from '@certd/acme-client';
|
import { setLogger } from '@certd/acme-client';
|
||||||
|
|
||||||
process.on('uncaughtException', error => {
|
process.on('uncaughtException', error => {
|
||||||
console.error('未捕获的异常:', error);
|
console.error('未捕获的异常:', error);
|
||||||
// 在这里可以添加日志记录、发送错误通知等操作
|
// 在这里可以添加日志记录、发送错误通知等操作
|
||||||
|
|
|
@ -10,6 +10,6 @@ export class BaseOpenController extends BaseController {
|
||||||
const encrypted = encryptor.encrypt(data);
|
const encrypted = encryptor.encrypt(data);
|
||||||
return this.ok(encrypted);
|
return this.ok(encrypted);
|
||||||
}
|
}
|
||||||
super.ok(res);
|
return super.ok(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@ import { OpenKey } from '../../../modules/open/service/open-key-service.js';
|
||||||
import { BaseOpenController } from '../base-open-controller.js';
|
import { BaseOpenController } from '../base-open-controller.js';
|
||||||
|
|
||||||
export type CertGetReq = {
|
export type CertGetReq = {
|
||||||
domains: string;
|
domains?: string;
|
||||||
|
certId: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,17 +26,13 @@ export class OpenCertController extends BaseOpenController {
|
||||||
const openKey: OpenKey = this.ctx.openKey;
|
const openKey: OpenKey = this.ctx.openKey;
|
||||||
const userId = openKey.userId;
|
const userId = openKey.userId;
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
return Constants.res.openKeyError;
|
throw new CodeException(Constants.res.openKeyError);
|
||||||
}
|
}
|
||||||
|
|
||||||
const domains = bean.domains || query.domains;
|
|
||||||
if (!domains) {
|
|
||||||
throw new CodeException(Constants.res.openParamError);
|
|
||||||
}
|
|
||||||
const domainArr = domains.split(',');
|
|
||||||
const res: CertInfo = await this.certInfoService.getCertInfo({
|
const res: CertInfo = await this.certInfoService.getCertInfo({
|
||||||
userId,
|
userId,
|
||||||
domains: domainArr,
|
domains: bean.domains || query.domains,
|
||||||
|
certId: bean.certId || query.certId,
|
||||||
});
|
});
|
||||||
return this.ok(res);
|
return this.ok(res);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,4 +62,11 @@ export class OpenKeyController extends CrudController<OpenKeyService> {
|
||||||
await this.service.checkUserId(id, this.getUserId());
|
await this.service.checkUserId(id, this.getUserId());
|
||||||
return await super.delete(id);
|
return await super.delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('/getApiToken', { summary: Constants.per.authOnly })
|
||||||
|
async getApiToken(@Query('id') id: number) {
|
||||||
|
await this.service.checkUserId(id, this.getUserId());
|
||||||
|
const token = await this.service.getApiToken(id);
|
||||||
|
return this.ok(token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,8 +88,7 @@ export class AuthorityMiddleware implements IWebMiddleware {
|
||||||
|
|
||||||
async doOpenHandler(ctx: IMidwayKoaContext, next: Next) {
|
async doOpenHandler(ctx: IMidwayKoaContext, next: Next) {
|
||||||
//开放接口
|
//开放接口
|
||||||
let openKey = ctx.get('Authorization') || '';
|
const openKey = ctx.get('x-api-token') || '';
|
||||||
openKey = openKey.replace('Bearer ', '').trim();
|
|
||||||
if (!openKey) {
|
if (!openKey) {
|
||||||
ctx.status = 401;
|
ctx.status = 401;
|
||||||
ctx.body = Constants.res.auth;
|
ctx.body = Constants.res.auth;
|
||||||
|
|
|
@ -72,10 +72,29 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCertInfo(param: { domains: string[]; userId: number }) {
|
async getCertInfo(params: { domains?: string; certId?: number; userId: number }) {
|
||||||
const { domains, userId } = param;
|
const { domains, certId, userId } = params;
|
||||||
|
if (certId) {
|
||||||
|
return await this.getCertInfoById({ id: certId, userId });
|
||||||
|
}
|
||||||
|
return await this.getCertInfoByDomains({
|
||||||
|
domains,
|
||||||
|
userId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getCertInfoByDomains(params: { domains: string; userId: number }) {
|
||||||
|
const { domains, userId } = params;
|
||||||
|
if (!domains) {
|
||||||
|
throw new CodeException(Constants.res.openCertNotFound);
|
||||||
|
}
|
||||||
|
const domainArr = domains.split(',');
|
||||||
|
|
||||||
const list = await this.find({
|
const list = await this.find({
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
domains: true,
|
||||||
|
},
|
||||||
where: {
|
where: {
|
||||||
userId,
|
userId,
|
||||||
},
|
},
|
||||||
|
@ -83,12 +102,25 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
||||||
//遍历查找
|
//遍历查找
|
||||||
const matched = list.find(item => {
|
const matched = list.find(item => {
|
||||||
const itemDomains = item.domains.split(',');
|
const itemDomains = item.domains.split(',');
|
||||||
return utils.domain.match(domains, itemDomains);
|
return utils.domain.match(domainArr, itemDomains);
|
||||||
});
|
});
|
||||||
if (!matched || !matched.certInfo) {
|
if (!matched) {
|
||||||
throw new CodeException(Constants.res.openCertNotFound);
|
throw new CodeException(Constants.res.openCertNotFound);
|
||||||
}
|
}
|
||||||
const certInfo = JSON.parse(matched.certInfo) as CertInfo;
|
|
||||||
|
return await this.getCertInfoById({ id: matched.id, userId: userId });
|
||||||
|
}
|
||||||
|
|
||||||
|
async getCertInfoById(req: { id: number; userId: number }) {
|
||||||
|
const entity = await this.info(req.id);
|
||||||
|
if (!entity || entity.userId !== req.userId) {
|
||||||
|
throw new CodeException(Constants.res.openCertNotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!entity.certInfo) {
|
||||||
|
throw new CodeException(Constants.res.openCertNotReady);
|
||||||
|
}
|
||||||
|
const certInfo = JSON.parse(entity.certInfo) as CertInfo;
|
||||||
const certReader = new CertReader(certInfo);
|
const certReader = new CertReader(certInfo);
|
||||||
return certReader.toCertInfo();
|
return certReader.toCertInfo();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { Repository } from 'typeorm';
|
||||||
import { OpenKeyEntity } from '../entity/open-key.js';
|
import { OpenKeyEntity } from '../entity/open-key.js';
|
||||||
import { utils } from '@certd/basic';
|
import { utils } from '@certd/basic';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
export type OpenKey = {
|
export type OpenKey = {
|
||||||
userId: number;
|
userId: number;
|
||||||
|
@ -85,4 +86,21 @@ export class OpenKeyService extends BaseService<OpenKeyEntity> {
|
||||||
encrypt: encrypt,
|
encrypt: encrypt,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getApiToken(id: number) {
|
||||||
|
const entity = await this.repository.findOne({ where: { id } });
|
||||||
|
if (!entity) {
|
||||||
|
throw new Error('id不存在');
|
||||||
|
}
|
||||||
|
const { keyId, keySecret } = entity;
|
||||||
|
const openKey = {
|
||||||
|
keyId,
|
||||||
|
t: dayjs().unix(),
|
||||||
|
encrypt: false,
|
||||||
|
signType: 'md5',
|
||||||
|
};
|
||||||
|
const content = JSON.stringify(openKey);
|
||||||
|
const sign = utils.hash.md5(content + keySecret);
|
||||||
|
return Buffer.from(content).toString('base64') + '.' + sign;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue