diff --git a/back/src/album/album.controller.ts b/back/src/album/album.controller.ts index 0444082..0a88e75 100644 --- a/back/src/album/album.controller.ts +++ b/back/src/album/album.controller.ts @@ -12,6 +12,7 @@ import { Post, Query, Req, + UseGuards, } from '@nestjs/common'; import { ApiOkResponsePlaginated, Plage } from 'src/models/plage'; import { CreateAlbumDto } from './dto/create-album.dto'; @@ -21,11 +22,18 @@ import { Prisma, Album } from '@prisma/client'; import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; import { FilterQuery } from 'src/utils/filter.pipe'; import { Album as _Album } from 'src/_gen/prisma-class/album'; +import { IncludeMap, mapInclude } from 'src/utils/include'; +import { JwtAuthGuard } from 'src/auth/jwt-auth.guard'; @Controller('album') @ApiTags('album') +@UseGuards(JwtAuthGuard) export class AlbumController { static filterableFields: string[] = ['+id', 'name', '+artistId']; + static includableFields: IncludeMap = { + artist: true, + Song: true, + }; constructor(private readonly albumService: AlbumService) {} @@ -65,6 +73,7 @@ export class AlbumController { @Req() req: Request, @FilterQuery(AlbumController.filterableFields) where: Prisma.AlbumWhereInput, + @Query('include') include: string, @Query('skip', new DefaultValuePipe(0), ParseIntPipe) skip: number, @Query('take', new DefaultValuePipe(20), ParseIntPipe) take: number, ): Promise> { @@ -72,6 +81,7 @@ export class AlbumController { skip, take, where, + include: mapInclude(include, req, AlbumController.includableFields), }); return new Plage(ret, req); } @@ -79,8 +89,15 @@ export class AlbumController { @Get(':id') @ApiOperation({ description: 'Get an album by id' }) @ApiOkResponse({ type: _Album }) - async findOne(@Param('id', ParseIntPipe) id: number) { - const res = await this.albumService.album({ id }); + async findOne( + @Req() req: Request, + @Query('include') include: string, + @Param('id', ParseIntPipe) id: number, + ) { + const res = await this.albumService.album( + { id }, + mapInclude(include, req, AlbumController.includableFields), + ); if (res === null) throw new NotFoundException('Album not found'); return res; diff --git a/back/src/album/album.service.ts b/back/src/album/album.service.ts index e144b32..796707f 100644 --- a/back/src/album/album.service.ts +++ b/back/src/album/album.service.ts @@ -14,9 +14,11 @@ export class AlbumService { async album( albumWhereUniqueInput: Prisma.AlbumWhereUniqueInput, + include?: Prisma.AlbumInclude, ): Promise { return this.prisma.album.findUnique({ where: albumWhereUniqueInput, + include, }); } @@ -26,14 +28,16 @@ export class AlbumService { cursor?: Prisma.AlbumWhereUniqueInput; where?: Prisma.AlbumWhereInput; orderBy?: Prisma.AlbumOrderByWithRelationInput; + include?: Prisma.AlbumInclude; }): Promise { - const { skip, take, cursor, where, orderBy } = params; + const { skip, take, cursor, where, orderBy, include } = params; return this.prisma.album.findMany({ skip, take, cursor, where, orderBy, + include, }); } diff --git a/back/src/artist/artist.controller.ts b/back/src/artist/artist.controller.ts index 92ad1c1..589f476 100644 --- a/back/src/artist/artist.controller.ts +++ b/back/src/artist/artist.controller.ts @@ -14,6 +14,7 @@ import { Query, Req, StreamableFile, + UseGuards, } from '@nestjs/common'; import { ApiOkResponsePlaginated, Plage } from 'src/models/plage'; import { CreateArtistDto } from './dto/create-artist.dto'; @@ -29,11 +30,18 @@ import { import { createReadStream, existsSync } from 'fs'; import { FilterQuery } from 'src/utils/filter.pipe'; import { Artist as _Artist } from 'src/_gen/prisma-class/artist'; +import { IncludeMap, mapInclude } from 'src/utils/include'; +import { JwtAuthGuard } from 'src/auth/jwt-auth.guard'; @Controller('artist') @ApiTags('artist') +@UseGuards(JwtAuthGuard) export class ArtistController { static filterableFields = ['+id', 'name']; + static includableFields: IncludeMap = { + Song: true, + Album: true, + }; constructor(private readonly service: ArtistService) {} @@ -84,6 +92,7 @@ export class ArtistController { @Req() req: Request, @FilterQuery(ArtistController.filterableFields) where: Prisma.ArtistWhereInput, + @Query('include') include: string, @Query('skip', new DefaultValuePipe(0), ParseIntPipe) skip: number, @Query('take', new DefaultValuePipe(20), ParseIntPipe) take: number, ): Promise> { @@ -91,6 +100,7 @@ export class ArtistController { skip, take, where, + include: mapInclude(include, req, ArtistController.includableFields), }); return new Plage(ret, req); } @@ -98,8 +108,15 @@ export class ArtistController { @Get(':id') @ApiOperation({ description: 'Get an artist by id' }) @ApiOkResponse({ type: _Artist }) - async findOne(@Param('id', ParseIntPipe) id: number) { - const res = await this.service.get({ id }); + async findOne( + @Req() req: Request, + @Query('include') include: string, + @Param('id', ParseIntPipe) id: number, + ) { + const res = await this.service.get( + { id }, + mapInclude(include, req, ArtistController.includableFields), + ); if (res === null) throw new NotFoundException('Artist not found'); return res; diff --git a/back/src/artist/artist.service.ts b/back/src/artist/artist.service.ts index 9140b86..658ee2c 100644 --- a/back/src/artist/artist.service.ts +++ b/back/src/artist/artist.service.ts @@ -12,9 +12,13 @@ export class ArtistService { }); } - async get(where: Prisma.ArtistWhereUniqueInput): Promise { + async get( + where: Prisma.ArtistWhereUniqueInput, + include?: Prisma.ArtistInclude, + ): Promise { return this.prisma.artist.findUnique({ where, + include, }); } @@ -24,14 +28,16 @@ export class ArtistService { cursor?: Prisma.ArtistWhereUniqueInput; where?: Prisma.ArtistWhereInput; orderBy?: Prisma.ArtistOrderByWithRelationInput; + include?: Prisma.ArtistInclude; }): Promise { - const { skip, take, cursor, where, orderBy } = params; + const { skip, take, cursor, where, orderBy, include } = params; return this.prisma.artist.findMany({ skip, take, cursor, where, orderBy, + include, }); } diff --git a/back/src/genre/genre.controller.ts b/back/src/genre/genre.controller.ts index 0ebf2af..d7f902b 100644 --- a/back/src/genre/genre.controller.ts +++ b/back/src/genre/genre.controller.ts @@ -13,6 +13,7 @@ import { Query, Req, StreamableFile, + UseGuards, } from '@nestjs/common'; import { ApiOkResponsePlaginated, Plage } from 'src/models/plage'; import { CreateGenreDto } from './dto/create-genre.dto'; @@ -23,11 +24,17 @@ import { ApiTags } from '@nestjs/swagger'; import { createReadStream, existsSync } from 'fs'; import { FilterQuery } from 'src/utils/filter.pipe'; import { Genre as _Genre } from 'src/_gen/prisma-class/genre'; +import { IncludeMap, mapInclude } from 'src/utils/include'; +import { JwtAuthGuard } from 'src/auth/jwt-auth.guard'; @Controller('genre') @ApiTags('genre') +@UseGuards(JwtAuthGuard) export class GenreController { static filterableFields: string[] = ['+id', 'name']; + static includableFields: IncludeMap = { + Song: true, + }; constructor(private readonly service: GenreService) {} @@ -71,6 +78,7 @@ export class GenreController { @Req() req: Request, @FilterQuery(GenreController.filterableFields) where: Prisma.GenreWhereInput, + @Query('include') include: string, @Query('skip', new DefaultValuePipe(0), ParseIntPipe) skip: number, @Query('take', new DefaultValuePipe(20), ParseIntPipe) take: number, ): Promise> { @@ -78,13 +86,21 @@ export class GenreController { skip, take, where, + include: mapInclude(include, req, GenreController.includableFields), }); return new Plage(ret, req); } @Get(':id') - async findOne(@Param('id', ParseIntPipe) id: number) { - const res = await this.service.get({ id }); + async findOne( + @Req() req: Request, + @Query('include') include: string, + @Param('id', ParseIntPipe) id: number, + ) { + const res = await this.service.get( + { id }, + mapInclude(include, req, GenreController.includableFields), + ); if (res === null) throw new NotFoundException('Genre not found'); return res; diff --git a/back/src/genre/genre.service.ts b/back/src/genre/genre.service.ts index 75cace2..ae6aab3 100644 --- a/back/src/genre/genre.service.ts +++ b/back/src/genre/genre.service.ts @@ -12,9 +12,13 @@ export class GenreService { }); } - async get(where: Prisma.GenreWhereUniqueInput): Promise { + async get( + where: Prisma.GenreWhereUniqueInput, + include?: Prisma.GenreInclude, + ): Promise { return this.prisma.genre.findUnique({ where, + include, }); } @@ -24,14 +28,16 @@ export class GenreService { cursor?: Prisma.GenreWhereUniqueInput; where?: Prisma.GenreWhereInput; orderBy?: Prisma.GenreOrderByWithRelationInput; + include?: Prisma.GenreInclude; }): Promise { - const { skip, take, cursor, where, orderBy } = params; + const { skip, take, cursor, where, orderBy, include } = params; return this.prisma.genre.findMany({ skip, take, cursor, where, orderBy, + include, }); } diff --git a/back/src/lesson/lesson.controller.ts b/back/src/lesson/lesson.controller.ts index 83098a5..1c692e9 100644 --- a/back/src/lesson/lesson.controller.ts +++ b/back/src/lesson/lesson.controller.ts @@ -3,7 +3,6 @@ import { Get, Query, Req, - Request, Param, ParseIntPipe, DefaultValuePipe, @@ -12,6 +11,7 @@ import { Body, Delete, NotFoundException, + UseGuards, } from '@nestjs/common'; import { ApiOkResponsePlaginated, Plage } from 'src/models/plage'; import { LessonService } from './lesson.service'; @@ -19,6 +19,9 @@ import { ApiOperation, ApiProperty, ApiTags } from '@nestjs/swagger'; import { Prisma, Skill } from '@prisma/client'; import { FilterQuery } from 'src/utils/filter.pipe'; import { Lesson as _Lesson } from 'src/_gen/prisma-class/lesson'; +import { JwtAuthGuard } from 'src/auth/jwt-auth.guard'; +import { IncludeMap, mapInclude } from 'src/utils/include'; +import { Request } from 'express'; export class Lesson { @ApiProperty() @@ -35,6 +38,7 @@ export class Lesson { @ApiTags('lessons') @Controller('lesson') +@UseGuards(JwtAuthGuard) export class LessonController { static filterableFields: string[] = [ '+id', @@ -42,6 +46,9 @@ export class LessonController { '+requiredLevel', 'mainSkill', ]; + static includableFields: IncludeMap = { + LessonHistory: true, + }; constructor(private lessonService: LessonService) {} @@ -54,6 +61,7 @@ export class LessonController { @Req() request: Request, @FilterQuery(LessonController.filterableFields) where: Prisma.LessonWhereInput, + @Query('include') include: string, @Query('skip', new DefaultValuePipe(0), ParseIntPipe) skip: number, @Query('take', new DefaultValuePipe(20), ParseIntPipe) take: number, ): Promise> { @@ -61,6 +69,7 @@ export class LessonController { skip, take, where, + include: mapInclude(include, request, LessonController.includableFields), }); return new Plage(ret, request); } @@ -69,8 +78,15 @@ export class LessonController { summary: 'Get a particular lessons', }) @Get(':id') - async get(@Param('id', ParseIntPipe) id: number): Promise { - const ret = await this.lessonService.get(id); + async get( + @Req() req: Request, + @Query('include') include: string, + @Param('id', ParseIntPipe) id: number, + ): Promise { + const ret = await this.lessonService.get( + id, + mapInclude(include, req, LessonController.includableFields), + ); if (!ret) throw new NotFoundException(); return ret; } diff --git a/back/src/lesson/lesson.service.ts b/back/src/lesson/lesson.service.ts index aed4a1e..9a1e94e 100644 --- a/back/src/lesson/lesson.service.ts +++ b/back/src/lesson/lesson.service.ts @@ -12,22 +12,28 @@ export class LessonService { cursor?: Prisma.LessonWhereUniqueInput; where?: Prisma.LessonWhereInput; orderBy?: Prisma.LessonOrderByWithRelationInput; + include?: Prisma.LessonInclude; }): Promise { - const { skip, take, cursor, where, orderBy } = params; + const { skip, take, cursor, where, orderBy, include } = params; return this.prisma.lesson.findMany({ skip, take, cursor, where, orderBy, + include, }); } - async get(id: number): Promise { + async get( + id: number, + include?: Prisma.LessonInclude, + ): Promise { return this.prisma.lesson.findFirst({ where: { id: id, }, + include, }); } diff --git a/back/src/search/search.controller.ts b/back/src/search/search.controller.ts index ac5d0f4..a6fad32 100644 --- a/back/src/search/search.controller.ts +++ b/back/src/search/search.controller.ts @@ -9,6 +9,7 @@ import { Param, ParseIntPipe, Post, + Query, Request, UseGuards, } from '@nestjs/common'; @@ -26,6 +27,10 @@ import { SearchService } from './search.service'; import { Song as _Song } from 'src/_gen/prisma-class/song'; import { Genre as _Genre } from 'src/_gen/prisma-class/genre'; import { Artist as _Artist } from 'src/_gen/prisma-class/artist'; +import { mapInclude } from 'src/utils/include'; +import { SongController } from 'src/song/song.controller'; +import { GenreController } from 'src/genre/genre.controller'; +import { ArtistController } from 'src/artist/artist.controller'; @ApiTags('search') @Controller('search') @@ -39,10 +44,15 @@ export class SearchController { @UseGuards(JwtAuthGuard) async searchSong( @Request() req: any, + @Query('include') include: string, @Param('query') query: string, ): Promise { try { - const ret = await this.searchService.songByGuess(query, req.user?.id); + const ret = await this.searchService.songByGuess( + query, + req.user?.id, + mapInclude(include, req, SongController.includableFields), + ); if (!ret.length) throw new NotFoundException(); else return ret; } catch (error) { @@ -57,10 +67,15 @@ export class SearchController { @ApiOperation({ description: 'Search a genre' }) async searchGenre( @Request() req: any, + @Query('include') include: string, @Param('query') query: string, ): Promise { try { - const ret = await this.searchService.genreByGuess(query, req.user?.id); + const ret = await this.searchService.genreByGuess( + query, + req.user?.id, + mapInclude(include, req, GenreController.includableFields), + ); if (!ret.length) throw new NotFoundException(); else return ret; } catch (error) { @@ -75,10 +90,15 @@ export class SearchController { @ApiOperation({ description: 'Search an artist' }) async searchArtists( @Request() req: any, + @Query('include') include: string, @Param('query') query: string, ): Promise { try { - const ret = await this.searchService.artistByGuess(query, req.user?.id); + const ret = await this.searchService.artistByGuess( + query, + req.user?.id, + mapInclude(include, req, ArtistController.includableFields), + ); if (!ret.length) throw new NotFoundException(); else return ret; } catch (error) { diff --git a/back/src/search/search.service.ts b/back/src/search/search.service.ts index fd0ad5d..5175831 100644 --- a/back/src/search/search.service.ts +++ b/back/src/search/search.service.ts @@ -10,27 +10,42 @@ export class SearchService { private history: HistoryService, ) {} - async songByGuess(query: string, userID: number): Promise { + async songByGuess( + query: string, + userID: number, + include?: Prisma.SongInclude, + ): Promise { return this.prisma.song.findMany({ where: { name: { contains: query, mode: 'insensitive' }, }, + include, }); } - async genreByGuess(query: string, userID: number): Promise { + async genreByGuess( + query: string, + userID: number, + include?: Prisma.GenreInclude, + ): Promise { return this.prisma.genre.findMany({ where: { name: { contains: query, mode: 'insensitive' }, }, + include, }); } - async artistByGuess(query: string, userID: number): Promise { + async artistByGuess( + query: string, + userID: number, + include?: Prisma.ArtistInclude, + ): Promise { return this.prisma.artist.findMany({ where: { name: { contains: query, mode: 'insensitive' }, }, + include, }); } } diff --git a/back/src/song/song.controller.ts b/back/src/song/song.controller.ts index 2553705..38269e9 100644 --- a/back/src/song/song.controller.ts +++ b/back/src/song/song.controller.ts @@ -46,6 +46,7 @@ class SongHistoryResult { @Controller('song') @ApiTags('song') +@UseGuards(JwtAuthGuard) export class SongController { static filterableFields: string[] = [ '+id', @@ -54,7 +55,7 @@ export class SongController { '+albumId', '+genreId', ]; - static includableFileds: IncludeMap = { + static includableFields: IncludeMap = { artist: true, album: true, genre: true, @@ -168,13 +169,12 @@ export class SongController { skip, take, where, - include: mapInclude(include, req, SongController.includableFileds), + include: mapInclude(include, req, SongController.includableFields), }); return new Plage(ret, req); } @Get(':id') - @UseGuards(JwtAuthGuard) @ApiOperation({ description: 'Get a specific song data' }) @ApiNotFoundResponse({ description: 'Song not found' }) @ApiOkResponse({ type: _Song, description: 'Requested song' }) @@ -187,7 +187,7 @@ export class SongController { { id, }, - mapInclude(include, req, SongController.includableFileds), + mapInclude(include, req, SongController.includableFields), ); if (res === null) throw new NotFoundException('Song not found'); @@ -196,7 +196,6 @@ export class SongController { @Get(':id/history') @HttpCode(200) - @UseGuards(JwtAuthGuard) @ApiOperation({ description: 'get the history of the connected user on a specific song', })