mirror of
https://github.com/ericasch6/scrum-poker-internal.git
synced 2026-10-15 11:46:10 +00:00
Handle authenticated room instance takeover
This commit is contained in:
@@ -205,6 +205,17 @@ class RoomParticipationService
|
||||
?User $user,
|
||||
mixed $sessionPlayerId,
|
||||
): ?Player {
|
||||
if ($user !== null) {
|
||||
$userPlayer = $room->players()
|
||||
->where('user_id', $user->id)
|
||||
->lockForUpdate()
|
||||
->first();
|
||||
|
||||
if ($userPlayer !== null) {
|
||||
return $userPlayer;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_numeric($sessionPlayerId)) {
|
||||
$sessionPlayer = $room->players()
|
||||
->whereKey((int) $sessionPlayerId)
|
||||
@@ -216,14 +227,53 @@ class RoomParticipationService
|
||||
}
|
||||
}
|
||||
|
||||
if ($user === null) {
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
public function activateInstance(Room $room, Player $player, string $instanceId): Player
|
||||
{
|
||||
[$activePlayer, $replacedInstanceId, $stateVersion] = DB::transaction(function () use ($room, $player, $instanceId): array {
|
||||
$lockedRoom = Room::query()
|
||||
->lockForUpdate()
|
||||
->findOrFail($room->id);
|
||||
$lockedPlayer = $lockedRoom->players()
|
||||
->lockForUpdate()
|
||||
->findOrFail($player->id);
|
||||
|
||||
if ($lockedPlayer->active_instance_id === $instanceId) {
|
||||
return [$lockedPlayer, null, null];
|
||||
}
|
||||
|
||||
$replacedInstanceId = $lockedPlayer->active_instance_id;
|
||||
$lockedPlayer->update([
|
||||
'active_instance_id' => $instanceId,
|
||||
'last_seen_at' => now(),
|
||||
]);
|
||||
|
||||
if ($replacedInstanceId === null) {
|
||||
return [$lockedPlayer, null, null];
|
||||
}
|
||||
|
||||
$lockedRoom->update([
|
||||
'last_activity_at' => now(),
|
||||
'state_version' => $lockedRoom->state_version + 1,
|
||||
]);
|
||||
|
||||
return [$lockedPlayer, $replacedInstanceId, $lockedRoom->state_version];
|
||||
});
|
||||
|
||||
if (is_string($replacedInstanceId) && is_int($stateVersion)) {
|
||||
RoomStateChanged::dispatch(
|
||||
$room->id,
|
||||
$stateVersion,
|
||||
RoomStateChange::PlayerInstanceReplaced,
|
||||
$this->realtimeState->for($room),
|
||||
$activePlayer->id,
|
||||
$replacedInstanceId,
|
||||
);
|
||||
}
|
||||
|
||||
return $room->players()
|
||||
->where('user_id', $user->id)
|
||||
->lockForUpdate()
|
||||
->first();
|
||||
return $activePlayer;
|
||||
}
|
||||
|
||||
public function kick(
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Rooms;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class RoomPlayerInstanceService
|
||||
{
|
||||
private const string SESSION_KEY = 'room_player_instance_id';
|
||||
|
||||
public function for(Request $request): string
|
||||
{
|
||||
$instanceId = $request->session()->get(self::SESSION_KEY);
|
||||
|
||||
if (is_string($instanceId) && Str::isUuid($instanceId)) {
|
||||
return $instanceId;
|
||||
}
|
||||
|
||||
$instanceId = (string) Str::uuid();
|
||||
$request->session()->put(self::SESSION_KEY, $instanceId);
|
||||
|
||||
return $instanceId;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user