Files
SVSimServer/SVSim.EmulatedEntrypoint/Controllers/CheckController.cs
gamer147 26bb0ac268 auth: link Steam to UDID-keyed viewer on first authenticated request
After /tool/signup, the client has a viewer_id but no Steam social row.
The first authenticated request (typically /check/game_start) carries
the Steam ticket; if the SteamId lookup misses but the UDID resolves
to a viewer, attach the Steam social now. Subsequent requests hit the
fast SteamId path. Closes the CheckController.GameStart TODO that was
blocking fresh-client boot.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 14:31:06 -04:00

71 lines
2.6 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SVSim.Database.Models;
using SVSim.Database.Repositories.Viewer;
using SVSim.EmulatedEntrypoint.Extensions;
using SVSim.EmulatedEntrypoint.Models.Dtos;
using SVSim.EmulatedEntrypoint.Models.Dtos.Requests;
using SVSim.EmulatedEntrypoint.Models.Dtos.Responses;
namespace SVSim.EmulatedEntrypoint.Controllers;
public class CheckController : SVSimController
{
private readonly ILogger _logger;
private readonly IViewerRepository _viewerRepository;
public CheckController(ILogger<CheckController> logger, IViewerRepository viewerRepository)
{
_logger = logger;
_viewerRepository = viewerRepository;
}
[AllowAnonymous]
[HttpPost("special_title")]
public Task<SpecialTitleCheckResponse> SpecialTitleCheck(SpecialTitleCheckRequest request)
{
return Task.FromResult(new SpecialTitleCheckResponse
{
TitleImageId = "0"
});
}
[HttpPost("game_start")]
public async Task<GameStartResponse> GameStart(GameStartRequest request)
{
Viewer viewer = HttpContext.GetViewer()
?? throw new InvalidOperationException("Auth handler must set viewer in context.");
Viewer fullViewer = await _viewerRepository.GetViewerWithSocials(viewer.Id) ?? viewer;
return new GameStartResponse
{
NowViewerId = fullViewer.Id,
NowName = fullViewer.DisplayName,
NowTutorialStep = fullViewer.MissionData.TutorialState.ToString(),
IsSetTransitionPassword = true,
// Stub rank map until per-format ranks are persisted (prod observed: "1"/"2"/"4"
// keys mapping to RankName_010 / RankName_017). Empty dict here may be safe but
// we don't yet know which client paths read this — match prod stub.
NowRank = new Dictionary<string, string>
{
{ "1", "RankName_010" },
{ "2", "RankName_010" },
{ "4", "RankName_017" }
},
TransitionAccountData = fullViewer.SocialAccountConnections
.Select(sac => new TransitionAccountData
{
SocialAccountId = sac.AccountId.ToString(),
SocialAccountType = ((int)sac.AccountType).ToString(),
ConnectedViewerId = fullViewer.Id.ToString()
}).ToList(),
TosState = 1,
PolicyState = 1,
KorAuthorityState = 0,
TosId = 1,
PolicyId = 1,
KorAuthorityId = 0
};
}
}