fix(web): add public-session guards and ON CONFLICT to RegisterFromShowcaseAsync

This commit is contained in:
2026-05-28 15:40:21 +03:00
parent b2497ed877
commit a5f4a68c6a
+28 -34
View File
@@ -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;
}