feat(imggen): feature-gate «imggen» с контролем по классам/ученикам (Спринт2)
- server: requireFeature('imggen') на /api/imggen (глобальный гейт).
- imggenController: enforcement через isFeatureEnabledForUser в status()/generate()
— учитывает глобальный флаг + оверлей класса + free_student (403 если выкл.).
- admin «games/features» + free-student: тумблер «Генерация картинок (ИИ)».
- classes.html: переключатель модуля imggen в настройках класса (per-class).
Дефолт — ON (opt-in disable), как у остальных фич. Проверено на features-движке.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const db = require('../db/db');
|
||||
const { isFeatureEnabledForUser } = require('../middleware/features');
|
||||
|
||||
const GEN_DIR = path.join(__dirname, '../../uploads/generated');
|
||||
const _cooldown = new Map(); // userId → last ts (антиспам)
|
||||
@@ -29,8 +30,11 @@ function _limits() {
|
||||
};
|
||||
}
|
||||
|
||||
// Фича включена для ЭТОГО пользователя (глобально + оверлей класса + free_student).
|
||||
function _featOn(req) { return isFeatureEnabledForUser(req.user.id, req.user.role, 'imggen'); }
|
||||
|
||||
/* GET /api/imggen/status — для UI (показывать кнопки или нет) */
|
||||
function status(req, res) { res.json({ enabled: _enabled() }); }
|
||||
function status(req, res) { res.json({ enabled: _enabled() && _featOn(req) }); }
|
||||
|
||||
/* FLUX лучше понимает английский. Если в промпте есть кириллица — переводим
|
||||
* через тот же LLM-провайдер, что и ассистент (с failover). При сбое — исходный текст. */
|
||||
@@ -119,6 +123,7 @@ function stats() {
|
||||
|
||||
/* POST /api/imggen { prompt } → { url } */
|
||||
async function generate(req, res) {
|
||||
if (!_featOn(req)) return res.status(403).json({ error: 'Генерация картинок отключена для вашего класса' });
|
||||
if (!_enabled()) return res.status(503).json({ error: _configured() ? 'Генерация картинок временно выключена' : 'Генерация изображений не настроена' });
|
||||
const prompt = String((req.body && req.body.prompt) || '').trim().slice(0, 500);
|
||||
if (prompt.length < 3) return res.status(400).json({ error: 'Опиши, что нарисовать (хотя бы пару слов)' });
|
||||
|
||||
@@ -160,7 +160,7 @@ app.use('/api/questions', questionRoutes);
|
||||
app.use('/api/classes', classRoutes);
|
||||
app.use('/api/assignments', assignmentRoutes);
|
||||
app.use('/api/files', fileRoutes);
|
||||
app.use('/api/imggen', require('./routes/imggen'));
|
||||
app.use('/api/imggen', requireFeature('imggen'), require('./routes/imggen'));
|
||||
app.use('/api/tests', testRoutes);
|
||||
app.use('/api/notifications', notificationRoutes);
|
||||
app.use('/api/permissions', permissionRoutes);
|
||||
|
||||
Reference in New Issue
Block a user