chore: project 初步

This commit is contained in:
xiaojunnuo
2026-02-11 00:54:56 +08:00
parent 1e416b9f8a
commit 28dfef985c
5 changed files with 184 additions and 47 deletions
@@ -61,7 +61,7 @@ export abstract class BaseController {
} }
} }
getProjectId(permission:string) { async getProjectId(permission:string) {
if (!isEnterprise()) { if (!isEnterprise()) {
return null return null
} }
@@ -71,13 +71,13 @@ export abstract class BaseController {
} }
const userId = this.getUserId() const userId = this.getUserId()
const projectId = parseInt(projectIdStr) const projectId = parseInt(projectIdStr)
this.checkProjectPermission(userId, projectId,permission) await this.checkProjectPermission(userId, projectId,permission)
return projectId; return projectId;
} }
getProjectUserId(permission:string){ async getProjectUserId(permission:string){
let userId = this.getUserId() let userId = this.getUserId()
const projectId = this.getProjectId(permission) const projectId = await this.getProjectId(permission)
if(projectId){ if(projectId){
userId = 0 userId = 0
} }
@@ -85,11 +85,19 @@ export abstract class BaseController {
projectId,userId projectId,userId
} }
} }
async getProjectUserIdRead(){
return await this.getProjectUserId("read")
}
async getProjectUserIdWrite(){
return await this.getProjectUserId("write")
}
async getProjectUserIdAdmin(){
return await this.getProjectUserId("admin")
}
async checkProjectPermission(userId: number, projectId: number,permission:string) { async checkProjectPermission(userId: number, projectId: number,permission:string) {
const projectService:any = await this.applicationContext.getAsync("projectService"); const projectService:any = await this.applicationContext.getAsync("projectService");
await projectService.checkPermission({userId,projectId,permission}) await projectService.checkPermission({userId,projectId,permission})
} }
@@ -9,6 +9,7 @@ import { cache, logger, mergeUtils, setGlobalProxy } from '@certd/basic';
import * as dns from 'node:dns'; import * as dns from 'node:dns';
import { BaseService, setAdminMode } from '../../../basic/index.js'; import { BaseService, setAdminMode } from '../../../basic/index.js';
import { executorQueue } from '../../basic/service/executor-queue.js'; import { executorQueue } from '../../basic/service/executor-queue.js';
import { isComm } from '@certd/plus-core';
const { merge } = mergeUtils; const { merge } = mergeUtils;
/** /**
* 设置 * 设置
@@ -116,6 +117,12 @@ export class SysSettingsService extends BaseService<SysSettingsEntity> {
} }
async savePublicSettings(bean: SysPublicSettings) { async savePublicSettings(bean: SysPublicSettings) {
if(isComm()){
if(bean.adminMode === 'enterprise'){
throw new Error("商业版不支持使用企业管理模式")
}
}
await this.saveSetting(bean); await this.saveSetting(bean);
//让设置生效 //让设置生效
await this.reloadPublicSettings(); await this.reloadPublicSettings();
@@ -35,8 +35,8 @@ export class PipelineController extends CrudController<PipelineService> {
const isAdmin = await this.authService.isAdmin(this.ctx); const isAdmin = await this.authService.isAdmin(this.ctx);
const publicSettings = await this.sysSettingsService.getPublicSettings(); const publicSettings = await this.sysSettingsService.getPublicSettings();
const {projectId,userId} = this.getProjectUserId("read") const { projectId, userId } = await this.getProjectUserIdRead()
body.query.projectId = projectId body.query.projectId = projectId
let onlyOther = false let onlyOther = false
if (isAdmin) { if (isAdmin) {
if (publicSettings.managerOtherUserPipeline) { if (publicSettings.managerOtherUserPipeline) {
@@ -79,15 +79,15 @@ export class PipelineController extends CrudController<PipelineService> {
@Post('/getSimpleByIds', { summary: Constants.per.authOnly }) @Post('/getSimpleByIds', { summary: Constants.per.authOnly })
async getSimpleById(@Body(ALL) body) { async getSimpleById(@Body(ALL) body) {
const {projectId,userId} = this.getProjectUserId("read") const { projectId, userId } = await this.getProjectUserIdRead()
const ret = await this.getService().getSimplePipelines(body.ids, userId,projectId); const ret = await this.getService().getSimplePipelines(body.ids, userId, projectId);
return this.ok(ret); return this.ok(ret);
} }
@Post('/add', { summary: Constants.per.authOnly }) @Post('/add', { summary: Constants.per.authOnly })
async add(@Body(ALL) bean: PipelineEntity) { async add(@Body(ALL) bean: PipelineEntity) {
const {projectId,userId} = this.getProjectUserId("write") const { projectId, userId } = await this.getProjectUserIdWrite()
bean.userId = userId bean.userId = userId
bean.projectId = projectId bean.projectId = projectId
return super.add(bean); return super.add(bean);
@@ -95,17 +95,27 @@ export class PipelineController extends CrudController<PipelineService> {
@Post('/update', { summary: Constants.per.authOnly }) @Post('/update', { summary: Constants.per.authOnly })
async update(@Body(ALL) bean) { async update(@Body(ALL) bean) {
await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id); 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);
}
delete bean.userId; delete bean.userId;
return super.update(bean); return super.update(bean);
} }
@Post('/save', { summary: Constants.per.authOnly }) @Post('/save', { summary: Constants.per.authOnly })
async save(@Body(ALL) bean: { addToMonitorEnabled: boolean, addToMonitorDomains: string } & PipelineEntity) { async save(@Body(ALL) bean: { addToMonitorEnabled: boolean, addToMonitorDomains: string } & PipelineEntity) {
const { projectId, userId } = await this.getProjectUserIdWrite()
if (bean.id > 0) { if (bean.id > 0) {
await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id); if (projectId) {
await this.authService.checkEntityProjectId(this.getService(), projectId, bean.id);
} else {
await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id);
}
} else { } else {
bean.userId = this.getUserId(); bean.userId = userId;
} }
if (!this.isAdmin()) { if (!this.isAdmin()) {
@@ -121,7 +131,7 @@ export class PipelineController extends CrudController<PipelineService> {
//增加证书监控 //增加证书监控
await this.siteInfoService.doImport({ await this.siteInfoService.doImport({
text: bean.addToMonitorDomains, text: bean.addToMonitorDomains,
userId: this.getUserId(), userId: userId,
}); });
} }
} }
@@ -130,14 +140,24 @@ export class PipelineController extends CrudController<PipelineService> {
@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.authService.checkEntityUserId(this.ctx, this.getService(), id); 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.service.delete(id); await this.service.delete(id);
return this.ok({}); return this.ok({});
} }
@Post('/disabled', { summary: Constants.per.authOnly }) @Post('/disabled', { summary: Constants.per.authOnly })
async disabled(@Body(ALL) bean) { async disabled(@Body(ALL) bean) {
await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id); 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);
}
delete bean.userId; delete bean.userId;
await this.service.disabled(bean.id, bean.disabled); await this.service.disabled(bean.id, bean.disabled);
return this.ok({}); return this.ok({});
@@ -145,75 +165,140 @@ export class PipelineController extends CrudController<PipelineService> {
@Post('/detail', { summary: Constants.per.authOnly }) @Post('/detail', { summary: Constants.per.authOnly })
async detail(@Query('id') id: number) { async detail(@Query('id') id: number) {
await this.authService.checkEntityUserId(this.ctx, this.getService(), id); 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);
}
const detail = await this.service.detail(id); const detail = await this.service.detail(id);
return this.ok(detail); return this.ok(detail);
} }
@Post('/trigger', { summary: Constants.per.authOnly }) @Post('/trigger', { summary: Constants.per.authOnly })
async trigger(@Query('id') id: number, @Query('stepId') stepId?: string) { async trigger(@Query('id') id: number, @Query('stepId') stepId?: string) {
await this.authService.checkEntityUserId(this.ctx, this.getService(), id); 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.service.trigger(id, stepId, true); await this.service.trigger(id, stepId, true);
return this.ok({}); return this.ok({});
} }
@Post('/cancel', { summary: Constants.per.authOnly }) @Post('/cancel', { summary: Constants.per.authOnly })
async cancel(@Query('historyId') historyId: number) { async cancel(@Query('historyId') historyId: number) {
await this.authService.checkEntityUserId(this.ctx, this.historyService, historyId); 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.service.cancel(historyId); await this.service.cancel(historyId);
return this.ok({}); return this.ok({});
} }
@Post('/count', { summary: Constants.per.authOnly }) @Post('/count', { summary: Constants.per.authOnly })
async count() { async count() {
const count = await this.service.count({ userId: this.getUserId() }); const { userId } = await this.getProjectUserIdRead()
const count = await this.service.count({ userId: userId });
return this.ok({ count }); return this.ok({ count });
} }
private async checkPermissionCall(callback:any){
let { projectId ,userId} = await this.getProjectUserIdWrite()
if(projectId){
return await callback({userId,projectId});
}
const isAdmin = await this.authService.isAdmin(this.ctx);
userId = isAdmin ? undefined : userId;
return await callback({userId});
}
@Post('/batchDelete', { summary: Constants.per.authOnly }) @Post('/batchDelete', { summary: Constants.per.authOnly })
async batchDelete(@Body('ids') ids: number[]) { async batchDelete(@Body('ids') ids: number[]) {
const isAdmin = await this.authService.isAdmin(this.ctx); // let { projectId ,userId} = await this.getProjectUserIdWrite()
const userId = isAdmin ? undefined : this.getUserId(); // if(projectId){
await this.service.batchDelete(ids, userId); // await this.service.batchDelete(ids, null,projectId);
return this.ok({}); // return this.ok({});
// }
// const isAdmin = await this.authService.isAdmin(this.ctx);
// userId = isAdmin ? undefined : userId;
// await this.service.batchDelete(ids, userId);
// return this.ok({});
await this.checkPermissionCall(async ({userId,projectId})=>{
await this.service.batchDelete(ids, userId,projectId);
})
return this.ok({})
} }
@Post('/batchUpdateGroup', { summary: Constants.per.authOnly }) @Post('/batchUpdateGroup', { summary: Constants.per.authOnly })
async batchUpdateGroup(@Body('ids') ids: number[], @Body('groupId') groupId: number) { async batchUpdateGroup(@Body('ids') ids: number[], @Body('groupId') groupId: number) {
const isAdmin = await this.authService.isAdmin(this.ctx); // let { projectId ,userId} = await this.getProjectUserIdWrite()
const userId = isAdmin ? undefined : this.getUserId(); // if(projectId){
await this.service.batchUpdateGroup(ids, groupId, userId); // await this.service.batchUpdateGroup(ids, groupId, null,projectId);
// return this.ok({});
// }
// const isAdmin = await this.authService.isAdmin(this.ctx);
// userId = isAdmin ? undefined : this.getUserId();
// await this.service.batchUpdateGroup(ids, groupId, userId);
await this.checkPermissionCall(async ({userId,projectId})=>{
await this.service.batchUpdateGroup(ids, groupId, userId,projectId);
})
return this.ok({}); return this.ok({});
} }
@Post('/batchUpdateTrigger', { summary: Constants.per.authOnly }) @Post('/batchUpdateTrigger', { summary: Constants.per.authOnly })
async batchUpdateTrigger(@Body('ids') ids: number[], @Body('trigger') trigger: any) { async batchUpdateTrigger(@Body('ids') ids: number[], @Body('trigger') trigger: any) {
const isAdmin = await this.authService.isAdmin(this.ctx); // let { projectId ,userId} = await this.getProjectUserIdWrite()
const userId = isAdmin ? undefined : this.getUserId(); // if(projectId){
await this.service.batchUpdateTrigger(ids, trigger, userId); // await this.service.batchUpdateTrigger(ids, trigger, null,projectId);
// return this.ok({});
// }
// const isAdmin = await this.authService.isAdmin(this.ctx);
// userId = isAdmin ? undefined : this.getUserId();
// await this.service.batchUpdateTrigger(ids, trigger, userId);
await this.checkPermissionCall(async ({userId,projectId})=>{
await this.service.batchUpdateTrigger(ids, trigger, userId,projectId);
})
return this.ok({}); return this.ok({});
} }
@Post('/batchUpdateNotification', { summary: Constants.per.authOnly }) @Post('/batchUpdateNotification', { summary: Constants.per.authOnly })
async batchUpdateNotification(@Body('ids') ids: number[], @Body('notification') notification: any) { async batchUpdateNotification(@Body('ids') ids: number[], @Body('notification') notification: any) {
const isAdmin = await this.authService.isAdmin(this.ctx); // const isAdmin = await this.authService.isAdmin(this.ctx);
const userId = isAdmin ? undefined : this.getUserId(); // const userId = isAdmin ? undefined : this.getUserId();
await this.service.batchUpdateNotifications(ids, notification, userId); // await this.service.batchUpdateNotifications(ids, notification, userId);
await this.checkPermissionCall(async ({userId,projectId})=>{
await this.service.batchUpdateNotifications(ids, notification, userId,projectId);
})
return this.ok({}); return this.ok({});
} }
@Post('/batchRerun', { summary: Constants.per.authOnly }) @Post('/batchRerun', { summary: Constants.per.authOnly })
async batchRerun(@Body('ids') ids: number[], @Body('force') force: boolean) { async batchRerun(@Body('ids') ids: number[], @Body('force') force: boolean) {
await this.service.batchRerun(ids, this.getUserId(), force); await this.checkPermissionCall(async ({userId,projectId})=>{
await this.service.batchRerun(ids, force,userId,projectId);
})
return this.ok({}); return this.ok({});
} }
@Post('/refreshWebhookKey', { summary: Constants.per.authOnly }) @Post('/refreshWebhookKey', { summary: Constants.per.authOnly })
async refreshWebhookKey(@Body('id') id: number) { async refreshWebhookKey(@Body('id') id: number) {
await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
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);
}
const res = await this.service.refreshWebhookKey(id); const res = await this.service.refreshWebhookKey(id);
return this.ok({ return this.ok({
webhookKey: res, webhookKey: res,
@@ -4,6 +4,7 @@ import { In, MoreThan, Repository } from "typeorm";
import { import {
AccessService, AccessService,
BaseService, BaseService,
isEnterprise,
NeedSuiteException, NeedSuiteException,
NeedVIPException, NeedVIPException,
PageReq, PageReq,
@@ -38,7 +39,7 @@ import { CnameRecordService } from "../../cname/service/cname-record-service.js"
import { PluginConfigGetter } from "../../plugin/service/plugin-config-getter.js"; import { PluginConfigGetter } from "../../plugin/service/plugin-config-getter.js";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { DbAdapter } from "../../db/index.js"; import { DbAdapter } from "../../db/index.js";
import { isComm, isPlus } from "@certd/plus-core"; import { checkPlus, isComm, isPlus } from "@certd/plus-core";
import { logger, utils } from "@certd/basic"; import { logger, utils } from "@certd/basic";
import { UrlService } from "./url-service.js"; import { UrlService } from "./url-service.js";
import { NotificationService } from "./notification-service.js"; import { NotificationService } from "./notification-service.js";
@@ -301,6 +302,12 @@ export class PipelineService extends BaseService<PipelineEntity> {
// throw new NeedVIPException(`基础版最多只能创建${freeCount}条流水线`); // throw new NeedVIPException(`基础版最多只能创建${freeCount}条流水线`);
// } // }
// } // }
if(isEnterprise()){
//企业模式不限制
checkPlus()
return;
}
if (isComm()) { if (isComm()) {
//校验pipelineCount //校验pipelineCount
const suiteSetting = await this.userSuiteService.getSuiteSetting(); const suiteSetting = await this.userSuiteService.getSuiteSetting();
@@ -328,6 +335,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
} }
} }
} }
} }
async foreachPipeline(callback: (pipeline: PipelineEntity) => void) { async foreachPipeline(callback: (pipeline: PipelineEntity) => void) {
@@ -559,6 +567,12 @@ export class PipelineService extends BaseService<PipelineEntity> {
} }
async beforeCheck(entity: PipelineEntity) { async beforeCheck(entity: PipelineEntity) {
if(isEnterprise()){
checkPlus()
return {}
}
const validTimeEnabled = await this.isPipelineValidTimeEnabled(entity) const validTimeEnabled = await this.isPipelineValidTimeEnabled(entity)
if (!validTimeEnabled) { if (!validTimeEnabled) {
throw new Error(`流水线${entity.id}已过期,不予执行`); throw new Error(`流水线${entity.id}已过期,不予执行`);
@@ -582,7 +596,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
const res = await this.beforeCheck(entity); const res = await this.beforeCheck(entity);
suite = res.suite suite = res.suite
} catch (e) { } catch (e) {
logger.error(`流水线${entity.id}触发${triggerId}失败${e.message}`); logger.error(`流水线${entity.id}触发失败(${triggerId}${e.message}`);
} }
const id = entity.id; const id = entity.id;
@@ -625,7 +639,10 @@ export class PipelineService extends BaseService<PipelineEntity> {
const userId = entity.userId; const userId = entity.userId;
const historyId = await this.historyService.start(entity, triggerType); const historyId = await this.historyService.start(entity, triggerType);
const userIsAdmin = await this.userService.isAdmin(userId); let userIsAdmin = false
if(userId){
userIsAdmin = await this.userService.isAdmin(userId);
}
const user: UserInfo = { const user: UserInfo = {
id: userId, id: userId,
role: userIsAdmin ? "admin" : "user" role: userIsAdmin ? "admin" : "user"
@@ -836,7 +853,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
return result; return result;
} }
async batchDelete(ids: number[], userId: number) { async batchDelete(ids: number[], userId?: number,projectId?:number) {
if (!isPlus()) { if (!isPlus()) {
throw new NeedVIPException("此功能需要升级专业版"); throw new NeedVIPException("此功能需要升级专业版");
} }
@@ -844,11 +861,14 @@ export class PipelineService extends BaseService<PipelineEntity> {
if (userId) { if (userId) {
await this.checkUserId(id, userId); await this.checkUserId(id, userId);
} }
if(projectId){
await this.checkUserId(id,projectId,"projectId")
}
await this.delete(id); await this.delete(id);
} }
} }
async batchUpdateGroup(ids: number[], groupId: number, userId: any) { async batchUpdateGroup(ids: number[], groupId: number, userId: any,projectId?:number) {
if (!isPlus()) { if (!isPlus()) {
throw new NeedVIPException("此功能需要升级专业版"); throw new NeedVIPException("此功能需要升级专业版");
} }
@@ -856,6 +876,9 @@ export class PipelineService extends BaseService<PipelineEntity> {
if (userId && userId > 0) { if (userId && userId > 0) {
query.userId = userId; query.userId = userId;
} }
if(projectId){
query.projectId = projectId;
}
await this.repository.update( await this.repository.update(
{ {
id: In(ids), id: In(ids),
@@ -866,7 +889,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
} }
async batchUpdateTrigger(ids: number[], trigger: any, userId: any) { async batchUpdateTrigger(ids: number[], trigger: any, userId: any,projectId?:number) {
if (!isPlus()) { if (!isPlus()) {
throw new NeedVIPException("此功能需要升级专业版"); throw new NeedVIPException("此功能需要升级专业版");
} }
@@ -874,6 +897,9 @@ export class PipelineService extends BaseService<PipelineEntity> {
if (userId && userId > 0) { if (userId && userId > 0) {
query.userId = userId; query.userId = userId;
} }
if(projectId){
query.projectId = projectId;
}
const list = await this.find({ const list = await this.find({
where: { where: {
id: In(ids), id: In(ids),
@@ -915,7 +941,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
} }
async batchUpdateNotifications(ids: number[], notification: Notification, userId: any) { async batchUpdateNotifications(ids: number[], notification: Notification, userId: any,projectId?:number) {
if (!isPlus()) { if (!isPlus()) {
throw new NeedVIPException("此功能需要升级专业版"); throw new NeedVIPException("此功能需要升级专业版");
} }
@@ -923,6 +949,9 @@ export class PipelineService extends BaseService<PipelineEntity> {
if (userId && userId > 0) { if (userId && userId > 0) {
query.userId = userId; query.userId = userId;
} }
if(projectId){
query.projectId = projectId;
}
const list = await this.find({ const list = await this.find({
where: { where: {
id: In(ids), id: In(ids),
@@ -950,7 +979,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
} }
} }
async batchRerun(ids: number[], userId: any, force: boolean) { async batchRerun(ids: number[], force: boolean,userId: any, projectId?:number) {
if (!isPlus()) { if (!isPlus()) {
throw new NeedVIPException("此功能需要升级专业版"); throw new NeedVIPException("此功能需要升级专业版");
} }
@@ -958,14 +987,18 @@ export class PipelineService extends BaseService<PipelineEntity> {
if (!userId || ids.length === 0) { if (!userId || ids.length === 0) {
return; return;
} }
const where:any = {
id: In(ids),
userId,
}
if(projectId){
where.projectId = projectId
}
const list = await this.repository.find({ const list = await this.repository.find({
select: { select: {
id: true id: true
}, },
where: { where:where
id: In(ids),
userId
}
}); });
ids = list.map(item => item.id); ids = list.map(item => item.id);
@@ -35,4 +35,8 @@ export class AuthService {
} }
await service.checkUserId(id, ctx.user.id, userKey); await service.checkUserId(id, ctx.user.id, userKey);
} }
async checkEntityProjectId(service:any,projectId = 0,id:any=0){
await service.checkUserId(id, projectId , "projectId");
}
} }