From b1080a37aae590675ddadbde569b96f8af0a4127 Mon Sep 17 00:00:00 2001
From: L4168 <L4168@student.jamk.fi>
Date: Mon, 1 Jul 2019 16:59:43 +0300
Subject: [PATCH] fixed group-joins

---
 src/faction/faction.controller.ts | 32 ++++++++++++------
 src/faction/faction.dto.ts        |  9 ++++++
 src/faction/faction.entity.ts     |  7 ++--
 src/faction/faction.service.ts    | 54 ++++++++++++++-----------------
 src/game/game.entity.ts           |  3 --
 5 files changed, 59 insertions(+), 46 deletions(-)

diff --git a/src/faction/faction.controller.ts b/src/faction/faction.controller.ts
index 9ff84e5..28552e9 100644
--- a/src/faction/faction.controller.ts
+++ b/src/faction/faction.controller.ts
@@ -12,7 +12,12 @@ import {
 import { AuthGuard } from '../shared/auth.guard';
 import { ValidationPipe } from '../shared/validation.pipe';
 import { User } from '../user/user.decorator';
-import { GameGroupDTO, PromotePlayerDTO, JoinFactionDTO } from './faction.dto';
+import {
+  GameGroupDTO,
+  PromotePlayerDTO,
+  JoinFactionDTO,
+  JoinGameGroupDTO,
+} from './faction.dto';
 import { FactionService } from './faction.service';
 import { Roles } from '../shared/roles.decorator';
 
@@ -20,8 +25,9 @@ import { Roles } from '../shared/roles.decorator';
 export class FactionController {
   constructor(private factionservice: FactionService) {}
 
-  @Post(':id')
-  @UseGuards(new AuthGuard())
+  // takes gameId from the url to verify user role
+  @Post('create-group/:id')
+  @Roles('soldier')
   @UsePipes(new ValidationPipe())
   async createGroup(
     @User('id') person,
@@ -33,15 +39,21 @@ export class FactionController {
     } catch (error) {}
   }
 
-  @Get('get-groups')
-  async getGroups() {
-    return this.factionservice.showGroups();
+  // id is faction ID
+  @Get('get-groups/:id')
+  async getGroups(@Param('id') id) {
+    return this.factionservice.showGroups(id);
   }
 
-  @Put('groups/:id')
-  @UseGuards(new AuthGuard())
-  async joinGroup(@User('id') person, @Param('id') id) {
-    return this.factionservice.joinGroup(person, id);
+  // takes gameId from the url to verify user role
+  @Put('join-group/:id')
+  @Roles('soldier')
+  async joinGroup(
+    @User('id') person,
+    @Param('id') id,
+    @Body() data: JoinGameGroupDTO,
+  ) {
+    return this.factionservice.joinGroup(person, id, data);
   }
 
   @Get('get-faction-members/:id')
diff --git a/src/faction/faction.dto.ts b/src/faction/faction.dto.ts
index ccc7672..c11e9cc 100644
--- a/src/faction/faction.dto.ts
+++ b/src/faction/faction.dto.ts
@@ -9,6 +9,8 @@ import {
 import { GameEntity } from '../game/game.entity';
 import { RoleValidation } from '../shared/custom-validation';
 import { GameDTO } from '../game/game.dto';
+import { FactionEntity, GameGroupEntity } from './faction.entity';
+import { PersonEntity } from 'src/user/user.entity';
 
 export class FactionDTO {
   @IsString()
@@ -40,4 +42,11 @@ export class GameGroupDTO {
   @IsString()
   @Length(3, 31)
   name: string;
+  @IsUUID('4')
+  faction: FactionEntity;
+}
+
+export class JoinGameGroupDTO {
+  @IsUUID('4')
+  groupId: GameGroupEntity;
 }
diff --git a/src/faction/faction.entity.ts b/src/faction/faction.entity.ts
index da8c418..410723c 100644
--- a/src/faction/faction.entity.ts
+++ b/src/faction/faction.entity.ts
@@ -6,6 +6,7 @@ import {
   ManyToOne,
   OneToOne,
   Timestamp,
+  JoinColumn,
 } from 'typeorm';
 
 import { GameEntity } from '../game/game.entity';
@@ -91,12 +92,12 @@ export class GameGroupEntity {
   @OneToOne(type => Game_PersonEntity, person => person.leaderGroup, {
     onDelete: 'CASCADE',
   })
-  //@JoinColumn({name:'leader'})
+  @JoinColumn({ name: 'leader' })
   leader: Game_PersonEntity;
   @OneToMany(type => Game_PersonEntity, person => person.group, {
     onDelete: 'CASCADE',
   })
   players: Game_PersonEntity[];
-  @ManyToOne(type => GameEntity, game => game.groups)
-  game: GameEntity;
+  @ManyToOne(type => FactionEntity, faction => faction.factionId)
+  faction: FactionEntity;
 }
diff --git a/src/faction/faction.service.ts b/src/faction/faction.service.ts
index 5814aeb..b1ea472 100644
--- a/src/faction/faction.service.ts
+++ b/src/faction/faction.service.ts
@@ -1,9 +1,9 @@
 import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
 import { InjectRepository } from '@nestjs/typeorm';
-import { Repository } from 'typeorm';
+import { Repository, Not } from 'typeorm';
 
 import { FactionEntity, GameGroupEntity } from './faction.entity';
-import { JoinFactionDTO, GameGroupDTO } from './faction.dto';
+import { JoinFactionDTO, GameGroupDTO, JoinGameGroupDTO } from './faction.dto';
 import { Game_PersonEntity } from '../game/game.entity';
 
 @Injectable()
@@ -64,11 +64,18 @@ export class FactionService {
 
   // checks the password, creates an entry in GamePerson table with associated role&faction
   async createGroup(person, gameId, groupData: GameGroupDTO) {
-    // check if the person already is in a group in this game
-    const checkDuplicate = await this.game_PersonRepository.findOne({
+    // get gamePerson ref
+    const gamePerson = await this.game_PersonRepository.findOne({
       person: person,
+      game: gameId,
     });
-    if (checkDuplicate) {
+    // check if the authenticated person already belongs to a group
+    if (
+      await this.game_PersonRepository.findOne({
+        group: Not(null),
+        person: person,
+      })
+    ) {
       throw new HttpException(
         'You already belong to a group!',
         HttpStatus.BAD_REQUEST,
@@ -78,46 +85,33 @@ export class FactionService {
     // create a group entry and insert it to db
     const group = await this.game_GroupRepository.create({
       ...groupData,
-      game: gameId,
+      leader: gamePerson,
     });
     const gameGroup = await this.game_GroupRepository.insert(group);
 
-    // create game_Person entry and insert it to db
-    const gamePerson = await this.game_PersonRepository.create({
-      role: 'soldier',
-      faction: null,
-      game: gameId,
-      person: person,
-      leaderGroup: gameGroup.identifiers[0]['id'],
-      group: gameGroup.identifiers[0]['id'],
-    });
-    await this.game_PersonRepository.insert(gamePerson);
+    // update the gamePerson entry with group data
+    gamePerson.group = gamePerson.leaderGroup = gameGroup.identifiers[0]['id'];
+    await this.game_PersonRepository.save(gamePerson);
 
     return {
       message: 'created new group',
     };
   }
 
-  async showGroups() {
+  async showGroups(factionId) {
     return await this.game_GroupRepository.find({
-      relations: ['leader', 'players', 'game'],
+      relations: ['leader', 'players'],
+      where: { faction: factionId },
     });
   }
 
-  async joinGroup(person, groupId) {
-    const gameData = await this.game_GroupRepository.findOne({
-      where: { id: groupId },
-      relations: ['players', 'game'],
-    });
-    const gamePerson = await this.game_PersonRepository.create({
-      role: 'soldier',
-      faction: null,
-      game: gameData.game,
+  async joinGroup(person, gameId, data: JoinGameGroupDTO) {
+    const gamePerson = await this.game_PersonRepository.findOne({
       person: person,
-      leaderGroup: null,
-      group: groupId,
+      game: gameId,
     });
-    await this.game_PersonRepository.insert(gamePerson);
+    gamePerson.group = data.groupId;
+    await this.game_PersonRepository.save(gamePerson);
     return {
       message: 'Joined group',
     };
diff --git a/src/game/game.entity.ts b/src/game/game.entity.ts
index 9038b5a..b1a9d38 100644
--- a/src/game/game.entity.ts
+++ b/src/game/game.entity.ts
@@ -31,8 +31,6 @@ export class GameEntity {
   factions: FactionEntity[];
   @OneToMany(type => Game_PersonEntity, game_persons => game_persons.game)
   game_persons: Game_PersonEntity[];
-  @OneToMany(type => GameGroupEntity, group => group.game)
-  groups: GameGroupEntity[];
   @OneToMany(
     type => ObjectivePointEntity,
     objective_points => objective_points.game,
@@ -61,7 +59,6 @@ export class Game_PersonEntity {
   @OneToOne(type => GameGroupEntity, group => group.leader, {
     onDelete: 'CASCADE',
   })
-  @JoinColumn({ name: 'leaderGroup' })
   leaderGroup: GameGroupEntity;
   @ManyToOne(type => GameGroupEntity, group => group.players, {
     onDelete: 'CASCADE',
-- 
GitLab