diff --git a/src/app.module.ts b/src/app.module.ts index 3b46ccb..0832907 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,19 +1,18 @@ import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; import { GamesModule } from './games/games.module'; import { UsersModule } from './users/users.module'; import { EventEmitterModule } from '@nestjs/event-emitter'; import { TypeOrmModule } from '@nestjs/typeorm'; import { User } from './users/entities/user.entity'; import { Game } from './games/entities/game.entity'; -import { Topic } from './words/entities/topic.entity'; -import { Word } from './words/entities/word.entity'; +import { Topic } from './word/entities/topic.entity'; +import { Word } from './word/entities/word.entity'; import { Player } from './games/entities/player.entity'; import { Concept } from './games/entities/concept.entity'; import { ConceptInTurn } from './games/entities/concept_in_turn.entity'; import { ConfigService } from '@nestjs/config'; +import { WordModule } from './word/words.module'; const configService = new ConfigService(); @@ -36,8 +35,7 @@ const configService = new ConfigService(); }), GamesModule, UsersModule, + WordModule, ], - // controllers: [AppController], - // providers: [AppService], }) export class AppModule {} diff --git a/src/app.service.ts b/src/app.service.ts deleted file mode 100644 index b4166f1..0000000 --- a/src/app.service.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -@Injectable() -export class AppService { - constructor() {} -} diff --git a/src/games/controllers/games.controller.ts b/src/games/controllers/games.controller.ts index 491331d..638deec 100644 --- a/src/games/controllers/games.controller.ts +++ b/src/games/controllers/games.controller.ts @@ -10,7 +10,7 @@ import { UseGuards, } from '@nestjs/common'; import { LobbyService } from '../services/lobby.service'; -import { AuthGuard } from '../guards/auth.guard'; +import { AuthGuard } from '../../users/guards/auth.guard'; import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; import { Game } from '../entities/game.entity'; import { GamePipe, GameStartedPipe } from '../pipe/game.pipe'; diff --git a/src/games/controllers/lobby.controller.ts b/src/games/controllers/lobby.controller.ts index 687ccd9..4955379 100644 --- a/src/games/controllers/lobby.controller.ts +++ b/src/games/controllers/lobby.controller.ts @@ -11,7 +11,7 @@ import { Sse, } from '@nestjs/common'; import { LobbyService } from '../services/lobby.service'; -import { AuthGuard } from '../guards/auth.guard'; +import { AuthGuard } from '../../users/guards/auth.guard'; import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; import { GamePipe } from '../pipe/game.pipe'; import { Game } from '../entities/game.entity'; diff --git a/src/games/games.module.ts b/src/games/games.module.ts index 0ee0a6b..2f94a47 100644 --- a/src/games/games.module.ts +++ b/src/games/games.module.ts @@ -7,12 +7,14 @@ import { GamesController } from './controllers/games.controller'; import { GameService } from './services/games.service'; import { TypeOrmModule } from '@nestjs/typeorm'; import { Player } from './entities/player.entity'; +import { User } from 'src/users/entities/user.entity'; @Module({ imports: [ UsersModule, TypeOrmModule.forFeature([Game]), TypeOrmModule.forFeature([Player]), + TypeOrmModule.forFeature([User]), ], controllers: [LobbyController, GamesController], providers: [LobbyService, GameService], diff --git a/src/express-session.d.ts b/src/types.d.ts/express-session.d.ts similarity index 79% rename from src/express-session.d.ts rename to src/types.d.ts/express-session.d.ts index 0f63f1c..e7c28ea 100644 --- a/src/express-session.d.ts +++ b/src/types.d.ts/express-session.d.ts @@ -1,4 +1,4 @@ -import { User } from './users/entities/user.entity'; +import { User } from '../users/entities/user.entity'; declare module 'express-session' { interface SessionData { user: User; diff --git a/src/games/guards/auth.guard.ts b/src/users/guards/auth.guard.ts similarity index 100% rename from src/games/guards/auth.guard.ts rename to src/users/guards/auth.guard.ts diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index fe24aed..face072 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -6,6 +6,8 @@ import { HttpException, HttpStatus, Redirect, + Param, + ParseIntPipe, } from '@nestjs/common'; import { UsersService } from './users.service'; import { UserResponseDTO } from './dto/userresponse.dto'; @@ -47,4 +49,13 @@ export class UsersController { await this.usersService.discordLogin(session); return new UserResponseDTO(session.user); } + + @Get('/users/:id') + async get(@Param('id') id: string) { + const user = await this.usersService.findUser(id); + if (!user) { + throw new HttpException('User not found', HttpStatus.NOT_FOUND); + } + return new UserResponseDTO(user); + } } diff --git a/src/users/users.module.ts b/src/users/users.module.ts index 1fc6ffb..935f126 100644 --- a/src/users/users.module.ts +++ b/src/users/users.module.ts @@ -8,5 +8,6 @@ import { TypeOrmModule } from '@nestjs/typeorm'; imports: [TypeOrmModule.forFeature([User])], controllers: [UsersController], providers: [UsersService], + exports: [UsersService], }) export class UsersModule {} diff --git a/src/users/users.service.ts b/src/users/users.service.ts index f6a06ca..c201543 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -157,6 +157,9 @@ export class UsersService { await this.usersRepository.save(user); return user; } + async findUser(id: string) { + return await this.usersRepository.findOneBy({ id }); + } async discordLogout(session: SessionData) { await this.revokeDiscordToken(session.tokenData.access_token); diff --git a/src/word/controllers/word.controller.ts b/src/word/controllers/word.controller.ts new file mode 100644 index 0000000..9cbe0be --- /dev/null +++ b/src/word/controllers/word.controller.ts @@ -0,0 +1,63 @@ +import { + Body, + Controller, + Delete, + Get, + HttpException, + HttpStatus, + Param, + Post, + Session, + Sse, + UseGuards, +} from '@nestjs/common'; + +import { WordService } from '../services/word.service'; +import { ApiBody, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { AuthGuard } from 'src/users/guards/auth.guard'; +import { SessionData } from 'express-session'; +import { UsersService } from 'src/users/users.service'; +import { WordResponseDTO } from '../dto/wordresponse.dto'; +import { WordRecieveDTO } from '../dto/wordrecieve.dto'; + +@ApiTags('words') +@Controller('words') +export class WordController { + constructor( + private readonly wordService: WordService, + private readonly userService: UsersService, + ) {} + + @Delete() + @ApiOperation({ summary: 'Delete a word' }) + @UseGuards(AuthGuard) + async delete(@Param('id') id: number) { + const word = await this.wordService.getById(id); + if (!word) { + throw new HttpException('Word not found', HttpStatus.NOT_FOUND); + } + await this.wordService.delete(word); + } + + @Post('/') + @ApiOperation({ summary: 'Submit a word' }) + @ApiBody({ type: WordRecieveDTO }) + @UseGuards(AuthGuard) + async create(@Body('value') value: string, @Session() session: SessionData) { + const user = await this.userService.findUser(session.user.id); + if (!user) { + throw new HttpException( + 'You are not authentified', + HttpStatus.UNAUTHORIZED, + ); + } + const word = await this.wordService.create(value, user); + return new WordResponseDTO(word); + } + + @Get('/') + @ApiOperation({ summary: 'List all words' }) + async read() { + return (await this.wordService.list()).map((w) => new WordResponseDTO(w)); + } +} diff --git a/src/word/dto/wordrecieve.dto.ts b/src/word/dto/wordrecieve.dto.ts new file mode 100644 index 0000000..1e9617f --- /dev/null +++ b/src/word/dto/wordrecieve.dto.ts @@ -0,0 +1,7 @@ +export class WordRecieveDTO { + constructor(partial: Partial) { + Object.assign(this, partial); + } + + value: string; +} diff --git a/src/word/dto/wordresponse.dto.ts b/src/word/dto/wordresponse.dto.ts new file mode 100644 index 0000000..ecde5aa --- /dev/null +++ b/src/word/dto/wordresponse.dto.ts @@ -0,0 +1,16 @@ +import { Expose, Type } from 'class-transformer'; +import { UserResponseDTO } from 'src/users/dto/userresponse.dto'; + +export class WordResponseDTO { + constructor(partial: Partial) { + Object.assign(this, partial); + } + @Expose() + id: number; + + @Expose() + value: string; + + @Expose() + ownerId: string; +} diff --git a/src/words/entities/topic.entity.ts b/src/word/entities/topic.entity.ts similarity index 100% rename from src/words/entities/topic.entity.ts rename to src/word/entities/topic.entity.ts diff --git a/src/words/entities/word.entity.ts b/src/word/entities/word.entity.ts similarity index 67% rename from src/words/entities/word.entity.ts rename to src/word/entities/word.entity.ts index 3d14777..569fee0 100644 --- a/src/words/entities/word.entity.ts +++ b/src/word/entities/word.entity.ts @@ -2,12 +2,11 @@ import { User } from 'src/users/entities/user.entity'; import { Column, Entity, + JoinColumn, JoinTable, ManyToMany, ManyToOne, - OneToMany, PrimaryGeneratedColumn, - Unique, } from 'typeorm'; import { Topic } from './topic.entity'; @@ -19,10 +18,14 @@ export class Word { @Column() value: string; - @ManyToOne((type) => User) + @JoinColumn({ name: 'ownerId' }) + @ManyToOne(() => User) owner: User; - @ManyToMany((type) => Topic, (topic) => topic.words) + @Column({ name: 'ownerId' }) + ownerId: string; + + @ManyToMany(() => Topic, (topic) => topic.words) @JoinTable() topics: Topic[]; } diff --git a/src/word/services/word.service.ts b/src/word/services/word.service.ts new file mode 100644 index 0000000..509512a --- /dev/null +++ b/src/word/services/word.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { Word } from '../entities/word.entity'; +import { User } from 'src/users/entities/user.entity'; + +@Injectable() +export class WordService { + constructor( + @InjectRepository(Word) private wordRepository: Repository, + ) {} + + async getById(id: number) { + return await this.wordRepository.findOneBy({ id }); + } + + async delete(word: Word) { + return await this.wordRepository.remove(word); + } + + async create(value: string, owner: User) { + const word = this.wordRepository.create(); + word.owner = owner; + word.value = value; + await this.wordRepository.save(word); + return word; + } + + async list() { + const words = await this.wordRepository.find({}); + return words; + } +} diff --git a/src/word/words.module.ts b/src/word/words.module.ts new file mode 100644 index 0000000..08a69d7 --- /dev/null +++ b/src/word/words.module.ts @@ -0,0 +1,14 @@ +import { Module } from '@nestjs/common'; + +import { TypeOrmModule } from '@nestjs/typeorm'; +import { Word } from './entities/word.entity'; +import { WordController } from './controllers/word.controller'; +import { WordService } from './services/word.service'; +import { UsersModule } from 'src/users/users.module'; + +@Module({ + imports: [UsersModule, TypeOrmModule.forFeature([Word])], + controllers: [WordController], + providers: [WordService], +}) +export class WordModule {}