Remove workspace session-token coupling
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&display=swap" rel="stylesheet">
|
||||
@if (UseInteractiveApp)
|
||||
{
|
||||
<HeadOutlet @rendermode="InteractiveServer"/>
|
||||
<HeadOutlet @rendermode="@(new InteractiveServerRenderMode(prerender: false))"/>
|
||||
}
|
||||
</head>
|
||||
<body>
|
||||
@@ -27,7 +27,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<Routes @rendermode="InteractiveServer"/>
|
||||
<Routes @rendermode="@(new InteractiveServerRenderMode(prerender: false))"/>
|
||||
}
|
||||
<script src="js/rpgroller-api.js"></script>
|
||||
@if (UseInteractiveApp)
|
||||
@@ -92,4 +92,4 @@ else
|
||||
return value.Count > 0 ? value[0] : null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,81 +1,70 @@
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using RpgRoller.Contracts;
|
||||
using RpgRoller.Services;
|
||||
|
||||
namespace RpgRoller.Components;
|
||||
|
||||
public sealed class WorkspaceQueryService(IGameService gameService, WorkspaceSessionTokenAccessor sessionTokenAccessor)
|
||||
public sealed class WorkspaceQueryService(RpgRollerApiClient apiClient)
|
||||
{
|
||||
public Task<MeResponse> GetMeAsync()
|
||||
{
|
||||
return Task.FromResult(GetValue(gameService.GetMe(GetRequiredSessionToken())));
|
||||
return apiClient.RequestAsync<MeResponse>("GET", "/api/me");
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<RulesetDefinition>> GetRulesetsAsync()
|
||||
public async Task<IReadOnlyList<RulesetDefinition>> GetRulesetsAsync()
|
||||
{
|
||||
return Task.FromResult(gameService.GetRulesets());
|
||||
return await apiClient.RequestAsync<RulesetDefinition[]>("GET", "/api/rulesets");
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<CampaignSummary>> GetCampaignsAsync()
|
||||
public async Task<IReadOnlyList<CampaignSummary>> GetCampaignsAsync()
|
||||
{
|
||||
return Task.FromResult(GetValue(gameService.GetCampaigns(GetRequiredSessionToken())));
|
||||
return await apiClient.RequestAsync<CampaignSummary[]>("GET", "/api/campaigns");
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<CampaignOption>> GetCharacterCampaignOptionsAsync()
|
||||
public async Task<IReadOnlyList<CampaignOption>> GetCharacterCampaignOptionsAsync()
|
||||
{
|
||||
return Task.FromResult(GetValue(gameService.GetCharacterCampaignOptions(GetRequiredSessionToken())));
|
||||
return await apiClient.RequestAsync<CampaignOption[]>("GET", "/api/campaigns/options");
|
||||
}
|
||||
|
||||
public Task<CampaignRoster> GetCampaignAsync(Guid campaignId)
|
||||
{
|
||||
return Task.FromResult(GetValue(gameService.GetCampaign(GetRequiredSessionToken(), campaignId)));
|
||||
return apiClient.RequestAsync<CampaignRoster>("GET", $"/api/campaigns/{campaignId:D}");
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<string>> GetUsernamesAsync()
|
||||
public async Task<IReadOnlyList<string>> GetUsernamesAsync()
|
||||
{
|
||||
return Task.FromResult(GetValue(gameService.GetUsernames(GetRequiredSessionToken())));
|
||||
return await apiClient.RequestAsync<string[]>("GET", "/api/users/usernames");
|
||||
}
|
||||
|
||||
public Task<CharacterSheet> GetCharacterSheetAsync(Guid characterId)
|
||||
{
|
||||
return Task.FromResult(GetValue(gameService.GetCharacterSheet(GetRequiredSessionToken(), characterId)));
|
||||
return apiClient.RequestAsync<CharacterSheet>("GET", $"/api/characters/{characterId:D}/sheet");
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<CampaignLogEntry>> GetCampaignLogAsync(Guid campaignId)
|
||||
public async Task<IReadOnlyList<CampaignLogEntry>> GetCampaignLogAsync(Guid campaignId)
|
||||
{
|
||||
return Task.FromResult(GetValue(gameService.GetCampaignLog(GetRequiredSessionToken(), campaignId)));
|
||||
return await apiClient.RequestAsync<CampaignLogEntry[]>("GET", $"/api/campaigns/{campaignId:D}/log");
|
||||
}
|
||||
|
||||
public Task<CampaignLogPage> GetCampaignLogPageAsync(Guid campaignId, Guid? afterRollId = null, int? limit = null)
|
||||
{
|
||||
return Task.FromResult(GetValue(gameService.GetCampaignLogPage(GetRequiredSessionToken(), campaignId, afterRollId, limit)));
|
||||
var query = new Dictionary<string, string?>();
|
||||
if (afterRollId.HasValue)
|
||||
query["afterRollId"] = afterRollId.Value.ToString("D");
|
||||
|
||||
if (limit.HasValue)
|
||||
query["limit"] = limit.Value.ToString();
|
||||
|
||||
var path = QueryHelpers.AddQueryString($"/api/campaigns/{campaignId:D}/log/page", query);
|
||||
return apiClient.RequestAsync<CampaignLogPage>("GET", path);
|
||||
}
|
||||
|
||||
public Task<CampaignRollDetail> GetRollDetailAsync(Guid rollId)
|
||||
{
|
||||
return Task.FromResult(GetValue(gameService.GetRollDetail(GetRequiredSessionToken(), rollId)));
|
||||
return apiClient.RequestAsync<CampaignRollDetail>("GET", $"/api/rolls/{rollId:D}");
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<AdminUserSummary>> GetAdminUsersAsync()
|
||||
public async Task<IReadOnlyList<AdminUserSummary>> GetAdminUsersAsync()
|
||||
{
|
||||
return Task.FromResult(GetValue(gameService.GetUsers(GetRequiredSessionToken())));
|
||||
}
|
||||
|
||||
private string GetRequiredSessionToken()
|
||||
{
|
||||
return sessionTokenAccessor.GetRequiredSessionToken();
|
||||
}
|
||||
|
||||
private static T GetValue<T>(ServiceResult<T> result)
|
||||
{
|
||||
if (result.Succeeded)
|
||||
return result.Value!;
|
||||
|
||||
throw ToApiRequestException(result.Error!);
|
||||
}
|
||||
|
||||
private static ApiRequestException ToApiRequestException(ServiceError error)
|
||||
{
|
||||
var statusCode = error.Code == "unauthorized" ? 401 : 400;
|
||||
return new(statusCode, error.Message, error.Code);
|
||||
return await apiClient.RequestAsync<AdminUserSummary[]>("GET", "/api/admin/users");
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using RpgRoller.Api;
|
||||
|
||||
namespace RpgRoller.Components;
|
||||
|
||||
public sealed class WorkspaceSessionTokenAccessor
|
||||
{
|
||||
public WorkspaceSessionTokenAccessor(IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
var httpContext = httpContextAccessor.HttpContext;
|
||||
if (httpContext is null)
|
||||
return;
|
||||
|
||||
if (httpContext.Items.TryGetValue(SessionTokenItemKey, out var storedToken) && storedToken is string sessionToken && !string.IsNullOrWhiteSpace(sessionToken))
|
||||
{
|
||||
m_SessionToken = sessionToken;
|
||||
return;
|
||||
}
|
||||
|
||||
if (httpContext.TryReadSessionTokenFromCookie(out sessionToken))
|
||||
m_SessionToken = sessionToken;
|
||||
}
|
||||
|
||||
public string GetRequiredSessionToken()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(m_SessionToken))
|
||||
return m_SessionToken;
|
||||
|
||||
throw new ApiRequestException(401, "You must be logged in.");
|
||||
}
|
||||
|
||||
private const string SessionTokenItemKey = "__rpgroller.session-token";
|
||||
private readonly string? m_SessionToken;
|
||||
}
|
||||
@@ -13,9 +13,7 @@ builder.Services.AddResponseCompression(options =>
|
||||
options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(["application/json"]);
|
||||
});
|
||||
builder.Services.ConfigureHttpJsonOptions(options => RpgRollerJson.Configure(options.SerializerOptions));
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
builder.Services.AddScoped<RpgRollerApiClient>();
|
||||
builder.Services.AddScoped<WorkspaceSessionTokenAccessor>();
|
||||
builder.Services.AddScoped<WorkspaceQueryService>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
Reference in New Issue
Block a user