mirror of
https://github.com/certd/certd.git
synced 2026-04-23 19:57:27 +08:00
build: trident-sync prepare
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
import {
|
||||
ALL,
|
||||
Body,
|
||||
Controller,
|
||||
Inject,
|
||||
Post,
|
||||
Provide,
|
||||
Query,
|
||||
} from '@midwayjs/decorator';
|
||||
import { CrudController } from '../../../basic/crud-controller';
|
||||
import { PermissionService } from '../service/permission-service';
|
||||
|
||||
/**
|
||||
* 权限资源
|
||||
*/
|
||||
@Provide()
|
||||
@Controller('/api/sys/authority/permission')
|
||||
export class PermissionController extends CrudController {
|
||||
@Inject()
|
||||
service: PermissionService;
|
||||
|
||||
getService() {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Post('/page')
|
||||
async page(
|
||||
@Body(ALL)
|
||||
body
|
||||
) {
|
||||
return await super.page(body);
|
||||
}
|
||||
|
||||
@Post('/add')
|
||||
async add(
|
||||
@Body(ALL)
|
||||
bean
|
||||
) {
|
||||
return await super.add(bean);
|
||||
}
|
||||
|
||||
@Post('/update')
|
||||
async update(
|
||||
@Body(ALL)
|
||||
bean
|
||||
) {
|
||||
return await super.update(bean);
|
||||
}
|
||||
@Post('/delete')
|
||||
async delete(
|
||||
@Query('id')
|
||||
id
|
||||
) {
|
||||
return await super.delete(id);
|
||||
}
|
||||
|
||||
@Post('/tree')
|
||||
async tree() {
|
||||
const tree = await this.service.tree({});
|
||||
return this.ok(tree);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import {
|
||||
ALL,
|
||||
Body,
|
||||
Controller,
|
||||
Inject,
|
||||
Post,
|
||||
Provide,
|
||||
Query,
|
||||
} from '@midwayjs/decorator';
|
||||
import { CrudController } from '../../../basic/crud-controller';
|
||||
import { RoleService } from '../service/role-service';
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*/
|
||||
@Provide()
|
||||
@Controller('/api/sys/authority/role')
|
||||
export class RoleController extends CrudController {
|
||||
@Inject()
|
||||
service: RoleService;
|
||||
|
||||
getService() {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Post('/page')
|
||||
async page(
|
||||
@Body(ALL)
|
||||
body
|
||||
) {
|
||||
return await super.page(body);
|
||||
}
|
||||
|
||||
@Post('/list')
|
||||
async list() {
|
||||
const ret = await this.service.find({});
|
||||
return this.ok(ret);
|
||||
}
|
||||
|
||||
@Post('/add')
|
||||
async add(
|
||||
@Body(ALL)
|
||||
bean
|
||||
) {
|
||||
return await super.add(bean);
|
||||
}
|
||||
|
||||
@Post('/update')
|
||||
async update(
|
||||
@Body(ALL)
|
||||
bean
|
||||
) {
|
||||
return await super.update(bean);
|
||||
}
|
||||
@Post('/delete')
|
||||
async delete(
|
||||
@Query('id')
|
||||
id
|
||||
) {
|
||||
return await super.delete(id);
|
||||
}
|
||||
|
||||
@Post('/getPermissionTree')
|
||||
async getPermissionTree(
|
||||
@Query('id')
|
||||
id
|
||||
) {
|
||||
const ret = await this.service.getPermissionTreeByRoleId(id);
|
||||
return this.ok(ret);
|
||||
}
|
||||
|
||||
@Post('/getPermissionIds')
|
||||
async getPermissionIds(
|
||||
@Query('id')
|
||||
id
|
||||
) {
|
||||
const ret = await this.service.getPermissionIdsByRoleId(id);
|
||||
return this.ok(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给角色授予权限
|
||||
* @param id
|
||||
*/
|
||||
@Post('/authz')
|
||||
async authz(
|
||||
@Body('roleId')
|
||||
roleId,
|
||||
@Body('permissionIds')
|
||||
permissionIds
|
||||
) {
|
||||
await this.service.authz(roleId, permissionIds);
|
||||
return this.ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
import {
|
||||
Provide,
|
||||
Controller,
|
||||
Post,
|
||||
Inject,
|
||||
Body,
|
||||
Query,
|
||||
ALL,
|
||||
} from '@midwayjs/decorator';
|
||||
import { UserService } from '../service/user-service';
|
||||
import { CrudController } from '../../../basic/crud-controller';
|
||||
import { RoleService } from '../service/role-service';
|
||||
import { PermissionService } from '../service/permission-service';
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*/
|
||||
@Provide()
|
||||
@Controller('/api/sys/authority/user')
|
||||
export class UserController extends CrudController {
|
||||
@Inject()
|
||||
service: UserService;
|
||||
|
||||
@Inject()
|
||||
roleService: RoleService;
|
||||
@Inject()
|
||||
permissionService: PermissionService;
|
||||
|
||||
getService() {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Post('/page')
|
||||
async page(
|
||||
@Body(ALL)
|
||||
body
|
||||
) {
|
||||
const ret = await super.page(body);
|
||||
|
||||
const users = ret.data.records;
|
||||
|
||||
//获取roles
|
||||
const userIds = users.map(item => item.id);
|
||||
const userRoles = await this.roleService.getByUserIds(userIds);
|
||||
const userRolesMap = new Map();
|
||||
for (const ur of userRoles) {
|
||||
let roles = userRolesMap.get(ur.userId);
|
||||
if (roles == null) {
|
||||
roles = [];
|
||||
userRolesMap.set(ur.userId, roles);
|
||||
}
|
||||
roles.push(ur.roleId);
|
||||
}
|
||||
|
||||
for (const record of users) {
|
||||
//withRoles
|
||||
record.roles = userRolesMap.get(record.id);
|
||||
//删除密码字段
|
||||
delete record.password;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Post('/add')
|
||||
async add(
|
||||
@Body(ALL)
|
||||
bean
|
||||
) {
|
||||
return await super.add(bean);
|
||||
}
|
||||
|
||||
@Post('/update')
|
||||
async update(
|
||||
@Body(ALL)
|
||||
bean
|
||||
) {
|
||||
return await super.update(bean);
|
||||
}
|
||||
@Post('/delete')
|
||||
async delete(
|
||||
@Query('id')
|
||||
id
|
||||
) {
|
||||
return await super.delete(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前登录用户的个人信息
|
||||
*/
|
||||
@Post('/mine')
|
||||
public async mine() {
|
||||
const id = this.ctx.user.id;
|
||||
const info = await this.service.info(id, ['password']);
|
||||
return this.ok(info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前登录用户的权限列表
|
||||
*/
|
||||
@Post('/permissions')
|
||||
public async permissions() {
|
||||
const id = this.ctx.user.id;
|
||||
const permissions = await this.service.getUserPermissions(id);
|
||||
return this.ok(permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前登录用户的权限树形列表
|
||||
*/
|
||||
@Post('/permissionTree')
|
||||
public async permissionTree() {
|
||||
const id = this.ctx.user.id;
|
||||
const permissions = await this.service.getUserPermissions(id);
|
||||
const tree = this.permissionService.buildTree(permissions);
|
||||
return this.ok(tree);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 权限
|
||||
*/
|
||||
@Entity('sys_permission')
|
||||
export class PermissionEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
@Column({ comment: '标题', length: 100 })
|
||||
title: string;
|
||||
/**
|
||||
* 权限代码
|
||||
* 示例:sys:user:read
|
||||
*/
|
||||
@Column({ comment: '权限代码', length: 100, nullable: true })
|
||||
permission: string;
|
||||
|
||||
@Column({ name: 'parent_id', comment: '父节点ID', default: -1 })
|
||||
parentId: number;
|
||||
|
||||
@Column({ comment: '排序号' })
|
||||
sort: number;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
createTime: Date;
|
||||
@Column({
|
||||
name: 'update_time',
|
||||
comment: '修改时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
|
||||
// @ManyToMany(type => RoleEntity, res => res.permissions)
|
||||
// roles: RoleEntity[];
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Entity, PrimaryColumn } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 角色权限多对多
|
||||
*/
|
||||
@Entity('sys_role_permission')
|
||||
export class RolePermissionEntity {
|
||||
@PrimaryColumn({ name: 'role_id' })
|
||||
roleId: number;
|
||||
@PrimaryColumn({ name: 'permission_id' })
|
||||
permissionId: number;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 角色
|
||||
*/
|
||||
@Entity('sys_role')
|
||||
export class RoleEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
@Index({ unique: true })
|
||||
@Column({ comment: '角色名称', length: 100 })
|
||||
name: string;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
createTime: Date;
|
||||
@Column({
|
||||
name: 'update_time',
|
||||
comment: '修改时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
|
||||
// @ManyToMany(type => PermissionEntity, res => res.roles)
|
||||
// @JoinTable({
|
||||
// name: 'sys_role_resources',
|
||||
// joinColumn: {
|
||||
// name: 'roleId',
|
||||
// referencedColumnName: 'id',
|
||||
// },
|
||||
// inverseJoinColumn: {
|
||||
// name: 'resourceId',
|
||||
// referencedColumnName: 'id',
|
||||
// },
|
||||
// })
|
||||
// resources: PermissionEntity[];
|
||||
|
||||
// @ManyToMany(type => UserEntity, res => res.roles)
|
||||
// users: UserEntity[];
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Entity, PrimaryColumn } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 用户角色多对多
|
||||
*/
|
||||
@Entity('sys_user_role')
|
||||
export class UserRoleEntity {
|
||||
@PrimaryColumn({ name: 'role_id' })
|
||||
roleId: number;
|
||||
@PrimaryColumn({ name: 'user_id' })
|
||||
userId: number;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*/
|
||||
@Entity('sys_user')
|
||||
export class UserEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
@Index({ unique: true })
|
||||
@Column({ comment: '用户名', length: 100 })
|
||||
username: string;
|
||||
|
||||
@Column({ comment: '密码', length: 100 })
|
||||
password: string;
|
||||
|
||||
@Column({ name: 'nick_name', comment: '昵称', length: 100, nullable: true })
|
||||
nickName: string;
|
||||
|
||||
@Column({ comment: '头像', length: 255, nullable: true })
|
||||
avatar: string;
|
||||
|
||||
@Column({ name: 'phone_code', comment: '区号', length: 20, nullable: true })
|
||||
phoneCode: string;
|
||||
|
||||
@Column({ comment: '手机', length: 20, nullable: true })
|
||||
mobile: string;
|
||||
|
||||
@Column({ comment: '邮箱', length: 50, nullable: true })
|
||||
email: string;
|
||||
|
||||
@Column({ comment: '备注', length: 100, nullable: true })
|
||||
remark: string;
|
||||
|
||||
@Column({ comment: '状态 0:禁用 1:启用', default: 1, type: 'int' })
|
||||
status: number;
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
createTime: Date;
|
||||
@Column({
|
||||
name: 'update_time',
|
||||
comment: '修改时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
|
||||
// @ManyToMany(type => RoleEntity, res => res.users)
|
||||
// @JoinTable({
|
||||
// name: 'sys_user_roles',
|
||||
// joinColumn: {
|
||||
// name: 'userId',
|
||||
// referencedColumnName: 'id',
|
||||
// },
|
||||
// inverseJoinColumn: {
|
||||
// name: 'roleId',
|
||||
// referencedColumnName: 'id',
|
||||
// },
|
||||
// })
|
||||
// roles: RoleEntity[];
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { EnumItem } from '../../../basic/enum-item';
|
||||
import * as _ from 'lodash';
|
||||
class ResourceTypes {
|
||||
MENU = new EnumItem('menu', '菜单', 'blue');
|
||||
BTN = new EnumItem('btn', '按钮', 'green');
|
||||
ROUTE = new EnumItem('route', '路由', 'red');
|
||||
|
||||
names() {
|
||||
const list = [];
|
||||
_.forEach(this, (item, key) => {
|
||||
list.push(item);
|
||||
});
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
export const ResourceTypeEnum = new ResourceTypes();
|
||||
@@ -0,0 +1,52 @@
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseService } from '../../../basic/base-service';
|
||||
import { PermissionEntity } from '../entity/permission';
|
||||
|
||||
/**
|
||||
* 权限资源
|
||||
*/
|
||||
@Provide()
|
||||
export class PermissionService extends BaseService<PermissionEntity> {
|
||||
@InjectEntityModel(PermissionEntity)
|
||||
repository: Repository<PermissionEntity>;
|
||||
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
async tree(options: any = {}) {
|
||||
if (options.order == null) {
|
||||
options.order = {
|
||||
sort: 'ASC',
|
||||
};
|
||||
}
|
||||
const list = await this.find(options);
|
||||
return this.buildTree(list);
|
||||
}
|
||||
|
||||
buildTree(list: any) {
|
||||
const idMap = {};
|
||||
const root = [];
|
||||
for (const item of list) {
|
||||
idMap[item.id] = item;
|
||||
if (item.parentId == null || item.parentId <= 0) {
|
||||
root.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of list) {
|
||||
if (item.parentId > 0) {
|
||||
const parent = idMap[item.parentId];
|
||||
if (parent) {
|
||||
if (parent.children == null) {
|
||||
parent.children = [];
|
||||
}
|
||||
parent.children.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseService } from '../../../basic/base-service';
|
||||
import { RolePermissionEntity } from '../entity/role-permission';
|
||||
|
||||
/**
|
||||
* 角色->权限
|
||||
*/
|
||||
@Provide()
|
||||
export class RolePermissionService extends BaseService<RolePermissionEntity> {
|
||||
@InjectEntityModel(RolePermissionEntity)
|
||||
repository: Repository<RolePermissionEntity>;
|
||||
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { In, Repository } from 'typeorm';
|
||||
import { BaseService } from '../../../basic/base-service';
|
||||
import { RoleEntity } from '../entity/role';
|
||||
import { UserRoleService } from './user-role-service';
|
||||
import { RolePermissionEntity } from '../entity/role-permission';
|
||||
import { PermissionService } from './permission-service';
|
||||
import * as _ from 'lodash';
|
||||
import { RolePermissionService } from './role-permission-service';
|
||||
/**
|
||||
* 角色
|
||||
*/
|
||||
@Provide()
|
||||
export class RoleService extends BaseService<RoleEntity> {
|
||||
@InjectEntityModel(RoleEntity)
|
||||
repository: Repository<RoleEntity>;
|
||||
@Inject()
|
||||
userRoleService: UserRoleService;
|
||||
@Inject()
|
||||
permissionService: PermissionService;
|
||||
@Inject()
|
||||
rolePermissionService: RolePermissionService;
|
||||
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
async getRoleIdsByUserId(id: any) {
|
||||
const userRoles = await this.userRoleService.find({
|
||||
where: { userId: id },
|
||||
});
|
||||
return userRoles.map(item => item.roleId);
|
||||
}
|
||||
async getByUserIds(ids: any) {
|
||||
return await this.userRoleService.find({
|
||||
where: {
|
||||
userId: In(ids),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getPermissionByRoleIds(roleIds: any) {
|
||||
return await this.permissionService.repository
|
||||
.createQueryBuilder('permission')
|
||||
.innerJoinAndSelect(
|
||||
RolePermissionEntity,
|
||||
'rp',
|
||||
'rp.permissionId = permission.id and rp.roleId in (:...roleIds)',
|
||||
{ roleIds }
|
||||
)
|
||||
.getMany();
|
||||
}
|
||||
|
||||
async addRoles(userId: number, roles) {
|
||||
if (roles == null || roles.length === 0) {
|
||||
return;
|
||||
}
|
||||
for (const roleId of roles) {
|
||||
await this.userRoleService.add({
|
||||
userId,
|
||||
roleId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async updateRoles(userId, roles) {
|
||||
if (roles == null) {
|
||||
return;
|
||||
}
|
||||
const oldRoleIds = await this.getRoleIdsByUserId(userId);
|
||||
if (_.xor(roles, oldRoleIds).length === 0) {
|
||||
//如果两个数组相等,则不修改
|
||||
return;
|
||||
}
|
||||
//先删除所有
|
||||
await this.userRoleService.delete({ userId });
|
||||
//再添加
|
||||
await this.addRoles(userId, roles);
|
||||
}
|
||||
|
||||
async getPermissionTreeByRoleId(id: any) {
|
||||
const list = await this.getPermissionByRoleIds([id]);
|
||||
return this.permissionService.buildTree(list);
|
||||
}
|
||||
|
||||
async getPermissionIdsByRoleId(id: any) {
|
||||
const list = await this.getPermissionByRoleIds([id]);
|
||||
return list.map(item => item.id);
|
||||
}
|
||||
|
||||
async authz(roleId: any, permissionIds: any) {
|
||||
await this.rolePermissionService.delete({ roleId });
|
||||
for (const permissionId of permissionIds) {
|
||||
await this.rolePermissionService.add({
|
||||
roleId,
|
||||
permissionId,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Provide } from '@midwayjs/decorator';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseService } from '../../../basic/base-service';
|
||||
import { UserRoleEntity } from '../entity/user-role';
|
||||
|
||||
/**
|
||||
* 用户->角色
|
||||
*/
|
||||
@Provide()
|
||||
export class UserRoleService extends BaseService<UserRoleEntity> {
|
||||
@InjectEntityModel(UserRoleEntity)
|
||||
repository: Repository<UserRoleEntity>;
|
||||
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { UserEntity } from '../entity/user';
|
||||
import _ from 'lodash';
|
||||
import md5 from 'md5';
|
||||
import { CommonException } from '../../../basic/exception/common-exception';
|
||||
import { BaseService } from '../../../basic/base-service';
|
||||
import { logger } from '../../../utils/logger';
|
||||
import { RoleService } from './role-service';
|
||||
import { PermissionService } from './permission-service';
|
||||
import { UserRoleService } from './user-role-service';
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*/
|
||||
@Provide()
|
||||
export class UserService extends BaseService<UserEntity> {
|
||||
@InjectEntityModel(UserEntity)
|
||||
repository: Repository<UserEntity>;
|
||||
@Inject()
|
||||
roleService: RoleService;
|
||||
@Inject()
|
||||
permissionService: PermissionService;
|
||||
@Inject()
|
||||
userRoleService: UserRoleService;
|
||||
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得个人信息
|
||||
*/
|
||||
async mine() {
|
||||
const info = await this.repository.findOne({
|
||||
where: {
|
||||
id: this.ctx.user.id,
|
||||
},
|
||||
});
|
||||
delete info.password;
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增
|
||||
* @param param
|
||||
*/
|
||||
async add(param) {
|
||||
const exists = await this.repository.findOne({
|
||||
where: {
|
||||
username: param.username,
|
||||
},
|
||||
});
|
||||
if (!_.isEmpty(exists)) {
|
||||
throw new CommonException('用户名已经存在');
|
||||
}
|
||||
const password = param.password ?? '123456';
|
||||
param.password = md5(password); // 默认密码 建议未改密码不能登陆
|
||||
await super.add(param);
|
||||
//添加角色
|
||||
if (param.roles && param.roles.length > 0) {
|
||||
await this.roleService.addRoles(param.id, param.roles);
|
||||
}
|
||||
return param.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改
|
||||
* @param param 数据
|
||||
*/
|
||||
async update(param) {
|
||||
if (param.id == null) {
|
||||
throw new CommonException('id不能为空');
|
||||
}
|
||||
const userInfo = await this.repository.findOne({
|
||||
where: { id: param.id },
|
||||
});
|
||||
if (!userInfo) {
|
||||
throw new CommonException('用户不存在');
|
||||
}
|
||||
|
||||
delete param.username;
|
||||
if (!_.isEmpty(param.password)) {
|
||||
param.password = md5(param.password);
|
||||
} else {
|
||||
delete param.password;
|
||||
}
|
||||
await super.update(param);
|
||||
await this.roleService.updateRoles(param.id, param.roles);
|
||||
}
|
||||
|
||||
async findOne(param) {
|
||||
return this.repository.findOne({
|
||||
where: param,
|
||||
});
|
||||
}
|
||||
|
||||
checkPassword(rawPassword: any, md5Password: any) {
|
||||
logger.info('md5', md5('123456'));
|
||||
return md5(rawPassword) === md5Password;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的菜单资源列表
|
||||
* @param id
|
||||
*/
|
||||
async getUserPermissions(id: any) {
|
||||
const roleIds = await this.roleService.getRoleIdsByUserId(id);
|
||||
|
||||
return await this.roleService.getPermissionByRoleIds(roleIds);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Rule, RuleType } from '@midwayjs/validate';
|
||||
import { ALL, Inject } from '@midwayjs/decorator';
|
||||
import { Body } from '@midwayjs/decorator';
|
||||
import { Controller, Post, Provide } from '@midwayjs/decorator';
|
||||
import { BaseController } from '../../../basic/base-controller';
|
||||
import { CodeService } from '../service/code-service';
|
||||
export class SmsCodeReq {
|
||||
@Rule(RuleType.number().required())
|
||||
phoneCode: number;
|
||||
|
||||
@Rule(RuleType.string().required())
|
||||
mobile: string;
|
||||
|
||||
@Rule(RuleType.string().required().max(10))
|
||||
randomStr: string;
|
||||
|
||||
@Rule(RuleType.number().required().max(4))
|
||||
imgCode: string;
|
||||
}
|
||||
|
||||
// const enumsMap = {};
|
||||
// glob('src/modules/**/enums/*.ts', {}, (err, matches) => {
|
||||
// console.log('matched', matches);
|
||||
// for (const filePath of matches) {
|
||||
// const module = require('/' + filePath);
|
||||
// console.log('modules', module);
|
||||
// }
|
||||
// });
|
||||
|
||||
/**
|
||||
*/
|
||||
@Provide()
|
||||
@Controller('/api/basic')
|
||||
export class BasicController extends BaseController {
|
||||
@Inject()
|
||||
codeService: CodeService;
|
||||
@Post('/sendSmsCode')
|
||||
public sendSmsCode(
|
||||
@Body(ALL)
|
||||
body: SmsCodeReq
|
||||
) {
|
||||
// 设置缓存内容
|
||||
return this.ok(null);
|
||||
}
|
||||
|
||||
@Post('/captcha')
|
||||
public async getCaptcha(
|
||||
@Body()
|
||||
randomStr
|
||||
) {
|
||||
console.assert(randomStr < 10, 'randomStr 过长');
|
||||
const captcha = await this.codeService.generateCaptcha(randomStr);
|
||||
return this.ok(captcha.data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import { Inject, Provide } from '@midwayjs/decorator';
|
||||
import { CacheManager } from '@midwayjs/cache';
|
||||
const svgCaptcha = require('svg-captcha');
|
||||
|
||||
// {data: '<svg.../svg>', text: 'abcd'}
|
||||
/**
|
||||
*/
|
||||
@Provide()
|
||||
export class CodeService {
|
||||
@Inject()
|
||||
cache: CacheManager; // 依赖注入CacheManager
|
||||
|
||||
/**
|
||||
*/
|
||||
async generateCaptcha(randomStr) {
|
||||
console.assert(randomStr < 10, 'randomStr 过长');
|
||||
const c = svgCaptcha.create();
|
||||
//{data: '<svg.../svg>', text: 'abcd'}
|
||||
const imgCode = c.text; // = RandomUtil.randomStr(4, true);
|
||||
await this.cache.set('imgCode:' + randomStr, imgCode, {
|
||||
ttl: 2 * 60 * 1000, //过期时间 2分钟
|
||||
});
|
||||
return c;
|
||||
}
|
||||
|
||||
async getCaptchaText(randomStr) {
|
||||
return await this.cache.get('imgCode:' + randomStr);
|
||||
}
|
||||
|
||||
async removeCaptcha(randomStr) {
|
||||
await this.cache.del('imgCode:' + randomStr);
|
||||
}
|
||||
|
||||
async checkCaptcha(randomStr, userCaptcha) {
|
||||
const code = await this.getCaptchaText(randomStr);
|
||||
if (code == null) {
|
||||
throw new Error('验证码已过期');
|
||||
}
|
||||
if (code !== userCaptcha) {
|
||||
throw new Error('验证码不正确');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
*/
|
||||
async sendSms(phoneCode, mobile, smsCode) {
|
||||
console.assert(phoneCode != null && mobile != null, '手机号不能为空');
|
||||
console.assert(smsCode != null, '验证码不能为空');
|
||||
}
|
||||
|
||||
/**
|
||||
* loginBySmsCode
|
||||
*/
|
||||
async loginBySmsCode(user, smsCode) {
|
||||
console.assert(user.mobile != null, '手机号不能为空');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Inject,
|
||||
Post,
|
||||
Provide,
|
||||
ALL,
|
||||
} from '@midwayjs/decorator';
|
||||
import { LoginService } from '../service/login-service';
|
||||
import { BaseController } from '../../../basic/base-controller';
|
||||
|
||||
/**
|
||||
*/
|
||||
@Provide()
|
||||
@Controller('/api/')
|
||||
export class LoginController extends BaseController {
|
||||
@Inject()
|
||||
loginService: LoginService;
|
||||
@Post('/login')
|
||||
public async login(
|
||||
@Body(ALL)
|
||||
user
|
||||
) {
|
||||
const token = await this.loginService.login(user);
|
||||
return this.ok(token);
|
||||
}
|
||||
|
||||
@Post('/logout')
|
||||
public logout() {}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { Config, Inject, Provide } from '@midwayjs/decorator';
|
||||
import { UserService } from '../../authority/service/user-service';
|
||||
import * as jwt from 'jsonwebtoken';
|
||||
import { CommonException } from '../../../basic/exception/common-exception';
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*/
|
||||
@Provide()
|
||||
export class LoginService {
|
||||
@Inject()
|
||||
userService: UserService;
|
||||
@Config('biz.jwt')
|
||||
private jwt: any;
|
||||
|
||||
/**
|
||||
* login
|
||||
*/
|
||||
async login(user) {
|
||||
console.assert(user.username != null, '用户名不能为空');
|
||||
const info = await this.userService.findOne({ username: user.username });
|
||||
if (info == null) {
|
||||
throw new CommonException('用户名或密码错误');
|
||||
}
|
||||
const right = this.userService.checkPassword(user.password, info.password);
|
||||
if (!right) {
|
||||
throw new CommonException('用户名或密码错误');
|
||||
}
|
||||
|
||||
return this.generateToken(info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成token
|
||||
* @param user 用户对象
|
||||
*/
|
||||
async generateToken(user) {
|
||||
const tokenInfo = {
|
||||
username: user.username,
|
||||
id: user.id,
|
||||
};
|
||||
const expire = this.jwt.expire;
|
||||
const token = jwt.sign(tokenInfo, this.jwt.secret, {
|
||||
expiresIn: expire,
|
||||
});
|
||||
|
||||
return {
|
||||
token,
|
||||
expire,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Autoload, Init, Inject, Scope, ScopeEnum } from "@midwayjs/decorator";
|
||||
import { PipelineService } from '../service/pipeline-service';
|
||||
import { logger } from '../../../utils/logger';
|
||||
|
||||
@Autoload()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
export class AutoRegisterCron {
|
||||
@Inject()
|
||||
pipelineService: PipelineService;
|
||||
|
||||
// @Inject()
|
||||
// echoPlugin: EchoPlugin;
|
||||
|
||||
@Init()
|
||||
async init() {
|
||||
logger.info('加载定时trigger开始');
|
||||
await this.pipelineService.onStartup();
|
||||
// logger.info(this.echoPlugin, this.echoPlugin.test);
|
||||
// logger.info('加载定时trigger完成');
|
||||
//
|
||||
// const meta = getClassMetadata(CLASS_KEY, this.echoPlugin);
|
||||
// console.log('meta', meta);
|
||||
// const metas = listPropertyDataFromClass(CLASS_KEY, this.echoPlugin);
|
||||
// console.log('metas', metas);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import {
|
||||
ALL,
|
||||
Body,
|
||||
Controller,
|
||||
Inject,
|
||||
Post,
|
||||
Provide,
|
||||
Query,
|
||||
} from '@midwayjs/decorator';
|
||||
import { CrudController } from '../../../basic/crud-controller';
|
||||
import { AccessService } from '../service/access-service';
|
||||
|
||||
/**
|
||||
* 授权
|
||||
*/
|
||||
@Provide()
|
||||
@Controller('/api/pi/access')
|
||||
export class AccessController extends CrudController {
|
||||
@Inject()
|
||||
service: AccessService;
|
||||
|
||||
getService() {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Post('/page')
|
||||
async page(@Body(ALL) body) {
|
||||
body.query = body.query ?? {};
|
||||
body.query.userId = this.ctx.user.id;
|
||||
return super.page(body);
|
||||
}
|
||||
|
||||
@Post('/list')
|
||||
async list(@Body(ALL) body) {
|
||||
body.userId = this.ctx.user.id;
|
||||
return super.list(body);
|
||||
}
|
||||
|
||||
@Post('/add')
|
||||
async add(@Body(ALL) bean) {
|
||||
bean.userId = this.ctx.user.id;
|
||||
return super.add(bean);
|
||||
}
|
||||
|
||||
@Post('/update')
|
||||
async update(@Body(ALL) bean) {
|
||||
await this.service.checkUserId(bean.id, this.ctx.user.id);
|
||||
return super.update(bean);
|
||||
}
|
||||
@Post('/info')
|
||||
async info(@Query('id') id) {
|
||||
await this.service.checkUserId(id, this.ctx.user.id);
|
||||
return super.info(id);
|
||||
}
|
||||
|
||||
@Post('/delete')
|
||||
async delete(@Query('id') id) {
|
||||
await this.service.checkUserId(id, this.ctx.user.id);
|
||||
return super.delete(id);
|
||||
}
|
||||
|
||||
@Post('/define')
|
||||
async define(@Query('type') type) {
|
||||
const provider = this.service.getDefineByType(type);
|
||||
return this.ok(provider);
|
||||
}
|
||||
|
||||
@Post('/accessTypeDict')
|
||||
async getAccessTypeDict() {
|
||||
const list = this.service.getDefineList();
|
||||
const dict = [];
|
||||
for (const item of list) {
|
||||
dict.push({
|
||||
value: item.name,
|
||||
label: item.title,
|
||||
});
|
||||
}
|
||||
return this.ok(dict);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import {
|
||||
ALL,
|
||||
Controller,
|
||||
Inject,
|
||||
Post,
|
||||
Provide,
|
||||
Query,
|
||||
} from '@midwayjs/decorator';
|
||||
import { DnsProviderService } from '../service/dns-provider-service';
|
||||
import { BaseController } from '../../../basic/base-controller';
|
||||
|
||||
/**
|
||||
* 插件
|
||||
*/
|
||||
@Provide()
|
||||
@Controller('/api/pi/dnsProvider')
|
||||
export class DnsProviderController extends BaseController {
|
||||
@Inject()
|
||||
service: DnsProviderService;
|
||||
|
||||
@Post('/list')
|
||||
async list(@Query(ALL) query) {
|
||||
query.userId = this.ctx.user.id;
|
||||
const list = this.service.getList();
|
||||
return this.ok(list);
|
||||
}
|
||||
|
||||
@Post('/dnsProviderTypeDict')
|
||||
async getDnsProviderTypeDict() {
|
||||
const list = this.service.getList();
|
||||
const dict = [];
|
||||
for (const item of list) {
|
||||
dict.push({
|
||||
value: item.name,
|
||||
label: item.title,
|
||||
});
|
||||
}
|
||||
return this.ok(dict);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import {
|
||||
ALL,
|
||||
Body,
|
||||
Controller,
|
||||
Inject,
|
||||
Post,
|
||||
Provide,
|
||||
Query,
|
||||
} from '@midwayjs/decorator';
|
||||
import { CrudController } from '../../../basic/crud-controller';
|
||||
import { PipelineEntity } from '../entity/pipeline';
|
||||
import { HistoryService } from '../service/history-service';
|
||||
import { HistoryLogService } from '../service/history-log-service';
|
||||
import { HistoryEntity } from '../entity/history';
|
||||
import { HistoryLogEntity } from '../entity/history-log';
|
||||
|
||||
/**
|
||||
* 证书
|
||||
*/
|
||||
@Provide()
|
||||
@Controller('/api/pi/history')
|
||||
export class HistoryController extends CrudController {
|
||||
@Inject()
|
||||
service: HistoryService;
|
||||
@Inject()
|
||||
logService: HistoryLogService;
|
||||
|
||||
getService() {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Post('/page')
|
||||
async page(@Body(ALL) body) {
|
||||
body.query.userId = this.ctx.user.id;
|
||||
return super.page(body);
|
||||
}
|
||||
|
||||
@Post('/list')
|
||||
async list(@Body(ALL) body) {
|
||||
body.userId = this.ctx.user.id;
|
||||
if (body.pipelineId == null) {
|
||||
return this.ok([]);
|
||||
}
|
||||
const buildQuery = qb => {
|
||||
qb.limit(10);
|
||||
};
|
||||
const listRet = await this.getService().list(
|
||||
body,
|
||||
{ prop: 'id', asc: false },
|
||||
buildQuery
|
||||
);
|
||||
return this.ok(listRet);
|
||||
}
|
||||
|
||||
@Post('/add')
|
||||
async add(@Body(ALL) bean: PipelineEntity) {
|
||||
bean.userId = this.ctx.user.id;
|
||||
return super.add(bean);
|
||||
}
|
||||
|
||||
@Post('/update')
|
||||
async update(@Body(ALL) bean) {
|
||||
await this.service.checkUserId(bean.id, this.ctx.user.id);
|
||||
return super.update(bean);
|
||||
}
|
||||
|
||||
@Post('/save')
|
||||
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.service.save(bean);
|
||||
return this.ok(bean.id);
|
||||
}
|
||||
|
||||
@Post('/saveLog')
|
||||
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.logService.save(bean);
|
||||
return this.ok(bean.id);
|
||||
}
|
||||
|
||||
@Post('/delete')
|
||||
async delete(@Query('id') id) {
|
||||
await this.service.checkUserId(id, this.ctx.user.id);
|
||||
return super.delete(id);
|
||||
}
|
||||
|
||||
@Post('/detail')
|
||||
async detail(@Query('id') id) {
|
||||
await this.service.checkUserId(id, this.ctx.user.id);
|
||||
const detail = await this.service.detail(id);
|
||||
return this.ok(detail);
|
||||
}
|
||||
|
||||
@Post('/logs')
|
||||
async logs(@Query('id') id) {
|
||||
await this.logService.checkUserId(id, this.ctx.user.id);
|
||||
const logInfo = await this.logService.info(id);
|
||||
return this.ok(logInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import {
|
||||
ALL,
|
||||
Body,
|
||||
Controller,
|
||||
Inject,
|
||||
Post,
|
||||
Provide,
|
||||
Query,
|
||||
} from '@midwayjs/decorator';
|
||||
import { CrudController } from '../../../basic/crud-controller';
|
||||
import { PipelineService } from '../service/pipeline-service';
|
||||
import { PipelineEntity } from '../entity/pipeline';
|
||||
|
||||
/**
|
||||
* 证书
|
||||
*/
|
||||
@Provide()
|
||||
@Controller('/api/pi/pipeline')
|
||||
export class PipelineController extends CrudController {
|
||||
@Inject()
|
||||
service: PipelineService;
|
||||
|
||||
getService() {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Post('/page')
|
||||
async page(@Body(ALL) body) {
|
||||
body.query.userId = this.ctx.user.id;
|
||||
const buildQuery = qb => {
|
||||
qb.where({});
|
||||
};
|
||||
return super.page({ ...body, buildQuery });
|
||||
}
|
||||
|
||||
@Post('/add')
|
||||
async add(@Body(ALL) bean: PipelineEntity) {
|
||||
bean.userId = this.ctx.user.id;
|
||||
return super.add(bean);
|
||||
}
|
||||
|
||||
@Post('/update')
|
||||
async update(@Body(ALL) bean) {
|
||||
await this.service.checkUserId(bean.id, this.ctx.user.id);
|
||||
return super.update(bean);
|
||||
}
|
||||
|
||||
@Post('/save')
|
||||
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.service.save(bean);
|
||||
return this.ok(bean.id);
|
||||
}
|
||||
|
||||
@Post('/delete')
|
||||
async delete(@Query('id') id) {
|
||||
await this.service.checkUserId(id, this.ctx.user.id);
|
||||
return super.delete(id);
|
||||
}
|
||||
|
||||
@Post('/detail')
|
||||
async detail(@Query('id') id) {
|
||||
await this.service.checkUserId(id, this.ctx.user.id);
|
||||
const detail = await this.service.detail(id);
|
||||
return this.ok(detail);
|
||||
}
|
||||
|
||||
@Post('/trigger')
|
||||
async trigger(@Query('id') id) {
|
||||
await this.service.checkUserId(id, this.ctx.user.id);
|
||||
await this.service.trigger(id);
|
||||
return this.ok({});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import {
|
||||
ALL,
|
||||
Controller,
|
||||
Inject,
|
||||
Post,
|
||||
Provide,
|
||||
Query,
|
||||
} from '@midwayjs/decorator';
|
||||
import { BaseController } from '../../../basic/base-controller';
|
||||
import { PluginService } from '../service/plugin-service';
|
||||
|
||||
/**
|
||||
* 插件
|
||||
*/
|
||||
@Provide()
|
||||
@Controller('/api/pi/plugin')
|
||||
export class PluginController extends BaseController {
|
||||
@Inject()
|
||||
service: PluginService;
|
||||
|
||||
@Post('/list')
|
||||
async list(@Query(ALL) query) {
|
||||
query.userId = this.ctx.user.id;
|
||||
const list = this.service.getList();
|
||||
return this.ok(list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
/**
|
||||
* 授权配置
|
||||
*/
|
||||
@Entity('cd_access')
|
||||
export class AccessEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
@Column({ name: 'user_id', comment: '用户id' })
|
||||
userId: number;
|
||||
@Column({ comment: '名称', length: 100 })
|
||||
name: string;
|
||||
|
||||
@Column({ comment: '类型', length: 100 })
|
||||
type: string;
|
||||
|
||||
@Column({ name: 'setting', comment: '设置', length: 1024, nullable: true })
|
||||
setting: string;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
createTime: Date;
|
||||
@Column({
|
||||
name: 'update_time',
|
||||
comment: '修改时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
@Entity('pi_history_log')
|
||||
export class HistoryLogEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ name: 'user_id', comment: '用户id' })
|
||||
userId: number;
|
||||
|
||||
@Column({ name: 'pipeline_id', comment: '流水线' })
|
||||
pipelineId: number;
|
||||
|
||||
@Column({ name: 'history_id', comment: '历史id' })
|
||||
historyId: number;
|
||||
|
||||
@Column({
|
||||
name: 'node_id',
|
||||
comment: '任务节点id',
|
||||
length: 100,
|
||||
nullable: true,
|
||||
})
|
||||
nodeId: string;
|
||||
|
||||
@Column({ comment: '日志内容', length: 40960, nullable: true })
|
||||
logs: string;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
createTime: Date;
|
||||
|
||||
@Column({
|
||||
name: 'update_time',
|
||||
comment: '修改时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
@Entity('pi_history')
|
||||
export class HistoryEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ name: 'user_id', comment: '用户id' })
|
||||
userId: number;
|
||||
|
||||
@Column({ name: 'pipeline_id', comment: '流水线' })
|
||||
pipelineId: number;
|
||||
@Column({ comment: '运行状态', length: 40960, nullable: true })
|
||||
pipeline: string;
|
||||
|
||||
@Column({ comment: '结果状态', length: 20, nullable: true })
|
||||
status: string;
|
||||
|
||||
@Column({
|
||||
name: 'end_time',
|
||||
comment: '结束时间',
|
||||
nullable: true,
|
||||
})
|
||||
endTime: Date;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
createTime: Date;
|
||||
@Column({
|
||||
name: 'update_time',
|
||||
comment: '修改时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
@Entity('pi_pipeline')
|
||||
export class PipelineEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ name: 'user_id', comment: '用户id' })
|
||||
userId: number;
|
||||
|
||||
@Column({ name: 'title', comment: '标题' })
|
||||
title: number;
|
||||
|
||||
@Column({ comment: '配置', length: 40960 })
|
||||
content: string;
|
||||
|
||||
@Column({
|
||||
name: 'keep_history_count',
|
||||
comment: '历史记录保持数量',
|
||||
nullable: true,
|
||||
})
|
||||
keepHistoryCount: number;
|
||||
|
||||
@Column({ comment: '备注', length: 100, nullable: true })
|
||||
remark: string;
|
||||
|
||||
@Column({ comment: '状态', length: 100, nullable: true })
|
||||
status: string;
|
||||
|
||||
@Column({ comment: '启用/禁用', nullable: true, default: false })
|
||||
disabled: boolean;
|
||||
|
||||
@Column({
|
||||
name: 'last_history_time',
|
||||
comment: '最后一次执行时间',
|
||||
nullable: true,
|
||||
})
|
||||
lastHistoryTime: number;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
createTime: Date;
|
||||
@Column({
|
||||
name: 'update_time',
|
||||
comment: '修改时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
@Entity('pi_storage')
|
||||
export class StorageEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ name: 'user_id', comment: '用户id' })
|
||||
userId: number;
|
||||
|
||||
@Column({ name: 'scope', comment: '范围' })
|
||||
scope: string;
|
||||
|
||||
@Column({ name: 'namespace', comment: '命名空间' })
|
||||
namespace: string;
|
||||
|
||||
@Column({ comment: 'key', length: 100, nullable: true })
|
||||
key: string;
|
||||
|
||||
@Column({ comment: 'value', length: 40960, nullable: true })
|
||||
value: string;
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
createTime: Date;
|
||||
@Column({
|
||||
name: 'update_time',
|
||||
comment: '修改时间',
|
||||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
updateTime: Date;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { HistoryEntity } from '../history';
|
||||
import { HistoryLogEntity } from '../history-log';
|
||||
|
||||
export class HistoryDetail {
|
||||
history: HistoryEntity;
|
||||
log: HistoryLogEntity;
|
||||
|
||||
constructor(history: HistoryEntity, log: HistoryLogEntity) {
|
||||
this.history = history;
|
||||
this.log = log;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { PipelineEntity } from '../pipeline';
|
||||
import { HistoryEntity } from '../history';
|
||||
import { HistoryLogEntity } from '../history-log';
|
||||
|
||||
export class PipelineDetail {
|
||||
pipeline: PipelineEntity;
|
||||
constructor(pipeline: PipelineEntity) {
|
||||
this.pipeline = pipeline;
|
||||
}
|
||||
|
||||
last: HistoryEntity;
|
||||
logs: HistoryLogEntity[];
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { Provide, Scope, ScopeEnum } from "@midwayjs/decorator";
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseService } from '../../../basic/base-service';
|
||||
import { AccessEntity } from '../entity/access';
|
||||
import {
|
||||
accessRegistry,
|
||||
IAccessService,
|
||||
} from '@certd/pipeline';
|
||||
|
||||
/**
|
||||
* 授权
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
export class AccessService
|
||||
extends BaseService<AccessEntity>
|
||||
implements IAccessService
|
||||
{
|
||||
@InjectEntityModel(AccessEntity)
|
||||
repository: Repository<AccessEntity>;
|
||||
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
async getById(id: any): Promise<any> {
|
||||
const entity = await this.info(id);
|
||||
// const access = accessRegistry.get(entity.type);
|
||||
const setting = JSON.parse(entity.setting);
|
||||
return {
|
||||
id: entity.id,
|
||||
...setting,
|
||||
};
|
||||
}
|
||||
|
||||
getDefineList() {
|
||||
return accessRegistry.getDefineList();
|
||||
}
|
||||
|
||||
getDefineByType(type) {
|
||||
return accessRegistry.getDefine(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import { IStorage } from '@certd/pipeline/src/core/storage';
|
||||
import { StorageService } from './storage-service';
|
||||
|
||||
export class DbStorage implements IStorage {
|
||||
/**
|
||||
* 范围: user / pipeline / runtime / task
|
||||
*/
|
||||
storageService: StorageService;
|
||||
userId: number;
|
||||
constructor(userId: number, storageService: StorageService) {
|
||||
this.userId = userId;
|
||||
this.storageService = storageService;
|
||||
}
|
||||
|
||||
async get(
|
||||
scope: string,
|
||||
namespace: string,
|
||||
key: string
|
||||
): Promise<string | null> {
|
||||
const storageEntity = await this.storageService.get({
|
||||
userId: this.userId,
|
||||
scope: scope,
|
||||
namespace: namespace,
|
||||
key,
|
||||
});
|
||||
|
||||
if (storageEntity != null) {
|
||||
return storageEntity.value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async set(
|
||||
scope: string,
|
||||
namespace: string,
|
||||
key: string,
|
||||
value: string
|
||||
): Promise<void> {
|
||||
await this.storageService.set({
|
||||
userId: this.userId,
|
||||
scope: scope,
|
||||
namespace: namespace,
|
||||
key,
|
||||
value,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Provide, Scope, ScopeEnum } from "@midwayjs/decorator";
|
||||
import { dnsProviderRegistry } from '@certd/plugin-cert';
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
export class DnsProviderService {
|
||||
getList() {
|
||||
return dnsProviderRegistry.getDefineList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Provide, Scope, ScopeEnum } from "@midwayjs/decorator";
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseService } from '../../../basic/base-service';
|
||||
import { HistoryLogEntity } from '../entity/history-log';
|
||||
|
||||
/**
|
||||
* 证书申请
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
export class HistoryLogService extends BaseService<HistoryLogEntity> {
|
||||
@InjectEntityModel(HistoryLogEntity)
|
||||
repository: Repository<HistoryLogEntity>;
|
||||
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
async save(bean: HistoryLogEntity) {
|
||||
if (bean.id > 0) {
|
||||
await this.update(bean);
|
||||
} else {
|
||||
await this.add(bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/decorator";
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseService } from '../../../basic/base-service';
|
||||
import { HistoryEntity } from '../entity/history';
|
||||
import { PipelineEntity } from '../entity/pipeline';
|
||||
import { HistoryDetail } from '../entity/vo/history-detail';
|
||||
import { HistoryLogService } from './history-log-service';
|
||||
|
||||
/**
|
||||
* 证书申请
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
export class HistoryService extends BaseService<HistoryEntity> {
|
||||
@InjectEntityModel(HistoryEntity)
|
||||
repository: Repository<HistoryEntity>;
|
||||
@Inject()
|
||||
logService: HistoryLogService;
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
async save(bean: HistoryEntity) {
|
||||
if (bean.id > 0) {
|
||||
await this.update(bean);
|
||||
} else {
|
||||
await this.add(bean);
|
||||
}
|
||||
}
|
||||
|
||||
async detail(historyId: string) {
|
||||
const entity = await this.info(historyId);
|
||||
const log = await this.logService.info(historyId);
|
||||
return new HistoryDetail(entity, log);
|
||||
}
|
||||
|
||||
async start(pipeline: PipelineEntity) {
|
||||
const bean = {
|
||||
userId: pipeline.userId,
|
||||
pipelineId: pipeline.id,
|
||||
title: pipeline.title,
|
||||
status: 'start',
|
||||
};
|
||||
const { id } = await this.add(bean);
|
||||
//清除大于pipeline.keepHistoryCount的历史记录
|
||||
this.clear(pipeline.id, pipeline.keepHistoryCount);
|
||||
return id;
|
||||
}
|
||||
|
||||
private async clear(pipelineId: number, keepCount = 30) {
|
||||
const count = await this.repository.count({
|
||||
where: {
|
||||
pipelineId,
|
||||
},
|
||||
});
|
||||
if (count <= keepCount) {
|
||||
return;
|
||||
}
|
||||
let shouldDeleteCount = count - keepCount;
|
||||
const deleteCountBatch = 100;
|
||||
while (shouldDeleteCount > 0) {
|
||||
const list = await this.repository.find({
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
where: {
|
||||
pipelineId,
|
||||
},
|
||||
order: {
|
||||
id: 'ASC',
|
||||
},
|
||||
skip: 0,
|
||||
take: deleteCountBatch,
|
||||
});
|
||||
await this.repository.remove(list);
|
||||
|
||||
shouldDeleteCount -= deleteCountBatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/decorator';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { In, Repository } from 'typeorm';
|
||||
import { BaseService } from '../../../basic/base-service';
|
||||
import { PipelineEntity } from '../entity/pipeline';
|
||||
import { PipelineDetail } from '../entity/vo/pipeline-detail';
|
||||
import { Executor, Pipeline, RunHistory } from '@certd/pipeline';
|
||||
import { AccessService } from './access-service';
|
||||
import { DbStorage } from './db-storage';
|
||||
import { StorageService } from './storage-service';
|
||||
import { Cron } from '../../../plugins/cron/cron';
|
||||
import { HistoryService } from './history-service';
|
||||
import { HistoryEntity } from '../entity/history';
|
||||
import { HistoryLogEntity } from '../entity/history-log';
|
||||
import { HistoryLogService } from './history-log-service';
|
||||
import { logger } from '../../../utils/logger';
|
||||
|
||||
/**
|
||||
* 证书申请
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
export class PipelineService extends BaseService<PipelineEntity> {
|
||||
@InjectEntityModel(PipelineEntity)
|
||||
repository: Repository<PipelineEntity>;
|
||||
|
||||
@Inject()
|
||||
accessService: AccessService;
|
||||
@Inject()
|
||||
storageService: StorageService;
|
||||
@Inject()
|
||||
historyService: HistoryService;
|
||||
@Inject()
|
||||
historyLogService: HistoryLogService;
|
||||
|
||||
@Inject()
|
||||
cron: Cron;
|
||||
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
async update(entity) {
|
||||
await super.update(entity);
|
||||
|
||||
await this.registerTriggerById(entity.id);
|
||||
}
|
||||
|
||||
private async registerTriggerById(pipelineId) {
|
||||
if (pipelineId == null) {
|
||||
return;
|
||||
}
|
||||
const info = await this.info(pipelineId);
|
||||
if (info && !info.disabled) {
|
||||
const pipeline = JSON.parse(info.content);
|
||||
this.registerTriggers(pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取详情
|
||||
* @param id
|
||||
*/
|
||||
async detail(id) {
|
||||
const pipeline = await this.info(id);
|
||||
return new PipelineDetail(pipeline);
|
||||
}
|
||||
|
||||
async save(bean: PipelineEntity) {
|
||||
const pipeline = JSON.parse(bean.content);
|
||||
bean.title = pipeline.title;
|
||||
await this.addOrUpdate(bean);
|
||||
await this.registerTriggerById(bean.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用启动后初始加载记录
|
||||
*/
|
||||
async onStartup() {
|
||||
const idEntityList = await this.repository.find({
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
where: {
|
||||
disabled: false,
|
||||
},
|
||||
});
|
||||
const ids = idEntityList.map(item => {
|
||||
return item.id;
|
||||
});
|
||||
|
||||
//id 分段
|
||||
const idsSpan = [];
|
||||
let arr = [];
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
if (i % 20 === 0) {
|
||||
arr = [];
|
||||
idsSpan.push(arr);
|
||||
}
|
||||
arr.push(ids[i]);
|
||||
}
|
||||
|
||||
//分段加载记录
|
||||
for (const idArr of idsSpan) {
|
||||
const list = await this.repository.findBy({
|
||||
id: In(idArr),
|
||||
});
|
||||
|
||||
for (const entity of list) {
|
||||
const pipeline = JSON.parse(entity.content ?? '{}');
|
||||
this.registerTriggers(pipeline);
|
||||
}
|
||||
}
|
||||
logger.info('定时器数量:', this.cron.getList());
|
||||
}
|
||||
|
||||
registerTriggers(pipeline?: Pipeline) {
|
||||
if (pipeline?.triggers == null) {
|
||||
return;
|
||||
}
|
||||
for (const trigger of pipeline.triggers) {
|
||||
this.registerCron(pipeline.id, trigger);
|
||||
}
|
||||
}
|
||||
|
||||
async trigger(id) {
|
||||
this.cron.register({
|
||||
name: `pipeline.${id}.trigger.once`,
|
||||
cron: null,
|
||||
job: async () => {
|
||||
await this.run(id, null);
|
||||
},
|
||||
});
|
||||
logger.info('定时器数量:', this.cron.getList());
|
||||
}
|
||||
|
||||
registerCron(pipelineId, trigger) {
|
||||
let cron = trigger.props?.cron;
|
||||
if (cron == null) {
|
||||
return;
|
||||
}
|
||||
if(cron.startsWith("*")){
|
||||
cron = "0"+ cron.substring(1,cron.length)
|
||||
return
|
||||
}
|
||||
this.cron.register({
|
||||
name: this.buildCronKey(pipelineId, trigger.id),
|
||||
cron: cron,
|
||||
job: async () => {
|
||||
logger.info('定时任务触发:', pipelineId, trigger.id);
|
||||
await this.run(pipelineId, trigger.id);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async run(id, triggerId) {
|
||||
const entity: PipelineEntity = await this.info(id);
|
||||
const pipeline = JSON.parse(entity.content);
|
||||
|
||||
if (!pipeline.stages || pipeline.stages.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const triggerType = this.getTriggerType(triggerId, pipeline);
|
||||
if (triggerType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const onChanged = async (history: RunHistory) => {
|
||||
//保存执行历史
|
||||
await this.saveHistory(history);
|
||||
};
|
||||
|
||||
const userId = entity.userId;
|
||||
const historyId = await this.historyService.start(entity);
|
||||
|
||||
const executor = new Executor({
|
||||
userId,
|
||||
pipeline,
|
||||
onChanged,
|
||||
accessService: this.accessService,
|
||||
storage: new DbStorage(userId, this.storageService),
|
||||
});
|
||||
|
||||
await executor.run(historyId, triggerType);
|
||||
}
|
||||
|
||||
private getTriggerType(triggerId, pipeline) {
|
||||
let triggerType = 'user';
|
||||
if (triggerId != null) {
|
||||
//如果不是手动触发
|
||||
//查找trigger
|
||||
const found = this.findTrigger(pipeline, triggerId);
|
||||
if (!found) {
|
||||
//如果没有找到triggerId,说明被用户删掉了,这里再删除一次
|
||||
this.cron.remove(this.buildCronKey(pipeline.id, triggerId));
|
||||
triggerType = null;
|
||||
} else {
|
||||
logger.info('timer trigger:' + found.id, found.title, found.cron);
|
||||
triggerType = 'timer';
|
||||
}
|
||||
}
|
||||
return triggerType;
|
||||
}
|
||||
|
||||
private buildCronKey(pipelineId, triggerId) {
|
||||
return `pipeline.${pipelineId}.trigger.${triggerId}`;
|
||||
}
|
||||
|
||||
private findTrigger(pipeline, triggerId) {
|
||||
for (const trigger of pipeline.triggers) {
|
||||
if (trigger.id === triggerId) {
|
||||
return trigger;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
private async saveHistory(history: RunHistory) {
|
||||
//修改pipeline状态
|
||||
const pipelineEntity = new PipelineEntity();
|
||||
pipelineEntity.id = parseInt(history.pipeline.id);
|
||||
pipelineEntity.status = history.pipeline.status.status;
|
||||
pipelineEntity.lastHistoryTime = history.pipeline.status.startTime;
|
||||
await this.update(pipelineEntity);
|
||||
|
||||
const entity: HistoryEntity = new HistoryEntity();
|
||||
entity.id = parseInt(history.id);
|
||||
entity.userId = history.pipeline.userId;
|
||||
entity.pipeline = JSON.stringify(history.pipeline);
|
||||
await this.historyService.save(entity);
|
||||
|
||||
const logEntity: HistoryLogEntity = new HistoryLogEntity();
|
||||
logEntity.id = entity.id;
|
||||
logEntity.userId = entity.userId;
|
||||
logEntity.pipelineId = entity.pipelineId;
|
||||
logEntity.historyId = entity.id;
|
||||
logEntity.logs = JSON.stringify(history.logs);
|
||||
await this.historyLogService.addOrUpdate(logEntity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Provide, Scope, ScopeEnum } from "@midwayjs/decorator";
|
||||
import { pluginRegistry } from '@certd/pipeline';
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
export class PluginService {
|
||||
getList() {
|
||||
const collection = pluginRegistry.storage;
|
||||
const list = [];
|
||||
for (const key in collection) {
|
||||
const Plugin = collection[key];
|
||||
list.push({ ...Plugin.define, key });
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import { Provide, Scope, ScopeEnum } from "@midwayjs/decorator";
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseService } from '../../../basic/base-service';
|
||||
import { StorageEntity } from '../entity/storage';
|
||||
|
||||
/**
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
export class StorageService extends BaseService<StorageEntity> {
|
||||
@InjectEntityModel(StorageEntity)
|
||||
repository: Repository<StorageEntity>;
|
||||
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
async get(where: {
|
||||
scope: any;
|
||||
namespace: any;
|
||||
userId: number;
|
||||
key: string;
|
||||
}) {
|
||||
if (where.userId == null) {
|
||||
throw new Error('userId 不能为空');
|
||||
}
|
||||
return await this.repository.findOne({
|
||||
where,
|
||||
});
|
||||
}
|
||||
|
||||
async set(entity: {
|
||||
id?: any;
|
||||
scope: any;
|
||||
namespace: any;
|
||||
userId: number;
|
||||
value: string;
|
||||
key: string;
|
||||
}) {
|
||||
entity.id = null;
|
||||
const query = { ...entity };
|
||||
delete query.value;
|
||||
const ret = await this.get(query);
|
||||
if (ret != null) {
|
||||
entity.id = ret.id;
|
||||
if (ret.userId !== entity.userId) {
|
||||
throw new Error('您没有权限修改此数据');
|
||||
}
|
||||
await this.repository.save(entity);
|
||||
} else {
|
||||
await this.repository.insert(entity);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user