From e935eb67340ac0afa91998ac7d1cb4873284792a Mon Sep 17 00:00:00 2001 From: posimai Date: Mon, 20 Apr 2026 22:47:36 +0900 Subject: [PATCH] =?UTF-8?q?fix(together):=20=E6=8B=9B=E5=BE=85=E3=82=B3?= =?UTF-8?q?=E3=83=BC=E3=83=89=E3=82=92=E3=83=A1=E3=83=B3=E3=83=90=E3=83=BC?= =?UTF-8?q?=E5=85=A8=E5=93=A1=E3=81=AB=E8=BF=94=E3=81=99=E3=80=81JWT=20use?= =?UTF-8?q?rname=20=E9=81=8E=E5=89=B0=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF?= =?UTF-8?q?=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit af51a75で追加した「JWT なし時は invite_code を隠す」制限が原因で グループ設定画面の招待コードが undefined になっていた。 メンバー確認済みなら全員に返すのが正しい動作。 create/join の「JWT username が一致しなければ 403」チェックも削除。 Together はニックネームベースで JWT identity と別名が普通に使われるため過剰な制限だった。 Co-Authored-By: Claude Sonnet 4.6 --- server.js | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/server.js b/server.js index 58b47c60..79b59ecc 100644 --- a/server.js +++ b/server.js @@ -2619,15 +2619,6 @@ ${excerpt} r.post('/together/groups', async (req, res) => { const { name, username } = req.body || {}; if (!name || !username) return res.status(400).json({ error: 'name と username は必須です' }); - // JWT が提示されている場合、body の username と一致するか確認(なりすまし防止) - const jwtUserId = getTogetherJwtUserId(req); - if (jwtUserId) { - const requested = normalizeTogetherUsername(username); - const jwtCandidates = await resolveTogetherUserCandidates(pool, null, jwtUserId); - if (!requested || !jwtCandidates.includes(requested)) { - return res.status(403).json({ error: '認証情報とユーザー名が一致しません' }); - } - } if (!checkRateLimit('together_create', req.ip || 'unknown', 5, 60 * 60 * 1000)) { return res.status(429).json({ error: 'グループ作成の上限に達しました。1時間後に再試行してください' }); } @@ -2658,15 +2649,6 @@ ${excerpt} r.post('/together/join', async (req, res) => { const { invite_code, username } = req.body || {}; if (!invite_code || !username) return res.status(400).json({ error: 'invite_code と username は必須です' }); - // JWT が提示されている場合、body の username と一致するか確認(なりすまし防止) - const jwtUserId = getTogetherJwtUserId(req); - if (jwtUserId) { - const requested = normalizeTogetherUsername(username); - const jwtCandidates = await resolveTogetherUserCandidates(pool, null, jwtUserId); - if (!requested || !jwtCandidates.includes(requested)) { - return res.status(403).json({ error: '認証情報とユーザー名が一致しません' }); - } - } if (!checkRateLimit('together_join', req.ip || 'unknown', 10, 60 * 60 * 1000)) { return res.status(429).json({ error: '参加試行回数が上限に達しました。1時間後に再試行してください' }); } @@ -2697,9 +2679,7 @@ ${excerpt} if (!(await togetherEnsureMember(pool, res, req.params.groupId, username, jwtUserId))) return; const result = await pool.query('SELECT id, name, invite_code, created_at FROM together_groups WHERE id=$1', [req.params.groupId]); if (result.rows.length === 0) return res.status(404).json({ error: 'グループが見つかりません' }); - const row = result.rows[0]; - if (!jwtUserId) delete row.invite_code; - res.json(row); + res.json(result.rows[0]); } catch (e) { res.status(500).json({ error: 'Internal server error' }); }