Add admin role with an admin-only hand range study page
- Optional ADMIN_KEY (6 digits, distinct from ACCESS_KEY): entering it on the key screen signs in as admin (role-specific HMAC cookie; member cookies stay valid). Logged-in members can open /key?admin to enter it. - /range (range chart + color/category quiz, ported from poker-hand and restyled to the site design) and its files under admin/ are served only to admins; everyone else gets 404. Card images cached privately for a day. - Lobby shows a link to the page for admins only (GET /api/me). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1e1ac4e91d
commit
e89d867f85
64 files changed
+477
-19
No files matched your search
+20
-2
@@ -9,7 +9,9 @@ const auth = require('./auth');
|
||||
const { TableManager } = require('./tables');
|
||||
|
||||
const PUBLIC = path.join(__dirname, '..', 'public');
|
||||
const page = (file) => (req, res) => res.sendFile(path.join(PUBLIC, file));
|
||||
// 管理者専用のファイル(public の外に置き、管理者の Cookie があるときだけ返す)
|
||||
const ADMIN = path.join(__dirname, '..', 'admin');
|
||||
const page = (file, dir = PUBLIC) => (req, res) => res.sendFile(path.join(dir, file));
|
||||
|
||||
const app = express();
|
||||
app.set('trust proxy', 'loopback'); // nginx 等のリバースプロキシ越しでも req.ip / req.secure を正しく
|
||||
@@ -70,7 +72,9 @@ app.use('/assets', express.static(path.join(PUBLIC, 'assets'), { index: false, d
|
||||
app.get('/favicon.ico', (req, res) => res.sendFile(path.join(PUBLIC, 'assets', 'favicon.ico')));
|
||||
app.get('/robots.txt', (req, res) => res.type('text/plain').send('User-agent: *\nDisallow: /\n'));
|
||||
app.get('/key', (req, res) => {
|
||||
if (auth.isAuthed(req)) return res.redirect(auth.safeNext(req.query.next));
|
||||
// 入室済みなら飛ばす。ただし /key?admin は管理者キーを入れるために開ける
|
||||
const wantsAdmin = req.query.admin !== undefined && !auth.isAdmin(req);
|
||||
if (auth.isAuthed(req) && !wantsAdmin) return res.redirect(auth.safeNext(req.query.next));
|
||||
page('key.html')(req, res);
|
||||
});
|
||||
app.post('/api/auth', auth.handleLogin);
|
||||
@@ -83,6 +87,20 @@ app.get('/', page('lobby.html'));
|
||||
app.get('/create', page('create.html'));
|
||||
app.get('/table/:id', page('table.html'));
|
||||
|
||||
// ---------- 管理者専用: ハンドレンジ学習 ----------
|
||||
app.get('/range', auth.requireAdmin, page('range.html', ADMIN));
|
||||
app.use(
|
||||
'/range/files',
|
||||
auth.requireAdmin,
|
||||
express.static(ADMIN, {
|
||||
index: false,
|
||||
dotfiles: 'deny',
|
||||
// カード画像を毎回読み込まないよう、本人のブラウザにだけキャッシュさせる
|
||||
setHeaders: (res) => res.setHeader('Cache-Control', 'private, max-age=86400'),
|
||||
})
|
||||
);
|
||||
|
||||
app.get('/api/me', (req, res) => res.json({ admin: auth.isAdmin(req) }));
|
||||
app.get('/api/tables', (req, res) => res.json(tables.list()));
|
||||
app.get('/api/tables/suggest-name', (req, res) => res.json({ name: tables.suggestName() }));
|
||||
|
||||
|
||||
Reference in new issue
Block a user