From 638a7f0ab4e64c53514bfaed8ff8eec0f628aa7f Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Wed, 11 Feb 2026 18:11:33 +0800 Subject: [PATCH] chore: history projectId --- package.json | 18 +-- .../lib-server/src/basic/base-controller.ts | 15 +++ .../libs/lib-server/src/basic/base-service.ts | 18 ++- .../certd-client/src/store/project/index.ts | 9 +- .../ui/certd-client/src/views/certd/dicts.ts | 2 + .../src/views/certd/pipeline/crud.tsx | 3 + .../db/migration/v10038__admin_mode.sql | 3 +- packages/ui/certd-server/package.json | 8 +- .../user/pipeline/history-controller.ts | 85 +++++++++----- .../user/pipeline/pipeline-controller.ts | 50 ++------ .../pipeline/service/history-service.ts | 3 +- .../pipeline/service/pipeline-service.ts | 20 +++- .../sys/authority/service/auth-service.ts | 8 +- .../sys/authority/service/role-service.ts | 19 +-- .../sys/enterprise/service/project-service.ts | 109 +++++++++++------- 15 files changed, 224 insertions(+), 146 deletions(-) diff --git a/package.json b/package.json index 798617d7b..e8d0d1c68 100644 --- a/package.json +++ b/package.json @@ -15,25 +15,25 @@ }, "scripts": { "start": "lerna bootstrap --hoist", - "start:server": "cd ./packages/ui/certd-server && npm start", + "start:server": "cd ./packages/ui/certd-server && pnpm start", "devb": "lerna run dev-build", "i-all": "lerna link && lerna exec npm install ", - "publish": "npm run prepublishOnly2 && lerna publish --force-publish=pro/plus-core --conventional-commits && npm run afterpublishOnly ", - "afterpublishOnly": "npm run copylogs && time /t >trigger/build.trigger && git add ./trigger/build.trigger && git commit -m \"build: trigger build image\" && TIMEOUT /T 10 && npm run commitAll", + "publish": "pnpm run prepublishOnly2 && lerna publish --force-publish=pro/plus-core --conventional-commits && pnpm run afterpublishOnly ", + "afterpublishOnly": "pnpm run copylogs && time /t >trigger/build.trigger && git add ./trigger/build.trigger && git commit -m \"build: trigger build image\" && TIMEOUT /T 10 && pnpm run commitAll", "transform-sql": "cd ./packages/ui/certd-server/db/ && node --experimental-json-modules transform.js", - "plugin-doc-gen": "cd ./packages/ui/certd-server/ && npm run export-metadata", - "commitAll": "git add . && git commit -m \"build: publish\" && git push && npm run commitPro", + "plugin-doc-gen": "cd ./packages/ui/certd-server/ && pnpm run export-metadata", + "commitAll": "git add . && git commit -m \"build: publish\" && git push && pnpm run commitPro", "commitPro": "cd ./packages/pro/ && git add . && git commit -m \"build: publish\" && git push", "copylogs": "copyfiles \"CHANGELOG.md\" ./docs/guide/changelogs/", - "prepublishOnly1": "npm run check && lerna run build ", - "prepublishOnly2": "npm run check && npm run before-build && lerna run build && npm run plugin-doc-gen", - "before-build": "npm run transform-sql && cd ./packages/core/basic && time /t >build.md && git add ./build.md && git commit -m \"build: prepare to build\"", + "prepublishOnly1": "pnpm run check && lerna run build ", + "prepublishOnly2": "pnpm run check && pnpm run before-build && lerna run build && pnpm run plugin-doc-gen", + "before-build": "pnpm run transform-sql && cd ./packages/core/basic && time /t >build.md && git add ./build.md && git commit -m \"build: prepare to build\"", "deploy1": "node --experimental-json-modules ./scripts/deploy.js ", "check": "node --experimental-json-modules ./scripts/publish-check.js", "init": "lerna run build", "init:dev": "lerna run build", "docs:dev": "vitepress dev docs", - "docs:build": "npm run copylogs && vitepress build docs", + "docs:build": "pnpm run copylogs && vitepress build docs", "docs:preview": "vitepress preview docs", "pub": "echo 1", "dev": "pnpm run -r --parallel compile ", diff --git a/packages/libs/lib-server/src/basic/base-controller.ts b/packages/libs/lib-server/src/basic/base-controller.ts index 26920077a..b618e3cde 100644 --- a/packages/libs/lib-server/src/basic/base-controller.ts +++ b/packages/libs/lib-server/src/basic/base-controller.ts @@ -100,5 +100,20 @@ export abstract class BaseController { await projectService.checkPermission({userId,projectId,permission}) } + /** + * + * @param service 检查记录是否属于某用户或某项目 + * @param id + */ + async checkEntityOwner(service:any,id:number,permission:string){ + let { projectId,userId } = await this.getProjectUserId(permission) + const authService:any = await this.applicationContext.getAsync("authService"); + if (projectId) { + await authService.checkEntityProjectId(service, id, projectId); + }else{ + await authService.checkEntityUserId(this.ctx, service, id); + } + return {projectId,userId} + } } diff --git a/packages/libs/lib-server/src/basic/base-service.ts b/packages/libs/lib-server/src/basic/base-service.ts index eed4ecc32..8efd4416c 100644 --- a/packages/libs/lib-server/src/basic/base-service.ts +++ b/packages/libs/lib-server/src/basic/base-service.ts @@ -206,18 +206,28 @@ export abstract class BaseService { return await qb.getMany(); } - async checkUserId(id: any = 0, userId: number, userKey = 'userId') { - const res = await this.getRepository().findOne({ + async checkUserId(ids: number | number[] = 0, userId: number, userKey = 'userId') { + if (ids == null) { + throw new ValidateException('id不能为空'); + } + if (userId == null) { + throw new ValidateException('userId不能为空'); + } + if (!Array.isArray(ids)) { + ids = [ids]; + } + const res = await this.getRepository().find({ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore select: { [userKey]: true }, where: { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - id, + id: In(ids), + [userKey]: userId, }, }); - if (!res || res[userKey] === userId) { + if (!res || res.length === ids.length) { return; } throw new PermissionException('权限不足'); diff --git a/packages/ui/certd-client/src/store/project/index.ts b/packages/ui/certd-client/src/store/project/index.ts index 156daba07..e8884a4e5 100644 --- a/packages/ui/certd-client/src/store/project/index.ts +++ b/packages/ui/certd-client/src/store/project/index.ts @@ -52,12 +52,17 @@ export const useProjectStore = defineStore("app.project", () => { } const projects = await api.MyProjectList(); myProjects.value = projects; + if (projects.length > 0 && !currentProjectId.value) { + changeCurrentProject(projects[0].id, true); + } } - function changeCurrentProject(id: string) { + function changeCurrentProject(id: string, silent?: boolean) { currentProjectId.value = id; LocalStorage.set("currentProjectId", id); - message.success("切换项目成功"); + if (!silent) { + message.success("切换项目成功"); + } } async function reload() { diff --git a/packages/ui/certd-client/src/views/certd/dicts.ts b/packages/ui/certd-client/src/views/certd/dicts.ts index dd6bfd0dc..afe870457 100644 --- a/packages/ui/certd-client/src/views/certd/dicts.ts +++ b/packages/ui/certd-client/src/views/certd/dicts.ts @@ -19,6 +19,8 @@ export const projectPermissionDict = dict({ export const myProjectDict = dict({ url: "/enterprise/project/list", + value: "id", + label: "name", }); export const userDict = dict({ diff --git a/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx b/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx index 7c2823295..d6608553c 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx @@ -640,6 +640,9 @@ export default function ({ crudExpose, context: { selectedRowKeys, openCertApply title: t("certd.fields.projectName"), type: "dict-select", dict: myProjectDict, + form: { + show: false, + }, }, updateTime: { title: t("certd.fields.updateTime"), diff --git a/packages/ui/certd-server/db/migration/v10038__admin_mode.sql b/packages/ui/certd-server/db/migration/v10038__admin_mode.sql index 74b691b29..f768b8543 100644 --- a/packages/ui/certd-server/db/migration/v10038__admin_mode.sql +++ b/packages/ui/certd-server/db/migration/v10038__admin_mode.sql @@ -13,8 +13,7 @@ CREATE TABLE "cd_project" CREATE INDEX "index_project_user_id" ON "cd_project" ("user_id"); CREATE INDEX "index_project_admin_id" ON "cd_project" ("admin_id"); -INSERT INTO cd_project (id, user_id, "name", "disabled") VALUES (1, 1, 'default', false); - +INSERT INTO cd_project (id, user_id, "admin_id", "name", "disabled") VALUES (1, 0, 1,'default', false); ALTER TABLE cd_cert_info ADD COLUMN project_id integer; CREATE INDEX "index_cert_project_id" ON "cd_cert_info" ("project_id"); diff --git a/packages/ui/certd-server/package.json b/packages/ui/certd-server/package.json index 4387bb78f..34af08f3e 100644 --- a/packages/ui/certd-server/package.json +++ b/packages/ui/certd-server/package.json @@ -19,16 +19,16 @@ "dev-new": "cross-env NODE_ENV=dev-new mwtsc --watch --run @midwayjs/mock/app", "rm-newdb": "rimraf ./data/db-new.sqlite", "test": "cross-env NODE_ENV=unittest mocha", - "cov": "cross-env c8 --all --reporter=text --reporter=lcovonly npm run test", + "cov": "cross-env c8 --all --reporter=text --reporter=lcovonly pnpm run test", "lint": "mwts check", "lint:fix": "mwts fix", - "ci": "npm run cov", + "ci": "pnpm run cov", "build-only": "cross-env NODE_ENV=production mwtsc --cleanOutDir --skipLibCheck", - "build": "npm run build-only && npm run export-metadata", + "build": "pnpm run build-only && pnpm run export-metadata", "export-metadata": "node export-plugin-yaml.js", "export-metadata-only": "node export-plugin-yaml.js docoff", "dev-build": "echo 1", - "build-on-docker": "node ./before-build.js && npm run build-only && npm run export-metadata-only", + "build-on-docker": "node ./before-build.js && pnpm run build-only && pnpm run export-metadata-only", "up-mw-deps": "npx midway-version -u -w", "heap": "cross-env NODE_ENV=production clinic heapprofiler -- node --optimize-for-size --inspect ./bootstrap.js", "flame": "clinic flame -- node ./bootstrap.js", diff --git a/packages/ui/certd-server/src/controller/user/pipeline/history-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/history-controller.ts index 9e8076c76..272e79d92 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/history-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/history-controller.ts @@ -1,17 +1,17 @@ -import { ALL, Body, Controller, Get, Inject, Post, Provide, Query } from "@midwayjs/core"; -import { CommonException, Constants, CrudController, PermissionException, SysSettingsService } from "@certd/lib-server"; -import { PipelineEntity } from "../../../modules/pipeline/entity/pipeline.js"; -import { HistoryService } from "../../../modules/pipeline/service/history-service.js"; -import { HistoryLogService } from "../../../modules/pipeline/service/history-log-service.js"; -import { HistoryEntity } from "../../../modules/pipeline/entity/history.js"; -import { HistoryLogEntity } from "../../../modules/pipeline/entity/history-log.js"; -import { PipelineService } from "../../../modules/pipeline/service/pipeline-service.js"; -import * as fs from "fs"; import { logger } from "@certd/basic"; -import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; +import { CommonException, Constants, CrudController, PermissionException, SysSettingsService } from "@certd/lib-server"; +import { ALL, Body, Controller, Get, Inject, Post, Provide, Query } from "@midwayjs/core"; +import * as fs from "fs"; import { In } from "typeorm"; -import { UserSettingsService } from "../../../modules/mine/service/user-settings-service.js"; import { UserGrantSetting } from "../../../modules/mine/service/models.js"; +import { UserSettingsService } from "../../../modules/mine/service/user-settings-service.js"; +import { HistoryLogEntity } from "../../../modules/pipeline/entity/history-log.js"; +import { HistoryEntity } from "../../../modules/pipeline/entity/history.js"; +import { PipelineEntity } from "../../../modules/pipeline/entity/pipeline.js"; +import { HistoryLogService } from "../../../modules/pipeline/service/history-log-service.js"; +import { HistoryService } from "../../../modules/pipeline/service/history-service.js"; +import { PipelineService } from "../../../modules/pipeline/service/pipeline-service.js"; +import { AuthService } from "../../../modules/sys/authority/service/auth-service.js"; /** * 证书 @@ -41,12 +41,18 @@ export class HistoryController extends CrudController { @Post('/page', { summary: Constants.per.authOnly }) async page(@Body(ALL) body: any) { + const { projectId, userId } = await this.getProjectUserIdRead() + body.query.projectId = projectId + const isAdmin = await this.authService.isAdmin(this.ctx); const publicSettings = await this.sysSettingsService.getPublicSettings(); const pipelineQuery: any = {}; if (!(publicSettings.managerOtherUserPipeline && isAdmin)) { - body.query.userId = this.getUserId(); - pipelineQuery.userId = this.getUserId(); + body.query.userId = userId; + pipelineQuery.userId = userId; + } + if (projectId) { + pipelineQuery.projectId = projectId; } let pipelineIds: any = null; @@ -82,10 +88,14 @@ export class HistoryController extends CrudController { @Post('/list', { summary: Constants.per.authOnly }) async list(@Body(ALL) body) { + const { projectId, userId } = await this.getProjectUserIdRead() + body.query.projectId = projectId + const isAdmin = this.authService.isAdmin(this.ctx); if (!isAdmin) { - body.userId = this.getUserId(); + body.userId = userId; } + if (body.pipelineId == null) { return this.ok([]); } @@ -106,7 +116,8 @@ export class HistoryController extends CrudController { triggerType: true, endTime: true, createTime: true, - updateTime: true + updateTime: true, + projectId: true, }; } const listRet = await this.getService().list({ @@ -135,32 +146,45 @@ export class HistoryController extends CrudController { @Post('/add', { summary: Constants.per.authOnly }) async add(@Body(ALL) bean: PipelineEntity) { - bean.userId = this.getUserId(); + const { projectId, userId } = await this.getProjectUserIdRead() + bean.projectId = projectId + bean.userId = userId; return super.add(bean); } @Post('/update', { summary: Constants.per.authOnly }) async update(@Body(ALL) bean) { - await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id); + await this.checkEntityOwner(this.getService(), bean.id,"write"); delete bean.userId; return super.update(bean); } @Post('/save', { summary: Constants.per.authOnly }) async save(@Body(ALL) bean: HistoryEntity) { - bean.userId = this.getUserId(); + const { projectId,userId } = await this.getProjectUserIdWrite() + bean.userId = userId; + bean.projectId = projectId; if (bean.id > 0) { - await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id); + //修改 + delete bean.projectId; + delete bean.userId; + await this.checkEntityOwner(this.getService(), bean.id,"write"); } + await this.service.save(bean); return this.ok(bean.id); } @Post('/saveLog', { summary: Constants.per.authOnly }) async saveLog(@Body(ALL) bean: HistoryLogEntity) { - bean.userId = this.getUserId(); + const { projectId,userId } = await this.getProjectUserIdWrite() + bean.projectId = projectId; + bean.userId = userId; if (bean.id > 0) { - await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id); + //修改 + delete bean.projectId; + delete bean.userId; + await this.checkEntityOwner(this.logService, bean.id,"write"); } await this.logService.save(bean); return this.ok(bean.id); @@ -168,30 +192,30 @@ export class HistoryController extends CrudController { @Post('/delete', { summary: Constants.per.authOnly }) async delete(@Query('id') id: number) { - await this.authService.checkEntityUserId(this.ctx, this.getService(), id); + await this.checkEntityOwner(this.getService(), id,"write"); await super.delete(id); return this.ok(); } @Post('/deleteByIds', { summary: Constants.per.authOnly }) async deleteByIds(@Body(ALL) body: any) { - await this.authService.checkEntityUserId(this.ctx, this.getService(), body.ids); + let {userId} = await this.checkEntityOwner(this.getService(), body.ids,"write"); const isAdmin = await this.authService.isAdmin(this.ctx); - const userId = isAdmin ? null : this.getUserId(); + userId = isAdmin ? null : userId; await this.getService().deleteByIds(body.ids, userId); return this.ok(); } @Post('/detail', { summary: Constants.per.authOnly }) async detail(@Query('id') id: number) { - await this.authService.checkEntityUserId(this.ctx, this.getService(), id); + await this.checkEntityOwner(this.getService(), id,"read"); const detail = await this.service.detail(id); return this.ok(detail); } @Post('/logs', { summary: Constants.per.authOnly }) async logs(@Query('id') id: number) { - await this.authService.checkEntityUserId(this.ctx, this.logService, id); + await this.checkEntityOwner(this.logService, id,"read"); const logInfo = await this.logService.info(id); return this.ok(logInfo); } @@ -213,7 +237,14 @@ export class HistoryController extends CrudController { if (history == null) { throw new CommonException('historyId is null'); } - if (history.userId !== this.getUserId()) { + const {projectId} = await this.getProjectUserIdRead() + if (projectId) { + //enterprise模式 + if(history.projectId !== projectId){ + throw new PermissionException("您没有权限下载该流水线证书,请先加入该项目:"+history.projectId); + } + //有权限下载 + }else if (history.userId !== this.getUserId()) { // 如果是管理员,检查用户是否有授权管理员查看 const isAdmin = await this.isAdmin() if (!isAdmin) { diff --git a/packages/ui/certd-server/src/controller/user/pipeline/pipeline-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/pipeline-controller.ts index 2d671a307..cc40999b6 100644 --- a/packages/ui/certd-server/src/controller/user/pipeline/pipeline-controller.ts +++ b/packages/ui/certd-server/src/controller/user/pipeline/pipeline-controller.ts @@ -95,25 +95,16 @@ export class PipelineController extends CrudController { @Post('/update', { summary: Constants.per.authOnly }) async update(@Body(ALL) bean) { - const { projectId } = await this.getProjectUserIdWrite() - if (projectId) { - await this.authService.checkEntityProjectId(this.getService(), projectId, bean.id); - } else { - await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id); - } + await this.checkEntityOwner(this.getService(), bean.id,"write"); delete bean.userId; return super.update(bean); } @Post('/save', { summary: Constants.per.authOnly }) async save(@Body(ALL) bean: { addToMonitorEnabled: boolean, addToMonitorDomains: string } & PipelineEntity) { - const { projectId, userId } = await this.getProjectUserIdWrite() + const { userId } = await this.getProjectUserIdWrite() if (bean.id > 0) { - if (projectId) { - await this.authService.checkEntityProjectId(this.getService(), projectId, bean.id); - } else { - await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id); - } + await this.checkEntityOwner(this.getService(), bean.id,"write"); } else { bean.userId = userId; } @@ -140,24 +131,14 @@ export class PipelineController extends CrudController { @Post('/delete', { summary: Constants.per.authOnly }) async delete(@Query('id') id: number) { - const { projectId } = await this.getProjectUserIdWrite() - if (projectId) { - await this.authService.checkEntityProjectId(this.getService(), projectId, id); - } else { - await this.authService.checkEntityUserId(this.ctx, this.getService(), id); - } + await this.checkEntityOwner(this.getService(), id,"write"); await this.service.delete(id); return this.ok({}); } @Post('/disabled', { summary: Constants.per.authOnly }) async disabled(@Body(ALL) bean) { - const { projectId } = await this.getProjectUserIdWrite() - if (projectId) { - await this.authService.checkEntityProjectId(this.getService(), projectId, bean.id); - } else { - await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id); - } + await this.checkEntityOwner(this.getService(), bean.id,"write"); delete bean.userId; await this.service.disabled(bean.id, bean.disabled); return this.ok({}); @@ -165,36 +146,21 @@ export class PipelineController extends CrudController { @Post('/detail', { summary: Constants.per.authOnly }) async detail(@Query('id') id: number) { - const { projectId } = await this.getProjectUserIdRead() - if (projectId) { - await this.authService.checkEntityProjectId(this.getService(), projectId, id); - } else { - await this.authService.checkEntityUserId(this.ctx, this.getService(), id); - } + await this.checkEntityOwner(this.getService(), id,"read"); const detail = await this.service.detail(id); return this.ok(detail); } @Post('/trigger', { summary: Constants.per.authOnly }) async trigger(@Query('id') id: number, @Query('stepId') stepId?: string) { - const { projectId } = await this.getProjectUserIdWrite() - if (projectId) { - await this.authService.checkEntityProjectId(this.getService(), projectId, id); - } else { - await this.authService.checkEntityUserId(this.ctx, this.getService(), id); - } + await this.checkEntityOwner(this.getService(), id,"write"); await this.service.trigger(id, stepId, true); return this.ok({}); } @Post('/cancel', { summary: Constants.per.authOnly }) async cancel(@Query('historyId') historyId: number) { - const { projectId } = await this.getProjectUserIdWrite() - if (projectId) { - await this.authService.checkEntityProjectId(this.historyService, projectId, historyId); - } else { - await this.authService.checkEntityUserId(this.ctx, this.historyService, historyId); - } + await this.checkEntityOwner(this.historyService, historyId,"write"); await this.service.cancel(historyId); return this.ok({}); } diff --git a/packages/ui/certd-server/src/modules/pipeline/service/history-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/history-service.ts index 5829f8f0d..296569c07 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/history-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/history-service.ts @@ -66,7 +66,8 @@ export class HistoryService extends BaseService { pipelineId: pipeline.id, title: pipeline.title, status: 'start', - triggerType + triggerType, + projectId: pipeline.projectId, }; const { id } = await this.add(bean); //清除大于pipeline.keepHistoryCount的历史记录 diff --git a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts index d06f0dea5..6405f8891 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts @@ -747,20 +747,35 @@ export class PipelineService extends BaseService { return; } + async getProjectId(pipelineId: number) { + const pipelineEntity = await this.repository.findOne({ + select: { + projectId: true, + }, + where: { + id: pipelineId, + }, + }); + return pipelineEntity.projectId; + } private async saveHistory(history: RunHistory) { //修改pipeline状态 - const pipelineEntity = new PipelineEntity(); + let pipelineEntity = new PipelineEntity(); pipelineEntity.id = parseInt(history.pipeline.id); pipelineEntity.status = history.pipeline.status.result + ""; pipelineEntity.lastHistoryTime = history.pipeline.status.startTime; await this.update(pipelineEntity); + const projectId = await this.getProjectId(pipelineEntity.id); + pipelineEntity.projectId = projectId; + const entity: HistoryEntity = new HistoryEntity(); entity.id = parseInt(history.id); entity.userId = history.pipeline.userId; entity.status = pipelineEntity.status; entity.pipeline = JSON.stringify(history.pipeline); entity.pipelineId = parseInt(history.pipeline.id); + entity.projectId = pipelineEntity.projectId; await this.historyService.save(entity); const logEntity: HistoryLogEntity = new HistoryLogEntity(); @@ -769,6 +784,7 @@ export class PipelineService extends BaseService { logEntity.pipelineId = entity.pipelineId; logEntity.historyId = entity.id; logEntity.logs = JSON.stringify(history.logs); + logEntity.projectId = pipelineEntity.projectId; await this.historyLogService.addOrUpdate(logEntity); } @@ -984,7 +1000,7 @@ export class PipelineService extends BaseService { throw new NeedVIPException("此功能需要升级专业版"); } - if (!userId || ids.length === 0) { + if (userId == null || ids.length === 0) { return; } const where:any = { diff --git a/packages/ui/certd-server/src/modules/sys/authority/service/auth-service.ts b/packages/ui/certd-server/src/modules/sys/authority/service/auth-service.ts index 0ea36a3e9..5ed4d78da 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/service/auth-service.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/service/auth-service.ts @@ -28,15 +28,15 @@ export class AuthService { } //管理员有权限查看其他用户的数据 - async checkEntityUserId(ctx: any, service: any, id: any = 0, userKey = 'userId') { + async checkEntityUserId(ctx: any, service: any, ids: number| number[] = null, userKey = 'userId') { const isAdmin = await this.isAdmin(ctx); if (isAdmin) { return true; } - await service.checkUserId(id, ctx.user.id, userKey); + await service.checkUserId(ids, ctx.user.id, userKey); } - async checkEntityProjectId(service:any,projectId = 0,id:any=0){ - await service.checkUserId(id, projectId , "projectId"); + async checkEntityProjectId(service:any,ids:number| number[] = null,projectId = null){ + await service.checkUserId(ids, projectId , "projectId"); } } diff --git a/packages/ui/certd-server/src/modules/sys/authority/service/role-service.ts b/packages/ui/certd-server/src/modules/sys/authority/service/role-service.ts index f710daa5d..636ae8488 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/service/role-service.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/service/role-service.ts @@ -9,6 +9,12 @@ import { PermissionService } from './permission-service.js'; import * as _ from 'lodash-es'; import { RolePermissionService } from './role-permission-service.js'; import { LRUCache } from 'lru-cache'; + +const permissionCache = new LRUCache({ + max: 1000, + ttl: 1000 * 60 * 10, +}); + /** * 角色 */ @@ -24,10 +30,7 @@ export class RoleService extends BaseService { @Inject() rolePermissionService: RolePermissionService; - permissionCache = new LRUCache({ - max: 1000, - ttl: 1000 * 60 * 10, - }); + //@ts-ignore getRepository() { @@ -84,7 +87,7 @@ export class RoleService extends BaseService { //再添加 await this.addRoles(userId, roles); - this.permissionCache.clear(); + permissionCache.clear(); } async getPermissionTreeByRoleId(id: any) { @@ -105,7 +108,7 @@ export class RoleService extends BaseService { permissionId, }); } - this.permissionCache.clear(); + permissionCache.clear(); } async getPermissionSetByRoleIds(roleIds: number[]): Promise> { @@ -120,12 +123,12 @@ export class RoleService extends BaseService { async getCachedPermissionSetByRoleIds(roleIds: number[]): Promise> { const roleIdsKey = roleIds.join(','); - let permissionSet = this.permissionCache.get(roleIdsKey); + let permissionSet = permissionCache.get(roleIdsKey); if (permissionSet) { return permissionSet; } permissionSet = await this.getPermissionSetByRoleIds(roleIds); - this.permissionCache.set(roleIdsKey, permissionSet); + permissionCache.set(roleIdsKey, permissionSet); return permissionSet; } diff --git a/packages/ui/certd-server/src/modules/sys/enterprise/service/project-service.ts b/packages/ui/certd-server/src/modules/sys/enterprise/service/project-service.ts index 521f6cf2e..27d4e524c 100644 --- a/packages/ui/certd-server/src/modules/sys/enterprise/service/project-service.ts +++ b/packages/ui/certd-server/src/modules/sys/enterprise/service/project-service.ts @@ -1,10 +1,16 @@ import { BaseService, SysSettingsService } from '@certd/lib-server'; import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; import { InjectEntityModel } from '@midwayjs/typeorm'; +import { LRUCache } from 'lru-cache'; import { Repository } from 'typeorm'; import { ProjectEntity } from '../entity/project.js'; import { ProjectMemberService } from './project-member-service.js'; +const projectCache = new LRUCache({ + max: 1000, + ttl: 1000 * 60 * 10, +}); + @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) export class ProjectService extends BaseService { @@ -23,7 +29,7 @@ export class ProjectService extends BaseService { } async add(bean: ProjectEntity) { - const {name} = bean; + const { name } = bean; if (!name) { throw new Error('项目名称不能为空'); } @@ -33,17 +39,25 @@ export class ProjectService extends BaseService { userId: 0, }, }); - if (exist) { - throw new Error('项目名称已存在'); - } - bean.disabled = false - return await super.add(bean) + if (exist) { + throw new Error('项目名称已存在'); + } + bean.disabled = false + const res= await super.add(bean) + projectCache.clear(); + return res; + } + + async update( bean: ProjectEntity) { + const res= await super.update(bean) + projectCache.clear(); + return res; } async setDisabled(id: number, disabled: boolean) { await this.repository.update({ id, - userId:0, + userId: 0, }, { disabled, }); @@ -55,7 +69,7 @@ export class ProjectService extends BaseService { const projectIds = memberList.map(item => item.projectId); const projectList = await this.repository.createQueryBuilder('project') .where(' project.disabled = false') - .where(' project.userId = :userId', { userId:0 }) + .where(' project.userId = :userId', { userId: 0 }) .where(' project.id IN (:...projectIds) or project.adminId = :userId', { projectIds, userId }) .getMany(); @@ -67,7 +81,7 @@ export class ProjectService extends BaseService { projectList.forEach(item => { if (item.adminId === userId) { item.permission = 'admin'; - }else{ + } else { item.permission = memberPermissionMap[item.id] || 'read'; } }) @@ -75,21 +89,21 @@ export class ProjectService extends BaseService { return projectList } - async checkAdminPermission({userId, projectId}: {userId: number, projectId: number}) { + async checkAdminPermission({ userId, projectId }: { userId: number, projectId: number }) { return await this.checkPermission({ userId, projectId, permission: 'admin', }) } - async checkWritePermission({userId, projectId}: {userId: number, projectId: number}) { + async checkWritePermission({ userId, projectId }: { userId: number, projectId: number }) { return await this.checkPermission({ userId, projectId, permission: 'write', }) } - async checkReadPermission({userId, projectId}: {userId: number, projectId: number}) { + async checkReadPermission({ userId, projectId }: { userId: number, projectId: number }) { return await this.checkPermission({ userId, projectId, @@ -97,47 +111,60 @@ export class ProjectService extends BaseService { }) } - async checkPermission({userId, projectId, permission}: {userId: number, projectId: number, permission: string}) { - if (permission !== 'admin' && permission !== 'write' && permission !== 'read') { - throw new Error('权限类型错误'); - } - if (!userId ){ - throw new Error('用户ID不能为空'); - } - if (!projectId ){ - throw new Error('项目ID不能为空'); - } - const project = await this.findOne({ - select: ['id', 'userId', 'adminId', 'disabled'], - where: { - id: projectId, - }, - }); - if (!project) { - throw new Error('项目不存在'); + async checkPermission({ userId, projectId, permission }: { userId: number, projectId: number, permission: string }) { + if (permission !== 'admin' && permission !== 'write' && permission !== 'read') { + throw new Error('权限类型错误'); } - if (project.adminId === userId) { - //创建者拥有管理权限 - return true + if (!userId) { + throw new Error('用户ID不能为空'); } - if (project.disabled) { - throw new Error('项目已禁用'); + if (!projectId) { + throw new Error('项目ID不能为空'); } - const member = await this.projectMemberService.getMember(projectId,userId); - if (!member) { - throw new Error('项目成员不存在'); + + const cacheKey = `projectPermission:${projectId}:${userId}` + let savedPermission = projectCache.get(cacheKey); + + if (!savedPermission){ + const project = await this.findOne({ + select: ['id', 'userId', 'adminId', 'disabled'], + where: { + id: projectId, + }, + }); + if (!project) { + throw new Error('项目不存在'); + } + if (project.adminId === userId) { + //创建者拥有管理权限 + savedPermission = 'admin'; + }else{ + if (project.disabled) { + throw new Error('项目已禁用'); + } + const member = await this.projectMemberService.getMember(projectId, userId); + if (!member) { + throw new Error('项目成员不存在'); + } + savedPermission = member.permission; + } } + projectCache.set(cacheKey, savedPermission,{ttl: 3 * 60 * 1000}); + if (!savedPermission) { + throw new Error('权限不足'); + } + if (permission === 'read') { return true } if (permission === 'write') { - if (member.permission === 'admin' || member.permission === 'write') { + if (savedPermission === 'admin' || savedPermission === 'write') { return true - }else{ + } else { throw new Error('权限不足'); } } - if (member.permission !== permission) { + if (savedPermission !== permission) { throw new Error('权限不足'); } return true