diff --git a/src/game/game.entity.ts b/src/game/game.entity.ts
index 3b36297c022992a43b7a4999fc9eccba1b493b27..036b31c8a3cf1d0343c8f31c691a50d749d97d0f 100644
--- a/src/game/game.entity.ts
+++ b/src/game/game.entity.ts
@@ -12,10 +12,8 @@ import {
 import { PersonEntity } from '../user/user.entity';
 import { GameGroupEntity } from './group.entity';
 import { FactionEntity } from './faction.entity';
-import {
-  MapDrawingEntity,
-  Game_Person_MapDrawingEntity,
-} from './coordinate.entity';
+import { MapDrawingEntity } from './coordinate.entity';
+import { TaskEntity } from '../task/task.entity';
 
 // table that stores all created games
 @Entity('Game')
@@ -40,6 +38,8 @@ export class GameEntity {
     objective_points => objective_points.game,
   )
   objective_points: ObjectivePointEntity[];
+  @OneToMany(type => TaskEntity, tasks => tasks.taskGame)
+  tasks: TaskEntity[];
 
   gameObject() {
     const { id, name } = this;
diff --git a/src/shared/array-validation.ts b/src/shared/array-validation.ts
deleted file mode 100644
index 494ab42f06d0d067fcb115e6eebb63ef8dca2746..0000000000000000000000000000000000000000
--- a/src/shared/array-validation.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import {ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments} from "class-validator";
-import { Logger } from "@nestjs/common";
-
-// validates array length
-@ValidatorConstraint({ name: "arrayLength", async: true })
-export class ArrayLength implements ValidatorConstraintInterface {
-
-    validate(array: string[], args: ValidationArguments) {
-        Logger.log(array.length)
-        return array.length > args.constraints[0] && array.length < args.constraints[1]; // for async validations you must return a Promise<boolean> here
-    }
-
-    defaultMessage(args: ValidationArguments) { // here you can provide default error message if validation failed
-        return "Please input all passwords";
-    }
-
-}
\ No newline at end of file
diff --git a/src/shared/custom-validation.ts b/src/shared/custom-validation.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a920e717e08a6981f5f2e82ddc5cf237ecddba11
--- /dev/null
+++ b/src/shared/custom-validation.ts
@@ -0,0 +1,32 @@
+import {
+  ValidatorConstraint,
+  ValidatorConstraintInterface,
+  ValidationArguments,
+  Validator,
+} from 'class-validator';
+
+// check if input is null or valid uuid
+@ValidatorConstraint({ name: 'uuid', async: true })
+export class Uuid implements ValidatorConstraintInterface {
+  validate(uuid: string, args: ValidationArguments) {
+    const validator = new Validator();
+    return validator.isUUID(uuid, '4') || uuid == null; // for async validations you must return a Promise<boolean> here
+  }
+
+  defaultMessage(args: ValidationArguments) {
+    return 'Not valid uuid';
+  }
+}
+
+// checks if role is valid
+@ValidatorConstraint({ name: 'roleValidation', async: true })
+export class RoleValidation implements ValidatorConstraintInterface {
+  validate(role: string, args: ValidationArguments) {
+    const validRoles = ['admin', 'soldier', 'factionleader'];
+    return validRoles.includes(role);
+  }
+
+  defaultMessage(args: ValidationArguments) {
+    return 'Not valid uuid';
+  }
+}
diff --git a/src/shared/roles.guard.ts b/src/shared/roles.guard.ts
index e65916a94b3cc552259a63a9f5395e3118f95e1b..73693f9e1551da1b1b34056a665eb59c1211b3ef 100644
--- a/src/shared/roles.guard.ts
+++ b/src/shared/roles.guard.ts
@@ -32,9 +32,9 @@ export class RolesGuard implements CanActivate {
       return false;
     }
     const gameId = request.params.id;
-    const user = await this.getUserObject(request.headers.authorization);
+    request.user = await this.getUserObject(request.headers.authorization);
     const role = await this.game_PersonRepository.findOne({
-      person: user['id'],
+      person: request.user['id'],
       game: gameId,
     });
     // check that the role matches the criteria and that token is valid for this game
diff --git a/src/task/task.controller.ts b/src/task/task.controller.ts
index 6f272a0ce4c9d51e49ec3fbba78d666e283b0910..32766ffd6bc1c6f5f51a5234ae2024bc345582e2 100644
--- a/src/task/task.controller.ts
+++ b/src/task/task.controller.ts
@@ -7,35 +7,41 @@ import {
   UseGuards,
   Param,
 } from '@nestjs/common';
+
 import { TaskService } from './task.service';
+import { CreateTaskDTO, EditTaskDTO } from './task.dto';
+import { AuthGuard } from '../shared/auth.guard';
 import { Roles } from '../shared/roles.decorator';
 import { ValidationPipe } from '../shared/validation.pipe';
-import { TaskDTO } from './task.dto';
+import { User } from 'src/user/user.decorator';
 
 @Controller('task')
 export class TaskController {
   constructor(private taskService: TaskService) {}
 
-  /*   @Post('new')
-  @UseGuards(new AuthGuard())
+  // creates a new task if the user has admin role in the game
+  // :id is the id of the game
+  @Post('new-task/:id')
+  @Roles('admin')
   @UsePipes(new ValidationPipe())
-  async newGame(@User('id') person, @Body() body: GameDTO) {
-    return this.gameservice.createNewGame(person, body);
+  async newTask(@Param('id') id: string, @Body() task: CreateTaskDTO) {
+    return this.taskService.newTask(task);
   }
 
-  @Put(':id')
+  // edits a created task if the user has admin role in the game
+  // :id is the id of the game
+  @Post('edit-task/:id')
   @Roles('admin')
   @UsePipes(new ValidationPipe())
-  async editGame(@Param('id') id: string, @Body() body: GameDTO) {
-    return this.gameservice.editGame(id, body);
-  } */
+  async editTask(@Param('id') id: string, @Body() data: EditTaskDTO) {
+    return this.taskService.editTask(data);
+  }
 
-  // creates a new task if the user has admin role in the game
+  // lists all the tasks for the game if user has game_person entry
   // :id is the id of the game
-  @Post('new-task/:id')
-  //@Roles('admin')
-  @UsePipes(new ValidationPipe())
-  async newTask(@Param('id') id: string, @Body() task: TaskDTO) {
-    return this.taskService.newTask(task);
+  @Get('get-tasks/:id')
+  @Roles('soldier', 'factionleader', 'admin')
+  async fetchTasks(@User('id') person, @Param('id') id: string) {
+    return this.taskService.fetchTasks(person, id);
   }
 }
diff --git a/src/task/task.dto.ts b/src/task/task.dto.ts
index aa3238f888d0ad2975d4c6bab519421ddd41635d..3a363b5f95602d03294a5d256982558f19c1b937 100644
--- a/src/task/task.dto.ts
+++ b/src/task/task.dto.ts
@@ -1,30 +1,38 @@
 import {
   IsString,
   Length,
-  IsNumber,
   IsBoolean,
-  Min,
-  Max,
+  Validate,
+  IsUUID,
+  Equals,
 } from 'class-validator';
-import { FactionEntity } from 'src/game/faction.entity';
+import { FactionEntity } from '../game/faction.entity';
+import { GameEntity } from '../game/game.entity';
+import { Uuid } from '../shared/custom-validation';
 
-export class TaskDTO {
+export class CreateTaskDTO {
   @IsString()
   @Length(3, 31)
   taskName: string;
   @IsString()
   @Length(0, 255)
   taskDescription: string;
-  @IsNumber()
-  @Min(1)
-  @Max(99)
-  taskScore: number;
-  @IsString()
-  @Length(3, 31)
-  taskWinner?: string;
   @IsBoolean()
   taskIsActive: boolean;
-  // faction unique id
-  @IsString()
+  @Validate(Uuid)
   faction: FactionEntity;
+  @Equals(null)
+  taskWinner: FactionEntity;
+  // faction unique id
+  @IsUUID('4')
+  taskGame: GameEntity;
+}
+
+export class EditTaskDTO {
+  @IsUUID('4')
+  taskId: string;
+  @IsUUID('4')
+  taskWinner: FactionEntity;
+  @IsUUID('4')
+  taskGame: GameEntity;
 }
diff --git a/src/task/task.entity.ts b/src/task/task.entity.ts
index 1e7470102800e44bb60d68d73340eedb67e8b93e..e6fd61879325993ff34609d7e0b15f5dd89dfc18 100644
--- a/src/task/task.entity.ts
+++ b/src/task/task.entity.ts
@@ -1,15 +1,25 @@
-import { PrimaryGeneratedColumn, Column, Entity, ManyToOne } from 'typeorm';
+import {
+  PrimaryGeneratedColumn,
+  Column,
+  Entity,
+  ManyToOne,
+  JoinColumn,
+} from 'typeorm';
 import { FactionEntity } from 'src/game/faction.entity';
+import { GameEntity } from 'src/game/game.entity';
 
 @Entity('Task')
 export class TaskEntity {
   @PrimaryGeneratedColumn('uuid') taskId: string;
   @Column({ type: 'text' }) taskName: string;
   @Column({ type: 'text' }) taskDescription: string;
-  @Column({ type: 'float' }) taskScore: number;
-  @Column({ type: 'text' }) taskWinner: string;
   @Column({ type: 'bool' }) taskIsActive: boolean;
 
   @ManyToOne(type => FactionEntity, faction => faction.factionId)
   faction: FactionEntity;
+  @ManyToOne(type => FactionEntity, faction => faction.factionId)
+  taskWinner: FactionEntity;
+  @ManyToOne(type => GameEntity, game => game.id)
+  @JoinColumn({ name: 'taskGame' })
+  taskGame: GameEntity;
 }
diff --git a/src/task/task.module.ts b/src/task/task.module.ts
index ea321484169a3868f1f5d8d49f62574ab2253be8..12112f92a47ef2c30f0c130d15dba0d5b4c41126 100644
--- a/src/task/task.module.ts
+++ b/src/task/task.module.ts
@@ -4,9 +4,15 @@ import { TypeOrmModule } from '@nestjs/typeorm';
 import { TaskService } from './task.service';
 import { TaskController } from './task.controller';
 import { TaskEntity } from './task.entity';
+import { FactionEntity } from '../game/faction.entity';
+import { Game_PersonEntity } from '../game/game.entity';
+import { NotificationModule } from '../notifications/notifications.module';
 
 @Module({
-  imports: [TypeOrmModule.forFeature([TaskEntity])],
+  imports: [
+    TypeOrmModule.forFeature([TaskEntity, FactionEntity, Game_PersonEntity]),
+    NotificationModule,
+  ],
   controllers: [TaskController],
   providers: [TaskService],
 })
diff --git a/src/task/task.service.ts b/src/task/task.service.ts
index 830e6156222be1039e16c44cd50de1b453628991..082f5b00f6203ca0558c88423d8a7e6da99fe7eb 100644
--- a/src/task/task.service.ts
+++ b/src/task/task.service.ts
@@ -1,21 +1,99 @@
 import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
 import { Repository } from 'typeorm';
 import { InjectRepository } from '@nestjs/typeorm';
+
 import { TaskEntity } from './task.entity';
-import { TaskDTO } from './task.dto';
+import { CreateTaskDTO, EditTaskDTO } from './task.dto';
+import { FactionEntity } from '../game/faction.entity';
+import { Game_PersonEntity } from '../game/game.entity';
+import { NotificationGateway } from '../notifications/notifications.gateway';
 
 @Injectable()
 export class TaskService {
   constructor(
     @InjectRepository(TaskEntity)
     private taskRepository: Repository<TaskEntity>,
+    @InjectRepository(FactionEntity)
+    private factionRepository: Repository<FactionEntity>,
+    @InjectRepository(Game_PersonEntity)
+    private gamePersonRepository: Repository<Game_PersonEntity>,
+    private notificationGateway: NotificationGateway,
   ) {}
 
-  async newTask(task: TaskDTO) {
+  async newTask(task: CreateTaskDTO) {
+    // check if is not null, check that the faction exists in the game
+    if (
+      task.faction != null &&
+      !(await this.factionRepository.findOne({
+        factionId: task.faction.toString(),
+        game: task.taskGame,
+      }))
+    ) {
+      throw new HttpException('Faction not found', HttpStatus.BAD_REQUEST);
+    }
     const createdTask = await this.taskRepository.create(task);
     await this.taskRepository.insert(createdTask);
+    // notify subscribers about a new task
+    // if faction was set it notifies only faction members, else everyone
+    this.notificationGateway.server.emit(
+      task.faction != null ? task.faction.toString() : 'global',
+      'new task',
+    );
     return {
       message: 'Task added',
     };
   }
+
+  async editTask(data: EditTaskDTO) {
+    const task = await this.taskRepository.findOne(data.taskId);
+    console.log(task);
+    // checks if task is already closed
+    if (!task.taskIsActive) {
+      throw new HttpException('Task is not active', HttpStatus.BAD_REQUEST);
+    }
+    // checks if faction is valid
+    if (
+      !(await this.factionRepository.findOne({
+        factionId: data.taskWinner.toString(),
+        game: data.taskGame,
+      }))
+    ) {
+      throw new HttpException('Faction not found', HttpStatus.BAD_REQUEST);
+    }
+    task.taskWinner = data.taskWinner;
+    task.taskIsActive = false;
+    await this.taskRepository.save(task);
+    return {
+      message: 'Task updated and closed',
+    };
+  }
+
+  async fetchTasks(user, taskGame) {
+    const gamePerson = await this.gamePersonRepository.findOne({
+      where: {
+        person: user,
+        game: taskGame,
+      },
+      relations: ['faction'],
+    });
+    if (gamePerson.role == 'admin') {
+      return await this.taskRepository.find({ taskGame: taskGame });
+    } else {
+      return await this.taskRepository.find({
+        relations: ['faction'],
+        where: [
+          {
+            taskGame: taskGame,
+            faction: gamePerson.faction.factionId,
+            taskIsActive: true,
+          },
+          {
+            taskGame: taskGame,
+            faction: null,
+            taskIsActive: true,
+          },
+        ],
+      });
+    }
+  }
 }