diff --git a/back/src/artist/artist.controller.ts b/back/src/artist/artist.controller.ts index 9a3ff8a..92ad1c1 100644 --- a/back/src/artist/artist.controller.ts +++ b/back/src/artist/artist.controller.ts @@ -20,10 +20,15 @@ import { CreateArtistDto } from './dto/create-artist.dto'; import { Request } from 'express'; import { ArtistService } from './artist.service'; import { Prisma, Artist } from '@prisma/client'; -import { ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { + ApiNotFoundResponse, + ApiOkResponse, + ApiOperation, + ApiTags, +} from '@nestjs/swagger'; import { createReadStream, existsSync } from 'fs'; import { FilterQuery } from 'src/utils/filter.pipe'; -import { Artist as _Artist} from 'src/_gen/prisma-class/artist'; +import { Artist as _Artist } from 'src/_gen/prisma-class/artist'; @Controller('artist') @ApiTags('artist') @@ -33,7 +38,9 @@ export class ArtistController { constructor(private readonly service: ArtistService) {} @Post() - @ApiOperation({ description: "Register a new artist, should not be used by frontend"}) + @ApiOperation({ + description: 'Register a new artist, should not be used by frontend', + }) async create(@Body() dto: CreateArtistDto) { try { return await this.service.create(dto); @@ -43,7 +50,7 @@ export class ArtistController { } @Delete(':id') - @ApiOperation({ description: "Delete an artist by id"}) + @ApiOperation({ description: 'Delete an artist by id' }) async remove(@Param('id', ParseIntPipe) id: number) { try { return await this.service.delete({ id }); @@ -53,8 +60,8 @@ export class ArtistController { } @Get(':id/illustration') - @ApiOperation({ description: "Get an artist's illustration"}) - @ApiNotFoundResponse({ description: "Artist or illustration not found"}) + @ApiOperation({ description: "Get an artist's illustration" }) + @ApiNotFoundResponse({ description: 'Artist or illustration not found' }) async getIllustration(@Param('id', ParseIntPipe) id: number) { const artist = await this.service.get({ id }); if (!artist) throw new NotFoundException('Artist not found'); @@ -71,7 +78,7 @@ export class ArtistController { } @Get() - @ApiOperation({ description: "Get all artists paginated"}) + @ApiOperation({ description: 'Get all artists paginated' }) @ApiOkResponsePlaginated(_Artist) async findAll( @Req() req: Request, @@ -89,8 +96,8 @@ export class ArtistController { } @Get(':id') - @ApiOperation({ description: "Get an artist by id"}) - @ApiOkResponse({ type: _Artist}) + @ApiOperation({ description: 'Get an artist by id' }) + @ApiOkResponse({ type: _Artist }) async findOne(@Param('id', ParseIntPipe) id: number) { const res = await this.service.get({ id }); diff --git a/back/src/history/history.controller.ts b/back/src/history/history.controller.ts index 1d4db7d..22534ec 100644 --- a/back/src/history/history.controller.ts +++ b/back/src/history/history.controller.ts @@ -10,14 +10,20 @@ import { Request, UseGuards, } from '@nestjs/common'; -import { ApiCreatedResponse, ApiOkResponse, ApiOperation, ApiTags, ApiUnauthorizedResponse } from '@nestjs/swagger'; +import { + ApiCreatedResponse, + ApiOkResponse, + ApiOperation, + ApiTags, + ApiUnauthorizedResponse, +} from '@nestjs/swagger'; import { SearchHistory, SongHistory } from '@prisma/client'; import { JwtAuthGuard } from 'src/auth/jwt-auth.guard'; import { SongHistoryDto } from './dto/SongHistoryDto'; import { HistoryService } from './history.service'; import { SearchHistoryDto } from './dto/SearchHistoryDto'; import { SongHistory as _SongHistory } from 'src/_gen/prisma-class/song_history'; -import { SearchHistory as _SearchHistory} from 'src/_gen/prisma-class/search_history'; +import { SearchHistory as _SearchHistory } from 'src/_gen/prisma-class/search_history'; @Controller('history') @ApiTags('history') @@ -26,9 +32,9 @@ export class HistoryController { @Get() @HttpCode(200) - @ApiOperation({ description: "Get song history of connected user"}) + @ApiOperation({ description: 'Get song history of connected user' }) @UseGuards(JwtAuthGuard) - @ApiOkResponse({ type: _SongHistory, isArray: true}) + @ApiOkResponse({ type: _SongHistory, isArray: true }) @ApiUnauthorizedResponse({ description: 'Invalid token' }) async getHistory( @Request() req: any, @@ -40,9 +46,9 @@ export class HistoryController { @Get('search') @HttpCode(200) - @ApiOperation({ description: "Get search history of connected user"}) + @ApiOperation({ description: 'Get search history of connected user' }) @UseGuards(JwtAuthGuard) - @ApiOkResponse({ type: _SearchHistory, isArray: true}) + @ApiOkResponse({ type: _SearchHistory, isArray: true }) @ApiUnauthorizedResponse({ description: 'Invalid token' }) async getSearchHistory( @Request() req: any, @@ -54,15 +60,15 @@ export class HistoryController { @Post() @HttpCode(201) - @ApiOperation({ description: "Create a record of a song played by a user"}) - @ApiCreatedResponse({ description: "Succesfully created a record"}) + @ApiOperation({ description: 'Create a record of a song played by a user' }) + @ApiCreatedResponse({ description: 'Succesfully created a record' }) async create(@Body() record: SongHistoryDto): Promise { return this.historyService.createSongHistoryRecord(record); } @Post('search') @HttpCode(201) - @ApiOperation({ description: "Creates a search record in the users history"}) + @ApiOperation({ description: 'Creates a search record in the users history' }) @UseGuards(JwtAuthGuard) @ApiUnauthorizedResponse({ description: 'Invalid token' }) async createSearchHistory( diff --git a/back/src/song/song.controller.ts b/back/src/song/song.controller.ts index e526773..2553705 100644 --- a/back/src/song/song.controller.ts +++ b/back/src/song/song.controller.ts @@ -174,6 +174,7 @@ export class SongController { } @Get(':id') + @UseGuards(JwtAuthGuard) @ApiOperation({ description: 'Get a specific song data' }) @ApiNotFoundResponse({ description: 'Song not found' }) @ApiOkResponse({ type: _Song, description: 'Requested song' }) diff --git a/back/src/utils/include.ts b/back/src/utils/include.ts index 3cbe0c7..0440fef 100644 --- a/back/src/utils/include.ts +++ b/back/src/utils/include.ts @@ -18,11 +18,10 @@ export function mapInclude( for (const key of include.split(',')) { const value = typeof fields[key] === 'function' - ? // @ts-expect-error typescript is dumb, once again - fields[key]({ user: req.user }) + ? fields[key]({ user: req.user }) : fields[key]; - if (value === true) include[key] = true; - else if (value !== false) { + if (value !== false && value !== undefined) ret[key] = value; + else { throw new BadRequestException( `Invalid include, ${key} is not valid. Valid includes are: ${Object.keys( fields, diff --git a/back/test/robot/songs/songs.robot b/back/test/robot/songs/songs.robot index 8bc7bb6..f35e78d 100644 --- a/back/test/robot/songs/songs.robot +++ b/back/test/robot/songs/songs.robot @@ -3,6 +3,7 @@ Documentation Tests of the /song route. ... Ensures that the songs CRUD works corectly. Resource ../rest.resource +Resource ../auth/auth.resource *** Test Cases *** @@ -133,5 +134,47 @@ Get midi file Integer response status 201 GET /song/${res.body.id}/midi Integer response status 200 - #Output + # Output [Teardown] DELETE /song/${res.body.id} + +Find a song with artist + [Documentation] Create a song and find it with it's artist + &{res2}= POST /artist { "name": "Tghjmk"} + Output + Integer response status 201 + &{res}= POST + ... /song + ... {"name": "Mama miaeyi", "artistId": ${res2.body.id}, "difficulties": {}, "midiPath": "/musics/Beethoven-125-4.midi", "musicXmlPath": "/musics/Beethoven-125-4.mxl"} + Output + Integer response status 201 + &{get}= GET /song/${res.body.id}?include=artist + Output + Integer response status 200 + Should Be Equal ${res2.body} ${get.body.artist} + [Teardown] Run Keywords DELETE /song/${res.body.id} + ... AND DELETE /artist/${res2.body.id} + +Find a song with artist and history + [Documentation] Create a song and find it with it's artist + ${userID}= RegisterLogin wowusersfkj + &{res2}= POST /artist { "name": "Tghjmk"} + Output + Integer response status 201 + &{res}= POST + ... /song + ... {"name": "Mama miaeyi", "artistId": ${res2.body.id}, "difficulties": {}, "midiPath": "/musics/Beethoven-125-4.midi", "musicXmlPath": "/musics/Beethoven-125-4.mxl"} + Output + Integer response status 201 + &{res3}= POST + ... /history + ... { "songID": ${res.body.id}, "userID": ${userID}, "score": 12, "difficulties": {}, "info": {} } + Output + Integer response status 201 + &{get}= GET /song/${res.body.id}?include=artist,SongHistory + Output + Integer response status 200 + Should Be Equal ${res2.body} ${get.body.artist} + Should Be Equal ${res3.body} ${get.body.SongHistory[0]} + [Teardown] Run Keywords DELETE /auth/me + ... AND DELETE /song/${res.body.id} + ... AND DELETE /artist/${res2.body.id}