207 lines
8.1 KiB
JavaScript
207 lines
8.1 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const db = require('../db');
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const { isAuthenticated, hasRole } = require('../middleware/authMiddleware');
|
|
const { generateLicense, verifyLicense } = require('../utils/licenseManager');
|
|
const { checkRemoteKey } = require('../utils/remoteLicense');
|
|
|
|
// Load Public Key for Verification
|
|
const publicKeyPath = path.join(__dirname, '../config/public_key.pem');
|
|
let publicKey = null;
|
|
try {
|
|
if (fs.existsSync(publicKeyPath)) {
|
|
publicKey = fs.readFileSync(publicKeyPath, 'utf8');
|
|
} else {
|
|
console.error('WARNING: public_key.pem not found in server root. License verification will fail.');
|
|
}
|
|
} catch (e) {
|
|
console.error('Error loading public key:', e);
|
|
}
|
|
|
|
// 0. Server Configuration (Subscriber ID & Session Timeout)
|
|
router.get('/settings', isAuthenticated, hasRole('admin'), async (req, res) => {
|
|
try {
|
|
const [rows] = await db.query("SELECT setting_key, setting_value FROM system_settings WHERE setting_key IN ('subscriber_id', 'session_timeout')");
|
|
const settings = {};
|
|
rows.forEach(r => settings[r.setting_key] = r.setting_value);
|
|
|
|
res.json({
|
|
subscriber_id: settings.subscriber_id || '',
|
|
session_timeout: parseInt(settings.session_timeout) || 60 // Default 60 min
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).json({ error: 'Database error' });
|
|
}
|
|
});
|
|
|
|
router.post('/settings', isAuthenticated, hasRole('admin'), async (req, res) => {
|
|
const { subscriber_id, session_timeout } = req.body;
|
|
|
|
try {
|
|
if (subscriber_id !== undefined) {
|
|
await db.query(`INSERT INTO system_settings (setting_key, setting_value) VALUES ('subscriber_id', ?) ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)`, [subscriber_id]);
|
|
}
|
|
if (session_timeout !== undefined) {
|
|
await db.query(`INSERT INTO system_settings (setting_key, setting_value) VALUES ('session_timeout', ?) ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)`, [session_timeout.toString()]);
|
|
}
|
|
res.json({ message: 'Settings saved' });
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).json({ error: 'Database error' });
|
|
}
|
|
});
|
|
|
|
// 1. Get All Modules Status
|
|
router.get('/modules', isAuthenticated, async (req, res) => {
|
|
try {
|
|
const [rows] = await db.query('SELECT * FROM system_modules');
|
|
|
|
const modules = {};
|
|
const defaults = ['asset', 'production', 'monitoring'];
|
|
|
|
// Get stored subscriber ID
|
|
const [subRows] = await db.query("SELECT setting_value FROM system_settings WHERE setting_key = 'subscriber_id'");
|
|
const serverSubscriberId = subRows.length > 0 ? subRows[0].setting_value : null;
|
|
|
|
defaults.forEach(code => {
|
|
const found = rows.find(r => r.code === code);
|
|
if (found) {
|
|
modules[code] = {
|
|
active: !!found.is_active,
|
|
type: found.license_type,
|
|
expiry: found.expiry_date,
|
|
subscriber_id: found.subscriber_id // Return who verified it
|
|
};
|
|
} else {
|
|
modules[code] = { active: false, type: null, expiry: null, subscriber_id: null };
|
|
}
|
|
});
|
|
|
|
res.json({ modules, serverSubscriberId });
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).json({ error: 'Database error' });
|
|
}
|
|
});
|
|
|
|
// 2. Activate Module (Apply License)
|
|
// Only admin can manage system modules
|
|
router.post('/modules/:code/activate', isAuthenticated, hasRole('admin'), async (req, res) => {
|
|
const { code } = req.params;
|
|
let { licenseKey } = req.body;
|
|
|
|
if (!licenseKey) {
|
|
return res.status(400).json({ error: 'License key is required' });
|
|
}
|
|
|
|
licenseKey = licenseKey.trim();
|
|
|
|
// 1. Verify Key validity
|
|
const result = verifyLicense(licenseKey, publicKey);
|
|
if (!result.isValid) {
|
|
return res.status(400).json({ error: `Invalid License: ${result.reason}` });
|
|
}
|
|
|
|
// 2. Check Module match
|
|
if (result.module !== code) {
|
|
return res.status(400).json({ error: `This license is for '${result.module}' module, not '${code}'` });
|
|
}
|
|
|
|
// 3. Check Subscriber match
|
|
try {
|
|
const [subRows] = await db.query("SELECT setting_value FROM system_settings WHERE setting_key = 'subscriber_id'");
|
|
const serverSubscriberId = subRows.length > 0 ? subRows[0].setting_value : null;
|
|
|
|
if (!serverSubscriberId) {
|
|
return res.status(400).json({ error: 'Server Subscriber ID is not set. Please configure it in settings first.' });
|
|
}
|
|
|
|
if (result.subscriberId !== serverSubscriberId) {
|
|
return res.status(403).json({
|
|
error: `License Subscriber Mismatch. Key is for '${result.subscriberId}', but Server is '${serverSubscriberId}'.`
|
|
});
|
|
}
|
|
|
|
// 4. Archive Current License if exists
|
|
const [current] = await db.query('SELECT * FROM system_modules WHERE code = ?', [code]);
|
|
if (current.length > 0 && current[0].is_active && current[0].license_key) {
|
|
const old = current[0];
|
|
const historySql = `
|
|
INSERT INTO license_history (module_code, license_key, license_type, subscriber_id, activated_at)
|
|
VALUES (?, ?, ?, ?, NOW())
|
|
`;
|
|
// Store "activated_at" as roughly the time it was active until now (or simply log the event time)
|
|
// Actually, let's treat "activated_at" in history as "when it was archived/replaced".
|
|
await db.query(historySql, [old.code, old.license_key, old.license_type, old.subscriber_id]);
|
|
}
|
|
|
|
// Upsert into system_modules
|
|
const sql = `
|
|
INSERT INTO system_modules (code, name, is_active, license_key, license_type, expiry_date, subscriber_id)
|
|
VALUES (?, ?, true, ?, ?, ?, ?)
|
|
ON DUPLICATE KEY UPDATE
|
|
is_active = true,
|
|
license_key = VALUES(license_key),
|
|
license_type = VALUES(license_type),
|
|
expiry_date = VALUES(expiry_date),
|
|
subscriber_id = VALUES(subscriber_id)
|
|
`;
|
|
|
|
// Map codes to names
|
|
const names = {
|
|
'asset': '자산 관리',
|
|
'production': '생산 관리',
|
|
'monitoring': 'CCTV'
|
|
};
|
|
|
|
await db.query(sql, [code, names[code] || code, licenseKey, result.type, result.expiryDate, result.subscriberId]);
|
|
|
|
res.json({ success: true, message: 'Module activated', type: result.type, expiry: result.expiryDate });
|
|
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).json({ error: 'Database error' });
|
|
}
|
|
});
|
|
|
|
// 3. Get Module History
|
|
router.get('/modules/:code/history', isAuthenticated, hasRole('admin'), async (req, res) => {
|
|
try {
|
|
const [rows] = await db.query('SELECT * FROM license_history WHERE module_code = ? ORDER BY id DESC LIMIT 10', [req.params.code]);
|
|
res.json(rows);
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).json({ error: 'Database error' });
|
|
}
|
|
});
|
|
|
|
// 4. Deactivate Module
|
|
router.post('/modules/:code/deactivate', isAuthenticated, hasRole('admin'), async (req, res) => {
|
|
const { code } = req.params;
|
|
try {
|
|
// Archive on deactivate too?
|
|
const [current] = await db.query('SELECT * FROM system_modules WHERE code = ?', [code]);
|
|
if (current.length > 0 && current[0].is_active) {
|
|
const old = current[0];
|
|
const historySql = `
|
|
INSERT INTO license_history (module_code, license_key, license_type, subscriber_id, activated_at)
|
|
VALUES (?, ?, ?, ?, NOW())
|
|
`;
|
|
await db.query(historySql, [old.code, old.license_key, old.license_type, old.subscriber_id]);
|
|
}
|
|
|
|
await db.query('UPDATE system_modules SET is_active = false WHERE code = ?', [code]);
|
|
res.json({ success: true, message: 'Module deactivated' });
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).json({ error: 'Database error' });
|
|
}
|
|
});
|
|
|
|
|
|
|
|
module.exports = router;
|