diff --git a/back/src/song/song.controller.ts b/back/src/song/song.controller.ts index 63ac65e..db7a3c4 100644 --- a/back/src/song/song.controller.ts +++ b/back/src/song/song.controller.ts @@ -1,5 +1,4 @@ import { - BadRequestException, Body, ConflictException, Controller, @@ -26,14 +25,23 @@ import { createReadStream, existsSync } from 'fs'; import { ApiTags, ApiUnauthorizedResponse } from '@nestjs/swagger'; import { HistoryService } from 'src/history/history.service'; import { JwtAuthGuard } from 'src/auth/jwt-auth.guard'; +import { FilterQuery } from 'src/utils/filter.pipe'; @Controller('song') @ApiTags('song') export class SongController { + static filterableFields: string[] = [ + '+id', + 'name', + '+artistId', + '+albumId', + '+genreId', + ]; + constructor( private readonly songService: SongService, private readonly historyService: HistoryService, - ) { } + ) {} @Get(':id/midi') async getMidi(@Param('id', ParseIntPipe) id: number) { @@ -104,24 +112,16 @@ export class SongController { @Get() async findAll( @Req() req: Request, - @Query() filter: Prisma.SongWhereInput, + @FilterQuery(SongController.filterableFields) where: Prisma.SongWhereInput, @Query('skip', new DefaultValuePipe(0), ParseIntPipe) skip: number, @Query('take', new DefaultValuePipe(20), ParseIntPipe) take: number, ): Promise> { - try { - const ret = await this.songService.songs({ - skip, - take, - where: { - ...filter, - id: filter.id ? +filter.id : undefined, - }, - }); - return new Plage(ret, req); - } catch (e) { - console.log(e); - throw new BadRequestException(null, e?.toString()); - } + const ret = await this.songService.songs({ + skip, + take, + where, + }); + return new Plage(ret, req); } @Get(':id') diff --git a/back/src/utils/filter.pipe.ts b/back/src/utils/filter.pipe.ts new file mode 100644 index 0000000..273858f --- /dev/null +++ b/back/src/utils/filter.pipe.ts @@ -0,0 +1,35 @@ +import { + BadRequestException, + Injectable, + PipeTransform, + Query, +} from '@nestjs/common'; + +@Injectable() +export class FilterPipe implements PipeTransform { + constructor(private readonly fields: string[]) {} + + transform(value: Record) { + const filter = {}; + for (const fieldIdentifier of this.fields) { + const field = fieldIdentifier.startsWith('+') + ? fieldIdentifier.slice(1) + : fieldIdentifier; + + if (value[field] === undefined) continue; + + if (fieldIdentifier.startsWith('+')) { + filter[field] = parseInt(value[field]); + if (isNaN(filter[field])) + throw new BadRequestException( + `Invalid filter, ${field} should be a number but it was ${value[field]}.`, + ); + } else filter[field] = value[field]; + } + return filter; + } +} + +export function FilterQuery(fields: string[]) { + return Query(new FilterPipe(fields)); +} diff --git a/back/test/robot/songs/songs.robot b/back/test/robot/songs/songs.robot index bcfdde6..8bc7bb6 100644 --- a/back/test/robot/songs/songs.robot +++ b/back/test/robot/songs/songs.robot @@ -76,7 +76,7 @@ Find multiples songs filtered [Teardown] Run Keywords DELETE /song/${res.body.id} ... AND DELETE /song/${res2.body.id} -Find multiples songs filtered by type +Find multiples songs filtered by id [Documentation] Create two songs and find them &{res}= POST ... /song @@ -97,6 +97,34 @@ Find multiples songs filtered by type [Teardown] Run Keywords DELETE /song/${res.body.id} ... AND DELETE /song/${res2.body.id} +Find multiples songs filtered and skiping the first + [Documentation] Create two songs and find them + &{genre}= POST + ... /genre + ... {"name": "Mama mia" } + Output + Integer response status 201 + + &{res}= POST + ... /song + ... {"name": "Mama mia", "difficulties": {}, "midiPath": "/musics/Beethoven-125-4.midi", "musicXmlPath": "/musics/Beethoven-125-4.mxl", "genreId": ${genre.body.id} } + Output + Integer response status 201 + &{res2}= POST + ... /song + ... {"name": "kldngsd", "difficulties": {}, "midiPath": "/musics/Beethoven-125-4.midi", "musicXmlPath": "/musics/Beethoven-125-4.mxl", "genreId": ${genre.body.id} } + Output + Integer response status 201 + + &{get}= GET /song?genreId=${genre.body.id}&skip=1 + Output + Integer response status 200 + Should Contain ${get.body.data} ${res2.body} + Should Not Contain ${get.body.data} ${res.body} + [Teardown] Run Keywords DELETE /song/${res.body.id} + ... AND DELETE /genre/${genre.body.id} + ... AND DELETE /song/${res2.body.id} + Get midi file &{res}= POST ... /song