feat: Add manager permissions management component and related functionality
- Implemented ManagerPermissions.vue for managing manager accounts, including adding, editing, and deleting managers. - Integrated a modal for adding new managers with form validation. - Added functionality to fetch, display, and paginate manager data. - Created a toast notification system for user feedback on actions. - Developed a reusable Toast component for displaying notifications. - Introduced a useToast composable for managing toast notifications. - Added permissions management for managers, including fetching and saving permissions. - Implemented password change functionality for managers. - Enhanced error handling and user feedback throughout the manager management process. - Added root CA and private key files for secure communication.
This commit is contained in:
+369
-37
@@ -16,17 +16,39 @@ export default function(db) {
|
||||
if (err || user.role !== 'manager') {
|
||||
return res.status(403).json({ message: 'Forbidden' });
|
||||
}
|
||||
req.user = user;
|
||||
req.user = { ...user, id: user.userId }; // Correctly map userId to id
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
res.status(401).json({ message: 'Unauthorized' });
|
||||
}
|
||||
};
|
||||
|
||||
// Middleware to check for specific permissions
|
||||
const checkPermission = (requiredPermission) => {
|
||||
return async (req, res, next) => {
|
||||
try {
|
||||
const managerId = req.user.id;
|
||||
const [rows] = await db.execute(
|
||||
'SELECT * FROM manager_permissions WHERE manager_id = ?',
|
||||
[managerId]
|
||||
);
|
||||
|
||||
if (rows.length === 0 || !rows[0][requiredPermission]) {
|
||||
return res.status(403).json({ message: 'Forbidden: Insufficient permissions.' });
|
||||
}
|
||||
next();
|
||||
} catch (error) {
|
||||
console.error('Permission check error:', error);
|
||||
res.status(500).json({ message: 'Database error during permission check.' });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
router.use(authenticateJWT);
|
||||
|
||||
// --- START: Date Management Routes ---
|
||||
router.get('/enabled-dates', async (req, res) => {
|
||||
router.get('/enabled-dates', checkPermission('view_all'), async (req, res) => {
|
||||
try {
|
||||
const [rows] = await db.execute('SELECT YEAR(enabled_date) as year, MONTH(enabled_date) as month, DAY(enabled_date) as day FROM enabled_dates');
|
||||
// Format date safely using components from the database to avoid timezone shifts
|
||||
@@ -39,7 +61,7 @@ export default function(db) {
|
||||
});
|
||||
|
||||
// Definitive version using a dedicated database connection
|
||||
router.post('/enabled-dates/update', async (req, res) => {
|
||||
router.post('/enabled-dates/update', checkPermission('view_all'), async (req, res) => {
|
||||
let connection; // Define connection here to ensure it's accessible in the 'finally' block
|
||||
try {
|
||||
const { datesToEnable, datesToDisable } = req.body;
|
||||
@@ -77,7 +99,7 @@ export default function(db) {
|
||||
|
||||
// --- ATTENDANCE & REPORTING ---
|
||||
|
||||
router.get('/failed-records', async (req, res) => {
|
||||
router.get('/failed-records', checkPermission('view_all'), async (req, res) => {
|
||||
try {
|
||||
const { search = '', startDate, endDate } = req.query;
|
||||
if (!startDate || !endDate) {
|
||||
@@ -112,7 +134,7 @@ export default function(db) {
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/failed-records/details', async (req, res) => {
|
||||
router.get('/failed-records/details', checkPermission('view_all'), async (req, res) => {
|
||||
try {
|
||||
const { workerId, startDate, endDate } = req.query;
|
||||
if (!workerId || !startDate || !endDate) {
|
||||
@@ -139,7 +161,7 @@ export default function(db) {
|
||||
});
|
||||
|
||||
// GET attendance records with a modified query to avoid the MySQL 5.7 bug
|
||||
router.get('/attendance-records/export-raw', async (req, res) => {
|
||||
router.get('/attendance-records/export-raw', checkPermission('view_all'), async (req, res) => {
|
||||
try {
|
||||
const { workerIds, startDate, endDate } = req.query;
|
||||
if (!startDate || !endDate) {
|
||||
@@ -177,7 +199,7 @@ export default function(db) {
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/add-record', authenticateJWT, async (req, res) => {
|
||||
router.post('/add-record', checkPermission('edit_workers'), async (req, res) => {
|
||||
try {
|
||||
const { workerId, eventType, timestamp, notes } = req.body
|
||||
|
||||
@@ -212,7 +234,7 @@ export default function(db) {
|
||||
}
|
||||
})
|
||||
|
||||
router.get('/attendance-records/export', async (req, res) => {
|
||||
router.get('/attendance-records/export', checkPermission('view_all'), async (req, res) => {
|
||||
try {
|
||||
const { workerIds, startDate, endDate } = req.query;
|
||||
if (!startDate || !endDate) {
|
||||
@@ -295,7 +317,7 @@ export default function(db) {
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/attendance-records', async (req, res) => {
|
||||
router.get('/attendance-records', checkPermission('view_all'), async (req, res) => {
|
||||
try {
|
||||
const { workerIds, startDate, endDate, format } = req.query;
|
||||
if (!workerIds) {
|
||||
@@ -351,22 +373,107 @@ export default function(db) {
|
||||
|
||||
// --- All other manager routes remain the same ---
|
||||
|
||||
// GET a specific manager's permissions
|
||||
router.get('/permissions/:id', async (req, res) => {
|
||||
try {
|
||||
const requesterId = req.user.id;
|
||||
const targetId = parseInt(req.params.id, 10);
|
||||
|
||||
// Check if the user is trying to access their own permissions
|
||||
if (requesterId !== targetId) {
|
||||
// If not, check if they have permission to manage permissions
|
||||
const [permissionRows] = await db.execute(
|
||||
'SELECT can_manage_permissions FROM manager_permissions WHERE manager_id = ?',
|
||||
[requesterId]
|
||||
);
|
||||
|
||||
if (permissionRows.length === 0 || !permissionRows[0].can_manage_permissions) {
|
||||
return res.status(403).json({ message: 'Forbidden: Insufficient permissions to view others\' permissions.' });
|
||||
}
|
||||
}
|
||||
|
||||
// If they are accessing their own, or have permission, fetch the target's permissions
|
||||
const [rows] = await db.execute(
|
||||
'SELECT * FROM manager_permissions WHERE manager_id = ?',
|
||||
[targetId]
|
||||
);
|
||||
|
||||
if (rows.length === 0) {
|
||||
// If no permissions are set, return a default set of all false
|
||||
const [fields] = await db.execute('DESCRIBE manager_permissions');
|
||||
const defaultPermissions = fields.reduce((acc, field) => {
|
||||
if (field.Field !== 'manager_id') {
|
||||
acc[field.Field] = 0; // Use 0 for false
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
return res.json(defaultPermissions);
|
||||
}
|
||||
|
||||
// Convert buffer values to booleans
|
||||
const permissions = Object.entries(rows[0]).reduce((acc, [key, value]) => {
|
||||
if (key !== 'manager_id') {
|
||||
acc[key] = Boolean(value);
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
res.json(permissions);
|
||||
} catch (error) {
|
||||
console.error('Get manager permissions error:', error);
|
||||
res.status(500).json({ message: 'Database error fetching manager permissions.', details: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// PUT (update) a manager's permissions
|
||||
router.put('/permissions/:id', checkPermission('manager_permissions'), async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const permissions = req.body;
|
||||
|
||||
const fields = [
|
||||
'view_all', 'edit_workers', 'manage_resources', 'manager_permissions'
|
||||
];
|
||||
const values = fields.map(field => permissions[field] || false);
|
||||
|
||||
// Convert to new simplified permissions schema
|
||||
const query = `
|
||||
INSERT INTO manager_permissions (manager_id, view_all, edit_workers, manage_resources, manager_permissions)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
view_all = VALUES(view_all),
|
||||
edit_workers = VALUES(edit_workers),
|
||||
manage_resources = VALUES(manage_resources),
|
||||
manager_permissions = VALUES(manager_permissions)
|
||||
`;
|
||||
|
||||
const queryParams = [id, ...values];
|
||||
|
||||
await db.execute(query, queryParams);
|
||||
|
||||
res.status(200).json({ message: 'Permissions updated successfully.' });
|
||||
} catch (error) {
|
||||
console.error('Update manager permissions error:', error);
|
||||
res.status(500).json({ message: 'Database error updating manager permissions.', details: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// GET all workers with filtering and pagination
|
||||
router.get('/workers', async (req, res) => {
|
||||
router.get('/workers', checkPermission('view_all'), async (req, res) => {
|
||||
try {
|
||||
const { search = '', page = 1, limit = 20 } = req.query;
|
||||
const offset = (parseInt(page) - 1) * parseInt(limit);
|
||||
const searchTerm = `%${search}%`;
|
||||
|
||||
let baseQuery = `
|
||||
SELECT w.id, w.username, w.full_name, w.department, w.position, w.created_at
|
||||
SELECT w.id, w.username, w.full_name, w.department, w.position, w.created_at, w.status
|
||||
FROM workers w
|
||||
`;
|
||||
let countQuery = `SELECT COUNT(w.id) as totalCount FROM workers w`;
|
||||
|
||||
const params = [];
|
||||
const countParams = [];
|
||||
let whereClauses = ["w.role = 'worker'"];
|
||||
let whereClauses = ["w.role = 'worker'", "w.status != 'deleted'"]; // Filter out soft-deleted workers
|
||||
|
||||
if (search) {
|
||||
whereClauses.push(`(w.full_name LIKE ? OR w.department LIKE ?)`);
|
||||
@@ -393,8 +500,91 @@ export default function(db) {
|
||||
}
|
||||
});
|
||||
|
||||
// GET all managers with their permissions
|
||||
router.get('/managers', checkPermission('manager_permissions'), async (req, res) => {
|
||||
try {
|
||||
const { search = '', page = 1, limit = 20 } = req.query;
|
||||
const offset = (parseInt(page) - 1) * parseInt(limit);
|
||||
const searchTerm = `%${search}%`;
|
||||
|
||||
let baseQuery = `
|
||||
SELECT
|
||||
w.id, w.username, w.full_name, w.department, w.position, w.created_at, w.status,
|
||||
mp.*
|
||||
FROM workers w
|
||||
LEFT JOIN manager_permissions mp ON w.id = mp.manager_id
|
||||
`;
|
||||
let countQuery = `SELECT COUNT(w.id) as totalCount FROM workers w`;
|
||||
|
||||
const params = [];
|
||||
const countParams = [];
|
||||
let whereClauses = ["w.role = 'manager'", "w.status != 'deleted'"];
|
||||
|
||||
if (search) {
|
||||
whereClauses.push(`(w.full_name LIKE ? OR w.department LIKE ?)`);
|
||||
params.push(searchTerm, searchTerm);
|
||||
countParams.push(searchTerm, searchTerm);
|
||||
}
|
||||
|
||||
if (whereClauses.length > 0) {
|
||||
const whereString = ` WHERE ${whereClauses.join(' AND ')}`;
|
||||
baseQuery += whereString;
|
||||
countQuery += whereString;
|
||||
}
|
||||
|
||||
baseQuery += ` ORDER BY w.created_at DESC LIMIT ? OFFSET ?`;
|
||||
params.push(parseInt(limit), offset);
|
||||
|
||||
const [managers] = await db.execute(baseQuery, params);
|
||||
const [[{ totalCount }]] = await db.execute(countQuery, countParams);
|
||||
|
||||
res.json({ managers, totalCount });
|
||||
} catch (error) {
|
||||
console.error('Get managers error:', error);
|
||||
res.status(500).json({ message: 'Database error fetching managers.', details: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// POST (add) a new manager
|
||||
router.post('/managers', checkPermission('manager_permissions'), async (req, res) => {
|
||||
try {
|
||||
const { username, password, fullName, department, position } = req.body;
|
||||
if (!username || !password || !fullName) {
|
||||
return res.status(400).json({ message: 'Username, password, and full name are required.' });
|
||||
}
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
const [result] = await db.execute(
|
||||
'INSERT INTO workers (username, password_hash, full_name, role, department, position, status) VALUES (?, ?, ?, ?, ?, ?, ?)',
|
||||
[username, hashedPassword, fullName, 'manager', department, position, 'active']
|
||||
);
|
||||
|
||||
// Set default view_all permission
|
||||
await db.execute(
|
||||
'INSERT INTO manager_permissions (manager_id, view_all) VALUES (?, ?)',
|
||||
[result.insertId, true]
|
||||
);
|
||||
|
||||
res.status(201).json({
|
||||
id: result.insertId,
|
||||
username,
|
||||
fullName,
|
||||
role: 'manager',
|
||||
department,
|
||||
position,
|
||||
status: 'active',
|
||||
view_all: true
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Add manager error:', error);
|
||||
if (error.code === 'ER_DUP_ENTRY') {
|
||||
return res.status(409).json({ message: 'Username already exists.' });
|
||||
}
|
||||
res.status(500).json({ message: 'Database error adding manager.', details: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// POST (add) a new worker
|
||||
router.post('/workers', async (req, res) => {
|
||||
router.post('/workers', checkPermission('edit_workers'), async (req, res) => {
|
||||
try {
|
||||
const { username, password, fullName, department, position, role = 'worker' } = req.body;
|
||||
if (!username || !password || !fullName) {
|
||||
@@ -402,10 +592,10 @@ export default function(db) {
|
||||
}
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
const [result] = await db.execute(
|
||||
'INSERT INTO workers (username, password_hash, full_name, role, department, position) VALUES (?, ?, ?, ?, ?, ?)',
|
||||
[username, hashedPassword, fullName, role, department, position]
|
||||
'INSERT INTO workers (username, password_hash, full_name, role, department, position, status) VALUES (?, ?, ?, ?, ?, ?, ?)',
|
||||
[username, hashedPassword, fullName, role, department, position, 'active'] // Default status to 'active'
|
||||
);
|
||||
res.status(201).json({ id: result.insertId, username, fullName, role, department, position });
|
||||
res.status(201).json({ id: result.insertId, username, fullName, role, department, position, status: 'active' });
|
||||
} catch (error) {
|
||||
console.error('Add worker error:', error);
|
||||
if (error.code === 'ER_DUP_ENTRY') {
|
||||
@@ -415,23 +605,132 @@ export default function(db) {
|
||||
}
|
||||
});
|
||||
|
||||
// DELETE a worker
|
||||
router.delete('/workers/:id', async (req, res) => {
|
||||
// Soft DELETE a worker (update status to 'deleted')
|
||||
router.delete('/workers/:id', checkPermission('edit_workers'), async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const [result] = await db.execute("DELETE FROM workers WHERE id = ? AND role = 'worker'", [id]);
|
||||
const [result] = await db.execute("UPDATE workers SET status = 'deleted' WHERE id = ? AND role = 'worker'", [id]);
|
||||
if (result.affectedRows === 0) {
|
||||
return res.status(404).json({ message: 'Worker not found.' });
|
||||
return res.status(404).json({ message: 'Worker not found or already deleted.' });
|
||||
}
|
||||
res.status(204).send(); // Maintain existing response for client compatibility
|
||||
} catch (error) {
|
||||
console.error('Soft delete worker error:', error);
|
||||
res.status(500).json({ message: 'Database error soft deleting worker.', details: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Soft DELETE a manager (update status to 'deleted')
|
||||
router.delete('/managers/:id', checkPermission('manager_permissions'), async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const [result] = await db.execute("UPDATE workers SET status = 'deleted' WHERE id = ? AND role = 'manager'", [id]);
|
||||
if (result.affectedRows === 0) {
|
||||
return res.status(404).json({ message: 'Manager not found or already deleted.' });
|
||||
}
|
||||
res.status(204).send();
|
||||
} catch (error) {
|
||||
console.error('Delete worker error:', error);
|
||||
res.status(500).json({ message: 'Database error deleting worker.', details: error.message });
|
||||
console.error('Soft delete manager error:', error);
|
||||
res.status(500).json({ message: 'Database error soft deleting manager.', details: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// PUT (update) a worker's details (department, position, status)
|
||||
router.put('/workers/:id', checkPermission('edit_workers'), async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { department, position, status } = req.body;
|
||||
|
||||
// Basic validation
|
||||
if (!department && !position && !status) {
|
||||
return res.status(400).json({ message: 'No update information provided.' });
|
||||
}
|
||||
if (status && !['active', 'inactive'].includes(status)) {
|
||||
return res.status(400).json({ message: 'Invalid status value.' });
|
||||
}
|
||||
|
||||
let updateQuery = 'UPDATE workers SET';
|
||||
const params = [];
|
||||
const fieldsToUpdate = [];
|
||||
|
||||
if (department) {
|
||||
fieldsToUpdate.push('department = ?');
|
||||
params.push(department);
|
||||
}
|
||||
if (position) {
|
||||
fieldsToUpdate.push('position = ?');
|
||||
params.push(position);
|
||||
}
|
||||
if (status) {
|
||||
fieldsToUpdate.push('status = ?');
|
||||
params.push(status);
|
||||
}
|
||||
|
||||
updateQuery += ` ${fieldsToUpdate.join(', ')} WHERE id = ? AND role = 'worker'`;
|
||||
params.push(id);
|
||||
|
||||
const [result] = await db.execute(updateQuery, params);
|
||||
|
||||
if (result.affectedRows === 0) {
|
||||
return res.status(404).json({ message: 'Worker not found.' });
|
||||
}
|
||||
|
||||
res.status(200).json({ message: 'Worker details updated successfully.' });
|
||||
} catch (error) {
|
||||
console.error('Update worker details error:', error);
|
||||
res.status(500).json({ message: 'Database error updating worker details.', details: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// PUT (update) a manager's details (department, position, status)
|
||||
router.put('/managers/:id', checkPermission('manager_permissions'), async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { department, position, status } = req.body;
|
||||
|
||||
// Basic validation
|
||||
if (!department && !position && !status) {
|
||||
return res.status(400).json({ message: 'No update information provided.' });
|
||||
}
|
||||
if (status && !['active', 'inactive'].includes(status)) {
|
||||
return res.status(400).json({ message: 'Invalid status value.' });
|
||||
}
|
||||
|
||||
let updateQuery = 'UPDATE workers SET';
|
||||
const params = [];
|
||||
const fieldsToUpdate = [];
|
||||
|
||||
if (department) {
|
||||
fieldsToUpdate.push('department = ?');
|
||||
params.push(department);
|
||||
}
|
||||
if (position) {
|
||||
fieldsToUpdate.push('position = ?');
|
||||
params.push(position);
|
||||
}
|
||||
if (status) {
|
||||
fieldsToUpdate.push('status = ?');
|
||||
params.push(status);
|
||||
}
|
||||
|
||||
updateQuery += ` ${fieldsToUpdate.join(', ')} WHERE id = ? AND role = 'manager'`;
|
||||
params.push(id);
|
||||
|
||||
const [result] = await db.execute(updateQuery, params);
|
||||
|
||||
if (result.affectedRows === 0) {
|
||||
return res.status(404).json({ message: 'Manager not found.' });
|
||||
}
|
||||
|
||||
res.status(200).json({ message: 'Manager details updated successfully.' });
|
||||
} catch (error) {
|
||||
console.error('Update manager details error:', error);
|
||||
res.status(500).json({ message: 'Database error updating manager details.', details: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// PUT (update) a worker's password
|
||||
router.put('/workers/:workerId/password', async (req, res) => {
|
||||
router.put('/workers/:workerId/password', checkPermission('edit_workers'), async (req, res) => {
|
||||
try {
|
||||
const { workerId } = req.params;
|
||||
const { newPassword } = req.body;
|
||||
@@ -450,24 +749,57 @@ export default function(db) {
|
||||
}
|
||||
});
|
||||
|
||||
// PUT (clear) a worker's device UUID
|
||||
router.put('/workers/:workerId/reset-device', async (req, res) => {
|
||||
// PUT (update) a manager's password
|
||||
router.put('/managers/:managerId/password', checkPermission('manager_permissions'), async (req, res) => {
|
||||
try {
|
||||
const { managerId } = req.params;
|
||||
const { newPassword } = req.body;
|
||||
if (!newPassword || newPassword.length < 6) {
|
||||
return res.status(400).json({ message: 'Password must be at least 6 characters long.' });
|
||||
}
|
||||
const hashedPassword = await bcrypt.hash(newPassword, 10);
|
||||
const [result] = await db.execute("UPDATE workers SET password_hash = ? WHERE id = ? AND role = 'manager'", [hashedPassword, managerId]);
|
||||
if (result.affectedRows === 0) {
|
||||
return res.status(404).json({ message: 'Manager not found.' });
|
||||
}
|
||||
res.status(200).json({ message: 'Password updated successfully.' });
|
||||
} catch (error) {
|
||||
console.error('Update manager password error:', error);
|
||||
res.status(500).json({ message: 'Database error updating manager password.', details: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// PUT (clear) a worker's device UUID and/or update status
|
||||
router.put('/workers/:workerId/reset-device', checkPermission('edit_workers'), async (req, res) => {
|
||||
try {
|
||||
const { workerId } = req.params;
|
||||
const [result] = await db.execute("UPDATE workers SET device_uuid = NULL WHERE id = ?", [workerId]);
|
||||
const { status } = req.body; // Optional status field
|
||||
|
||||
let updateQuery = "UPDATE workers SET device_uuid = NULL";
|
||||
const params = [workerId];
|
||||
|
||||
if (status && ['active', 'inactive', 'deleted'].includes(status)) {
|
||||
updateQuery += ", status = ?";
|
||||
params.unshift(status); // Add status to the beginning of params for correct order
|
||||
}
|
||||
|
||||
updateQuery += " WHERE id = ?";
|
||||
|
||||
const [result] = await db.execute(updateQuery, params);
|
||||
|
||||
if (result.affectedRows === 0) {
|
||||
return res.status(404).json({ message: 'Worker not found.' });
|
||||
}
|
||||
res.status(200).json({ message: 'Device registration cleared.' });
|
||||
res.status(200).json({ message: 'Device registration cleared and/or status updated.' });
|
||||
} catch (error) {
|
||||
console.error('Reset device error:', error);
|
||||
res.status(500).json({ message: 'Database error resetting device.', details: error.message });
|
||||
console.error('Reset device/update status error:', error);
|
||||
res.status(500).json({ message: 'Database error resetting device or updating status.', details: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Geofence Management Routes
|
||||
router.get('/geofences', async (req, res) => {
|
||||
router.get('/geofences', checkPermission('view_all'), async (req, res) => {
|
||||
try {
|
||||
const [rows] = await db.execute(
|
||||
'SELECT id, name, coordinates, is_active, created_at FROM geofences ORDER BY created_at DESC'
|
||||
@@ -483,7 +815,7 @@ export default function(db) {
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/geofences', async (req, res) => {
|
||||
router.post('/geofences', checkPermission('manage_resources'), async (req, res) => {
|
||||
try {
|
||||
const { name, coordinates } = req.body;
|
||||
if (!name || !coordinates) {
|
||||
@@ -508,7 +840,7 @@ export default function(db) {
|
||||
}
|
||||
});
|
||||
|
||||
router.put('/geofences/:id', async (req, res) => {
|
||||
router.put('/geofences/:id', checkPermission('manage_resources'), async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { is_active } = req.body;
|
||||
@@ -533,7 +865,7 @@ export default function(db) {
|
||||
}
|
||||
});
|
||||
|
||||
router.delete('/geofences/:id', async (req, res) => {
|
||||
router.delete('/geofences/:id', checkPermission('manage_resources'), async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const [result] = await db.execute('DELETE FROM geofences WHERE id = ?', [id]);
|
||||
@@ -551,7 +883,7 @@ export default function(db) {
|
||||
|
||||
|
||||
// QR Code Management Routes
|
||||
router.get('/qr-codes', authenticateJWT, async (req, res) => {
|
||||
router.get('/qr-codes', checkPermission('view_all'), async (req, res) => {
|
||||
try {
|
||||
const [rows] = await db.execute(
|
||||
'SELECT id, name, is_active, created_at FROM qr_codes ORDER BY created_at DESC'
|
||||
@@ -563,7 +895,7 @@ export default function(db) {
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/qr-codes', authenticateJWT, async (req, res) => {
|
||||
router.post('/qr-codes', checkPermission('manage_resources'), async (req, res) => {
|
||||
try {
|
||||
const { name } = req.body;
|
||||
if (!name) return res.status(400).json({ message: 'QR Code name is required.' });
|
||||
@@ -586,7 +918,7 @@ export default function(db) {
|
||||
}
|
||||
});
|
||||
|
||||
router.put('/qr-codes/:id', authenticateJWT, async (req, res) => {
|
||||
router.put('/qr-codes/:id', checkPermission('manage_resources'), async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
// Handle both isActive (camelCase) and is_active (snake_case)
|
||||
@@ -612,7 +944,7 @@ export default function(db) {
|
||||
}
|
||||
});
|
||||
|
||||
router.delete('/qr-codes/:id', authenticateJWT, async (req, res) => {
|
||||
router.delete('/qr-codes/:id', checkPermission('manage_resources'), async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const [result] = await db.execute(
|
||||
|
||||
Reference in New Issue
Block a user