serve project files by token hash, preview images inline and download other files
This commit is contained in:
@@ -194,8 +194,8 @@ app.post('/api/restore', requireAdmin, uploadBackup.single('backup'), async (req
|
||||
}
|
||||
for (const x of data.project_files || []) {
|
||||
await client.query(
|
||||
'INSERT INTO project_files (id, entry_id, path, name, created_at) VALUES ($1,$2,$3,$4,$5)',
|
||||
[x.id, x.entry_id, x.path, x.name, x.created_at]
|
||||
'INSERT INTO project_files (id, entry_id, token, path, name, created_at) VALUES ($1,$2,$3,$4,$5,$6)',
|
||||
[x.id, x.entry_id, x.token, x.path, x.name, x.created_at]
|
||||
);
|
||||
}
|
||||
for (const [k, v] of Object.entries(data.settings || {})) {
|
||||
@@ -481,7 +481,7 @@ app.get('/api/entries', requireAdmin, async (req, res) => {
|
||||
if (rows.length) {
|
||||
const ids = rows.map(r => r.id);
|
||||
const fRes = await pool.query(
|
||||
'SELECT id, entry_id, path, name FROM project_files WHERE entry_id = ANY($1) ORDER BY id',
|
||||
'SELECT entry_id, token, name FROM project_files WHERE entry_id = ANY($1) ORDER BY id',
|
||||
[ids]
|
||||
);
|
||||
files = {};
|
||||
@@ -495,18 +495,24 @@ app.get('/api/entries', requireAdmin, async (req, res) => {
|
||||
|
||||
app.get('/api/entries/:id/files', requireAdmin, async (req, res) => {
|
||||
const { rows } = await pool.query(
|
||||
'SELECT id, path, name FROM project_files WHERE entry_id = $1 ORDER BY id',
|
||||
'SELECT token, name FROM project_files WHERE entry_id = $1 ORDER BY id',
|
||||
[req.params.id]
|
||||
);
|
||||
res.json(rows);
|
||||
});
|
||||
|
||||
app.get('/api/files/:id', requireAdmin, async (req, res) => {
|
||||
const { rows } = await pool.query('SELECT path, name FROM project_files WHERE id = $1', [req.params.id]);
|
||||
function isImageName(name) {
|
||||
return /\.(jpe?g|png|gif|webp|bmp|avif|svg|ico)$/i.test(name || '');
|
||||
}
|
||||
|
||||
app.get('/api/files/:token', requireAdmin, async (req, res) => {
|
||||
const { rows } = await pool.query('SELECT path, name FROM project_files WHERE token = $1', [req.params.token]);
|
||||
if (!rows.length) return res.status(404).json({ error: 'Not found' });
|
||||
const fp = path.join(__dirname, rows[0].path);
|
||||
const r = rows[0];
|
||||
const fp = path.join(__dirname, r.path);
|
||||
if (!fs.existsSync(fp)) return res.status(404).json({ error: 'File missing' });
|
||||
res.download(fp, rows[0].name);
|
||||
if (isImageName(r.name)) res.sendFile(fp);
|
||||
else res.download(fp, r.name);
|
||||
});
|
||||
|
||||
app.get('/api/stats', requireAdmin, async (_, res) => {
|
||||
@@ -559,9 +565,10 @@ app.post('/api/entries', upload.fields([{ name: 'photo', maxCount: 1 }, { name:
|
||||
[student_name.trim(), group_id, description.trim(), photo_path]
|
||||
);
|
||||
for (const f of projectFiles) {
|
||||
const token = crypto.randomBytes(16).toString('hex');
|
||||
await client.query(
|
||||
'INSERT INTO project_files (entry_id, path, name) VALUES ($1, $2, $3)',
|
||||
[rows[0].id, `/uploads/${f.filename}`, f.originalname]
|
||||
'INSERT INTO project_files (entry_id, token, path, name) VALUES ($1, $2, $3, $4)',
|
||||
[rows[0].id, token, `/uploads/${f.filename}`, f.originalname]
|
||||
);
|
||||
}
|
||||
await client.query('COMMIT');
|
||||
|
||||
Reference in New Issue
Block a user