import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { Repository, getConnectionManager } from 'typeorm'; import { RunnerCardHasScansError, RunnerCardIdsNotMatchingError, RunnerCardNotFoundError } from '../errors/RunnerCardErrors'; import { RunnerNotFoundError } from '../errors/RunnerErrors'; import { CreateRunnerCard } from '../models/actions/create/CreateRunnerCard'; import { UpdateRunnerCard } from '../models/actions/update/UpdateRunnerCard'; import { RunnerCard } from '../models/entities/RunnerCard'; import { ResponseEmpty } from '../models/responses/ResponseEmpty'; import { ResponseRunnerCard } from '../models/responses/ResponseRunnerCard'; import { ScanController } from './ScanController'; @JsonController('/cards') @OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] }) export class RunnerCardController { private cardRepository: Repository; /** * Gets the repository of this controller's model/entity. */ constructor() { this.cardRepository = getConnectionManager().get().getRepository(RunnerCard); } @Get() @Authorized("CARD:GET") @ResponseSchema(ResponseRunnerCard, { isArray: true }) @OpenAPI({ description: 'Lists all card.' }) async getAll() { let responseCards: ResponseRunnerCard[] = new Array(); const cards = await this.cardRepository.find({ relations: ['runner', 'runner.group', 'runner.group.parentGroup'] }); cards.forEach(card => { responseCards.push(new ResponseRunnerCard(card)); }); return responseCards; } @Get('/:id') @Authorized("CARD:GET") @ResponseSchema(ResponseRunnerCard) @ResponseSchema(RunnerCardNotFoundError, { statusCode: 404 }) @OnUndefined(RunnerCardNotFoundError) @OpenAPI({ description: "Lists all information about the card whose id got provided." }) async getOne(@Param('id') id: number) { let card = await this.cardRepository.findOne({ id: id }, { relations: ['runner', 'runner.group', 'runner.group.parentGroup'] }); if (!card) { throw new RunnerCardNotFoundError(); } return card.toResponse(); } @Post('/bulk') @Authorized("CARD:CREATE") @ResponseSchema(ResponseEmpty, { statusCode: 200 }) @OpenAPI({ description: "Create blank cards in bulk.
Just provide the count as a query param and wait for the 200 response.
You can provide the 'returnCards' query param if you want to receive the RESPONSERUNNERCARD objects in the response." }) async postBlancoBulk(@QueryParam("count") count: number, @QueryParam("returnCards") returnCards: boolean = false) { let createPromises = new Array(); for (let index = 0; index < count; index++) { createPromises.push(this.cardRepository.save({ runner: null, enabled: true })) } const cards = await Promise.all(createPromises); if (returnCards) { let responseCards: ResponseRunnerCard[] = new Array(); for await (let card of cards) { let dbCard = await this.cardRepository.findOne({ id: card.id }); responseCards.push(new ResponseRunnerCard(dbCard)); } return responseCards; } let response = new ResponseEmpty(); response.response = `Created ${count} new blanco cards.` return response; } @Post() @Authorized("CARD:CREATE") @ResponseSchema(ResponseRunnerCard) @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @OpenAPI({ description: "Create a new card.
You can provide a associated runner by id but you don't have to." }) async post(@Body({ validate: true }) createCard: CreateRunnerCard) { let card = await createCard.toEntity(); card = await this.cardRepository.save(card); return (await this.cardRepository.findOne({ id: card.id }, { relations: ['runner', 'runner.group', 'runner.group.parentGroup'] })).toResponse(); } @Put('/:id') @Authorized("CARD:UPDATE") @ResponseSchema(ResponseRunnerCard) @ResponseSchema(RunnerCardNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerNotFoundError, { statusCode: 404 }) @ResponseSchema(RunnerCardIdsNotMatchingError, { statusCode: 406 }) @OpenAPI({ description: "Update the card whose id you provided.
Scans created via this card will still be associated with the old runner.
Please remember that ids can't be changed." }) async put(@Param('id') id: number, @Body({ validate: true }) card: UpdateRunnerCard) { let oldCard = await this.cardRepository.findOne({ id: id }); if (!oldCard) { throw new RunnerCardNotFoundError(); } if (oldCard.id != card.id) { throw new RunnerCardIdsNotMatchingError(); } await this.cardRepository.save(await card.update(oldCard)); return (await this.cardRepository.findOne({ id: id }, { relations: ['runner', 'runner.group', 'runner.group.parentGroup'] })).toResponse(); } @Delete('/:id') @Authorized("CARD:DELETE") @ResponseSchema(ResponseRunnerCard) @ResponseSchema(ResponseEmpty, { statusCode: 204 }) @ResponseSchema(RunnerCardHasScansError, { statusCode: 406 }) @OnUndefined(204) @OpenAPI({ description: "Delete the card whose id you provided.
If no card with this id exists it will just return 204(no content).
If the card still has scans associated you have to provide the force=true query param (warning: this deletes all scans associated with by this card - please disable it instead or just remove the runner association)." }) async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let card = await this.cardRepository.findOne({ id: id }); if (!card) { return null; } const cardScans = (await this.cardRepository.findOne({ id: id }, { relations: ["scans"] })).scans; if (cardScans.length != 0 && !force) { throw new RunnerCardHasScansError(); } const scanController = new ScanController; for (let scan of cardScans) { await scanController.remove(scan.id, force); } await this.cardRepository.delete(card); return card.toResponse(); } }