From 398764a4cc1dfe306c213f67d8dd3e6f54fed0ab Mon Sep 17 00:00:00 2001 From: gamer147 Date: Fri, 12 Jun 2026 22:54:52 -0400 Subject: [PATCH] feat(profile): /profile/update_official_mark_display Co-Authored-By: Claude Sonnet 4.6 --- .../Controllers/ProfileController.cs | 24 +++++++++++++- ...ProfileUpdateOfficialMarkDisplayRequest.cs | 13 ++++++++ ...ontrollerUpdateOfficialMarkDisplayTests.cs | 33 +++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 SVSim.EmulatedEntrypoint/Models/Dtos/Requests/Profile/ProfileUpdateOfficialMarkDisplayRequest.cs create mode 100644 SVSim.UnitTests/Controllers/ProfileControllerUpdateOfficialMarkDisplayTests.cs diff --git a/SVSim.EmulatedEntrypoint/Controllers/ProfileController.cs b/SVSim.EmulatedEntrypoint/Controllers/ProfileController.cs index 843a3dec..fa543f9d 100644 --- a/SVSim.EmulatedEntrypoint/Controllers/ProfileController.cs +++ b/SVSim.EmulatedEntrypoint/Controllers/ProfileController.cs @@ -1,8 +1,12 @@ using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using SVSim.Database; using SVSim.Database.Repositories.Viewer; using SVSim.EmulatedEntrypoint.Constants; using SVSim.EmulatedEntrypoint.Models.Dtos; +using SVSim.EmulatedEntrypoint.Models.Dtos.Common; using SVSim.EmulatedEntrypoint.Models.Dtos.Profile; +using SVSim.EmulatedEntrypoint.Models.Dtos.Requests.Profile; namespace SVSim.EmulatedEntrypoint.Controllers; @@ -14,9 +18,13 @@ namespace SVSim.EmulatedEntrypoint.Controllers; public sealed class ProfileController : SVSimController { private readonly IViewerRepository _viewerRepository; + private readonly SVSimDbContext _db; - public ProfileController(IViewerRepository viewerRepository) => + public ProfileController(IViewerRepository viewerRepository, SVSimDbContext db) + { _viewerRepository = viewerRepository; + _db = db; + } [HttpPost("index")] public async Task> Index( @@ -48,4 +56,18 @@ public sealed class ProfileController : SVSimController UserClassList = classes, }; } + + [HttpPost("update_official_mark_display")] + public async Task> UpdateOfficialMarkDisplay( + ProfileUpdateOfficialMarkDisplayRequest request, + CancellationToken ct) + { + if (!TryGetViewerId(out long viewerId)) return Unauthorized(); + + var viewer = await _db.Viewers.FirstAsync(v => v.Id == viewerId, ct); + viewer.Info.IsOfficialMarkDisplayed = request.IsOfficialMarkDisplayed != 0; + await _db.SaveChangesAsync(ct); + + return new EmptyResponse(); + } } diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/Profile/ProfileUpdateOfficialMarkDisplayRequest.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/Profile/ProfileUpdateOfficialMarkDisplayRequest.cs new file mode 100644 index 00000000..c64334e4 --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/Profile/ProfileUpdateOfficialMarkDisplayRequest.cs @@ -0,0 +1,13 @@ +// SVSim.EmulatedEntrypoint/Models/Dtos/Requests/Profile/ProfileUpdateOfficialMarkDisplayRequest.cs +using MessagePack; +using System.Text.Json.Serialization; + +namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests.Profile; + +[MessagePackObject] +public class ProfileUpdateOfficialMarkDisplayRequest : BaseRequest +{ + [JsonPropertyName("is_official_mark_displayed")] + [Key("is_official_mark_displayed")] + public int IsOfficialMarkDisplayed { get; set; } +} diff --git a/SVSim.UnitTests/Controllers/ProfileControllerUpdateOfficialMarkDisplayTests.cs b/SVSim.UnitTests/Controllers/ProfileControllerUpdateOfficialMarkDisplayTests.cs new file mode 100644 index 00000000..939e7cb2 --- /dev/null +++ b/SVSim.UnitTests/Controllers/ProfileControllerUpdateOfficialMarkDisplayTests.cs @@ -0,0 +1,33 @@ +// SVSim.UnitTests/Controllers/ProfileControllerUpdateOfficialMarkDisplayTests.cs +using System.Net; +using System.Text; +using NUnit.Framework; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using SVSim.Database; +using SVSim.UnitTests.Infrastructure; + +namespace SVSim.UnitTests.Controllers; + +public class ProfileControllerUpdateOfficialMarkDisplayTests +{ + [TestCase(0, false)] + [TestCase(1, true)] + public async Task UpdateOfficialMarkDisplay_persists_flag(int wireValue, bool expected) + { + using var factory = new SVSimTestFactory(); + long viewerId = await factory.SeedViewerAsync(tutorialState: 0); + using var client = factory.CreateAuthenticatedClient(viewerId); + + var requestJson = $$"""{"is_official_mark_displayed":{{wireValue}},"viewer_id":"0","steam_id":0,"steam_session_ticket":""}"""; + var response = await client.PostAsync("/profile/update_official_mark_display", + new StringContent(requestJson, Encoding.UTF8, "application/json")); + + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + + using var scope = factory.Services.CreateScope(); + var db = scope.ServiceProvider.GetRequiredService(); + var viewer = await db.Viewers.FirstAsync(v => v.Id == viewerId); + Assert.That(viewer.Info.IsOfficialMarkDisplayed, Is.EqualTo(expected)); + } +}