fix: connection leak in UpsertDiscordUserAsync + false conflict in LinkIdentityAsync
PR Checks / test-and-build (pull_request) Successful in 7m25s

- UpsertDiscordUserAsync: restore await using on opened connection
- LinkIdentityAsync: compute effectiveCurrentPrimary before existingLink check
  to prevent false conflict when current user is a secondary identity

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 13:59:41 +03:00
parent baa25f2e1e
commit 9c59240f48
+15 -12
View File
@@ -1412,6 +1412,17 @@ public sealed class SessionService(
throw new InvalidOperationException("Target identity is already the primary account of another linked set.");
}
// Check if current is already a secondary (then their primary becomes the effective primary)
var currentPrimaryId = await conn.QuerySingleOrDefaultAsync<Guid?>(
"""
SELECT primary_player_id
FROM player_links
WHERE secondary_player_id = @CurrentPlayerId
""",
new { CurrentPlayerId = currentPlayerId.Value }, transaction);
var effectiveCurrentPrimary = currentPrimaryId ?? currentPlayerId.Value;
// Check if target is already linked to someone else as secondary
var existingLink = await conn.QuerySingleOrDefaultAsync<Guid?>(
"""
@@ -1421,23 +1432,14 @@ public sealed class SessionService(
""",
new { TargetPlayerId = targetPlayerId }, transaction);
if (existingLink is not null && existingLink.Value != currentPlayerId.Value)
if (existingLink is not null && existingLink.Value != effectiveCurrentPrimary)
{
await _LogIdentityAuditAsync(conn, currentPlayerId.Value, "link_attempt_conflict",
await _LogIdentityAuditAsync(conn, effectiveCurrentPrimary, "link_attempt_conflict",
targetPlatform, targetExternalUserId, currentPlayerId.Value, transaction);
await transaction.CommitAsync();
throw new InvalidOperationException("Target identity is already linked to another account.");
}
// Check if current is already a secondary (then their primary becomes the effective primary)
var currentPrimaryId = await conn.QuerySingleOrDefaultAsync<Guid?>(
"""
SELECT primary_player_id
FROM player_links
WHERE secondary_player_id = @CurrentPlayerId
""",
new { CurrentPlayerId = currentPlayerId.Value }, transaction);
var effectivePrimary = currentPrimaryId ?? currentPlayerId.Value;
// Check if already linked
@@ -1527,7 +1529,8 @@ public sealed class SessionService(
public async Task UpsertDiscordUserAsync(string discordId, string displayName, string? avatarUrl)
{
await _UpsertPlayerAndGetIdAsync(await dataSource.OpenConnectionAsync(), "Discord", discordId, displayName, avatarUrl, null);
await using var conn = await dataSource.OpenConnectionAsync();
await _UpsertPlayerAndGetIdAsync(conn, "Discord", discordId, displayName, avatarUrl, null);
}
// --- Private helpers ---