diff --git a/src/GmRelay.Web/Services/SessionService.cs b/src/GmRelay.Web/Services/SessionService.cs index 0ac82ad..c99c976 100644 --- a/src/GmRelay.Web/Services/SessionService.cs +++ b/src/GmRelay.Web/Services/SessionService.cs @@ -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( + """ + 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( """ @@ -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( - """ - 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 ---