fix: 初回アクティベートのレースコンディションを修正

WHERE device_id IS NULL を追加してアトミックにし、
競合した場合は再取得して照合する

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
posimai 2026-04-11 06:42:42 +09:00
parent 04b40a5b67
commit ee7b3053e2
1 changed files with 19 additions and 3 deletions

View File

@ -40,12 +40,28 @@ module.exports = function createPonshuRouter(pool, authMiddleware) {
});
}
// 初回アクティベート
// 初回アクティベート — WHERE device_id IS NULL で競合を防ぐ
if (!license.device_id) {
await pool.query(
`UPDATE ponshu_licenses SET device_id = $1, activated_at = NOW() WHERE license_key = $2`,
const activateResult = await pool.query(
`UPDATE ponshu_licenses SET device_id = $1, activated_at = NOW()
WHERE license_key = $2 AND device_id IS NULL
RETURNING license_key`,
[device_id, license_key]
);
if (activateResult.rowCount === 0) {
// 別リクエストが先にアクティベートした → 再取得して照合
const retry = await pool.query(
`SELECT device_id FROM ponshu_licenses WHERE license_key = $1`, [license_key]
);
const current = retry.rows[0];
if (!current || current.device_id !== device_id) {
return res.json({
valid: false,
error: '別のデバイスで登録済みです。端末変更の場合はサポートまでご連絡ください。',
supportEmail: APP_SUPPORT_EMAIL,
});
}
}
console.log(`[Ponshu] License activated: ${license_key.substring(0, 12)}... -> Device: ${device_id.substring(0, 8)}...`);
return res.json({ valid: true, plan: license.plan, activated: true });
}