mirror of
https://github.com/certd/certd.git
synced 2026-04-25 05:07:25 +08:00
perf: 支持批量转移流水线到其他项目
This commit is contained in:
@@ -7,8 +7,12 @@ import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
|||||||
export class AccessEntity {
|
export class AccessEntity {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
id: number;
|
id: number;
|
||||||
|
@Column({ name: 'key_id', comment: 'key_id', length: 100 })
|
||||||
|
keyId: string;
|
||||||
|
|
||||||
@Column({ name: 'user_id', comment: '用户id' })
|
@Column({ name: 'user_id', comment: '用户id' })
|
||||||
userId: number; // 0为系统级别, -1为企业,大于1为用户
|
userId: number; // 0为系统级别, -1为企业,大于1为用户
|
||||||
|
|
||||||
@Column({ comment: '名称', length: 100 })
|
@Column({ comment: '名称', length: 100 })
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {AccessGetter, BaseService, PageReq, PermissionException, ValidateExcepti
|
|||||||
import {AccessEntity} from '../entity/access.js';
|
import {AccessEntity} from '../entity/access.js';
|
||||||
import {AccessDefine, accessRegistry, newAccess} from '@certd/pipeline';
|
import {AccessDefine, accessRegistry, newAccess} from '@certd/pipeline';
|
||||||
import {EncryptService} from './encrypt-service.js';
|
import {EncryptService} from './encrypt-service.js';
|
||||||
|
import { logger, utils } from '@certd/basic';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 授权
|
* 授权
|
||||||
@@ -46,6 +47,7 @@ export class AccessService extends BaseService<AccessEntity> {
|
|||||||
}
|
}
|
||||||
delete param._copyFrom
|
delete param._copyFrom
|
||||||
this.encryptSetting(param, oldEntity);
|
this.encryptSetting(param, oldEntity);
|
||||||
|
param.keyId = "ac_" + utils.id.simpleNanoId();
|
||||||
return await super.add(param);
|
return await super.add(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,6 +119,7 @@ export class AccessService extends BaseService<AccessEntity> {
|
|||||||
throw new ValidateException('该授权配置不存在,请确认是否已被删除');
|
throw new ValidateException('该授权配置不存在,请确认是否已被删除');
|
||||||
}
|
}
|
||||||
this.encryptSetting(param, oldEntity);
|
this.encryptSetting(param, oldEntity);
|
||||||
|
delete param.keyId
|
||||||
return await super.update(param);
|
return await super.update(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,4 +218,36 @@ export class AccessService extends BaseService<AccessEntity> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制授权到其他项目
|
||||||
|
* @param accessId
|
||||||
|
* @param projectId
|
||||||
|
*/
|
||||||
|
async copyTo(accessId: number,projectId?: number) {
|
||||||
|
const access = await this.info(accessId);
|
||||||
|
if (access == null) {
|
||||||
|
throw new Error(`该授权配置不存在,请确认是否已被删除:id=${accessId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyId = access.keyId;
|
||||||
|
//检查目标项目里是否已经有相同keyId的配置
|
||||||
|
const existAccess = await this.repository.findOne({
|
||||||
|
where: {
|
||||||
|
keyId,
|
||||||
|
projectId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (existAccess) {
|
||||||
|
logger.info(`目标项目已存在相同keyId的授权配置,跳过复制:keyId=${keyId}`);
|
||||||
|
return existAccess.id;
|
||||||
|
}
|
||||||
|
const newAccess = {
|
||||||
|
...access,
|
||||||
|
id: undefined,
|
||||||
|
projectId,
|
||||||
|
}
|
||||||
|
await this.add(newAccess);
|
||||||
|
return newAccess.id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
|||||||
export class AddonEntity {
|
export class AddonEntity {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
id: number;
|
id: number;
|
||||||
|
@Column({ name: 'key_id', comment: 'key_id', length: 100 })
|
||||||
|
keyId: string;
|
||||||
@Column({ name: 'user_id', comment: '用户id' })
|
@Column({ name: 'user_id', comment: '用户id' })
|
||||||
userId: number;
|
userId: number;
|
||||||
@Column({ comment: '名称', length: 100 })
|
@Column({ comment: '名称', length: 100 })
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { In, Repository } from "typeorm";
|
|||||||
import { AddonDefine, BaseService, PageReq, ValidateException } from "../../../index.js";
|
import { AddonDefine, BaseService, PageReq, ValidateException } from "../../../index.js";
|
||||||
import { addonRegistry } from "../api/index.js";
|
import { addonRegistry } from "../api/index.js";
|
||||||
import { AddonEntity } from "../entity/addon.js";
|
import { AddonEntity } from "../entity/addon.js";
|
||||||
|
import { utils } from "@certd/basic";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Addon
|
* Addon
|
||||||
@@ -43,6 +44,7 @@ export class AddonService extends BaseService<AddonEntity> {
|
|||||||
} else {
|
} else {
|
||||||
param.isSystem = false;
|
param.isSystem = false;
|
||||||
}
|
}
|
||||||
|
param.keyId = "ad_" + utils.id.simpleNanoId();
|
||||||
delete param._copyFrom;
|
delete param._copyFrom;
|
||||||
return await super.add(param);
|
return await super.add(param);
|
||||||
}
|
}
|
||||||
@@ -57,6 +59,7 @@ export class AddonService extends BaseService<AddonEntity> {
|
|||||||
if (oldEntity == null) {
|
if (oldEntity == null) {
|
||||||
throw new ValidateException("该Addon配置不存在,请确认是否已被删除");
|
throw new ValidateException("该Addon配置不存在,请确认是否已被删除");
|
||||||
}
|
}
|
||||||
|
delete param.keyId
|
||||||
return await super.update(param);
|
return await super.update(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +70,7 @@ export class AddonService extends BaseService<AddonEntity> {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
id: entity.id,
|
id: entity.id,
|
||||||
|
keyId: entity.keyId,
|
||||||
name: entity.name,
|
name: entity.name,
|
||||||
userId: entity.userId,
|
userId: entity.userId,
|
||||||
addonType: entity.addonType,
|
addonType: entity.addonType,
|
||||||
@@ -100,6 +104,7 @@ export class AddonService extends BaseService<AddonEntity> {
|
|||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
|
keyId: true,
|
||||||
name: true,
|
name: true,
|
||||||
addonType: true,
|
addonType: true,
|
||||||
type: true,
|
type: true,
|
||||||
@@ -132,6 +137,7 @@ export class AddonService extends BaseService<AddonEntity> {
|
|||||||
const setting = JSON.parse(res.setting);
|
const setting = JSON.parse(res.setting);
|
||||||
return {
|
return {
|
||||||
id: res.id,
|
id: res.id,
|
||||||
|
keyId: res.keyId,
|
||||||
addonType: res.addonType,
|
addonType: res.addonType,
|
||||||
type: res.type,
|
type: res.type,
|
||||||
name: res.name,
|
name: res.name,
|
||||||
|
|||||||
@@ -784,7 +784,7 @@ onMounted(async () => {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 40px 20px;
|
padding: 20px 10px;
|
||||||
color: #9ca3af;
|
color: #9ca3af;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,14 @@ export async function BatchUpdateNotificaiton(pipelineIds: number[], notificatio
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function BatchUpdateProject(pipelineIds: number[], toProjectId: number): Promise<void> {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/batchTransfer",
|
||||||
|
method: "post",
|
||||||
|
data: { ids: pipelineIds, toProjectId: toProjectId },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export async function BatchDelete(pipelineIds: number[]): Promise<void> {
|
export async function BatchDelete(pipelineIds: number[]): Promise<void> {
|
||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/batchDelete",
|
url: apiPrefix + "/batchDelete",
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<template>
|
||||||
|
<fs-button icon="mdi:format-list-group" class="need-plus" type="link" text="转到其他项目" @click="openProjectSelectDialog"></fs-button>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import * as api from "../api";
|
||||||
|
import { notification } from "ant-design-vue";
|
||||||
|
import { dict, useFormWrapper } from "@fast-crud/fast-crud";
|
||||||
|
import { useSettingStore } from "/@/store/settings";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
selectedRowKeys: any[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
change: any;
|
||||||
|
}>();
|
||||||
|
async function batchUpdateProjectRequest(toProjectId: number) {
|
||||||
|
await api.BatchUpdateProject(props.selectedRowKeys, toProjectId);
|
||||||
|
emit("change");
|
||||||
|
}
|
||||||
|
|
||||||
|
const pipelineProjectDictRef = dict({
|
||||||
|
url: "/enterprise/project/all",
|
||||||
|
value: "id",
|
||||||
|
label: "name",
|
||||||
|
});
|
||||||
|
const { openCrudFormDialog } = useFormWrapper();
|
||||||
|
const settingStore = useSettingStore();
|
||||||
|
async function openProjectSelectDialog() {
|
||||||
|
settingStore.checkPlus();
|
||||||
|
const crudOptions: any = {
|
||||||
|
columns: {
|
||||||
|
toProjectId: {
|
||||||
|
title: "转到项目",
|
||||||
|
type: "dict-select",
|
||||||
|
dict: pipelineProjectDictRef,
|
||||||
|
form: {
|
||||||
|
rules: [{ required: true, message: "请选择项目" }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
mode: "edit",
|
||||||
|
//@ts-ignore
|
||||||
|
async doSubmit({ form }) {
|
||||||
|
await batchUpdateProjectRequest(form.toProjectId);
|
||||||
|
},
|
||||||
|
col: {
|
||||||
|
span: 22,
|
||||||
|
},
|
||||||
|
labelCol: {
|
||||||
|
style: {
|
||||||
|
width: "100px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wrapper: {
|
||||||
|
title: "批量转到其他项目",
|
||||||
|
width: 600,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as any;
|
||||||
|
await openCrudFormDialog({ crudOptions });
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -42,6 +42,7 @@
|
|||||||
<change-group v-if="hasActionPermission('write')" :selected-row-keys="selectedRowKeys" @change="batchFinished"></change-group>
|
<change-group v-if="hasActionPermission('write')" :selected-row-keys="selectedRowKeys" @change="batchFinished"></change-group>
|
||||||
<change-notification v-if="hasActionPermission('write')" :selected-row-keys="selectedRowKeys" @change="batchFinished"></change-notification>
|
<change-notification v-if="hasActionPermission('write')" :selected-row-keys="selectedRowKeys" @change="batchFinished"></change-notification>
|
||||||
<change-trigger v-if="hasActionPermission('write')" :selected-row-keys="selectedRowKeys" @change="batchFinished"></change-trigger>
|
<change-trigger v-if="hasActionPermission('write')" :selected-row-keys="selectedRowKeys" @change="batchFinished"></change-trigger>
|
||||||
|
<change-project v-if="hasActionPermission('write')" :selected-row-keys="selectedRowKeys" @change="batchFinished"></change-project>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template #form-bottom>
|
<template #form-bottom>
|
||||||
@@ -57,6 +58,8 @@ import { dict, useFs } from "@fast-crud/fast-crud";
|
|||||||
import createCrudOptions from "./crud";
|
import createCrudOptions from "./crud";
|
||||||
import ChangeGroup from "./components/change-group.vue";
|
import ChangeGroup from "./components/change-group.vue";
|
||||||
import ChangeTrigger from "./components/change-trigger.vue";
|
import ChangeTrigger from "./components/change-trigger.vue";
|
||||||
|
import ChangeProject from "./components/change-project.vue";
|
||||||
|
|
||||||
import BatchRerun from "./components/batch-rerun.vue";
|
import BatchRerun from "./components/batch-rerun.vue";
|
||||||
import { Modal, notification } from "ant-design-vue";
|
import { Modal, notification } from "ant-design-vue";
|
||||||
import * as api from "./api";
|
import * as api from "./api";
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
ALTER TABLE cd_access ADD COLUMN key_id varchar(100) NULL;
|
||||||
|
CREATE INDEX "index_access_key_id" ON "cd_access" ("key_id");
|
||||||
|
update cd_access set key_id = id where key_id is null;
|
||||||
|
|
||||||
|
ALTER TABLE pi_notification ADD COLUMN key_id varchar(100) NULL;
|
||||||
|
CREATE INDEX "index_notification_key_id" ON "pi_notification" ("key_id");
|
||||||
|
update pi_notification set key_id = id where key_id is null;
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE cd_addon ADD COLUMN key_id varchar(100) NULL;
|
||||||
|
CREATE INDEX "index_addon_key_id" ON "cd_addon" ("key_id");
|
||||||
|
update cd_addon set key_id = id where key_id is null;
|
||||||
@@ -262,6 +262,14 @@ export class PipelineController extends CrudController<PipelineService> {
|
|||||||
return this.ok({});
|
return this.ok({});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('/batchTransfer', { summary: Constants.per.authOnly })
|
||||||
|
async batchTransfer(@Body('ids') ids: number[], @Body('toProjectId') toProjectId: number) {
|
||||||
|
await this.checkPermissionCall(async ({})=>{
|
||||||
|
await this.service.batchTransfer(ids, toProjectId);
|
||||||
|
})
|
||||||
|
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.checkOwner(this.getService(), id,"write",true);
|
await this.checkOwner(this.getService(), id,"write",true);
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ export class NotificationEntity {
|
|||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
|
@Column({ name: 'key_id', comment: 'key_id', length: 100 })
|
||||||
|
keyId: string;
|
||||||
|
|
||||||
@Column({ name: 'user_id', comment: 'UserId' })
|
@Column({ name: 'user_id', comment: 'UserId' })
|
||||||
userId: number;
|
userId: number;
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export class NotificationService extends BaseService<NotificationEntity> {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
id: entity.id,
|
id: entity.id,
|
||||||
|
keyId: entity.keyId,
|
||||||
name: entity.name,
|
name: entity.name,
|
||||||
userId: entity.userId,
|
userId: entity.userId,
|
||||||
};
|
};
|
||||||
@@ -58,6 +59,7 @@ export class NotificationService extends BaseService<NotificationEntity> {
|
|||||||
if(bean.isDefault){
|
if(bean.isDefault){
|
||||||
await this.setDefault(res.id, bean.userId);
|
await this.setDefault(res.id, bean.userId);
|
||||||
}
|
}
|
||||||
|
bean.keyId = "nt_" + utils.id.simpleNanoId();
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +70,7 @@ export class NotificationService extends BaseService<NotificationEntity> {
|
|||||||
|
|
||||||
delete bean.userId;
|
delete bean.userId;
|
||||||
delete bean.type
|
delete bean.type
|
||||||
|
delete bean.keyId
|
||||||
const res = await super.update(bean);
|
const res = await super.update(bean);
|
||||||
if(bean.isDefault){
|
if(bean.isDefault){
|
||||||
await this.setDefault(bean.id, old.userId);
|
await this.setDefault(bean.id, old.userId);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
ICnameProxyService,
|
ICnameProxyService,
|
||||||
INotificationService, Notification,
|
INotificationService, Notification,
|
||||||
Pipeline,
|
Pipeline,
|
||||||
|
pluginRegistry,
|
||||||
ResultType,
|
ResultType,
|
||||||
RunHistory,
|
RunHistory,
|
||||||
RunnableCollection,
|
RunnableCollection,
|
||||||
@@ -163,8 +164,8 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
nextTimes.push(...ret);
|
nextTimes.push(...ret);
|
||||||
}
|
}
|
||||||
item.nextRunTime = nextTimes[0]
|
item.nextRunTime = nextTimes[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete item.content;
|
delete item.content;
|
||||||
@@ -304,8 +305,8 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
fromType = "auto";
|
fromType = "auto";
|
||||||
}
|
}
|
||||||
const userId = bean.userId;
|
const userId = bean.userId;
|
||||||
const projectId = bean.projectId ??null;
|
const projectId = bean.projectId ?? null;
|
||||||
await this.certInfoService.updateDomains(pipeline.id, userId, projectId , domains, fromType);
|
await this.certInfoService.updateDomains(pipeline.id, userId, projectId, domains, fromType);
|
||||||
return {
|
return {
|
||||||
...bean,
|
...bean,
|
||||||
version: pipeline.version,
|
version: pipeline.version,
|
||||||
@@ -344,12 +345,12 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
// throw new NeedVIPException(`基础版最多只能创建${freeCount}条流水线`);
|
// throw new NeedVIPException(`基础版最多只能创建${freeCount}条流水线`);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
if(isEnterprise()){
|
if (isEnterprise()) {
|
||||||
//企业模式不限制
|
//企业模式不限制
|
||||||
checkPlus()
|
checkPlus()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isComm()) {
|
if (isComm()) {
|
||||||
//校验pipelineCount
|
//校验pipelineCount
|
||||||
const suiteSetting = await this.userSuiteService.getSuiteSetting();
|
const suiteSetting = await this.userSuiteService.getSuiteSetting();
|
||||||
@@ -377,7 +378,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async foreachPipeline(callback: (pipeline: PipelineEntity) => void) {
|
async foreachPipeline(callback: (pipeline: PipelineEntity) => void) {
|
||||||
@@ -610,7 +611,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
|
|
||||||
async beforeCheck(entity: PipelineEntity) {
|
async beforeCheck(entity: PipelineEntity) {
|
||||||
|
|
||||||
if(isEnterprise()){
|
if (isEnterprise()) {
|
||||||
checkPlus()
|
checkPlus()
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
@@ -683,9 +684,9 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
const projectId = entity.projectId;
|
const projectId = entity.projectId;
|
||||||
let userIsAdmin = false
|
let userIsAdmin = false
|
||||||
|
|
||||||
if (projectId && projectId>0) {
|
if (projectId && projectId > 0) {
|
||||||
userIsAdmin = await this.projectService.isAdmin(projectId);
|
userIsAdmin = await this.projectService.isAdmin(projectId);
|
||||||
}else if(userId>0){
|
} else if (userId > 0) {
|
||||||
userIsAdmin = await this.userService.isAdmin(userId);
|
userIsAdmin = await this.userService.isAdmin(userId);
|
||||||
}
|
}
|
||||||
const user: UserInfo = {
|
const user: UserInfo = {
|
||||||
@@ -693,7 +694,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
role: userIsAdmin ? "admin" : "user"
|
role: userIsAdmin ? "admin" : "user"
|
||||||
};
|
};
|
||||||
|
|
||||||
const historyId = await this.historyService.start(entity, triggerType);
|
const historyId = await this.historyService.start(entity, triggerType);
|
||||||
const sysInfo: SysInfo = {};
|
const sysInfo: SysInfo = {};
|
||||||
if (isComm()) {
|
if (isComm()) {
|
||||||
const siteInfo = await this.sysSettingsService.getSetting<SysSiteInfo>(SysSiteInfo);
|
const siteInfo = await this.sysSettingsService.getSetting<SysSiteInfo>(SysSiteInfo);
|
||||||
@@ -802,7 +803,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
id: pipelineId,
|
id: pipelineId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if(!pipelineEntity){
|
if (!pipelineEntity) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return pipelineEntity.projectId;
|
return pipelineEntity.projectId;
|
||||||
@@ -837,7 +838,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
await this.historyLogService.addOrUpdate(logEntity);
|
await this.historyLogService.addOrUpdate(logEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
async count(param: { userId?: any,projectId?:number }) {
|
async count(param: { userId?: any, projectId?: number }) {
|
||||||
const count = await this.repository.count({
|
const count = await this.repository.count({
|
||||||
where: {
|
where: {
|
||||||
userId: param.userId,
|
userId: param.userId,
|
||||||
@@ -848,7 +849,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
async statusCount(param: { userId?: any,projectId?:number } = {}) {
|
async statusCount(param: { userId?: any, projectId?: number } = {}) {
|
||||||
const statusCount = await this.repository
|
const statusCount = await this.repository
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.select("status")
|
.select("status")
|
||||||
@@ -863,7 +864,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
return statusCount;
|
return statusCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
async enableCount(param: { userId?: any,projectId?:number } = {}) {
|
async enableCount(param: { userId?: any, projectId?: number } = {}) {
|
||||||
const statusCount = await this.repository
|
const statusCount = await this.repository
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.select("disabled")
|
.select("disabled")
|
||||||
@@ -885,7 +886,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async latestExpiringList({ userId,projectId }: any) {
|
async latestExpiringList({ userId, projectId }: any) {
|
||||||
let list = await this.repository.find({
|
let list = await this.repository.find({
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
@@ -927,7 +928,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async batchDelete(ids: number[], userId?: number,projectId?:number) {
|
async batchDelete(ids: number[], userId?: number, projectId?: number) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级专业版");
|
||||||
}
|
}
|
||||||
@@ -935,14 +936,14 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
if (userId && userId > 0) {
|
if (userId && userId > 0) {
|
||||||
await this.checkUserId(id, userId);
|
await this.checkUserId(id, userId);
|
||||||
}
|
}
|
||||||
if(projectId){
|
if (projectId) {
|
||||||
await this.checkUserId(id,projectId,"projectId")
|
await this.checkUserId(id, projectId, "projectId")
|
||||||
}
|
}
|
||||||
await this.delete(id);
|
await this.delete(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async batchUpdateGroup(ids: number[], groupId: number, userId: any,projectId?:number) {
|
async batchUpdateGroup(ids: number[], groupId: number, userId: any, projectId?: number) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级专业版");
|
||||||
}
|
}
|
||||||
@@ -950,7 +951,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
if (userId && userId > 0) {
|
if (userId && userId > 0) {
|
||||||
query.userId = userId;
|
query.userId = userId;
|
||||||
}
|
}
|
||||||
if(projectId){
|
if (projectId) {
|
||||||
query.projectId = projectId;
|
query.projectId = projectId;
|
||||||
}
|
}
|
||||||
await this.repository.update(
|
await this.repository.update(
|
||||||
@@ -963,7 +964,105 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async batchUpdateTrigger(ids: number[], trigger: any, userId: any,projectId?:number) {
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量转移到其他项目
|
||||||
|
*/
|
||||||
|
async batchTransfer(ids: number[], projectId: number) {
|
||||||
|
if (!isPlus()) {
|
||||||
|
throw new NeedVIPException("此功能需要升级专业版");
|
||||||
|
}
|
||||||
|
if (!isEnterprise()) {
|
||||||
|
throw new Error("当前为非企业模式,不允许转移到其他项目");
|
||||||
|
}
|
||||||
|
if (!projectId || projectId <= 0) {
|
||||||
|
throw new Error("projectId不能为空");
|
||||||
|
}
|
||||||
|
const userId = -1 // 强制为-1
|
||||||
|
|
||||||
|
async function eachSteps(pipeline, callback) {
|
||||||
|
for (const stage of pipeline.stages) {
|
||||||
|
for (const task of stage.tasks) {
|
||||||
|
for (const step of task.steps) {
|
||||||
|
await callback(step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (const id of ids) {
|
||||||
|
const pipelineEntity = await this.info(id);
|
||||||
|
if (!pipelineEntity) {
|
||||||
|
logger.error(`转移流水线失败,pipeline:${id}不存在`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pipelineEntity.projectId === projectId) {
|
||||||
|
logger.info(`流水线:${id}已在项目${projectId}中,跳过`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const entity: any = {
|
||||||
|
...pipelineEntity,
|
||||||
|
id: pipelineEntity.id,
|
||||||
|
userId: userId,
|
||||||
|
projectId: projectId,
|
||||||
|
groupId: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
const pipeline = JSON.parse(pipelineEntity.content);
|
||||||
|
pipeline.userId = userId;
|
||||||
|
pipeline.projectId = projectId;
|
||||||
|
|
||||||
|
//转移和修改access 和 Notification
|
||||||
|
await eachSteps(pipeline, async (step) => {
|
||||||
|
const type = step.type;
|
||||||
|
//plugin
|
||||||
|
const pluginDefine: any = pluginRegistry.getDefine(type);
|
||||||
|
if (pluginDefine) {
|
||||||
|
for (const key in step.input) {
|
||||||
|
const value = step.input[key];
|
||||||
|
if (!value || value <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!pluginDefine.input[key]){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const componentName = pluginDefine.input[key].component?.name;
|
||||||
|
if (componentName === "access-selector" || componentName === "AccessSelector") {
|
||||||
|
//这是一个授权ID属性,检查是否需要转移授权
|
||||||
|
const newAccessId = await this.accessService.copyTo(value,projectId);
|
||||||
|
step.input[key] = newAccessId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
pipeline.notifications = [
|
||||||
|
{
|
||||||
|
"type": "custom",
|
||||||
|
"when": [
|
||||||
|
"error",
|
||||||
|
"turnToSuccess"
|
||||||
|
],
|
||||||
|
"notificationId": 0,
|
||||||
|
"title": "使用默认通知",
|
||||||
|
"id": nanoid()
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
entity.content = JSON.stringify(pipeline);
|
||||||
|
await this.unregisterTriggers(entity.id);
|
||||||
|
await this.repository.save(entity);
|
||||||
|
await this.save(entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async batchUpdateTrigger(ids: number[], trigger: any, userId: any, projectId?: number) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级专业版");
|
||||||
}
|
}
|
||||||
@@ -971,7 +1070,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
if (userId && userId > 0) {
|
if (userId && userId > 0) {
|
||||||
query.userId = userId;
|
query.userId = userId;
|
||||||
}
|
}
|
||||||
if(projectId){
|
if (projectId) {
|
||||||
query.projectId = projectId;
|
query.projectId = projectId;
|
||||||
}
|
}
|
||||||
const list = await this.find({
|
const list = await this.find({
|
||||||
@@ -1015,7 +1114,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async batchUpdateNotifications(ids: number[], notification: Notification, userId: any,projectId?:number) {
|
async batchUpdateNotifications(ids: number[], notification: Notification, userId: any, projectId?: number) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级专业版");
|
||||||
}
|
}
|
||||||
@@ -1023,7 +1122,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
if (userId && userId > 0) {
|
if (userId && userId > 0) {
|
||||||
query.userId = userId;
|
query.userId = userId;
|
||||||
}
|
}
|
||||||
if(projectId){
|
if (projectId) {
|
||||||
query.projectId = projectId;
|
query.projectId = projectId;
|
||||||
}
|
}
|
||||||
const list = await this.find({
|
const list = await this.find({
|
||||||
@@ -1053,7 +1152,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async batchRerun(ids: number[], force: boolean,userId: any, projectId?:number) {
|
async batchRerun(ids: number[], force: boolean, userId: any, projectId?: number) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级专业版");
|
||||||
}
|
}
|
||||||
@@ -1061,18 +1160,18 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
if (userId == null || ids.length === 0) {
|
if (userId == null || ids.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const where:any = {
|
const where: any = {
|
||||||
id: In(ids),
|
id: In(ids),
|
||||||
userId,
|
userId,
|
||||||
}
|
}
|
||||||
if(projectId){
|
if (projectId) {
|
||||||
where.projectId = 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: where
|
||||||
});
|
});
|
||||||
|
|
||||||
ids = list.map(item => item.id);
|
ids = list.map(item => item.id);
|
||||||
@@ -1100,7 +1199,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
return await this.repository.count({ where: { userId } });
|
return await this.repository.count({ where: { userId } });
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSimplePipelines(pipelineIds: number[], userId?: number,projectId?:number) {
|
async getSimplePipelines(pipelineIds: number[], userId?: number, projectId?: number) {
|
||||||
return await this.repository.find({
|
return await this.repository.find({
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
@@ -1116,9 +1215,9 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
|
|
||||||
|
|
||||||
private async checkUserStatus(userId: number) {
|
private async checkUserStatus(userId: number) {
|
||||||
if(isEnterprise()){
|
if (isEnterprise()) {
|
||||||
//企业模式不检查用户状态,都允许运行流水线
|
//企业模式不检查用户状态,都允许运行流水线
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const userEntity = await this.userService.info(userId);
|
const userEntity = await this.userService.info(userId);
|
||||||
if (userEntity == null) {
|
if (userEntity == null) {
|
||||||
@@ -1141,7 +1240,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async createAutoPipeline(req: { domains: string[]; email: string; userId: number,projectId?:number, from: string }) {
|
async createAutoPipeline(req: { domains: string[]; email: string; userId: number, projectId?: number, from: string }) {
|
||||||
|
|
||||||
const randomHour = Math.floor(Math.random() * 6);
|
const randomHour = Math.floor(Math.random() * 6);
|
||||||
const randomMin = Math.floor(Math.random() * 60);
|
const randomMin = Math.floor(Math.random() * 60);
|
||||||
|
|||||||
Reference in New Issue
Block a user