Verification done

This commit is contained in:
Frank
2026-01-07 20:06:28 +01:00
parent c6adb00219
commit de4b7bca6a
7 changed files with 726 additions and 8 deletions

View File

@@ -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;
}