fix(web): add public-session guards and ON CONFLICT to RegisterFromShowcaseAsync
This commit is contained in:
@@ -541,12 +541,18 @@ public sealed class SessionService(
|
||||
|
||||
var session = await conn.QuerySingleOrDefaultAsync<dynamic>(
|
||||
"""
|
||||
SELECT id, max_players AS MaxPlayers, allow_direct_registration AS AllowDirectRegistration
|
||||
FROM sessions
|
||||
WHERE id = @SessionId
|
||||
FOR UPDATE
|
||||
SELECT s.id, s.max_players AS MaxPlayers, s.allow_direct_registration AS AllowDirectRegistration
|
||||
FROM sessions s
|
||||
JOIN game_groups g ON g.id = s.group_id
|
||||
WHERE s.id = @SessionId
|
||||
AND s.is_public = true
|
||||
AND g.public_schedule_enabled = true
|
||||
AND g.public_slug IS NOT NULL
|
||||
AND s.scheduled_at > now() - interval '4 hours'
|
||||
AND s.status <> @Cancelled
|
||||
FOR UPDATE OF s
|
||||
""",
|
||||
new { SessionId = sessionId },
|
||||
new { SessionId = sessionId, Cancelled = SessionStatus.Cancelled },
|
||||
transaction);
|
||||
|
||||
if (session is null || !(bool)session.allowdirectregistration)
|
||||
@@ -557,39 +563,21 @@ public sealed class SessionService(
|
||||
|
||||
var playerId = await _UpsertPlayerAndGetIdAsync(conn, platform, externalUserId, displayName, null, transaction);
|
||||
|
||||
var existing = await conn.ExecuteScalarAsync<bool>(
|
||||
"""
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM session_participants
|
||||
WHERE session_id = @SessionId AND player_id = @PlayerId
|
||||
)
|
||||
""",
|
||||
new { SessionId = sessionId, PlayerId = playerId },
|
||||
transaction);
|
||||
var registrationStatus = SessionCapacityRules.DecideJoinStatus(
|
||||
(int?)session.maxplayers,
|
||||
await conn.ExecuteScalarAsync<int>(
|
||||
"""
|
||||
SELECT COUNT(*) FROM session_participants
|
||||
WHERE session_id = @SessionId AND is_gm = false AND registration_status = @Active
|
||||
""",
|
||||
new { SessionId = sessionId, Active = ParticipantRegistrationStatus.Active },
|
||||
transaction));
|
||||
|
||||
if (existing)
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
return false;
|
||||
}
|
||||
|
||||
var activeCount = await conn.ExecuteScalarAsync<int>(
|
||||
"""
|
||||
SELECT COUNT(*)
|
||||
FROM session_participants
|
||||
WHERE session_id = @SessionId
|
||||
AND is_gm = false
|
||||
AND registration_status = @Active
|
||||
""",
|
||||
new { SessionId = sessionId, Active = ParticipantRegistrationStatus.Active },
|
||||
transaction);
|
||||
|
||||
var registrationStatus = SessionCapacityRules.DecideJoinStatus((int?)session.maxplayers, activeCount);
|
||||
|
||||
await conn.ExecuteAsync(
|
||||
var inserted = await conn.ExecuteAsync(
|
||||
"""
|
||||
INSERT INTO session_participants (session_id, player_id, is_gm, rsvp_status, registration_status)
|
||||
VALUES (@SessionId, @PlayerId, false, @Pending, @RegistrationStatus)
|
||||
ON CONFLICT (session_id, player_id) DO NOTHING
|
||||
""",
|
||||
new
|
||||
{
|
||||
@@ -600,6 +588,12 @@ public sealed class SessionService(
|
||||
},
|
||||
transaction);
|
||||
|
||||
if (inserted == 0)
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
return false;
|
||||
}
|
||||
|
||||
await transaction.CommitAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user