Restrict play screen to owned characters and own private rolls

This commit is contained in:
2026-02-26 19:23:05 +01:00
parent fa7f88e209
commit 637a2ef7ac
3 changed files with 91 additions and 6 deletions

View File

@@ -54,6 +54,7 @@ Gameplay capabilities now include:
- Role-aware authorization with admin role support (including admin user/role management) - Role-aware authorization with admin role support (including admin user/role management)
- Campaign deletion by campaign owner or admin (unlinks characters from the campaign and clears campaign log entries) - Campaign deletion by campaign owner or admin (unlinks characters from the campaign and clears campaign log entries)
- User deletion by admin also deletes campaigns owned by that user and unlinks all characters from those deleted campaigns - User deletion by admin also deletes campaigns owned by that user and unlinks all characters from those deleted campaigns
- Play screen visibility is owner-scoped: only owned characters are listed, and private log entries are visible only to the roller
- Campaign management owner labels use account display names (no GUID fallback rendering) - Campaign management owner labels use account display names (no GUID fallback rendering)
- Character edit flow supports unlinking from campaigns (owner/GM/admin) and assigning to any existing campaign via expanded campaign options - Character edit flow supports unlinking from campaigns (owner/GM/admin) and assigning to any existing campaign via expanded campaign options
- Campaign management supports character deletion by character owner or admin - Campaign management supports character deletion by character owner or admin

View File

@@ -33,12 +33,12 @@
<main class="play-screen @(MobilePanel == "log" ? "mobile-log" : "mobile-character")"> <main class="play-screen @(MobilePanel == "log" ? "mobile-log" : "mobile-character")">
<CharacterPanel <CharacterPanel
IsCampaignDataLoading="IsCampaignDataLoading" IsCampaignDataLoading="IsCampaignDataLoading"
SelectedCampaign="SelectedCampaign" SelectedCampaign="PlaySelectedCampaign"
SelectedCharacterId="SelectedCharacterId" SelectedCharacterId="PlaySelectedCharacterId"
SelectedCharacter="SelectedCharacter" SelectedCharacter="PlaySelectedCharacter"
IsMutating="IsMutating" IsMutating="IsMutating"
SelectedCharacterSkills="SelectedCharacterSkills" SelectedCharacterSkills="PlaySelectedCharacterSkills"
SelectedCharacterSkillGroups="SelectedCharacterSkillGroups" SelectedCharacterSkillGroups="PlaySelectedCharacterSkillGroups"
IsD6="IsSelectedCampaignD6" IsD6="IsSelectedCampaignD6"
RollVisibility="RollVisibility" RollVisibility="RollVisibility"
RollVisibilityChanged="OnRollVisibilityChanged" RollVisibilityChanged="OnRollVisibilityChanged"
@@ -59,7 +59,7 @@
<CampaignLogPanel <CampaignLogPanel
IsCampaignDataLoading="IsCampaignDataLoading" IsCampaignDataLoading="IsCampaignDataLoading"
CampaignLog="CampaignLog" CampaignLog="PlayVisibleCampaignLog"
RollerLabel="RollerLabel" RollerLabel="RollerLabel"
SkillLabel="SkillLabel" SkillLabel="SkillLabel"
CharacterLabel="CharacterLabel" CharacterLabel="CharacterLabel"

View File

@@ -975,6 +975,90 @@ public partial class Workspace : IAsyncDisposable
private CharacterSummary? SelectedCharacter => private CharacterSummary? SelectedCharacter =>
SelectedCampaign?.Characters.FirstOrDefault(c => c.Id == SelectedCharacterId); SelectedCampaign?.Characters.FirstOrDefault(c => c.Id == SelectedCharacterId);
private CampaignDetails? PlaySelectedCampaign
{
get
{
if (SelectedCampaign is null)
return null;
if (User is null)
return new CampaignDetails(SelectedCampaign.Id, SelectedCampaign.Name, SelectedCampaign.RulesetId, SelectedCampaign.Gm, [], [], []);
var ownedCharacters = SelectedCampaign.Characters
.Where(character => character.OwnerUserId == User.Id)
.ToList();
var ownedCharacterIds = ownedCharacters.Select(character => character.Id).ToHashSet();
var ownedSkillGroups = SelectedCampaign.SkillGroups
.Where(group => ownedCharacterIds.Contains(group.CharacterId))
.ToList();
var ownedSkills = SelectedCampaign.Skills
.Where(skill => ownedCharacterIds.Contains(skill.CharacterId))
.ToList();
return new CampaignDetails(
SelectedCampaign.Id,
SelectedCampaign.Name,
SelectedCampaign.RulesetId,
SelectedCampaign.Gm,
ownedCharacters,
ownedSkillGroups,
ownedSkills);
}
}
private CharacterSummary? PlaySelectedCharacter
{
get
{
if (PlaySelectedCampaign is null || PlaySelectedCampaign.Characters.Count == 0)
return null;
if (SelectedCharacterId.HasValue)
{
var selectedCharacter = PlaySelectedCampaign.Characters.FirstOrDefault(character => character.Id == SelectedCharacterId.Value);
if (selectedCharacter is not null)
return selectedCharacter;
}
if (ActiveCharacterId.HasValue)
{
var activeCharacter = PlaySelectedCampaign.Characters.FirstOrDefault(character => character.Id == ActiveCharacterId.Value);
if (activeCharacter is not null)
return activeCharacter;
}
return PlaySelectedCampaign.Characters[0];
}
}
private Guid? PlaySelectedCharacterId => PlaySelectedCharacter?.Id;
private List<SkillSummary> PlaySelectedCharacterSkills =>
PlaySelectedCampaign is null || !PlaySelectedCharacterId.HasValue
? []
: PlaySelectedCampaign.Skills
.Where(skill => skill.CharacterId == PlaySelectedCharacterId.Value)
.OrderBy(skill => skill.Name, StringComparer.OrdinalIgnoreCase)
.ToList();
private List<SkillGroupSummary> PlaySelectedCharacterSkillGroups =>
PlaySelectedCampaign is null || !PlaySelectedCharacterId.HasValue
? []
: PlaySelectedCampaign.SkillGroups
.Where(group => group.CharacterId == PlaySelectedCharacterId.Value)
.OrderBy(group => group.Name, StringComparer.OrdinalIgnoreCase)
.ToList();
private List<CampaignLogEntry> PlayVisibleCampaignLog =>
User is null
? CampaignLog.Where(entry => !string.Equals(entry.Visibility, "private", StringComparison.OrdinalIgnoreCase)).ToList()
: CampaignLog
.Where(entry =>
!string.Equals(entry.Visibility, "private", StringComparison.OrdinalIgnoreCase) ||
entry.RollerUserId == User.Id)
.ToList();
private bool IsCurrentUserGm => private bool IsCurrentUserGm =>
SelectedCampaign is not null && User is not null && SelectedCampaign.Gm.Id == User.Id; SelectedCampaign is not null && User is not null && SelectedCampaign.Gm.Id == User.Id;