diff --git a/src/Game/Controller/GameController.php b/src/Game/Controller/GameController.php index a685602..6c46080 100644 --- a/src/Game/Controller/GameController.php +++ b/src/Game/Controller/GameController.php @@ -39,6 +39,13 @@ final class GameController extends AbstractController $this->addFlash('success', 'New session created!'); } } + } elseif ($request->request->has('join_session')) { + $inviteCode = $request->request->get('invite_code'); + if ($dashboardService->joinSession($inviteCode, $user)) { + $this->addFlash('success', 'Joined session successfully!'); + } else { + $this->addFlash('error', 'Invalid invite code or session full.'); + } } elseif ($request->request->has('create_invite')) { $sessionId = $request->request->get('session_id'); $session = $sessionRepository->find($sessionId); @@ -52,6 +59,17 @@ final class GameController extends AbstractController if ($inviteCode) { $this->addFlash('success', 'Invite link created: ' . $inviteCode); } + } elseif ($request->request->has('leave_session')) { + $sessionId = $request->request->get('session_id'); + $session = $sessionRepository->find($sessionId); + + if ($session) { + if ($dashboardService->leaveSession($session, $user)) { + $this->addFlash('success', 'Left session successfully.'); + } else { + $this->addFlash('error', 'Could not leave session (game might have started).'); + } + } } return $this->redirectToRoute('game_dashboard'); diff --git a/src/Game/Enum/SessionSettingType.php b/src/Game/Enum/SessionSettingType.php index 1cdd428..66123c0 100644 --- a/src/Game/Enum/SessionSettingType.php +++ b/src/Game/Enum/SessionSettingType.php @@ -12,4 +12,13 @@ enum SessionSettingType: string case RIGHTS_FOR_PLAYER3 = 'RightsForPlayer3'; case INVITE_CODE = 'InviteCode'; case SET_OF_DELETED_FILES = 'SetOfDeletedFiles'; + case CHAT_TRACKING_FOR_PLAYER1 = 'ChatTrackingForPlayer1'; + case CHAT_TRACKING_FOR_PLAYER2 = 'ChatTrackingForPlayer2'; + case CHAT_TRACKING_FOR_PLAYER3 = 'ChatTrackingForPlayer3'; + case VERIFY_CODES_FOR_PLAYER1 = 'VerifyCodesForPlayer1'; + case VERIFY_CODES_FOR_PLAYER2 = 'VerifyCodesForPlayer2'; + case VERIFY_CODES_FOR_PLAYER3 = 'VerifyCodesForPlayer3'; + case VERIFICATION_PROGRESS_FOR_PLAYER1 = 'VerificationProgressForPlayer1'; + case VERIFICATION_PROGRESS_FOR_PLAYER2 = 'VerificationProgressForPlayer2'; + case VERIFICATION_PROGRESS_FOR_PLAYER3 = 'VerificationProgressForPlayer3'; } diff --git a/src/Game/Service/GameDashboardService.php b/src/Game/Service/GameDashboardService.php index b930682..93d2d93 100644 --- a/src/Game/Service/GameDashboardService.php +++ b/src/Game/Service/GameDashboardService.php @@ -71,11 +71,193 @@ final class GameDashboardService $this->entityManager->persist($session); $this->entityManager->persist($player); + + $this->initializePlayerSettings($player); + $this->entityManager->flush(); return $session; } + public function joinSession(string $inviteCode, UserInterface $user): bool + { + if (!$user instanceof User) { + return false; + } + + $setting = $this->entityManager->getRepository(SessionSetting::class)->findOneBy([ + 'name' => SessionSettingType::INVITE_CODE, + 'value' => $inviteCode, + ]); + + if (!$setting) { + return false; + } + + $session = $setting->getSession(); + + // Check if user is already in this session + foreach ($session->getPlayers() as $player) { + if ($player->getUser() === $user) { + return true; // Already joined + } + } + + $playerCount = count($session->getPlayers()); + if ($playerCount >= 3) { + return false; // Session full + } + + $player = new Player(); + $player->setUser($user); + $player->setSession($session); + $player->setScreen($playerCount + 1); + + $this->entityManager->persist($player); + $this->initializePlayerSettings($player); + + $this->entityManager->flush(); + + return true; + } + + public function leaveSession(Session $session, UserInterface $user): bool + { + if (!$user instanceof User) { + return false; + } + + if ($session->getStatus() !== SessionStatus::CREATED || $session->getTimer() > 0) { + return false; + } + + $playerToDelete = null; + foreach ($session->getPlayers() as $player) { + if ($player->getUser() === $user) { + $playerToDelete = $player; + break; + } + } + + if (!$playerToDelete) { + return false; + } + + // Remove player specific settings (like rights) + foreach ($session->getSettings() as $setting) { + if ($setting->getPlayer() === $playerToDelete) { + $session->removeSetting($setting); + $this->entityManager->remove($setting); + } + } + + $session->removePlayer($playerToDelete); + $this->entityManager->remove($playerToDelete); + + // If no players left, we might want to delete the session and its remaining settings + if ($session->getPlayers()->isEmpty()) { + foreach ($session->getSettings() as $setting) { + $this->entityManager->remove($setting); + } + $this->entityManager->remove($session); + } + + $this->entityManager->flush(); + + return true; + } + + private function initializePlayerSettings(Player $player): void + { + $screen = $player->getScreen(); + $rightsSettingName = match ($screen) { + 1 => SessionSettingType::RIGHTS_FOR_PLAYER1, + 2 => SessionSettingType::RIGHTS_FOR_PLAYER2, + 3 => SessionSettingType::RIGHTS_FOR_PLAYER3, + default => null, + }; + + if ($rightsSettingName) { + $setting = new SessionSetting(); + $setting->setSession($player->getSession()); + $setting->setPlayer($player); + $setting->setName($rightsSettingName); + $setting->setValue(json_encode(['chat', 'help', 'ls', 'pwd'])); + $this->entityManager->persist($setting); + } + + $pwdSettingName = match ($screen) { + 1 => SessionSettingType::PWD_FOR_PLAYER1, + 2 => SessionSettingType::PWD_FOR_PLAYER2, + 3 => SessionSettingType::PWD_FOR_PLAYER3, + default => null, + }; + + if ($pwdSettingName) { + $setting = new SessionSetting(); + $setting->setSession($player->getSession()); + $setting->setPlayer($player); + $setting->setName($pwdSettingName); + $setting->setValue('home/' . $player->getUser()->getUserIdentifier()); + $this->entityManager->persist($setting); + } + + $chatTrackingSettingName = match ($screen) { + 1 => SessionSettingType::CHAT_TRACKING_FOR_PLAYER1, + 2 => SessionSettingType::CHAT_TRACKING_FOR_PLAYER2, + 3 => SessionSettingType::CHAT_TRACKING_FOR_PLAYER3, + default => null, + }; + + if ($chatTrackingSettingName) { + $setting = new SessionSetting(); + $setting->setSession($player->getSession()); + $setting->setPlayer($player); + $setting->setName($chatTrackingSettingName); + $setting->setValue(json_encode([])); + $this->entityManager->persist($setting); + } + + $verifyCodesSettingName = match ($screen) { + 1 => SessionSettingType::VERIFY_CODES_FOR_PLAYER1, + 2 => SessionSettingType::VERIFY_CODES_FOR_PLAYER2, + 3 => SessionSettingType::VERIFY_CODES_FOR_PLAYER3, + default => null, + }; + + if ($verifyCodesSettingName) { + $codes = []; + for ($i = 1; $i <= 3; $i++) { + if ($i !== $screen) { + $codes[$i] = bin2hex(random_bytes(3)); // 6 characters code + } + } + + $setting = new SessionSetting(); + $setting->setSession($player->getSession()); + $setting->setPlayer($player); + $setting->setName($verifyCodesSettingName); + $setting->setValue(json_encode($codes)); + $this->entityManager->persist($setting); + } + + $verificationProgressSettingName = match ($screen) { + 1 => SessionSettingType::VERIFICATION_PROGRESS_FOR_PLAYER1, + 2 => SessionSettingType::VERIFICATION_PROGRESS_FOR_PLAYER2, + 3 => SessionSettingType::VERIFICATION_PROGRESS_FOR_PLAYER3, + default => null, + }; + + if ($verificationProgressSettingName) { + $setting = new SessionSetting(); + $setting->setSession($player->getSession()); + $setting->setPlayer($player); + $setting->setName($verificationProgressSettingName); + $setting->setValue(json_encode([])); + $this->entityManager->persist($setting); + } + } + public function generateInviteCode(Session $session, UserInterface $user, bool $isAdmin): ?string { // Security check: is user part of this session? diff --git a/src/Game/Service/GameResponseService.php b/src/Game/Service/GameResponseService.php index 8168f99..707b3b8 100644 --- a/src/Game/Service/GameResponseService.php +++ b/src/Game/Service/GameResponseService.php @@ -5,8 +5,10 @@ namespace App\Game\Service; use App\Game\Enum\DecodeMessage; use App\Game\Enum\SessionSettingType; use App\Game\Entity\Player; +use App\Game\Entity\SessionSetting; use App\Game\Repository\SessionSettingRepository; use App\Tech\Entity\User; +use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Mercure\HubInterface; use Symfony\Component\Mercure\Update; @@ -18,6 +20,7 @@ class GameResponseService private PlayerService $playerService, private SessionSettingRepository $sessionSettingRepository, private HubInterface $hub, + private EntityManagerInterface $entityManager, ) { } @@ -101,7 +104,7 @@ class GameResponseService if(!in_array('verify', $rechten)) return ['result' => ['Unknown command']]; - $result = $this->handleVerifyMessage($message); + $result = $this->handleVerifyMessage($message, $player); return ['result' => [$result]]; default: return ['result' => ['Unknown command']]; @@ -275,9 +278,10 @@ class GameResponseService if ($toSingle) { $sendTo = array_shift($messageParts); + $chatMessage = array_shift($messageParts); } - $message = $player->getUser()->getUsername() . ': ' . $chatMessage; + $message = $player->getUser()->getUsername() . ': ' . $chatMessage . ' '; foreach($messageParts as $messagePart) { $message .= $messagePart . ' '; } @@ -292,9 +296,146 @@ class GameResponseService $topic = $_ENV['MERCURE_TOPIC_BASE'] . '/game/hub-' . $activeGame; $this->hub->publish(new Update($topic, json_encode([$sendTo, $message]))); + $this->updateChatTracking($player, (int)$sendTo); + + $this->checkAndRegenerateVerifyCodes($player, $chatMessage . ' ' . implode(' ', $messageParts)); + return true; } + private function checkAndRegenerateVerifyCodes(Player $player, string $messageContent): void + { + $screen = $player->getScreen(); + $session = $player->getSession(); + + $verifyCodesSettingName = match ($screen) { + 1 => SessionSettingType::VERIFY_CODES_FOR_PLAYER1, + 2 => SessionSettingType::VERIFY_CODES_FOR_PLAYER2, + 3 => SessionSettingType::VERIFY_CODES_FOR_PLAYER3, + default => null, + }; + + if (!$verifyCodesSettingName) { + return; + } + + $setting = $this->sessionSettingRepository->getSetting($session, $verifyCodesSettingName, $player); + if (!$setting) { + return; + } + + $codes = json_decode($setting->getValue() ?? '[]', true) ?? []; + $regenerated = false; + + foreach ($codes as $targetPlayerScreen => $code) { + if (str_contains($messageContent, (string)$code)) { + $codes[$targetPlayerScreen] = bin2hex(random_bytes(3)); + $regenerated = true; + } + } + + if ($regenerated) { + $setting->setValue(json_encode($codes)); + $this->entityManager->persist($setting); + $this->entityManager->flush(); + + // Notify the player that their codes have changed + $topic = $_ENV['MERCURE_TOPIC_BASE'] . '/game/hub-' . $session->getId(); + $notification = "Security Alert: One of your verify codes was shared and has been regenerated."; + // We send it only to this player (screen) + $this->hub->publish(new Update($topic, json_encode([$screen, $notification]))); + } + } + + private function updateChatTracking(Player $player, int $sendTo): void + { + $rights = $this->getRechten($player); + if(in_array('verify', $rights)) + return; + + $trackingSettingName = match ($player->getScreen()) { + 1 => SessionSettingType::CHAT_TRACKING_FOR_PLAYER1, + 2 => SessionSettingType::CHAT_TRACKING_FOR_PLAYER2, + 3 => SessionSettingType::CHAT_TRACKING_FOR_PLAYER3, + default => null, + }; + + if (!$trackingSettingName) { + return; + } + + $setting = $this->sessionSettingRepository->getSetting($player->getSession(), $trackingSettingName, $player); + if (!$setting) { + $setting = new SessionSetting(); + $setting->setSession($player->getSession()); + $setting->setPlayer($player); + $setting->setName($trackingSettingName); + $setting->setValue(json_encode([])); + } + + $tracking = json_decode($setting->getValue() ?? '[]', true) ?? []; + if (!in_array($sendTo, $tracking)) { + $tracking[] = $sendTo; + $setting->setValue(json_encode($tracking)); + $this->entityManager->persist($setting); + $this->entityManager->flush(); + + $this->checkAndGrantVerifyRight($player, $tracking); + } + } + + private function checkAndGrantVerifyRight(Player $player, array $tracking): void + { + $screen = $player->getScreen(); + $requiredTargets = [0]; // Everyone + for ($i = 1; $i <= 3; $i++) { + if ($i !== $screen) { + $requiredTargets[] = $i; + } + } + + // Check if all required targets are in tracking + foreach ($requiredTargets as $target) { + if (!in_array($target, $tracking)) { + return; + } + } + + // Grant verify right + $rightsSettingName = match ($screen) { + 1 => SessionSettingType::RIGHTS_FOR_PLAYER1, + 2 => SessionSettingType::RIGHTS_FOR_PLAYER2, + 3 => SessionSettingType::RIGHTS_FOR_PLAYER3, + default => null, + }; + + if (!$rightsSettingName) { + return; + } + + $setting = $this->sessionSettingRepository->getSetting($player->getSession(), $rightsSettingName, $player); + if (!$setting) { + return; // Should have been initialized + } + + $rights = json_decode($setting->getValue() ?? '[]', true) ?? []; + $newRights = ['verify', 'cat']; + + $updated = false; + foreach ($newRights as $newRight) { + if (!in_array($newRight, $rights)) { + $rights[] = $newRight; + $updated = true; + } + } + + if ($updated) { + $setting->setValue(json_encode($rights)); + $this->entityManager->persist($setting); + $this->entityManager->flush(); + } + } + private function handleDecodeMessage(string $message, Player $player) { $userNumber = $player->getScreen(); @@ -327,9 +468,123 @@ class GameResponseService return $randomString; } - private function handleVerifyMessage(string $message) : string + private function handleVerifyMessage(string $message, Player $player) : string { - return ''; + $messageParts = explode(' ', $message); + if (count($messageParts) < 2) { + return 'Usage: /verify {code}'; + } + + $code = $messageParts[1]; + $screen = $player->getScreen(); + $session = $player->getSession(); + + $progressSettingName = match ($screen) { + 1 => SessionSettingType::VERIFICATION_PROGRESS_FOR_PLAYER1, + 2 => SessionSettingType::VERIFICATION_PROGRESS_FOR_PLAYER2, + 3 => SessionSettingType::VERIFICATION_PROGRESS_FOR_PLAYER3, + default => null, + }; + + if (!$progressSettingName) { + return 'Error: Invalid player screen.'; + } + + $progressSetting = $this->sessionSettingRepository->getSetting($session, $progressSettingName, $player); + if (!$progressSetting) { + return 'Error: Verification progress setting not found.'; + } + + $progress = json_decode($progressSetting->getValue() ?? '[]', true) ?? []; + + $verifiedBy = null; + foreach ($session->getPlayers() as $otherPlayer) { + if ($otherPlayer->getId() === $player->getId()) { + continue; + } + + $otherScreen = $otherPlayer->getScreen(); + $codesSettingName = match ($otherScreen) { + 1 => SessionSettingType::VERIFY_CODES_FOR_PLAYER1, + 2 => SessionSettingType::VERIFY_CODES_FOR_PLAYER2, + 3 => SessionSettingType::VERIFY_CODES_FOR_PLAYER3, + default => null, + }; + + if (!$codesSettingName) { + continue; + } + + $codesSetting = $this->sessionSettingRepository->getSetting($session, $codesSettingName, $otherPlayer); + if (!$codesSetting) { + continue; + } + + $codes = json_decode($codesSetting->getValue() ?? '[]', true) ?? []; + if (isset($codes[$screen]) && $codes[$screen] === $code) { + $verifiedBy = $otherScreen; + break; + } + } + + if ($verifiedBy !== null) { + if (!in_array($verifiedBy, $progress)) { + $progress[] = $verifiedBy; + $progressSetting->setValue(json_encode($progress)); + $this->entityManager->persist($progressSetting); + $this->entityManager->flush(); + + $response = 'You have been successfully verified by Agent ' . $verifiedBy . '.'; + + if (count($progress) >= 2) { + $this->grantVerificationRights($player); + $response .= ' You have received additional rights!'; + } + + return $response; + } else { + return 'You were already verified by Agent ' . $verifiedBy . '.'; + } + } + + return 'Invalid verification code.'; + } + + private function grantVerificationRights(Player $player): void + { + $screen = $player->getScreen(); + $rightsSettingName = match ($screen) { + 1 => SessionSettingType::RIGHTS_FOR_PLAYER1, + 2 => SessionSettingType::RIGHTS_FOR_PLAYER2, + 3 => SessionSettingType::RIGHTS_FOR_PLAYER3, + default => null, + }; + + if (!$rightsSettingName) { + return; + } + + $setting = $this->sessionSettingRepository->getSetting($player->getSession(), $rightsSettingName, $player); + if (!$setting) { + return; + } + + $rights = json_decode($setting->getValue() ?? '[]', true) ?? []; + $newRights = ['cd', 'decode']; + + $updated = false; + foreach ($newRights as $newRight) { + if (!in_array($newRight, $rights)) { + $rights[] = $newRight; + $updated = true; + } + } + + if ($updated) { + $setting->setValue(json_encode($rights)); + $this->entityManager->persist($setting); + $this->entityManager->flush(); + } } private function goToNewDir(string $pwd, string $newPwd, Player $player) : string|bool @@ -412,7 +667,7 @@ class GameResponseService private function isAllowedToRemove(string $file, Player $player, bool $sudo) : bool { - if(!$this->fileExists($file)) + if(!$this->fileExists($file, $player)) return false; if(str_starts_with($file, '/var/rapports/')) @@ -432,9 +687,9 @@ class GameResponseService return !in_array($file, $sudoFiles); } - private function fileExists(string $file) + private function fileExists(string $file, Player $player) : bool { - $files = $this->getAllPossibleFiles(); + $files = $this->getAllPossibleFiles($player); if(in_array($file, $files)) return true; @@ -442,7 +697,7 @@ class GameResponseService return false; } - private function getAllPossibleFiles() + private function getAllPossibleFiles(Player $player = null) : array { $files = []; @@ -472,6 +727,12 @@ class GameResponseService $files[] = '/var/rapports/001_145-93.txt'; $files[] = '/var/rapports/index.txt'; + $players = $player->getSession()->getPlayers(); + + foreach($players as $player) { + $files[] = '/var/home/' . $player->getUser()->getUsername() . '/verifyCodes.txt'; + } + return $files; } diff --git a/templates/game/dashboard.html.twig b/templates/game/dashboard.html.twig index 9dd8245..e177c42 100644 --- a/templates/game/dashboard.html.twig +++ b/templates/game/dashboard.html.twig @@ -24,6 +24,12 @@

No games available to start.

{% endif %} +

Join Session

+
+ + +
+

Your Sessions

{% if sessions is not empty %} @@ -63,6 +69,12 @@ {% endfor %} diff --git a/tests/Game/GameDashboardServiceTest.php b/tests/Game/GameDashboardServiceTest.php new file mode 100644 index 0000000..e1aba6b --- /dev/null +++ b/tests/Game/GameDashboardServiceTest.php @@ -0,0 +1,135 @@ +entityManager = $this->createMock(EntityManagerInterface::class); + $this->gameRepository = $this->createMock(GameRepository::class); + $this->sessionRepository = $this->createMock(SessionRepository::class); + + $this->service = new GameDashboardService( + $this->gameRepository, + $this->sessionRepository, + $this->entityManager + ); + } + + public function testCreateSessionInitializesRightsAndPwd(): void + { + $game = new Game(); + $game->setStatus(GameStatus::OPEN); + + $user = new User(); + $user->setUsername('testuser'); + + $this->entityManager->expects($this->exactly(7)) + ->method('persist'); + // 1. Session, 2. Player, 3. SessionSetting (rights), 4. SessionSetting (pwd), 5. SessionSetting (chat tracking), 6. SessionSetting (verify codes), 7. SessionSetting (verification progress) + + $session = $this->service->createSession($game, $user, false); + + $this->assertInstanceOf(Session::class, $session); + } + + public function testJoinSessionInitializesRightsAndPwd(): void + { + $user = new User(); + $user->setUsername('testuser'); + $session = new Session(); + + $setting = new SessionSetting(); + $setting->setSession($session); + $setting->setName(SessionSettingType::INVITE_CODE); + $setting->setValue('abc-123'); + + $repo = $this->createMock(\Doctrine\ORM\EntityRepository::class); + $this->entityManager->method('getRepository') + ->willReturn($repo); + + $repo->method('findOneBy') + ->willReturn($setting); + + $this->entityManager->expects($this->exactly(6)) + ->method('persist'); + // 1. Player, 2. SessionSetting (rights), 3. SessionSetting (pwd), 4. SessionSetting (chat tracking), 5. SessionSetting (verify codes), 6. SessionSetting (verification progress) + + $result = $this->service->joinSession('abc-123', $user); + + $this->assertTrue($result); + } + + public function testLeaveSession(): void + { + $user = new User(); + $session = new Session(); + $session->setStatus(\App\Game\Enum\SessionStatus::CREATED); + $session->setTimer(0); + + $player1 = new Player(); + $player1->setUser($user); + $player1->setSession($session); + $session->addPlayer($player1); + + $player2 = new Player(); + $player2->setUser(new User()); + $player2->setSession($session); + $session->addPlayer($player2); + + $setting = new SessionSetting(); + $setting->setPlayer($player1); + $setting->setSession($session); + $session->addSetting($setting); + + $this->entityManager->expects($this->exactly(2)) + ->method('remove'); + // 1. SessionSetting, 2. Player + + $result = $this->service->leaveSession($session, $user); + + $this->assertTrue($result); + $this->assertCount(1, $session->getPlayers()); + } + + public function testLeaveSessionDeletesSessionIfLastPlayer(): void + { + $user = new User(); + $session = new Session(); + $session->setStatus(\App\Game\Enum\SessionStatus::CREATED); + $session->setTimer(0); + + $player = new Player(); + $player->setUser($user); + $player->setSession($session); + $session->addPlayer($player); + + $this->entityManager->expects($this->exactly(2)) + ->method('remove'); + // 1. Player, 2. Session + + $result = $this->service->leaveSession($session, $user); + + $this->assertTrue($result); + } +} diff --git a/tests/Game/GameResponseServiceChatVerifyCodeTest.php b/tests/Game/GameResponseServiceChatVerifyCodeTest.php new file mode 100644 index 0000000..dbdaea0 --- /dev/null +++ b/tests/Game/GameResponseServiceChatVerifyCodeTest.php @@ -0,0 +1,101 @@ +security = $this->createMock(Security::class); + $this->playerService = $this->createMock(PlayerService::class); + $this->sessionSettingRepository = $this->createMock(SessionSettingRepository::class); + $this->hub = $this->createMock(HubInterface::class); + $this->entityManager = $this->createMock(EntityManagerInterface::class); + + $this->service = new GameResponseService( + $this->security, + $this->playerService, + $this->sessionSettingRepository, + $this->hub, + $this->entityManager + ); + + $_ENV['MERCURE_TOPIC_BASE'] = 'http://test'; + } + + public function testChatRegeneratesVerifyCodesIfShared(): void + { + $user = new User(); + $user->setUsername('testuser'); + + $session = $this->createMock(Session::class); + $session->method('getId')->willReturn(123); + + $player = $this->createMock(Player::class); + $player->method('getUser')->willReturn($user); + $player->method('getScreen')->willReturn(1); + $player->method('getSession')->willReturn($session); + + $this->security->method('getUser')->willReturn($user); + $this->playerService->method('GetCurrentlyActiveAsPlayer')->willReturn($player); + + // Mock rights + $rightsSetting = new SessionSetting(); + $rightsSetting->setValue(json_encode(['chat'])); + $this->sessionSettingRepository->method('getSetting') + ->willReturnMap([ + [$session, SessionSettingType::RIGHTS_FOR_PLAYER1, $player, $rightsSetting], + ]); + + // Mock verify codes + $verifyCodesSetting = new SessionSetting(); + $initialCodes = ['2' => 'secret123', '3' => 'secret456']; + $verifyCodesSetting->setValue(json_encode($initialCodes)); + + // Setting repository map for multiple calls + $this->sessionSettingRepository->method('getSetting') + ->willReturnCallback(function($s, $t, $p = null) use ($rightsSetting, $verifyCodesSetting) { + if ($t === SessionSettingType::RIGHTS_FOR_PLAYER1) return $rightsSetting; + if ($t === SessionSettingType::VERIFY_CODES_FOR_PLAYER1) return $verifyCodesSetting; + return null; + }); + + // Expect Mercure updates: 1 for chat, 1 for notification + $this->hub->expects($this->exactly(2)) + ->method('publish'); + + $this->entityManager->expects($this->once()) + ->method('flush'); + + $raw = json_encode(['message' => '/chat Hello look at my code secret123', 'ts' => '123']); + $result = $this->service->getGameResponse($raw); + + $this->assertEquals(['result' => ['succesfully send']], $result); + + $newCodes = json_decode($verifyCodesSetting->getValue(), true); + $this->assertNotEquals('secret123', $newCodes['2']); + $this->assertEquals('secret456', $newCodes['3']); + } +}
Enter Game + {% if session.status.value == 'created' and session.timer == 0 %} +
+ + +
+ {% endif %}