const express = require('express'); const multer = require('multer'); const cors = require('cors'); const { decodeFromImageBuffer } = require('./decoder'); // Import our logic const app = express(); const PORT = process.env.PORT || 7860; // --- 1. SECURE CORS CONFIGURATION --- // Define the list of allowed client origins from an environment variable. // This allows you to change the allowed origins without changing the code. // The variable should be a comma-separated list of URLs. const allowedOrigins = process.env.ALLOWED_ORIGINS ? process.env.ALLOWED_ORIGINS.split(',') : []; const corsOptions = { origin: (origin, callback) => { // 'origin' will be undefined for server-to-server requests or curl. // Allow requests with no origin OR if the origin is in our whitelist. if (!origin || allowedOrigins.indexOf(origin) !== -1) { callback(null, true); } else { // If the origin is not in the whitelist, reject the request. callback(new Error(`Not allowed by CORS. Origin: ${origin}`)); } }, methods: ['GET', 'POST'], // Allow only specific methods }; // Use the configured CORS middleware app.use(cors(corsOptions)); // --- 2. HEALTH CHECK ENDPOINT --- app.get('/', (req, res) => { res.status(200).json({ status: 'ok', message: 'Secure Decoder API is running.', // Also report which origins are allowed, for easy debugging. allowed_origins: allowedOrigins.length > 0 ? allowedOrigins : "None configured (check ALLOWED_ORIGINS secret)." }); }); const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 5 * 1024 * 1024 }, // 5MB limit }); // --- 3. DECODE API ENDPOINT --- app.post('/api/decode', upload.single('authImage'), async (req, res) => { console.log(`Received a request to /api/decode from origin: ${req.get('origin') || 'unknown'}`); const privateKey = process.env.PLUGIN_PRIVATE_KEY; if (!privateKey) { console.error("FATAL: PLUGIN_PRIVATE_KEY secret is not set in the Space settings."); return res.status(500).json({ error: 'Server is not configured with a private key.' }); } if (!req.file) { console.log("Request failed: No image file provided."); return res.status(400).json({ error: 'No image file provided. Please upload a file with the key "authImage".' }); } try { const credentials = await decodeFromImageBuffer(req.file.buffer, privateKey); console.log("Successfully decoded data."); res.json({ success: true, data: credentials }); } catch (error) { console.error("Decryption failed:", error.message); res.status(400).json({ success: false, error: `Decryption failed: ${error.message}` }); } }); app.listen(PORT, () => { console.log(`Secure decoder API listening on port ${PORT}`); if (allowedOrigins.length > 0) { console.log(`CORS whitelist enabled for the following origins: ${allowedOrigins.join(', ')}`); } else { console.warn("WARNING: No CORS origins are whitelisted. Set the ALLOWED_ORIGINS secret. All cross-origin requests will be blocked."); } if (!process.env.PLUGIN_PRIVATE_KEY) { console.warn("WARNING: PLUGIN_PRIVATE_KEY environment variable is not set. The /api/decode endpoint will fail."); } else { console.log("PLUGIN_PRIVATE_KEY secret has been loaded successfully."); } });