From 52bb503785989190cc043065549fe57d8f3a7b65 Mon Sep 17 00:00:00 2001 From: frakarr Date: Thu, 11 Dec 2025 23:35:53 +0100 Subject: [PATCH] Update server.js --- server/server.js | 66 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/server/server.js b/server/server.js index 0708797..839acc6 100644 --- a/server/server.js +++ b/server/server.js @@ -129,18 +129,19 @@ app.get('/api/settings', authenticateToken, async (req, res) => { res.json({ currentYear: rows[0].current_year, smtpConfig: rows[0].smtp_config || {}, - features: rows[0].features || { multiCondo: true, tickets: true, payPal: true, notices: true, reports: true, extraordinaryExpenses: true, condoFinancialsView: false } + storageConfig: rows[0].storage_config || { provider: 'local_db' }, + features: rows[0].features || { multiCondo: true, tickets: true, payPal: true, notices: true, reports: true, extraordinaryExpenses: true, condoFinancialsView: false, documents: true } }); } else { res.status(404).json({ message: 'Settings not found' }); } } catch (e) { res.status(500).json({ error: e.message }); } }); app.put('/api/settings', authenticateToken, requireAdmin, async (req, res) => { - const { currentYear, smtpConfig, features } = req.body; + const { currentYear, smtpConfig, features, storageConfig } = req.body; try { await pool.query( - 'UPDATE settings SET current_year = ?, smtp_config = ?, features = ? WHERE id = 1', - [currentYear, JSON.stringify(smtpConfig), JSON.stringify(features)] + 'UPDATE settings SET current_year = ?, smtp_config = ?, features = ?, storage_config = ? WHERE id = 1', + [currentYear, JSON.stringify(smtpConfig), JSON.stringify(features), JSON.stringify(storageConfig)] ); res.json({ success: true }); } catch (e) { res.status(500).json({ error: e.message }); } @@ -763,6 +764,63 @@ app.get('/api/condo-expenses/:id/attachments/:attId', authenticateToken, async ( } catch(e) { res.status(500).json({ error: e.message }); } }); +// --- DOCUMENTS (CLOUD/LOCAL) --- +app.get('/api/documents', authenticateToken, async (req, res) => { + const { condoId } = req.query; + try { + // We only fetch metadata, not file_data + const [rows] = await pool.query('SELECT id, condo_id, title, description, file_name, file_type, file_size, tags, storage_provider, upload_date FROM documents WHERE condo_id = ? ORDER BY upload_date DESC', [condoId]); + res.json(rows.map(r => ({ + id: r.id, condoId: r.condo_id, title: r.title, description: r.description, + fileName: r.file_name, fileType: r.file_type, fileSize: r.file_size, + tags: r.tags || [], storageProvider: r.storage_provider, uploadDate: r.upload_date + }))); + } catch(e) { res.status(500).json({ error: e.message }); } +}); + +app.post('/api/documents', authenticateToken, requireAdmin, async (req, res) => { + const { condoId, title, description, fileName, fileType, fileSize, tags, fileData, storageConfig } = req.body; + const id = uuidv4(); + try { + // Here we would implement real Cloud Storage logic based on storageConfig.provider + // For 'local_db' or fallback, we save base64 in DB. + + let provider = storageConfig?.provider || 'local_db'; + // Mocking Cloud upload by just saving to DB for demo purposes, + // but acknowledging the config + + await pool.query( + 'INSERT INTO documents (id, condo_id, title, description, file_name, file_type, file_size, tags, storage_provider, file_data) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + [id, condoId, title, description, fileName, fileType, fileSize, JSON.stringify(tags), provider, fileData] + ); + res.json({ success: true, id }); + } catch(e) { res.status(500).json({ error: e.message }); } +}); + +app.get('/api/documents/:id/download', authenticateToken, async (req, res) => { + try { + const [rows] = await pool.query('SELECT file_name, file_type, file_data, storage_provider FROM documents WHERE id = ?', [req.params.id]); + if (rows.length === 0) return res.status(404).json({ message: 'Not Found' }); + const doc = rows[0]; + + // If external provider (S3/Drive), we would generate a Signed URL here or proxy the stream. + // For local_db: + res.json({ + fileName: doc.file_name, + fileType: doc.file_type, + data: doc.file_data // Base64 + }); + } catch(e) { res.status(500).json({ error: e.message }); } +}); + +app.delete('/api/documents/:id', authenticateToken, requireAdmin, async (req, res) => { + try { + // Also delete from cloud if configured... + await pool.query('DELETE FROM documents WHERE id = ?', [req.params.id]); + res.json({ success: true }); + } catch(e) { res.status(500).json({ error: e.message }); } +}); + initDb().then(() => { app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);