Skip to content

Commit

Permalink
[feat]: refactored pipeline module
Browse files Browse the repository at this point in the history
  • Loading branch information
ignavan39 committed Mar 22, 2023
1 parent 3eac838 commit 4d86b20
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 112 deletions.
14 changes: 14 additions & 0 deletions src/auth/entities/refresh-token.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { BaseEntity, Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
import { User } from '../../user/entities/user.entity';

@Entity('refresh_token')
export class RefreshToken extends BaseEntity {
@Column('text')
token: string;

@Column('timestamp')
expiresIn: Date;

@ManyToOne(() => User)
user: User;
}
18 changes: 9 additions & 9 deletions src/dashboard/dashboard.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BadRequestException, Body, Controller, Delete, Get, Param, Patch, Post, UseGuards } from '@nestjs/common';
import { BadRequestException, Body, Controller, Delete, Get, Inject, Param, Patch, Post, UseGuards } from '@nestjs/common';
import { IAM } from '../common/decorators';
import { JwtAuthGuard } from '../user/guards/jwt.guard';
import {
Expand All @@ -16,12 +16,12 @@ import { DashboardPermissionGuard } from './guards/dashboard-permission.guard';
@UseGuards(JwtAuthGuard)
@Controller('dashboard')
export class DashboardController {
constructor(private readonly service: DashboardService) {}
constructor(@Inject(DashboardService) private readonly dashboardService: DashboardService) {}

@Post('/create')
async create(@Body() body: CreateDashboardDto, @IAM('id') userId: string) {
try {
const dashboard = await this.service.create(body.name, userId);
const dashboard = await this.dashboardService.create(body.name, userId);

return dashboard;
} catch (e) {
Expand All @@ -34,32 +34,32 @@ export class DashboardController {

@Get('/')
async getByUserId(@IAM('id') userId: string): Promise<Dashboard[]> {
return this.service.getByUserId(userId);
return this.dashboardService.getByUserId(userId);
}

@UseGuards(DashboardPermissionGuard())
@Get('/:id')
async getById(@Param('id') id: string, @IAM('id') userId: string) {
return this.service.getById(id);
return this.dashboardService.getById(id);
}

@UseGuards(DashboardPermissionGuard(PermissionType.Admin))
@Patch('/:id')
async update(@Param('id') id: string, @Body() body: UpdateDashboardDto): Promise<void> {
await this.service.update(id, body.name);
await this.dashboardService.update(id, body.name);
}

@UseGuards(DashboardPermissionGuard(PermissionType.Admin))
@Delete('/:id')
async delete(@Param('id') id: string, @IAM('id') userId: string): Promise<void> {
await this.service.delete(id, userId);
await this.dashboardService.delete(id, userId);
}

@UseGuards(DashboardPermissionGuard(PermissionType.Admin))
@Delete('/:id/permission/:email')
async deletePermission(@Param('id') id: string, @Param('email') email: string): Promise<void> {
try {
await this.service.deletePermission(id, email);
await this.dashboardService.deletePermission(id, email);
} catch (e) {
if (e instanceof PermissionNotFoundException) {
throw new BadRequestException(e.message);
Expand All @@ -72,7 +72,7 @@ export class DashboardController {
@Post('/:id/permission/add')
async addAccess(@Param('id') id: string, @IAM('id') userId: string, @Body() body: AddPermissionDto): Promise<void> {
try {
await this.service.addAccess(id, userId, body);
await this.dashboardService.addAccess(id, userId, body);
} catch (e) {
if (e instanceof PermissionNotFoundException) {
throw new BadRequestException(e.message);
Expand Down
122 changes: 24 additions & 98 deletions src/pipeline/pipeline.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import {
Delete,
BadRequestException,
Get,
Inject,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { isViolatedUniqueConstraintError } from 'src/common/utils/database-helpers';
import { Permission, PermissionType } from '../dashboard/entities/permission.entity';
import { DashboardPermissionGuard } from '../dashboard/guards/dashboard-permission.guard';
import { JwtAuthGuard } from '../user/guards/jwt.guard';
Expand All @@ -21,138 +23,62 @@ import { MovePipelineDto } from './dto/move-pipeline.dto';
import { UpdatePipelineDto } from './dto/update-pipeline.dto';
import { Pipeline } from './entities/pipeline.entity';
import { PipelinePermissionGuard } from './guards/pipeline-permission.guard';
import { PipelineService } from './pipeline.service';
import { PipelineAlreadyExist, PipelineNotFoundException, UnableToMovePipeline } from './pipeline.exceptions';

@UseGuards(JwtAuthGuard)
@Controller('pipeline')
export class PipelineController {
constructor(
@InjectRepository(Pipeline) private readonly repository: Repository<Pipeline>,
@InjectRepository(Permission) private readonly permissionRepository: Repository<Permission>,
) {}
constructor(@Inject(PipelineService) private readonly pipelineService: PipelineService) {}

@UseGuards(DashboardPermissionGuard(PermissionType.Admin))
@Post('/create')
async create(@Body() args: CreatePipelineDto) {
const pipelines = await this.repository.find({
where: {
dashboardId: args.dashboardId,
},
order: {
order: 'DESC',
},
});
const lastOrder = pipelines.length === 0 ? 0 : pipelines[0].order;
try {
return await this.repository.save({
name: args.name,
dashboardId: args.dashboardId,
order: lastOrder + 1,
});
return this.pipelineService.create(args);
} catch (e) {
if ('detail' in e && e.detail.includes('already exists')) {
throw new ForbiddenException('pipeline with this name already exist');
if (e instanceof PipelineAlreadyExist) {
throw new ForbiddenException(e.message);
}
}
}

@UseGuards(PipelinePermissionGuard(PermissionType.Admin))
@Patch('/:id')
public async update(@Body() args: UpdatePipelineDto, @Param('id') id: string) {
await this.repository.update(
{
id,
},
{
name: args.name,
},
);
await this.pipelineService.update(args, id);
}

@UseGuards(PipelinePermissionGuard(PermissionType.Admin))
@Delete('/:id')
public async delete(@Param('id') id: string) {
const pipeline = await this.repository.findOne({
where: {
id,
},
});
if (!pipeline) {
throw new ForbiddenException();
try {
await this.pipelineService.delete(id);
} catch (e) {
if (e instanceof PipelineNotFoundException) {
throw new ForbiddenException(e.message);
}
}

await this.repository.query(
`
UPDATE pipeline SET "order" = "order" - 1
WHERE "order" > $1
AND dashboard_id = $2
`,
[pipeline.order, pipeline.dashboardId],
);

await this.repository.delete({
id: pipeline.id,
});
}

@UseGuards(PipelinePermissionGuard(PermissionType.Admin))
@Patch('/move/:id')
public async move(@Body() args: MovePipelineDto, @Param('id') id: string) {
const pipeline = await this.repository.findOne({
where: {
id,
},
});
if (!pipeline) {
throw new ForbiddenException();
}

let oldOrder = 0;

if (args.leftId) {
const leftTemplate = await this.repository.findOne({
where: {
id: args.leftId,
},
});
if (!leftTemplate) {
throw new BadRequestException('pipeline not found');
try {
await this.pipelineService.move(args, id);
} catch (e) {
if (e instanceof PipelineNotFoundException) {
throw new ForbiddenException(e.message);
}
if (e instanceof UnableToMovePipeline) {
throw new BadRequestException(e.message);
}

oldOrder = leftTemplate.order;
}

if (oldOrder > pipeline.order) {
await this.repository.query(
`UPDATE pipeline SET "order" = "order" - 1
WHERE "order" > $1
AND "order" <= $2
AND dashboard_id = $2`,
[pipeline.order, oldOrder, pipeline.dashboardId],
);
pipeline.order = oldOrder;
} else {
await this.repository.query(
`UPDATE pipeline SET "order" = "order" + 1
WHERE "order" > $1
AND "order" < $2
AND dashboard_id = $2`,
[oldOrder, pipeline.order, pipeline.dashboardId],
);
pipeline.order = oldOrder + 1;
}
await this.repository.save(pipeline);
}

@UseGuards(DashboardPermissionGuard())
@Get('/:dashboardId')
public async getAllByDashboardId(@Param('dashboardId') dashboardId: string) {
return this.repository.find({
where: {
dashboardId,
},
order: {
order: 'ASC',
},
});
return this.pipelineService.getAllByDashboardId(dashboardId);
}
}
3 changes: 3 additions & 0 deletions src/pipeline/pipeline.exceptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export class PipelineNotFoundException extends Error {}
export class UnableToMovePipeline extends Error {}
export class PipelineAlreadyExist extends Error {}
135 changes: 135 additions & 0 deletions src/pipeline/pipeline.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Permission } from '../dashboard/entities/permission.entity';
import { isViolatedUniqueConstraintError } from '../common/utils/database-helpers';
import { Pipeline } from './entities/pipeline.entity';
import { CreatePipelineDto } from './dto/create-pipeline.dto';
import { UpdatePipelineDto } from './dto/update-pipeline.dto';
import { MovePipelineDto } from './dto/move-pipeline.dto';
import { PipelineAlreadyExist, PipelineNotFoundException, UnableToMovePipeline } from './pipeline.exceptions';

@Injectable()
export class PipelineService {
constructor(
@InjectRepository(Pipeline) private readonly pipelineRepository: Repository<Pipeline>,
@InjectRepository(Permission) private readonly permissionRepository: Repository<Permission>,
) {}

async create(dto: CreatePipelineDto): Promise<Pipeline> {
const pipelines = await this.pipelineRepository.find({
where: {
dashboardId: dto.dashboardId,
},
order: {
order: 'DESC',
},
});
const lastOrder = pipelines.length === 0 ? 0 : pipelines[0].order;
try {
return await this.pipelineRepository.save({
name: dto.name,
dashboardId: dto.dashboardId,
order: lastOrder + 1,
});
} catch (e) {
if (isViolatedUniqueConstraintError(e)) {
throw new PipelineAlreadyExist();
}
throw e;
}
}

async update(dto: UpdatePipelineDto, id: string): Promise<void> {
await this.pipelineRepository.update(
{
id,
},
{
name: dto.name,
},
);
}

async delete(id: string): Promise<void> {
const pipeline = await this.pipelineRepository.findOne({
where: {
id,
},
});
if (!pipeline) {
throw new PipelineNotFoundException('pipeline not found');
}

await this.pipelineRepository.query(
`
UPDATE pipeline SET "order" = "order" - 1
WHERE "order" > $1
AND dashboard_id = $2
`,
[pipeline.order, pipeline.dashboardId],
);

await this.pipelineRepository.delete({
id: pipeline.id,
});
}

async move(dto: MovePipelineDto, id: string): Promise<void> {
const pipeline = await this.pipelineRepository.findOne({
where: {
id,
},
});
if (!pipeline) {
throw new PipelineNotFoundException('pipeline not found');
}

let oldOrder = 0;

if (dto.leftId) {
const leftPipeline = await this.pipelineRepository.findOne({
where: {
id: dto.leftId,
},
});
if (!leftPipeline) {
throw new UnableToMovePipeline('unable to move pipeline');
}

oldOrder = leftPipeline.order;
}

if (oldOrder > pipeline.order) {
await this.pipelineRepository.query(
`UPDATE pipeline SET "order" = "order" - 1
WHERE "order" > $1
AND "order" <= $2
AND dashboard_id = $2`,
[pipeline.order, oldOrder, pipeline.dashboardId],
);
pipeline.order = oldOrder;
} else {
await this.pipelineRepository.query(
`UPDATE pipeline SET "order" = "order" + 1
WHERE "order" > $1
AND "order" < $2
AND dashboard_id = $2`,
[oldOrder, pipeline.order, pipeline.dashboardId],
);
pipeline.order = oldOrder + 1;
}
await this.pipelineRepository.save(pipeline);
}

async getAllByDashboardId(dashboardId: string): Promise<Pipeline[]> {
return this.pipelineRepository.find({
where: {
dashboardId,
},
order: {
order: 'ASC',
},
});
}
}
Loading

0 comments on commit 4d86b20

Please sign in to comment.