mirror of
https://github.com/certd/certd.git
synced 2026-04-23 19:57:27 +08:00
perf: 修复删除历史记录没有删除log的bug,新增history管理页面,演示站点启动时不自动启动非管理员用户的定时任务
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||
import { RoleService } from './role-service.js';
|
||||
import { BaseService } from '../../../basic/base-service.js';
|
||||
|
||||
/**
|
||||
* 权限校验
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
export class AuthService {
|
||||
@Inject()
|
||||
roleService: RoleService;
|
||||
|
||||
async checkPermission(ctx: any, permission: string) {
|
||||
//如果不是仅校验登录,还需要校验是否拥有权限
|
||||
const roleIds: number[] = ctx.user.roles;
|
||||
const permissions = await this.roleService.getCachedPermissionSetByRoleIds(roleIds);
|
||||
if (!permissions.has(permission)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async isAdmin(ctx: any) {
|
||||
const roleIds: number[] = ctx.user.roles;
|
||||
if (roleIds.includes(1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
async checkEntityUserId(ctx: any, service: BaseService<any>, id: any = 0, userKey = 'userId') {
|
||||
const isAdmin = await this.isAdmin(ctx);
|
||||
if (isAdmin) {
|
||||
return true;
|
||||
}
|
||||
await service.checkUserId(id, ctx.user.id, userKey);
|
||||
}
|
||||
}
|
||||
+6
-3
@@ -1,6 +1,6 @@
|
||||
import { Autoload, Config, Init, Inject, Scope, ScopeEnum } from '@midwayjs/core';
|
||||
import { PipelineService } from '../service/pipeline-service.js';
|
||||
import { logger } from '../../../utils/logger.js';
|
||||
import { PipelineService } from '../pipeline/service/pipeline-service.js';
|
||||
import { logger } from '../../utils/logger.js';
|
||||
|
||||
@Autoload()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@@ -8,6 +8,9 @@ export class AutoRegisterCron {
|
||||
@Inject()
|
||||
pipelineService: PipelineService;
|
||||
|
||||
@Config('preview.enabled')
|
||||
private preview: boolean;
|
||||
|
||||
// @Inject()
|
||||
// echoPlugin: EchoPlugin;
|
||||
@Config('cron.immediateTriggerOnce')
|
||||
@@ -16,7 +19,7 @@ export class AutoRegisterCron {
|
||||
@Init()
|
||||
async init() {
|
||||
logger.info('加载定时trigger开始');
|
||||
await this.pipelineService.onStartup(this.immediateTriggerOnce);
|
||||
await this.pipelineService.onStartup(this.immediateTriggerOnce, this.preview);
|
||||
// logger.info(this.echoPlugin, this.echoPlugin.test);
|
||||
// logger.info('加载定时trigger完成');
|
||||
//
|
||||
@@ -11,6 +11,8 @@ import { CommonException } from '../../../basic/exception/common-exception.js';
|
||||
import { PermissionException } from '../../../basic/exception/permission-exception.js';
|
||||
import * as fs from 'fs';
|
||||
import { logger } from '../../../utils/logger.js';
|
||||
import { AuthService } from '../../authority/service/auth-service.js';
|
||||
import { SysSettingsService } from '../../system/service/sys-settings-service.js';
|
||||
|
||||
/**
|
||||
* 证书
|
||||
@@ -25,19 +27,35 @@ export class HistoryController extends CrudController<HistoryService> {
|
||||
@Inject()
|
||||
logService: HistoryLogService;
|
||||
|
||||
@Inject()
|
||||
authService: AuthService;
|
||||
|
||||
@Inject()
|
||||
sysSettingsService: SysSettingsService;
|
||||
|
||||
getService() {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Post('/page', { summary: Constants.per.authOnly })
|
||||
async page(@Body(ALL) body) {
|
||||
body.query.userId = this.ctx.user.id;
|
||||
return super.page(body);
|
||||
const isAdmin = await this.authService.isAdmin(this.ctx);
|
||||
const publicSettings = await this.sysSettingsService.getPublicSettings();
|
||||
if (!(publicSettings.managerOtherUserPipeline && isAdmin)) {
|
||||
body.query.userId = this.ctx.user.id;
|
||||
}
|
||||
|
||||
const res = await super.page(body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Post('/list', { summary: Constants.per.authOnly })
|
||||
async list(@Body(ALL) body) {
|
||||
body.userId = this.ctx.user.id;
|
||||
const isAdmin = await this.authService.isAdmin(this.ctx);
|
||||
if (!isAdmin) {
|
||||
body.userId = this.ctx.user.id;
|
||||
}
|
||||
if (body.pipelineId == null) {
|
||||
return this.ok([]);
|
||||
}
|
||||
@@ -56,7 +74,7 @@ export class HistoryController extends CrudController<HistoryService> {
|
||||
|
||||
@Post('/update', { summary: Constants.per.authOnly })
|
||||
async update(@Body(ALL) bean) {
|
||||
await this.service.checkUserId(bean.id, this.ctx.user.id);
|
||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id);
|
||||
return super.update(bean);
|
||||
}
|
||||
|
||||
@@ -64,7 +82,7 @@ export class HistoryController extends CrudController<HistoryService> {
|
||||
async save(@Body(ALL) bean: HistoryEntity) {
|
||||
bean.userId = this.ctx.user.id;
|
||||
if (bean.id > 0) {
|
||||
await this.service.checkUserId(bean.id, this.ctx.user.id);
|
||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id);
|
||||
}
|
||||
await this.service.save(bean);
|
||||
return this.ok(bean.id);
|
||||
@@ -74,7 +92,7 @@ export class HistoryController extends CrudController<HistoryService> {
|
||||
async saveLog(@Body(ALL) bean: HistoryLogEntity) {
|
||||
bean.userId = this.ctx.user.id;
|
||||
if (bean.id > 0) {
|
||||
await this.service.checkUserId(bean.id, this.ctx.user.id);
|
||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id);
|
||||
}
|
||||
await this.logService.save(bean);
|
||||
return this.ok(bean.id);
|
||||
@@ -82,26 +100,37 @@ export class HistoryController extends CrudController<HistoryService> {
|
||||
|
||||
@Post('/delete', { summary: Constants.per.authOnly })
|
||||
async delete(@Query('id') id) {
|
||||
await this.service.checkUserId(id, this.ctx.user.id);
|
||||
return super.delete(id);
|
||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
|
||||
await super.delete(id);
|
||||
return this.ok();
|
||||
}
|
||||
|
||||
@Post('/deleteByIds', { summary: Constants.per.authOnly })
|
||||
async deleteByIds(@Body(ALL) body) {
|
||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), body.ids);
|
||||
const isAdmin = await this.authService.isAdmin(this.ctx);
|
||||
const userId = isAdmin ? null : this.ctx.user.id;
|
||||
await this.getService().deleteByIds(body.ids, userId);
|
||||
return this.ok();
|
||||
}
|
||||
|
||||
@Post('/detail', { summary: Constants.per.authOnly })
|
||||
async detail(@Query('id') id) {
|
||||
await this.service.checkUserId(id, this.ctx.user.id);
|
||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
|
||||
const detail = await this.service.detail(id);
|
||||
return this.ok(detail);
|
||||
}
|
||||
|
||||
@Post('/logs', { summary: Constants.per.authOnly })
|
||||
async logs(@Query('id') id) {
|
||||
await this.logService.checkUserId(id, this.ctx.user.id);
|
||||
await this.authService.checkEntityUserId(this.ctx, this.logService, id);
|
||||
const logInfo = await this.logService.info(id);
|
||||
return this.ok(logInfo);
|
||||
}
|
||||
|
||||
@Post('/files', { summary: Constants.per.authOnly })
|
||||
async files(@Query('pipelineId') pipelineId, @Query('historyId') historyId) {
|
||||
await this.authService.checkEntityUserId(this.ctx, this.service, historyId);
|
||||
const files = await this.getFiles(historyId, pipelineId);
|
||||
return this.ok(files);
|
||||
}
|
||||
@@ -125,6 +154,7 @@ export class HistoryController extends CrudController<HistoryService> {
|
||||
|
||||
@Get('/download', { summary: Constants.per.authOnly })
|
||||
async download(@Query('pipelineId') pipelineId, @Query('historyId') historyId, @Query('fileId') fileId) {
|
||||
await this.authService.checkEntityUserId(this.ctx, this.service, historyId);
|
||||
const files = await this.getFiles(historyId, pipelineId);
|
||||
const file = files.find(f => f.id === fileId);
|
||||
if (file == null) {
|
||||
|
||||
@@ -4,6 +4,8 @@ import { PipelineService } from '../service/pipeline-service.js';
|
||||
import { PipelineEntity } from '../entity/pipeline.js';
|
||||
import { Constants } from '../../../basic/constants.js';
|
||||
import { HistoryService } from '../service/history-service.js';
|
||||
import { AuthService } from '../../authority/service/auth-service.js';
|
||||
import { SysSettingsService } from '../../system/service/sys-settings-service.js';
|
||||
|
||||
/**
|
||||
* 证书
|
||||
@@ -15,6 +17,10 @@ export class PipelineController extends CrudController<PipelineService> {
|
||||
service: PipelineService;
|
||||
@Inject()
|
||||
historyService: HistoryService;
|
||||
@Inject()
|
||||
authService: AuthService;
|
||||
@Inject()
|
||||
sysSettingsService: SysSettingsService;
|
||||
|
||||
getService() {
|
||||
return this.service;
|
||||
@@ -22,7 +28,11 @@ export class PipelineController extends CrudController<PipelineService> {
|
||||
|
||||
@Post('/page', { summary: Constants.per.authOnly })
|
||||
async page(@Body(ALL) body) {
|
||||
body.query.userId = this.ctx.user.id;
|
||||
const isAdmin = await this.authService.isAdmin(this.ctx);
|
||||
const publicSettings = await this.sysSettingsService.getPublicSettings();
|
||||
if (!(publicSettings.managerOtherUserPipeline && isAdmin)) {
|
||||
body.query.userId = this.ctx.user.id;
|
||||
}
|
||||
|
||||
const title = body.query.title;
|
||||
delete body.query.title;
|
||||
@@ -47,7 +57,7 @@ export class PipelineController extends CrudController<PipelineService> {
|
||||
|
||||
@Post('/update', { summary: Constants.per.authOnly })
|
||||
async update(@Body(ALL) bean) {
|
||||
await this.service.checkUserId(bean.id, this.ctx.user.id);
|
||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id);
|
||||
return super.update(bean);
|
||||
}
|
||||
|
||||
@@ -55,7 +65,7 @@ export class PipelineController extends CrudController<PipelineService> {
|
||||
async save(@Body(ALL) bean: PipelineEntity) {
|
||||
bean.userId = this.ctx.user.id;
|
||||
if (bean.id > 0) {
|
||||
await this.service.checkUserId(bean.id, this.ctx.user.id);
|
||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), bean.id);
|
||||
}
|
||||
await this.service.save(bean);
|
||||
return this.ok(bean.id);
|
||||
@@ -63,28 +73,28 @@ export class PipelineController extends CrudController<PipelineService> {
|
||||
|
||||
@Post('/delete', { summary: Constants.per.authOnly })
|
||||
async delete(@Query('id') id) {
|
||||
await this.service.checkUserId(id, this.ctx.user.id);
|
||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
|
||||
await this.service.delete(id);
|
||||
return this.ok({});
|
||||
}
|
||||
|
||||
@Post('/detail', { summary: Constants.per.authOnly })
|
||||
async detail(@Query('id') id) {
|
||||
await this.service.checkUserId(id, this.ctx.user.id);
|
||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
|
||||
const detail = await this.service.detail(id);
|
||||
return this.ok(detail);
|
||||
}
|
||||
|
||||
@Post('/trigger', { summary: Constants.per.authOnly })
|
||||
async trigger(@Query('id') id) {
|
||||
await this.service.checkUserId(id, this.ctx.user.id);
|
||||
await this.authService.checkEntityUserId(this.ctx, this.getService(), id);
|
||||
await this.service.trigger(id);
|
||||
return this.ok({});
|
||||
}
|
||||
|
||||
@Post('/cancel', { summary: Constants.per.authOnly })
|
||||
async cancel(@Query('historyId') historyId) {
|
||||
await this.historyService.checkUserId(historyId, this.ctx.user.id);
|
||||
await this.authService.checkEntityUserId(this.ctx, this.historyService, historyId);
|
||||
await this.service.cancel(historyId);
|
||||
return this.ok({});
|
||||
}
|
||||
|
||||
@@ -35,4 +35,13 @@ export class HistoryEntity {
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
|
||||
pipelineTitle: string;
|
||||
|
||||
fillPipelineTitle() {
|
||||
if (this.pipeline) {
|
||||
const pipeline = JSON.parse(this.pipeline);
|
||||
this.pipelineTitle = pipeline.title;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { In, Repository } from 'typeorm';
|
||||
import { BaseService } from '../../../basic/base-service.js';
|
||||
import { HistoryLogEntity } from '../entity/history-log.js';
|
||||
|
||||
@@ -24,4 +24,11 @@ export class HistoryLogService extends BaseService<HistoryLogEntity> {
|
||||
await this.add(bean);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteByHistoryIds(numbers: number[]) {
|
||||
if (numbers.length === 0) {
|
||||
return;
|
||||
}
|
||||
await this.repository.delete({ historyId: In(numbers) });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Config, Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { In, Repository } from 'typeorm';
|
||||
import { BaseService } from '../../../basic/base-service.js';
|
||||
import { HistoryEntity } from '../entity/history.js';
|
||||
import { PipelineEntity } from '../entity/pipeline.js';
|
||||
@@ -28,6 +28,14 @@ export class HistoryService extends BaseService<HistoryEntity> {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
async page(query, page, sort, buildQuery) {
|
||||
const res = await super.page(query, page, sort, buildQuery);
|
||||
for (const item of res.records) {
|
||||
item.fillPipelineTitle();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
async save(bean: HistoryEntity) {
|
||||
if (bean.id > 0) {
|
||||
await this.update(bean);
|
||||
@@ -51,7 +59,7 @@ export class HistoryService extends BaseService<HistoryEntity> {
|
||||
};
|
||||
const { id } = await this.add(bean);
|
||||
//清除大于pipeline.keepHistoryCount的历史记录
|
||||
this.clear(pipeline.id, pipeline.keepHistoryCount);
|
||||
await this.clear(pipeline.id, pipeline.keepHistoryCount);
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -85,7 +93,6 @@ export class HistoryService extends BaseService<HistoryEntity> {
|
||||
skip: 0,
|
||||
take: deleteCountBatch,
|
||||
});
|
||||
await this.repository.remove(list);
|
||||
|
||||
for (const historyEntity of list) {
|
||||
const id = historyEntity.id;
|
||||
@@ -95,6 +102,9 @@ export class HistoryService extends BaseService<HistoryEntity> {
|
||||
logger.error('删除文件失败', e);
|
||||
}
|
||||
}
|
||||
await this.repository.remove(list);
|
||||
|
||||
await this.logService.deleteByHistoryIds(list.map(item => item.id));
|
||||
|
||||
shouldDeleteCount -= deleteCountBatch;
|
||||
}
|
||||
@@ -124,4 +134,12 @@ export class HistoryService extends BaseService<HistoryEntity> {
|
||||
});
|
||||
return files;
|
||||
}
|
||||
|
||||
async deleteByIds(ids: number[], userId: number) {
|
||||
await this.repository.delete({
|
||||
id: In(ids),
|
||||
userId,
|
||||
});
|
||||
await this.logService.deleteByHistoryIds(ids);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,11 +100,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
await this.registerTriggerById(bean.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用启动后初始加载记录
|
||||
*/
|
||||
async onStartup(immediateTriggerOnce: boolean) {
|
||||
logger.info('加载定时trigger开始');
|
||||
async foreachPipeline(callback: (pipeline: PipelineEntity) => void) {
|
||||
const idEntityList = await this.repository.find({
|
||||
select: {
|
||||
id: true,
|
||||
@@ -135,14 +131,35 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
});
|
||||
|
||||
for (const entity of list) {
|
||||
const pipeline = JSON.parse(entity.content ?? '{}');
|
||||
try {
|
||||
await this.registerTriggers(pipeline, immediateTriggerOnce);
|
||||
} catch (e) {
|
||||
logger.error('加载定时trigger失败:', e);
|
||||
}
|
||||
await callback(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async stopOtherUserPipeline(userId: number) {
|
||||
await this.foreachPipeline(async entity => {
|
||||
if (entity.userId !== userId) {
|
||||
await this.clearTriggers(entity.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用启动后初始加载记录
|
||||
*/
|
||||
async onStartup(immediateTriggerOnce: boolean, preview: boolean) {
|
||||
logger.info('加载定时trigger开始');
|
||||
await this.foreachPipeline(async entity => {
|
||||
if (preview && entity.userId !== 1) {
|
||||
return;
|
||||
}
|
||||
const pipeline = JSON.parse(entity.content ?? '{}');
|
||||
try {
|
||||
await this.registerTriggers(pipeline, immediateTriggerOnce);
|
||||
} catch (e) {
|
||||
logger.error('加载定时trigger失败:', e);
|
||||
}
|
||||
});
|
||||
logger.info('定时器数量:', this.cron.getTaskSize());
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { SysSettingsService } from '../service/sys-settings-service.js';
|
||||
import { SysSettingsEntity } from '../entity/sys-settings.js';
|
||||
import { SysPublicSettings } from '../service/models.js';
|
||||
import * as _ from 'lodash-es';
|
||||
import { PipelineService } from '../../pipeline/service/pipeline-service.js';
|
||||
|
||||
/**
|
||||
*/
|
||||
@@ -12,6 +13,8 @@ import * as _ from 'lodash-es';
|
||||
export class SysSettingsController extends CrudController<SysSettingsService> {
|
||||
@Inject()
|
||||
service: SysSettingsService;
|
||||
@Inject()
|
||||
pipelineService: PipelineService;
|
||||
|
||||
getService() {
|
||||
return this.service;
|
||||
@@ -73,4 +76,9 @@ export class SysSettingsController extends CrudController<SysSettingsService> {
|
||||
await this.service.savePublicSettings(setting);
|
||||
return this.ok({});
|
||||
}
|
||||
@Post('/stopOtherUserTimer', { summary: 'sys:settings:edit' })
|
||||
async stopOtherUserTimer(@Body(ALL) body) {
|
||||
await this.pipelineService.stopOtherUserPipeline(1);
|
||||
return this.ok({});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ export class SysPublicSettings extends BaseSettings {
|
||||
static __title__ = '系统公共设置';
|
||||
static __access__ = 'public';
|
||||
registerEnabled = false;
|
||||
managerOtherUserPipeline = false;
|
||||
}
|
||||
|
||||
export class SysPrivateSettings extends BaseSettings {
|
||||
|
||||
Reference in New Issue
Block a user