The job_run_logs table tracks scheduled job orchestration, not individual worker jobs. Worker info (worker_id, worker_hostname) belongs on dispensary_crawl_jobs, not job_run_logs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
192 lines
5.6 KiB
TypeScript
192 lines
5.6 KiB
TypeScript
import { Router } from 'express';
|
|
import { authMiddleware, requireRole } from '../auth/middleware';
|
|
import { pool } from '../db/migrate';
|
|
import crypto from 'crypto';
|
|
|
|
const router = Router();
|
|
router.use(authMiddleware);
|
|
|
|
// Generate secure random API key (64-character hex)
|
|
function generateApiKey(): string {
|
|
return crypto.randomBytes(32).toString('hex');
|
|
}
|
|
|
|
// Get all API permissions
|
|
router.get('/', requireRole('superadmin', 'admin'), async (req, res) => {
|
|
try {
|
|
const result = await pool.query(`
|
|
SELECT *
|
|
FROM wp_dutchie_api_permissions
|
|
ORDER BY created_at DESC
|
|
`);
|
|
|
|
res.json({ permissions: result.rows });
|
|
} catch (error) {
|
|
console.error('Error fetching API permissions:', error);
|
|
res.status(500).json({ error: 'Failed to fetch API permissions' });
|
|
}
|
|
});
|
|
|
|
// Get all dispensaries for dropdown (must be before /:id to avoid route conflict)
|
|
router.get('/dispensaries', requireRole('superadmin', 'admin'), async (req, res) => {
|
|
try {
|
|
const result = await pool.query(`
|
|
SELECT id, name
|
|
FROM dispensaries
|
|
ORDER BY name
|
|
`);
|
|
res.json({ dispensaries: result.rows });
|
|
} catch (error) {
|
|
console.error('Error fetching dispensaries:', error);
|
|
res.status(500).json({ error: 'Failed to fetch dispensaries' });
|
|
}
|
|
});
|
|
|
|
// Get single API permission
|
|
router.get('/:id', requireRole('superadmin', 'admin'), async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
|
|
const result = await pool.query(`
|
|
SELECT *
|
|
FROM wp_dutchie_api_permissions
|
|
WHERE id = $1
|
|
`, [id]);
|
|
|
|
if (result.rows.length === 0) {
|
|
return res.status(404).json({ error: 'Permission not found' });
|
|
}
|
|
|
|
res.json({ permission: result.rows[0] });
|
|
} catch (error) {
|
|
console.error('Error fetching API permission:', error);
|
|
res.status(500).json({ error: 'Failed to fetch API permission' });
|
|
}
|
|
});
|
|
|
|
// Create new API permission
|
|
router.post('/', requireRole('superadmin', 'admin'), async (req, res) => {
|
|
try {
|
|
// Support both store_id (existing) and dispensary_id (for compatibility)
|
|
const { user_name, allowed_ips, allowed_domains, store_id, dispensary_id } = req.body;
|
|
const storeIdToUse = store_id || dispensary_id;
|
|
|
|
if (!user_name) {
|
|
return res.status(400).json({ error: 'User name is required' });
|
|
}
|
|
|
|
if (!storeIdToUse) {
|
|
return res.status(400).json({ error: 'Store/Dispensary is required' });
|
|
}
|
|
|
|
// Get dispensary name for display
|
|
const dispensaryResult = await pool.query('SELECT name FROM dispensaries WHERE id = $1', [storeIdToUse]);
|
|
if (dispensaryResult.rows.length === 0) {
|
|
return res.status(400).json({ error: 'Invalid store/dispensary ID' });
|
|
}
|
|
const storeName = dispensaryResult.rows[0].name;
|
|
|
|
const apiKey = generateApiKey();
|
|
|
|
const result = await pool.query(`
|
|
INSERT INTO wp_dutchie_api_permissions (
|
|
user_name,
|
|
api_key,
|
|
allowed_ips,
|
|
allowed_domains,
|
|
is_active,
|
|
store_id,
|
|
store_name
|
|
)
|
|
VALUES ($1, $2, $3, $4, 1, $5, $6)
|
|
RETURNING *
|
|
`, [
|
|
user_name,
|
|
apiKey,
|
|
allowed_ips || null,
|
|
allowed_domains || null,
|
|
storeIdToUse,
|
|
storeName
|
|
]);
|
|
|
|
res.status(201).json({
|
|
permission: result.rows[0],
|
|
message: 'API permission created successfully. Save the API key securely - it cannot be retrieved later.'
|
|
});
|
|
} catch (error) {
|
|
console.error('Error creating API permission:', error);
|
|
res.status(500).json({ error: 'Failed to create API permission' });
|
|
}
|
|
});
|
|
|
|
// Update API permission
|
|
router.put('/:id', requireRole('superadmin', 'admin'), async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { user_name, allowed_ips, allowed_domains, is_active } = req.body;
|
|
|
|
const result = await pool.query(`
|
|
UPDATE wp_dutchie_api_permissions
|
|
SET
|
|
user_name = COALESCE($1, user_name),
|
|
allowed_ips = COALESCE($2, allowed_ips),
|
|
allowed_domains = COALESCE($3, allowed_domains),
|
|
is_active = COALESCE($4, is_active)
|
|
WHERE id = $5
|
|
RETURNING *
|
|
`, [user_name, allowed_ips, allowed_domains, is_active, id]);
|
|
|
|
if (result.rows.length === 0) {
|
|
return res.status(404).json({ error: 'Permission not found' });
|
|
}
|
|
|
|
res.json({ permission: result.rows[0] });
|
|
} catch (error) {
|
|
console.error('Error updating API permission:', error);
|
|
res.status(500).json({ error: 'Failed to update API permission' });
|
|
}
|
|
});
|
|
|
|
// Toggle permission active status
|
|
router.patch('/:id/toggle', requireRole('superadmin', 'admin'), async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
|
|
const result = await pool.query(`
|
|
UPDATE wp_dutchie_api_permissions
|
|
SET is_active = NOT is_active
|
|
WHERE id = $1
|
|
RETURNING *
|
|
`, [id]);
|
|
|
|
if (result.rows.length === 0) {
|
|
return res.status(404).json({ error: 'Permission not found' });
|
|
}
|
|
|
|
res.json({ permission: result.rows[0] });
|
|
} catch (error) {
|
|
console.error('Error toggling API permission:', error);
|
|
res.status(500).json({ error: 'Failed to toggle API permission' });
|
|
}
|
|
});
|
|
|
|
// Delete API permission
|
|
router.delete('/:id', requireRole('superadmin'), async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
|
|
const result = await pool.query('DELETE FROM wp_dutchie_api_permissions WHERE id = $1 RETURNING *', [id]);
|
|
|
|
if (result.rows.length === 0) {
|
|
return res.status(404).json({ error: 'Permission not found' });
|
|
}
|
|
|
|
res.json({ message: 'API permission deleted successfully' });
|
|
} catch (error) {
|
|
console.error('Error deleting API permission:', error);
|
|
res.status(500).json({ error: 'Failed to delete API permission' });
|
|
}
|
|
});
|
|
|
|
export default router;
|