fix: connection leak in UpsertDiscordUserAsync + false conflict in LinkIdentityAsync
PR Checks / test-and-build (pull_request) Successful in 7m25s
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:
@@ -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 ---
|
||||
|
||||
Reference in New Issue
Block a user