const express = require('express'); const log = require("../logger.js"); const db = global.db; const router = express.Router(); const expressWs = require('express-ws')(router); router.use((req, res, next) => { if (!req.session.user) return res.redirect('/login?err=4'); const perms = req.session.user.perms ? JSON.parse(req.session.user.perms) : []; if (perms.includes('*') || perms.includes('acl')) { return next(); } return res.status(403).render('error', { error: 'Forbidden', button: { text: 'Back', action: 'back' } }); }); router.get('/', async (req, res) => { const acl = await db.query('SELECT * FROM ACL'); res.render('acl', { acl, user: req.session.user }); }); router.put('/:cardNumber', async (req, res) => { // Attempt to create new ACL entry. Fail if cardNumber already exists const cardNumber = parseInt(req.params.cardNumber); if (isNaN(cardNumber) || cardNumber <= 0) { return res.status(400).json({ error: 'Invalid card number' }); } const data = req.body; data.cardNumber = cardNumber; try { const check = await db.query('SELECT * FROM ACL WHERE CardNumber = ?', [cardNumber]); if (check && check.length > 0) { return res.status(409).json({ error: 'Card number already exists' }); } // Name, CardNumber, PIN, StartDate, EndDate, [Doors (will be array of door names from client, for each add that column adn set to 1)] const fields = ['Name', 'CardNumber', 'PIN', 'StartDate', 'EndDate']; const placeholders = ['?', '?', '?', '?', '?']; const values = [ data.Name || "Unknown/Not Set", data.cardNumber, data.PIN || null, data.StartDate || new Date(), data.EndDate || new Date(new Date().setFullYear(new Date().getFullYear() + 99)) ]; data.doors.forEach(door => { fields.push(door); placeholders.push('?'); values.push(1); }); const sql = `INSERT INTO ACL (${fields.join(', ')}) VALUES (${placeholders.join(', ')})`; db.query(sql, values).then(result => { return res.status(201).json({ message: 'ACL entry created' }); }).catch(err => { log.error(`Database error creating ACL entry: ${err}`); return res.status(500).json({ error: 'Internal server error' }); }); } catch (err) { log.error(`Database error checking ACL entry: ${err}`); return res.status(500).json({ error: 'Internal server error' }); } }); router.get('/edit/:cardNumber', async (req, res) => { // Get ACL entry for editing const cardNumber = parseInt(req.params.cardNumber); if (isNaN(cardNumber) || cardNumber <= 0) { return res.status(400).json({ error: 'Invalid card number' }); } try { const entry = await db.query('SELECT * FROM ACL WHERE CardNumber = ?', [cardNumber]); if (!entry || entry.length === 0) { return res.render('error', { error: 'Card number not found', button: { text: 'Back', action: 'back' } }); } // generate doors object const doors = {} Object.keys(entry[0]).forEach(key => { if (key !== 'id' && key !== 'Name' && key !== 'CardNumber' && key !== 'PIN' && key !== 'StartDate' && key !== 'EndDate') { doors[key] = entry[0][key] === 1; } }); return res.render('acl-edit', { aclEntry: entry[0], doorsList: doors, user: req.session.user }); } catch (err) { log.error(`Database error fetching ACL entry: ${err}`); return res.status(500).render('error', { error: 'Internal server error', button: { text: 'Back', action: 'back' } }); } }); router.patch('/edit/:cardNumber', async (req, res) => { // Update ACL entry. Fail if cardNumber does not exist const cardNumber = parseInt(req.params.cardNumber); if (isNaN(cardNumber) || cardNumber <= 0) { return res.status(400).json({ error: 'Invalid card number' }); } const data = req.body; data.cardNumber = cardNumber; try { const check = await db.query('SELECT * FROM ACL WHERE CardNumber = ?', [cardNumber]); if (!check || check.length === 0) { return res.status(404).json({ error: 'Card number not found' }); } // Name, CardNumber, PIN, StartDate, EndDate, [Doors (will be object of door names : true/false from client, for each add that column adn set to 1)] const fields = []; const values = []; if (data.Name) { fields.push('Name = ?'); values.push(data.Name); } if (data.PIN) { fields.push('PIN = ?'); values.push(data.PIN); } if (data.StartDate) { fields.push('StartDate = ?'); values.push(data.StartDate); } if (data.EndDate) { fields.push('EndDate = ?'); values.push(data.EndDate); } for (const door in data.doors) { if (data.doors.hasOwnProperty(door)) { fields.push(`${door} = ?`); values.push(data.doors[door] ? 1 : 0); } if (fields.length === 0) { return res.status(400).json({ error: 'No fields to update' }); } } values.push(cardNumber); const sql = `UPDATE ACL SET ${fields.join(', ')} WHERE CardNumber = ?`; db.query(sql, values).then(result => { return res.status(200).json({ message: 'ACL entry updated' }); }).catch(err => { log.error(`Database error updating ACL entry: ${err}`); return res.status(500).json({ error: 'Internal server error' }); }); } catch (err) { log.error(`Database error checking ACL entry: ${err}`); return res.status(500).json({ error: 'Internal server error' }); } }); router.get('/delete/:cardNumber', async (req, res) => { // Delete ACL entry. Fail if cardNumber does not exist const cardNumber = parseInt(req.params.cardNumber); if (isNaN(cardNumber) || cardNumber <= 0) { return res.status(400).json({ error: 'Invalid card number' }); } try { const check = await db.query('SELECT * FROM ACL WHERE CardNumber = ?', [cardNumber]); if (!check || check.length === 0) { return res.status(404).json({ error: 'Card number not found' }); } db.query('DELETE FROM ACL WHERE CardNumber = ?', [cardNumber]).then(result => { return res.status(200).json({ message: 'ACL entry deleted' }); }).catch(err => { log.error(`Database error deleting ACL entry: ${err}`); return res.status(500).json({ error: 'Internal server error' }); }); } catch (err) { log.error(`Database error checking ACL entry: ${err}`); return res.status(500).json({ error: 'Internal server error' }); } }); module.exports = router;