Files
decePubClient/Pages/Administration.razor
T
thepraandClaude Opus 5.5 c572471b88 R6 moderation in decePub: users and personas, accounts, report actions, deletions, suspended personas
Administration's Users & personas (administrators): logins searched and opened into their personas and groups; roles,
bans, two-factor reset and deletion of a login; silence, suspension and deletion of a persona; a group deleted. Accounts
(moderators): local personas and remote accounts searched or listed as moderated, silenced and suspended with a staff
note and a warning. Reports resolve with an action. ActDialog asks for the note, the warning or the password and is the
act's confirmation. A login deletes its own persona and the groups it owns with its password. Suspended personas can't
be chosen; one refused a token mid-session moves the session to another, or to none, once. Warnings show in
notifications, limited accounts on their profile, and moderators remove a post from its card.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WpVCoDeM1qUTRp4fXQdfof
2026-10-17 05:41:10 +02:00

177 lines
5.3 KiB
Plaintext

@page "/administration"
@attribute [Authorize(Policy = Policies.IsModerator)]
@inherits LocalizableComponentBase
<Title>@Localizer["Administration"]</Title>
@* Moderators handle reports, moderate accounts here and elsewhere (Accounts) and read the staff's log. Administrators
also change the logins and their personas (Users & personas), say what the server is (Instance), set its rules, write
its announcements, block servers for everyone, choose its relays and media limits, read the federation statistics, and
back up and restore the server. PrivaPub checks the role on every call; the sections only follow it. Each section is
a collapse marked data-admin-section; its panel loads when the page opens. *@
<section class="block relative w-full h-full neo-inset neo-xs rounded-xl">
<div class="flex flex-col gap-4 p-4 md:p-5 w-full h-full absolute overflow-y-auto">
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="reports">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-flag text-xl"></i> <span>@Localizer["Reports"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<ReportsPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="accounts">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-contacts text-xl"></i> <span>@Localizer["Accounts"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<AccountsPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="log">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-list-box text-xl"></i> <span>@Localizer["Moderation log"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<ModerationLogPanel />
</div>
</ChildContent>
</DCollapse>
<AuthorizeView Policy="@Policies.IsAdmin">
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="users">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-people text-xl"></i> <span>@Localizer["Users & personas"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<UsersPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="instance">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-information-circle text-xl"></i> <span>@Localizer["Instance"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<InstancePanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="rules">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-book text-xl"></i> <span>@Localizer["Rules"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<RulesPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="announcements">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-megaphone text-xl"></i> <span>@Localizer["Announcements"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<AnnouncementsPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="blocks">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-globe text-xl"></i> <span>@Localizer["Blocked servers"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<ServerBlocksPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="relays">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-radio text-xl"></i> <span>@Localizer["Relays"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<RelaysPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="media">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-images text-xl"></i> <span>@Localizer["Media limits"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<MediaLimitsPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="statistics">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-stats text-xl"></i> <span>@Localizer["Statistics"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<StatisticsPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="backups">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-archive text-xl"></i> <span>@Localizer["Backups"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<BackupsPanel />
</div>
</ChildContent>
</DCollapse>
</AuthorizeView>
</div>
</section>