fix(ai/generate): temperature クランプ・role バリデーション追加

- temperature を 0〜2 でクランプ(不正値でのSDKエラー防止)
- contents の role を user/model のみ許可(system injection 防止)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
posimai 2026-04-21 06:52:46 +09:00
parent a2282fe33b
commit 4360f9090f
1 changed files with 30 additions and 1 deletions

View File

@ -2000,6 +2000,12 @@ ${excerpt}
if (JSON.stringify(contents).length > 60000) {
return res.status(400).json({ error: 'contents too large' });
}
const VALID_ROLES = new Set(['user', 'model']);
for (const item of contents) {
if (!VALID_ROLES.has(item?.role)) {
return res.status(400).json({ error: 'invalid role in contents' });
}
}
try {
const modelOpts = { model: 'gemini-2.5-flash' };
if (systemPrompt && typeof systemPrompt === 'string') {
@ -2008,7 +2014,7 @@ ${excerpt}
const model = genAI.getGenerativeModel(modelOpts);
const generationConfig = {
maxOutputTokens: Math.min(config.maxOutputTokens || 500, 1000),
temperature: config.temperature ?? 0.5
temperature: Math.max(0, Math.min(config.temperature ?? 0.5, 2))
};
const timeoutPromise = new Promise((_, reject) =>
setTimeout(() => reject(new Error('timeout')), 15000)
@ -2782,6 +2788,29 @@ ${excerpt}
}
});
// PUT /together/members/rename — 表示名変更
r.put('/together/members/rename', async (req, res) => {
const { group_id, old_username, new_username } = req.body || {};
const trimmed = normalizeTogetherUsername(new_username);
if (!group_id || !old_username || !trimmed) return res.status(400).json({ error: 'group_id, old_username, new_username は必須です' });
if (trimmed.length > 30) return res.status(400).json({ error: '名前は30文字以内にしてください' });
const jwtUserId = getTogetherJwtUserId(req);
try {
if (!(await togetherEnsureMember(pool, res, group_id, old_username, jwtUserId))) return;
const conflict = await pool.query(
'SELECT 1 FROM together_members WHERE group_id=$1 AND username=$2',
[group_id, trimmed]
);
if (conflict.rows.length > 0) return res.status(409).json({ error: '同じ名前のメンバーが既にいます' });
await pool.query('UPDATE together_members SET username=$1 WHERE group_id=$2 AND username=$3', [trimmed, group_id, old_username]);
await pool.query('UPDATE together_shares SET shared_by=$1 WHERE group_id=$2 AND shared_by=$3', [trimmed, group_id, old_username]);
res.json({ ok: true });
} catch (e) {
console.error('[together/rename]', e.message);
res.status(500).json({ error: 'Internal server error' });
}
});
// DELETE /together/share/:id — 自分の投稿を削除
r.delete('/together/share/:id', async (req, res) => {
const { username } = req.body || {};