// ── The `admin.users.detail` slot's handlers ────────────────────────────── // // What an operator can see and do about one website user's Rust identity. The // user id is the PARENT's — `req.params.id` off core's `/admin/users/:id` — and // every statement here is scoped by it, so a panel opened on one user cannot // read or write another's rows by editing a path segment. const core = require('../../core') const links = require('../../model/links/links.model') const log = core.logger('admin') /** * GET /admin/users/:id/rust/links * * The linked Steam accounts and, per server, what this module knows about the * player behind them — all-time rather than this wipe's, because an operator * looking at a user wants their history and the public leaderboard already * answers the other question. * * **An empty array is an answer.** Most users have no Rust link at all, and the * panel renders nothing rather than an error for them. */ async function listLinks(req, res) { try { res.json({ links: await links.forAdmin(req.params.id) }) } catch (err) { log.error('failed to read a user’s Rust links', { error: err.message }) res.status(500).json({ message: 'Failed to read this user’s Rust accounts' }) } } /** * DELETE /admin/users/:id/rust/links/:steamId — staff sever a link (D25). * * **This is the counterweight to D23.** The site refuses to move a Steam id that * another website account already holds, and the player's own way out is * `/unlink` in game — which is no way out at all for somebody who has lost access * to that Steam account, or to the site account holding it. Staff are that route. * * Scoped by the parent user id in the statement rather than checked first: the * ownership test and the deletion are one operation, and a link that belongs to a * different user answers 404 from the page it was not on. */ async function removeLink(req, res) { const { steamId } = req.params const userId = req.params.id try { const removed = await links.unlinkOwned(steamId, userId) if (!removed) return res.status(404).json({ message: 'That account is not linked to this user' }) // The one write this panel has, so it is the one thing here worth an audit // row: after phase 7 a link is what permissions are granted against, and // "who severed it" stops being a curiosity. await core.activity.log({ req, action: 'rust.account.unlink.staff', detail: { steamId, userId: Number(userId) }, }) return res.json({ unlinked: true }) } catch (err) { log.error('failed to unlink a Steam account', { error: err.message }) return res.status(500).json({ message: 'Failed to unlink that account' }) } } module.exports = { listLinks, removeLink }