mirror of
https://github.com/screentinker/screentinker.git
synced 2026-06-14 18:22:46 -06:00
fix(api): consolidate device pairing to /pair, remove vestigial bare endpoint (#90)
POST /api/provision was a second pairing endpoint that paired a device by code but, unlike POST /api/provision/pair, did NOT assign a workspace, enforce checkDeviceLimit, or emit device:paired / dashboard:device-added - a silently-diverging duplicate that no client ever called. It now returns 410 Gone and points callers at /pair, so /api/provision/pair is the single, fully-protected pairing endpoint. The mount stays in the JWT-only partition, so a Bearer st_ token still gets 401 (requireAuth) before the 410. Closes #90 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
538f4a7b03
commit
3305e79e61
|
|
@ -1,23 +1,17 @@
|
|||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const { db } = require('../db/database');
|
||||
|
||||
// Provision (pair) a device by entering its pairing code
|
||||
// #90: the bare POST /api/provision was a vestigial SECOND pairing endpoint. It paired a
|
||||
// device by pairing code but - unlike POST /api/provision/pair (server.js) - did NOT
|
||||
// assign the device to a workspace, did NOT enforce checkDeviceLimit, and did NOT emit
|
||||
// device:paired / dashboard:device-added. A silently-diverging duplicate of /pair that
|
||||
// no client ever called (verified). Consolidated to /pair (the single, fully-protected
|
||||
// pairing endpoint); this path now returns 410 Gone and points callers at the right one.
|
||||
//
|
||||
// The mount stays in the JWT-only partition (config/api-surface.js), so a Bearer st_
|
||||
// token still gets 401 from requireAuth before ever reaching this handler.
|
||||
router.post('/', (req, res) => {
|
||||
const { pairing_code } = req.body;
|
||||
if (!pairing_code) return res.status(400).json({ error: 'pairing_code required' });
|
||||
|
||||
const device = db.prepare('SELECT * FROM devices WHERE pairing_code = ?').get(pairing_code);
|
||||
if (!device) return res.status(404).json({ error: 'No device found with that pairing code' });
|
||||
|
||||
// Clear pairing code and set online
|
||||
db.prepare(`
|
||||
UPDATE devices SET pairing_code = NULL, status = 'online', updated_at = strftime('%s','now')
|
||||
WHERE id = ?
|
||||
`).run(device.id);
|
||||
|
||||
const updated = db.prepare('SELECT * FROM devices WHERE id = ?').get(device.id);
|
||||
res.json(require('../lib/device-sanitize').stripDeviceSecrets(updated));
|
||||
res.status(410).json({ error: 'This endpoint has been removed. Pair a device with POST /api/provision/pair.' });
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
|
|
|||
29
server/test/provisioning.test.js
Normal file
29
server/test/provisioning.test.js
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
'use strict';
|
||||
|
||||
// #90: the vestigial bare POST /api/provision is consolidated to POST /api/provision/pair.
|
||||
// It must now return 410 Gone and point callers at /pair. Mounts the router in-process
|
||||
// (it no longer touches the DB, so no server boot or injection is needed). The token ->
|
||||
// 401 firewall for /api/provision is covered by the partition test in api.test.js.
|
||||
|
||||
const { test, before, after } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const express = require('express');
|
||||
const provisioningRouter = require('../routes/provisioning');
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
app.use('/api/provision', provisioningRouter);
|
||||
|
||||
let server, base;
|
||||
before(() => new Promise((resolve) => {
|
||||
server = app.listen(0, () => { base = `http://127.0.0.1:${server.address().port}`; resolve(); });
|
||||
}));
|
||||
after(() => { if (server) server.close(); });
|
||||
|
||||
test('provisioning: the bare POST /api/provision is gone (410, consolidated to /pair)', async () => {
|
||||
const res = await fetch(base + '/api/provision', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ pairing_code: '123456' }),
|
||||
});
|
||||
assert.equal(res.status, 410);
|
||||
assert.match(JSON.stringify(await res.json()), /provision\/pair/i, 'should point at POST /api/provision/pair');
|
||||
});
|
||||
Loading…
Reference in a new issue