import { Router } from "express"; import crypto from "crypto"; import fs from "fs"; import path from "path"; const router = Router(); const LICENSE_FILE = path.join(process.cwd(), "license.json"); const SECRET = process.env.LICENSE_SECRET || ""; function validateKey(key: string): { valid: boolean; expiry?: string; error?: string } { // Format: DENTAL-{24-char-signature}-{YYYY-MM-DD} const parts = key.trim().split("-"); if (parts.length !== 5 || parts[0] !== "DENTAL") { return { valid: false, error: "Invalid license key format" }; } const signature = parts[1]; const expiryStr = `${parts[2]}-${parts[3]}-${parts[4]}`; // Verify signature const payload = `DENTAL:${expiryStr}`; const expectedSig = crypto .createHmac("sha256", SECRET) .update(payload) .digest("hex") .substring(0, 24) .toUpperCase(); if (signature !== expectedSig) { return { valid: false, error: "Invalid license key" }; } // Check expiry const expiry = new Date(expiryStr); if (isNaN(expiry.getTime())) { return { valid: false, error: "Invalid expiry date in key" }; } if (new Date() > expiry) { return { valid: false, expiry: expiryStr, error: "License key has expired" }; } return { valid: true, expiry: expiryStr }; } function loadLicense(): { key: string; expiry: string } | null { try { if (!fs.existsSync(LICENSE_FILE)) return null; return JSON.parse(fs.readFileSync(LICENSE_FILE, "utf8")); } catch { return null; } } function saveLicense(key: string, expiry: string) { fs.writeFileSync(LICENSE_FILE, JSON.stringify({ key, expiry }, null, 2)); } // GET /api/license/status router.get("/status", (req, res) => { const stored = loadLicense(); if (!stored) { return res.json({ activated: false, expired: false, expiry: null, daysLeft: null }); } const result = validateKey(stored.key); if (!result.valid && result.expiry) { return res.json({ activated: true, expired: true, expiry: stored.expiry, daysLeft: 0 }); } if (!result.valid) { return res.json({ activated: false, expired: false, expiry: null, daysLeft: null }); } const expiry = new Date(stored.expiry); const daysLeft = Math.ceil((expiry.getTime() - Date.now()) / (1000 * 60 * 60 * 24)); return res.json({ activated: true, expired: false, expiry: stored.expiry, daysLeft }); }); // POST /api/license/activate router.post("/activate", (req, res) => { const { key } = req.body; if (!key) { return res.status(400).json({ error: "License key is required" }); } const result = validateKey(key); if (!result.valid) { return res.status(400).json({ error: result.error }); } saveLicense(key.trim(), result.expiry!); return res.json({ success: true, expiry: result.expiry }); }); export default router;