krsyer-server-monitor-pro 1.0.10 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +1 -1
- package/lib/controllers/cloudflareController.js +1 -1
- package/lib/controllers/dockerController.js +1 -1
- package/lib/controllers/networkController.js +1 -1
- package/lib/controllers/serverController.js +1 -1
- package/lib/ecosystem.config.js +1 -1
- package/lib/middleware/saasAuth.js +1 -1
- package/lib/public/script.js +88 -28
- package/lib/public/style.css +5 -1
- package/lib/routes/cloudflareRoutes.js +1 -1
- package/lib/routes/dockerRoutes.js +1 -1
- package/lib/routes/networkRoutes.js +1 -1
- package/lib/routes/serverRoutes.js +1 -1
- package/lib/server.js +1 -1
- package/lib/services/cashfreeService.js +1 -1
- package/lib/views/index.html +2 -1
- package/license-portal/server.js +95 -38
- package/license-portal/views/pricing.html +41 -5
- package/package.json +1 -1
package/license-portal/server.js
CHANGED
|
@@ -17,8 +17,8 @@ const mysql = require('mysql2/promise');
|
|
|
17
17
|
// --- Database (MySQL) ---
|
|
18
18
|
const dbConfig = {
|
|
19
19
|
host: process.env.DB_HOST || 'localhost',
|
|
20
|
-
user: process.env.DB_USER || '
|
|
21
|
-
password: process.env.DB_PASSWORD || '',
|
|
20
|
+
user: process.env.DB_USER || 'mulaorg',
|
|
21
|
+
password: process.env.DB_PASSWORD || 'Krishika@9959',
|
|
22
22
|
waitForConnections: true,
|
|
23
23
|
connectionLimit: 10,
|
|
24
24
|
queueLimit: 0
|
|
@@ -65,7 +65,13 @@ let pool;
|
|
|
65
65
|
console.log('MySQL Database initialized');
|
|
66
66
|
conn.release();
|
|
67
67
|
} catch (err) {
|
|
68
|
-
console.error('MySQL Init Error:', err);
|
|
68
|
+
console.error('MySQL Init Error:', err.message);
|
|
69
|
+
if (err.code === 'ECONNREFUSED') {
|
|
70
|
+
console.error('❌ Could not connect to MySQL Server. Is it installed and running?');
|
|
71
|
+
console.error('👉 Try: sudo systemctl start mysql');
|
|
72
|
+
} else if (err.code === 'ER_ACCESS_DENIED_ERROR') {
|
|
73
|
+
console.error('❌ Access Denied. Check DB_USER and DB_PASSWORD.');
|
|
74
|
+
}
|
|
69
75
|
}
|
|
70
76
|
})();
|
|
71
77
|
|
|
@@ -121,20 +127,22 @@ app.post('/api/buy', async (req, res) => {
|
|
|
121
127
|
|
|
122
128
|
// 3. Verify Route (Return URL)
|
|
123
129
|
app.get('/verify', async (req, res) => {
|
|
124
|
-
const { order_id } = req.query;
|
|
130
|
+
const { order_id, email, phone } = req.query;
|
|
131
|
+
|
|
132
|
+
if (!order_id) {
|
|
133
|
+
return res.redirect('/');
|
|
134
|
+
}
|
|
135
|
+
|
|
125
136
|
try {
|
|
126
137
|
const cf = getCashfree();
|
|
138
|
+
// Check Payment Status
|
|
127
139
|
const response = await cf.PGOrderFetchPayments(order_id);
|
|
128
140
|
const payments = response.data;
|
|
141
|
+
|
|
142
|
+
// Find successful payment
|
|
129
143
|
const isPaid = payments.some(p => p.payment_status === 'SUCCESS');
|
|
130
144
|
|
|
131
145
|
if (isPaid) {
|
|
132
|
-
// Get Customer Details from Order Fetch?
|
|
133
|
-
// To simplify, we get email from stored order or just query Cashfree Order details again
|
|
134
|
-
const orderDetails = await cf.PGOrderFetch(order_id);
|
|
135
|
-
const email = orderDetails.data.customer_details.customer_email;
|
|
136
|
-
const phone = orderDetails.data.customer_details.customer_phone;
|
|
137
|
-
|
|
138
146
|
// Generate License
|
|
139
147
|
const licenseKey = 'PRO-' + Math.random().toString(36).substring(2, 10).toUpperCase() + '-' + Date.now().toString(36).toUpperCase();
|
|
140
148
|
|
|
@@ -142,40 +150,29 @@ app.get('/verify', async (req, res) => {
|
|
|
142
150
|
const expiryDate = new Date();
|
|
143
151
|
expiryDate.setFullYear(expiryDate.getFullYear() + 1);
|
|
144
152
|
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
153
|
+
// Check if license already exists for this order (Idempotency)
|
|
154
|
+
if (pool) {
|
|
155
|
+
const [existing] = await pool.query('SELECT license_key FROM licenses WHERE order_id = ?', [order_id]);
|
|
156
|
+
if (existing.length > 0) {
|
|
157
|
+
return res.send(getSuccessHtml(existing[0].license_key, order_id, true));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
await pool.query(
|
|
161
|
+
'INSERT INTO licenses (license_key, order_id, customer_email, customer_phone, expiry_date, active) VALUES (?, ?, ?, ?, ?, ?)',
|
|
162
|
+
[licenseKey, order_id, email || 'Unknown', phone || 'Unknown', expiryDate, true]
|
|
163
|
+
);
|
|
164
|
+
} else {
|
|
165
|
+
console.error("Critical: DB Pool missing during verify. License generated but not saved:", licenseKey);
|
|
166
|
+
}
|
|
150
167
|
|
|
151
168
|
// Show Success Page
|
|
152
|
-
res.send(
|
|
153
|
-
<html>
|
|
154
|
-
<body style="font-family: sans-serif; text-align: center; padding: 50px; background: #0f172a; color: white;">
|
|
155
|
-
<div style="max-width: 600px; margin: auto; background: #1e293b; padding: 40px; border-radius: 12px; border: 1px solid #334155;">
|
|
156
|
-
<h1 style="color: #4ade80;">Payment Successful!</h1>
|
|
157
|
-
<p style="color: #94a3b8; font-size: 18px;">Thank you for your yearly subscription.</p>
|
|
158
|
-
|
|
159
|
-
<div style="background: #0f172a; padding: 20px; margin: 30px 0; border-radius: 8px; border: 1px dashed #4ade80;">
|
|
160
|
-
<p style="margin: 0; color: #94a3b8; font-size: 14px;">YOUR LICENSE KEY (Valid until ${expiryDate.toDateString()})</p>
|
|
161
|
-
<h2 style="margin: 10px 0; letter-spacing: 2px; font-family: monospace;">${licenseKey}</h2>
|
|
162
|
-
</div>
|
|
163
|
-
|
|
164
|
-
<p style="color: #cbd5e1;">Copy this key and paste it into your server <code>.env</code> file:</p>
|
|
165
|
-
<code style="background: black; padding: 10px; display: block; text-align: left; color: #fbbf24;">LICENSE_KEY=${licenseKey}</code>
|
|
166
|
-
|
|
167
|
-
<br>
|
|
168
|
-
<a href="/" style="color: white; text-decoration: none; border-bottom: 1px solid white;">Back Home</a>
|
|
169
|
-
</div>
|
|
170
|
-
</body>
|
|
171
|
-
</html>
|
|
172
|
-
`);
|
|
169
|
+
res.send(getSuccessHtml(licenseKey, order_id, false));
|
|
173
170
|
} else {
|
|
174
171
|
res.send(`<h1>Payment Failed or Pending</h1><a href="/">Try Again</a>`);
|
|
175
172
|
}
|
|
176
173
|
} catch (e) {
|
|
177
|
-
console.error("Cashfree Verification Error:", e
|
|
178
|
-
res.status(500).send(
|
|
174
|
+
console.error("Cashfree Verification Error:", e);
|
|
175
|
+
res.status(500).send(`<h1>Verification Error</h1><p>${e.message}</p><pre>${JSON.stringify(e.response?.data || {}, null, 2)}</pre>`);
|
|
179
176
|
}
|
|
180
177
|
});
|
|
181
178
|
|
|
@@ -191,6 +188,11 @@ app.get('/api/validate', async (req, res) => {
|
|
|
191
188
|
return res.json({ valid: true, plan: 'Pro (Demo)' });
|
|
192
189
|
}
|
|
193
190
|
|
|
191
|
+
if (!pool) {
|
|
192
|
+
console.error("DB Pool not ready");
|
|
193
|
+
return res.json({ valid: false, message: 'Server Starting...' });
|
|
194
|
+
}
|
|
195
|
+
|
|
194
196
|
try {
|
|
195
197
|
const [rows] = await pool.query('SELECT * FROM licenses WHERE license_key = ?', [key]);
|
|
196
198
|
const license = rows[0];
|
|
@@ -217,5 +219,60 @@ app.get('/api/validate', async (req, res) => {
|
|
|
217
219
|
return res.json({ valid: false, message: 'Invalid Key' });
|
|
218
220
|
});
|
|
219
221
|
|
|
222
|
+
const getSuccessHtml = (licenseKey, orderId, isExisting) => {
|
|
223
|
+
return `
|
|
224
|
+
<!DOCTYPE html>
|
|
225
|
+
<html lang="en">
|
|
226
|
+
<head>
|
|
227
|
+
<meta charset="UTF-8">
|
|
228
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
229
|
+
<title>License Activated</title>
|
|
230
|
+
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
231
|
+
<style>
|
|
232
|
+
body { font-family: 'Space Grotesk', sans-serif; background: #0f172a; color: white; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; }
|
|
233
|
+
.card { background: #1e293b; padding: 2.5rem; border-radius: 16px; box-shadow: 0 10px 25px rgba(0,0,0,0.5); text-align: center; max-width: 500px; width: 90%; border: 1px solid #334155; }
|
|
234
|
+
h1 { color: ${isExisting ? '#fbbf24' : '#4ade80'}; margin-bottom: 0.5rem; font-size: 2rem; }
|
|
235
|
+
.key-box { background: rgba(0,0,0,0.3); padding: 15px; border-radius: 8px; margin: 20px 0; border: 1px dashed #475569; position: relative; }
|
|
236
|
+
.label { color: #94a3b8; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 5px; display: block; }
|
|
237
|
+
.value { font-family: monospace; font-size: 1.25rem; color: #fbbf24; word-break: break-all; font-weight: bold; }
|
|
238
|
+
.credentials { background: #334155; padding: 15px; border-radius: 8px; margin-top: 20px; text-align: left; }
|
|
239
|
+
.cred-row { display: flex; justify-content: space-between; margin-bottom: 8px; font-size: 0.95rem; }
|
|
240
|
+
.cred-label { color: #cbd5e1; }
|
|
241
|
+
.cred-val { color: #fff; font-weight: 600; font-family: monospace; }
|
|
242
|
+
.warning { color: #f87171; font-size: 0.85rem; margin-top: 10px; font-style: italic; text-align: center;}
|
|
243
|
+
.btn { display: inline-block; margin-top: 25px; padding: 12px 24px; background: #3b82f6; color: white; text-decoration: none; border-radius: 8px; font-weight: 600; transition: all 0.2s; }
|
|
244
|
+
.btn:hover { background: #2563eb; transform: translateY(-1px); }
|
|
245
|
+
</style>
|
|
246
|
+
</head>
|
|
247
|
+
<body>
|
|
248
|
+
<div class="card">
|
|
249
|
+
<h1>${isExisting ? 'License Retrieved' : 'Payment Successful!'}</h1>
|
|
250
|
+
<p style="color: #cbd5e1;">Your License is active.</p>
|
|
251
|
+
|
|
252
|
+
<div class="key-box">
|
|
253
|
+
<span class="label">License Key</span>
|
|
254
|
+
<div class="value">${licenseKey}</div>
|
|
255
|
+
</div>
|
|
256
|
+
|
|
257
|
+
<div class="credentials">
|
|
258
|
+
<div style="margin-bottom:12px; color:#60a5fa; font-weight:bold; font-size:0.95rem; text-align:center; text-transform:uppercase; letter-spacing:1px;">Monitor Credentials</div>
|
|
259
|
+
<div class="cred-row">
|
|
260
|
+
<span class="cred-label">Username:</span>
|
|
261
|
+
<span class="cred-val">admin@monitor.com</span>
|
|
262
|
+
</div>
|
|
263
|
+
<div class="cred-row">
|
|
264
|
+
<span class="cred-label">Password:</span>
|
|
265
|
+
<span class="cred-val">AdminPass123!</span>
|
|
266
|
+
</div>
|
|
267
|
+
<div class="warning">⚠️ Please change your password after initial login</div>
|
|
268
|
+
</div>
|
|
269
|
+
|
|
270
|
+
<a href="/" class="btn">Back Home</a>
|
|
271
|
+
</div>
|
|
272
|
+
</body>
|
|
273
|
+
</html>
|
|
274
|
+
`;
|
|
275
|
+
};
|
|
276
|
+
|
|
220
277
|
const PORT = process.env.PORT || 3011;
|
|
221
278
|
app.listen(PORT, () => console.log(`License Portal running on port ${PORT}`));
|
|
@@ -214,7 +214,7 @@
|
|
|
214
214
|
</div>
|
|
215
215
|
|
|
216
216
|
<p style="text-align: center; color: var(--text-muted); margin-top: 20px;">
|
|
217
|
-
Once installed, visit your server IP on port
|
|
217
|
+
Once installed, visit your server IP on port 3014 to activate.
|
|
218
218
|
</p>
|
|
219
219
|
</div>
|
|
220
220
|
|
|
@@ -240,6 +240,30 @@
|
|
|
240
240
|
</div>
|
|
241
241
|
</div>
|
|
242
242
|
|
|
243
|
+
<style>
|
|
244
|
+
.loader-spinner {
|
|
245
|
+
border: 2px solid rgba(255, 255, 255, 0.3);
|
|
246
|
+
border-top: 2px solid #fff;
|
|
247
|
+
border-radius: 50%;
|
|
248
|
+
width: 16px;
|
|
249
|
+
height: 16px;
|
|
250
|
+
animation: spin 1s linear infinite;
|
|
251
|
+
display: inline-block;
|
|
252
|
+
vertical-align: middle;
|
|
253
|
+
margin-right: 8px;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
@keyframes spin {
|
|
257
|
+
0% {
|
|
258
|
+
transform: rotate(0deg);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
100% {
|
|
262
|
+
transform: rotate(360deg);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
</style>
|
|
266
|
+
|
|
243
267
|
<script>
|
|
244
268
|
const cashfree = Cashfree({
|
|
245
269
|
mode: "production"
|
|
@@ -255,7 +279,7 @@
|
|
|
255
279
|
return;
|
|
256
280
|
}
|
|
257
281
|
|
|
258
|
-
btn.
|
|
282
|
+
btn.innerHTML = '<span class="loader-spinner"></span> Processing...';
|
|
259
283
|
btn.disabled = true;
|
|
260
284
|
|
|
261
285
|
try {
|
|
@@ -269,10 +293,22 @@
|
|
|
269
293
|
|
|
270
294
|
if (data.payment_session_id) {
|
|
271
295
|
// Redirect to Payment
|
|
296
|
+
const email = document.getElementById('email').value;
|
|
297
|
+
const phone = document.getElementById('phone').value;
|
|
298
|
+
|
|
272
299
|
cashfree.checkout({
|
|
273
|
-
paymentSessionId: data.payment_session_id
|
|
274
|
-
|
|
275
|
-
|
|
300
|
+
paymentSessionId: data.payment_session_id
|
|
301
|
+
}).then(() => {
|
|
302
|
+
console.log("Checkout initiated");
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
cashfree.on("payment.success", (data) => {
|
|
306
|
+
// Pass email/phone to verify route
|
|
307
|
+
window.location.href = `/verify?order_id=${data.orderId}&email=${encodeURIComponent(email)}&phone=${encodeURIComponent(phone)}`;
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
cashfree.on("payment.failed", (data) => {
|
|
311
|
+
alert("Payment Failed: " + data.message);
|
|
276
312
|
});
|
|
277
313
|
} else {
|
|
278
314
|
alert('Error creating order');
|