chore: project fix

This commit is contained in:
xiaojunnuo
2026-03-04 23:53:19 +08:00
parent 17dd77cc96
commit 5ee3874b7e
14 changed files with 48 additions and 48 deletions
+7 -3
View File
@@ -170,9 +170,7 @@ export abstract class AbstractTaskPlugin implements ITaskPlugin {
} }
if (this.ctx?.define?.onlyAdmin) { if (this.ctx?.define?.onlyAdmin) {
if (!this.isAdmin()) { this.checkAdmin();
throw new Error("只有管理员才能运行此任务");
}
} }
} }
@@ -284,6 +282,12 @@ export abstract class AbstractTaskPlugin implements ITaskPlugin {
return this.ctx.user.role === "admin"; return this.ctx.user.role === "admin";
} }
checkAdmin() {
if (!this.isAdmin()) {
throw new Error("只有“管理员”或“系统级项目”才有权限运行此插件任务");
}
}
getStepFromPipeline(stepId: string) { getStepFromPipeline(stepId: string) {
let found: any = null; let found: any = null;
RunnableCollection.each(this.ctx.pipeline.stages, step => { RunnableCollection.each(this.ctx.pipeline.stages, step => {
@@ -734,7 +734,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
}), }),
}, },
column: { column: {
width: 100, width: 140,
sorter: true, sorter: true,
align: "center", align: "center",
}, },
@@ -757,7 +757,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
helper: t("monitor.ipSyncModeHelper"), helper: t("monitor.ipSyncModeHelper"),
}, },
column: { column: {
width: 100, width: 140,
sorter: true, sorter: true,
align: "center", align: "center",
}, },
@@ -779,7 +779,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
helper: t("monitor.ipIgnoreCoherenceHelper"), helper: t("monitor.ipIgnoreCoherenceHelper"),
}, },
column: { column: {
width: 100, width: 180,
sorter: true, sorter: true,
align: "center", align: "center",
}, },
@@ -16,13 +16,16 @@ import { useCertViewer } from "/@/views/certd/pipeline/use";
import { useI18n } from "/src/locales"; import { useI18n } from "/src/locales";
import { useDicts } from "../dicts"; import { useDicts } from "../dicts";
import { useProjectStore } from "/@/store/project"; import { useProjectStore } from "/@/store/project";
import { useCrudPermission } from "/@/plugin/permission";
export default function ({ crudExpose, context: { selectedRowKeys, openCertApplyDialog, hasActionPermission } }: CreateCrudOptionsProps): CreateCrudOptionsRet { export default function ({ crudExpose, context: { selectedRowKeys, openCertApplyDialog, permission } }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const router = useRouter(); const router = useRouter();
const lastResRef = ref(); const lastResRef = ref();
const { t } = useI18n(); const { t } = useI18n();
const { hasActionPermission } = useCrudPermission({ permission });
const { openUploadCreateDialog } = useCertUpload(); const { openUploadCreateDialog } = useCertUpload();
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => { const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
@@ -104,7 +104,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
helper: t("certd.ent.isSystemHelper"), helper: t("certd.ent.isSystemHelper"),
}, },
column: { column: {
width: 100, width: 150,
}, },
}, },
adminId: { adminId: {
@@ -20,8 +20,6 @@ export class CnameProviderController extends BaseController {
@Post('/list', { summary: Constants.per.authOnly }) @Post('/list', { summary: Constants.per.authOnly })
async list(@Body(ALL) body: any) { async list(@Body(ALL) body: any) {
body.query = body.query ?? {};
body.query.userId = this.getUserId();
const res = await this.providerService.list({}); const res = await this.providerService.list({});
return this.ok(res); return this.ok(res);
} }
@@ -67,50 +67,51 @@ export class CnameRecordController extends CrudController<CnameRecordService> {
@Post('/info', { summary: Constants.per.authOnly }) @Post('/info', { summary: Constants.per.authOnly })
async info(@Query('id') id: number) { async info(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "read");
return super.info(id); return super.info(id);
} }
@Post('/delete', { summary: Constants.per.authOnly }) @Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id: number) { async delete(@Query('id') id: number) {
await this.service.checkUserId(id, this.getUserId()); await this.checkOwner(this.getService(), id, "write");
return super.delete(id); return super.delete(id);
} }
@Post('/deleteByIds', { summary: Constants.per.authOnly }) @Post('/deleteByIds', { summary: Constants.per.authOnly })
async deleteByIds(@Body(ALL) body: any) { async deleteByIds(@Body(ALL) body: any) {
const {userId,projectId} = await this.getProjectUserIdWrite();
await this.service.delete(body.ids, { await this.service.delete(body.ids, {
userId: this.getUserId(), userId,
projectId,
}); });
return this.ok(); return this.ok();
} }
@Post('/getByDomain', { summary: Constants.per.authOnly }) @Post('/getByDomain', { summary: Constants.per.authOnly })
async getByDomain(@Body(ALL) body: { domain: string; createOnNotFound: boolean }) { async getByDomain(@Body(ALL) body: { domain: string; createOnNotFound: boolean }) {
const userId = this.getUserId(); const {userId,projectId} = await this.getProjectUserIdRead();
const res = await this.service.getByDomain(body.domain, userId, body.createOnNotFound); const res = await this.service.getByDomain(body.domain, userId,projectId, body.createOnNotFound);
return this.ok(res); return this.ok(res);
} }
@Post('/verify', { summary: Constants.per.authOnly }) @Post('/verify', { summary: Constants.per.authOnly })
async verify(@Body(ALL) body: { id: number }) { async verify(@Body(ALL) body: { id: number }) {
const userId = this.getUserId(); await this.checkOwner(this.getService(), body.id, "read");
await this.service.checkUserId(body.id, userId);
const res = await this.service.verify(body.id); const res = await this.service.verify(body.id);
return this.ok(res); return this.ok(res);
} }
@Post('/resetStatus', { summary: Constants.per.authOnly }) @Post('/resetStatus', { summary: Constants.per.authOnly })
async resetStatus(@Body(ALL) body: { id: number }) { async resetStatus(@Body(ALL) body: { id: number }) {
const userId = this.getUserId(); await this.checkOwner(this.getService(), body.id, "read");
await this.service.checkUserId(body.id, userId);
const res = await this.service.resetStatus(body.id); const res = await this.service.resetStatus(body.id);
return this.ok(res); return this.ok(res);
} }
@Post('/import', { summary: Constants.per.authOnly }) @Post('/import', { summary: Constants.per.authOnly })
async import(@Body(ALL) body: { domainList: string; cnameProviderId: any }) { async import(@Body(ALL) body: { domainList: string; cnameProviderId: any }) {
const userId = this.getUserId(); const {userId,projectId} = await this.getProjectUserIdWrite();
const res = await this.service.doImport({ const res = await this.service.doImport({
userId, userId,
projectId,
domainList: body.domainList, domainList: body.domainList,
cnameProviderId: body.cnameProviderId, cnameProviderId: body.cnameProviderId,
}); });
@@ -164,8 +164,8 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
// // 3. 检查原域名是否有cname记录 // // 3. 检查原域名是否有cname记录
// } // }
async getWithAccessByDomain(domain: string, userId: number) { async getWithAccessByDomain(domain: string, userId: number,projectId?:number) {
const record: CnameRecord = await this.getByDomain(domain, userId); const record: CnameRecord = await this.getByDomain(domain, userId,projectId);
if (record.cnameProvider.id > 0) { if (record.cnameProvider.id > 0) {
//自定义cname服务 //自定义cname服务
record.cnameProvider.access = await this.accessService.getAccessById(record.cnameProvider.accessId, false); record.cnameProvider.access = await this.accessService.getAccessById(record.cnameProvider.accessId, false);
@@ -179,17 +179,17 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
return record; return record;
} }
async getByDomain(domain: string, userId: number, createOnNotFound = true) { async getByDomain(domain: string, userId: number,projectId?:number, createOnNotFound = true) {
if (!domain) { if (!domain) {
throw new ValidateException("domain不能为空"); throw new ValidateException("domain不能为空");
} }
if (userId == null) { if (userId == null) {
throw new ValidateException("userId不能为空"); throw new ValidateException("userId不能为空");
} }
let record = await this.getRepository().findOne({ where: { domain, userId } }); let record = await this.getRepository().findOne({ where: { domain, userId,projectId } });
if (record == null) { if (record == null) {
if (createOnNotFound) { if (createOnNotFound) {
record = await this.add({ domain, userId }); record = await this.add({ domain, userId,projectId });
} else { } else {
throw new ValidateException(`找不到${domain}的CNAME记录`); throw new ValidateException(`找不到${domain}的CNAME记录`);
} }
@@ -489,8 +489,8 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
await this.getRepository().update(id, { status: "cname", mainDomain: "" }); await this.getRepository().update(id, { status: "cname", mainDomain: "" });
} }
async doImport(req:{ userId: number; domainList: string; cnameProviderId: any }) { async doImport(req:{ userId: number; projectId: number; domainList: string; cnameProviderId: any }) {
const {userId,cnameProviderId,domainList} = req; const {userId,projectId,cnameProviderId,domainList} = req;
const domains = domainList.split("\n").map(item => item.trim()).filter(item => item.length > 0); const domains = domainList.split("\n").map(item => item.trim()).filter(item => item.length > 0);
if (domains.length === 0) { if (domains.length === 0) {
throw new ValidateException("域名列表不能为空"); throw new ValidateException("域名列表不能为空");
@@ -504,18 +504,19 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
key: "user_"+userId, key: "user_"+userId,
title: "导入CNAME记录", title: "导入CNAME记录",
run: async (task) => { run: async (task) => {
await this._import({ userId, domains, cnameProviderId },task); await this._import({ userId,projectId, domains, cnameProviderId },task);
} }
})); }));
} }
async _import(req :{ userId: number; domains: string[]; cnameProviderId: any },task:BackTask) { async _import(req :{ userId: number; projectId: number; domains: string[]; cnameProviderId: any },task:BackTask) {
const userId = req.userId; const userId = req.userId;
for (const domain of req.domains) { for (const domain of req.domains) {
const old = await this.getRepository().findOne({ const old = await this.getRepository().findOne({
where: { where: {
userId: req.userId, userId: req.userId,
domain, domain,
projectId: req.projectId,
}, },
}); });
if (old) { if (old) {
@@ -526,6 +527,7 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
await this.add({ await this.add({
userId, userId,
domain: domain, domain: domain,
projectId: req.projectId,
cnameProviderId: req.cnameProviderId, cnameProviderId: req.cnameProviderId,
}); });
}catch(e){ }catch(e){
@@ -2,13 +2,15 @@ import { CnameRecord, ICnameProxyService } from '@certd/pipeline';
export class CnameProxyService implements ICnameProxyService { export class CnameProxyService implements ICnameProxyService {
userId: number; userId: number;
getter: <T>(domain: string, userId?: number) => Promise<T>; projectId: number;
constructor(userId: number, getter: (domain: string, userId: number) => Promise<any>) { getter: <T>(domain: string, userId?: number, projectId?: number) => Promise<T>;
constructor(userId: number, projectId: number, getter: (domain: string, userId: number, projectId: number) => Promise<any>) {
this.userId = userId; this.userId = userId;
this.projectId = projectId;
this.getter = getter; this.getter = getter;
} }
async getByDomain(domain: string): Promise<CnameRecord> { async getByDomain(domain: string): Promise<CnameRecord> {
return await this.getter<CnameRecord>(domain, this.userId); return await this.getter<CnameRecord>(domain, this.userId, this.projectId);
} }
} }
@@ -59,7 +59,7 @@ export class TaskServiceGetter implements IServiceGetter{
async getCnameProxyService(): Promise<CnameProxyService> { async getCnameProxyService(): Promise<CnameProxyService> {
const cnameRecordService:CnameRecordService = await this.appCtx.getAsync("cnameRecordService") const cnameRecordService:CnameRecordService = await this.appCtx.getAsync("cnameRecordService")
return new CnameProxyService(this.userId, cnameRecordService.getWithAccessByDomain.bind(cnameRecordService)); return new CnameProxyService(this.userId, this.projectId, cnameRecordService.getWithAccessByDomain.bind(cnameRecordService));
} }
async getNotificationService(): Promise<NotificationGetter> { async getNotificationService(): Promise<NotificationGetter> {
@@ -157,9 +157,7 @@ export class DBBackupPlugin extends AbstractPlusTaskPlugin {
async onInstance() {} async onInstance() {}
async execute(): Promise<void> { async execute(): Promise<void> {
if (!this.isAdmin()) { this.checkAdmin();
throw new Error("只有管理员才能运行此任务");
}
this.logger.info("开始备份数据库"); this.logger.info("开始备份数据库");
@@ -32,9 +32,7 @@ export class DeployToCertdPlugin extends AbstractTaskPlugin {
cert!: CertInfo; cert!: CertInfo;
async onInstance() { } async onInstance() { }
async execute(): Promise<void> { async execute(): Promise<void> {
if (!this.isAdmin()) { this.checkAdmin();
throw new Error('只有管理员才能运行此任务');
}
//部署证书 //部署证书
let crtPath = "ssl/cert.crt"; let crtPath = "ssl/cert.crt";
@@ -17,9 +17,7 @@ import { httpsServer } from '../../modules/auto/https/server.js';
export class RestartCertdPlugin extends AbstractTaskPlugin { export class RestartCertdPlugin extends AbstractTaskPlugin {
async onInstance() {} async onInstance() {}
async execute(): Promise<void> { async execute(): Promise<void> {
if (!this.isAdmin()) { this.checkAdmin();
throw new Error('只有管理员才能运行此任务');
}
this.logger.info('Certd https server 将在 3 秒后重启'); this.logger.info('Certd https server 将在 3 秒后重启');
await this.ctx.utils.sleep(3000); await this.ctx.utils.sleep(3000);
await httpsServer.restart(); await httpsServer.restart();
@@ -47,9 +47,7 @@ export class CustomScriptPlugin extends AbstractTaskPlugin {
async onInstance() {} async onInstance() {}
async execute(): Promise<void> { async execute(): Promise<void> {
if (!this.isAdmin()) { this.checkAdmin();
throw new Error('只有管理员才能运行此任务');
}
this.logger.info('执行自定义脚本:\n', this.script); this.logger.info('执行自定义脚本:\n', this.script);
const ctx: CustomScriptContext = { const ctx: CustomScriptContext = {
CertReader, CertReader,
@@ -198,9 +198,7 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin {
fs.copyFileSync(srcFile, destFile); fs.copyFileSync(srcFile, destFile);
} }
async execute(): Promise<void> { async execute(): Promise<void> {
if (!this.isAdmin()) { this.checkAdmin();
throw new Error('只有管理员才能运行此任务');
}
let { crtPath, keyPath, icPath, pfxPath, derPath, jksPath } = this; let { crtPath, keyPath, icPath, pfxPath, derPath, jksPath } = this;
const certReader = new CertReader(this.cert); const certReader = new CertReader(this.cert);