mirror of
https://github.com/certd/certd.git
synced 2026-04-03 14:10:54 +08:00
chore: history projectId
This commit is contained in:
18
package.json
18
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 ",
|
||||
|
||||
@@ -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}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -206,18 +206,28 @@ export abstract class BaseService<T> {
|
||||
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('权限不足');
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -19,6 +19,8 @@ export const projectPermissionDict = dict({
|
||||
|
||||
export const myProjectDict = dict({
|
||||
url: "/enterprise/project/list",
|
||||
value: "id",
|
||||
label: "name",
|
||||
});
|
||||
|
||||
export const userDict = dict({
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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<HistoryService> {
|
||||
|
||||
@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<HistoryService> {
|
||||
|
||||
@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<HistoryService> {
|
||||
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<HistoryService> {
|
||||
|
||||
@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<HistoryService> {
|
||||
|
||||
@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<HistoryService> {
|
||||
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) {
|
||||
|
||||
@@ -95,25 +95,16 @@ export class PipelineController extends CrudController<PipelineService> {
|
||||
|
||||
@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<PipelineService> {
|
||||
|
||||
@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<PipelineService> {
|
||||
|
||||
@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({});
|
||||
}
|
||||
|
||||
@@ -66,7 +66,8 @@ export class HistoryService extends BaseService<HistoryEntity> {
|
||||
pipelineId: pipeline.id,
|
||||
title: pipeline.title,
|
||||
status: 'start',
|
||||
triggerType
|
||||
triggerType,
|
||||
projectId: pipeline.projectId,
|
||||
};
|
||||
const { id } = await this.add(bean);
|
||||
//清除大于pipeline.keepHistoryCount的历史记录
|
||||
|
||||
@@ -747,20 +747,35 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
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<PipelineEntity> {
|
||||
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<PipelineEntity> {
|
||||
throw new NeedVIPException("此功能需要升级专业版");
|
||||
}
|
||||
|
||||
if (!userId || ids.length === 0) {
|
||||
if (userId == null || ids.length === 0) {
|
||||
return;
|
||||
}
|
||||
const where:any = {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<string, any>({
|
||||
max: 1000,
|
||||
ttl: 1000 * 60 * 10,
|
||||
});
|
||||
|
||||
/**
|
||||
* 角色
|
||||
*/
|
||||
@@ -24,10 +30,7 @@ export class RoleService extends BaseService<RoleEntity> {
|
||||
@Inject()
|
||||
rolePermissionService: RolePermissionService;
|
||||
|
||||
permissionCache = new LRUCache<string, any>({
|
||||
max: 1000,
|
||||
ttl: 1000 * 60 * 10,
|
||||
});
|
||||
|
||||
|
||||
//@ts-ignore
|
||||
getRepository() {
|
||||
@@ -84,7 +87,7 @@ export class RoleService extends BaseService<RoleEntity> {
|
||||
//再添加
|
||||
await this.addRoles(userId, roles);
|
||||
|
||||
this.permissionCache.clear();
|
||||
permissionCache.clear();
|
||||
}
|
||||
|
||||
async getPermissionTreeByRoleId(id: any) {
|
||||
@@ -105,7 +108,7 @@ export class RoleService extends BaseService<RoleEntity> {
|
||||
permissionId,
|
||||
});
|
||||
}
|
||||
this.permissionCache.clear();
|
||||
permissionCache.clear();
|
||||
}
|
||||
|
||||
async getPermissionSetByRoleIds(roleIds: number[]): Promise<Set<string>> {
|
||||
@@ -120,12 +123,12 @@ export class RoleService extends BaseService<RoleEntity> {
|
||||
|
||||
async getCachedPermissionSetByRoleIds(roleIds: number[]): Promise<Set<string>> {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<string, any>({
|
||||
max: 1000,
|
||||
ttl: 1000 * 60 * 10,
|
||||
});
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class ProjectService extends BaseService<ProjectEntity> {
|
||||
@@ -23,7 +29,7 @@ export class ProjectService extends BaseService<ProjectEntity> {
|
||||
}
|
||||
|
||||
async add(bean: ProjectEntity) {
|
||||
const {name} = bean;
|
||||
const { name } = bean;
|
||||
if (!name) {
|
||||
throw new Error('项目名称不能为空');
|
||||
}
|
||||
@@ -33,17 +39,25 @@ export class ProjectService extends BaseService<ProjectEntity> {
|
||||
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<ProjectEntity> {
|
||||
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<ProjectEntity> {
|
||||
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<ProjectEntity> {
|
||||
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<ProjectEntity> {
|
||||
})
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user