Restrict public presence to staff + let admins view any character
Public "Online now" now lists only players whose game account is linked to a STAFF website user (admin/editor/moderator) — linked players are no longer exposed publicly with their name and location. listOnlineLinked joins through to users and filters on role; the section is relabeled "Staff online". Character/roster/vendor reads gain an admin bypass: admins may view any character's data, while players (and editor/moderator staff) stay limited to accounts they have personally linked. The bypass lives in the shared player controller and only ever widens access for genuine admins. Also finalizes the uo-link character/vendor front end (player + admin character sheets, VendorSales component, ShardChar removed) and regenerates swagger-output.json. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018kj5s1QCKobuFPYmqxjy1q
This commit is contained in:
@@ -47,11 +47,10 @@ export default function Shard() {
|
||||
const { loading, error, data } = useAsync(() =>
|
||||
Promise.all([
|
||||
api.shard.status(),
|
||||
api.shard.feed({ kind: 'vendor.sale', limit: 8 }),
|
||||
api.shard.idoc(),
|
||||
api.shard.economy(60),
|
||||
api.shard.online(),
|
||||
]).then(([status, sales, idoc, economy, online]) => ({ status, sales, idoc, economy, online })),
|
||||
]).then(([status, idoc, economy, online]) => ({ status, idoc, economy, online })),
|
||||
)
|
||||
const { events, connected } = useShardFeed({ max: 30 })
|
||||
|
||||
@@ -115,26 +114,25 @@ export default function Shard() {
|
||||
<Stat value={online ? 'Up' : 'Down'} label="Shard link" />
|
||||
</section>
|
||||
|
||||
{/* Online now */}
|
||||
{/* Staff online — linked staff accounts only, with location */}
|
||||
<section className="panel" style={{ padding: 20, marginBottom: 24 }}>
|
||||
<div className="sans" style={{ color: 'var(--accent)', fontSize: '0.7rem', letterSpacing: '0.12em', textTransform: 'uppercase', marginBottom: 12 }}>
|
||||
Online now
|
||||
Staff online
|
||||
</div>
|
||||
{(!data.online || data.online.length === 0) ? (
|
||||
<p className="sans dim" style={{ margin: 0, fontSize: '0.88rem' }}>No one is online right now.</p>
|
||||
<p className="sans dim" style={{ margin: 0, fontSize: '0.88rem' }}>No staff are online right now.</p>
|
||||
) : (
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
||||
{data.online.map((p) => (
|
||||
<Link
|
||||
key={p.serial}
|
||||
to={`/site/shard/char/${p.serial}`}
|
||||
className="sans"
|
||||
style={{ display: 'inline-flex', alignItems: 'center', gap: 8, padding: '8px 14px', border: '1px solid var(--line)', borderRadius: 999, color: 'var(--ink)', textDecoration: 'none' }}
|
||||
>
|
||||
<span style={{ width: 8, height: 8, borderRadius: '50%', background: '#7fd0a4' }} />
|
||||
{p.name || p.serial}
|
||||
{p.map && <span className="dim" style={{ fontSize: '0.76rem' }}>· {p.map}</span>}
|
||||
</Link>
|
||||
<div key={p.serial} className="sans" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, fontSize: '0.9rem', color: 'var(--ink)' }}>
|
||||
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 8, minWidth: 0 }}>
|
||||
<span style={{ flex: 'none', width: 8, height: 8, borderRadius: '50%', background: '#7fd0a4' }} />
|
||||
{p.name || p.serial}
|
||||
</span>
|
||||
<span className="dim" style={{ flex: 'none', fontSize: '0.78rem' }}>
|
||||
{p.map || '—'}{p.x != null ? ` (${p.x}, ${p.y})` : ''}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
@@ -150,13 +148,7 @@ export default function Shard() {
|
||||
</section>
|
||||
)}
|
||||
|
||||
<div className="grid-2" style={{ gap: 18, marginBottom: 24 }}>
|
||||
{/* Recent vendor sales */}
|
||||
<FeedList
|
||||
title="Recent vendor sales"
|
||||
empty="No sales recorded yet."
|
||||
items={data.sales.map((s) => ({ id: s.id, text: describe(s), when: s.t }))}
|
||||
/>
|
||||
<div style={{ marginBottom: 24 }}>
|
||||
{/* Latest IDOC */}
|
||||
<FeedList
|
||||
title="Houses in danger (IDOC)"
|
||||
|
||||
Reference in New Issue
Block a user