Web panel
Voxen ships a small web panel for the staff. It is off by default, binds to localhost and serves the pages other modules register, today the report queue, the ticket queue and the audit log of every moderator action. Other plugins can add their own pages through the API; they use the same accounts and the same permission list.
enabled: falsehost: "127.0.0.1"port: 8085title: "Voxen"realm: "Voxen"threads: 2max-login-attempts: 10lockout: 15mauto-refresh: 5susers: - name: "admin" password: "change-me" permissions: ["*"]The panel needs no extra dependency and no external web server; it is the HTTP server that
ships with Java. host: "127.0.0.1" is only reachable from the machine itself, 0.0.0.0
from everywhere. threads is how many requests it handles at the same time.
auto-refresh is how often a page reloads itself while the switch on the
report queue is on; 0 removes the switch. No page
reloads on its own until someone asks for it.
/voxen reload restarts it, so a new port, new accounts and new wording apply without a
restart of the server.
Accounts and permissions
Section titled “Accounts and permissions”Panel accounts are not Minecraft accounts and their permissions are their own; a browser
session never carries a player’s LuckPerms nodes. List each account under users:
users: - name: "admin" password: "a-long-random-password" permissions: ["*"] - name: "moderator" password: "another-long-password" permissions: ["reports.view", "reports.manage", "reports.audit"] - name: "trainee" password: "a-third-long-password" permissions: ["reports.view"]| Permission | What it allows |
|---|---|
reports.view |
seeing the report queue and opening a single case |
reports.manage |
claiming, resolving, dismissing and deleting reports, and the custom buttons |
reports.audit |
the audit log of every moderator action |
reports.* |
everything the report pages offer |
tickets.view |
seeing the ticket queue and reading a conversation |
tickets.manage |
answering a player and closing a ticket |
* |
every page, including ones added by later versions |
The audit node is separate on purpose: a trainee can be given reports.view and
reports.manage without being handed a record of what everyone else on the team did.
A page the account may not see is not in the sidebar, is not on the start page and answers with 403 when it is opened directly. Every action checks its permission again when it runs, so a page left open in a tab grants nothing after the permission is taken away.
Keeping it safe
Section titled “Keeping it safe”The panel refuses to start at all while any account still has the shipped change-me
password, an empty one, a password shorter than eight characters, or while one name is
defined twice. The reason is written to the console.
What it does on its own:
- Login lockout. After
max-login-attemptswrong passwords one address is refused for the wholelockoutwindow, right password included, so the accounts cannot be guessed at speed. Setting either to0turns it off, which only makes sense behind something that already rate limits. - Passwords are compared in constant time, and an unknown account costs the same as a known one, so neither the password nor the list of accounts leaks through timing.
- Every form carries a token tied to the session, so another site cannot make your browser resolve a report in the background. A form from before a reload is refused, not silently accepted.
- Everything a player wrote is HTML-escaped, so a report reason cannot smuggle markup into a moderator’s browser.
- Responses carry a strict
Content-Security-Policy,X-Frame-Options: DENY,X-Content-Type-Options: nosniff,Referrer-Policy: no-referrerandCache-Control: no-store, so the page loads nothing from outside, cannot be framed and is not left in a shared cache. - Requests are bounded. Bodies past 64 KB are refused, redirects are rebuilt from parsed parameters instead of echoing what came in, and the paths written to the log are stripped of control characters.
What it cannot do for you:
Also worth doing: give every moderator their own account rather than sharing one, so the
console log names who acted; grant reports.manage only to people who may run your custom
action commands, since those run from the console; and remember that modules/web.yml
contains passwords in plain text, so keep the plugin folder off shared backups and out of
public repositories.
Wording
Section titled “Wording”Every string the panel shows can be renamed or translated under labels. Anything left out
falls back to the English default, so only list what you want to change.
labels: reports: title: "Zgłoszenia" heading: "Zgłoszenia graczy" empty: "Nie ma nic do obsłużenia." action: claim: "Zajmij się" resolve: "Rozpatrz" audit: title: "Dziennik" heading: "Działania moderatorów"The panel follows the browser’s light or dark theme and needs no assets of its own.