Skip to content
This repository was archived by the owner on Jul 28, 2026. It is now read-only.

Commit 27a2e0b

Browse files
committed
use suspended_by column instead of faking dates; admin suspend blocks renew, scheduler/renew-now allows it
1 parent 14d0c77 commit 27a2e0b

3 files changed

Lines changed: 10 additions & 9 deletions

File tree

config/migrate.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const tables = {
2626
{ name: 'expires_at', def: 'TIMESTAMP NOT NULL' },
2727
{ name: 'status', def: "ENUM('active', 'suspended', 'expired') DEFAULT 'active'" },
2828
{ name: 'suspend_reason', def: 'TEXT DEFAULT NULL' },
29+
{ name: 'suspended_by', def: "VARCHAR(20) DEFAULT NULL" },
2930
],
3031
},
3132
user_ips: {

routes/admin.js

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,9 @@ router.post('/servers/:id/suspend', authenticateToken, requireAdmin, async (req,
115115
return res.status(400).json({ error: 'Invalid server ID' });
116116
}
117117

118-
const reason = req.body.reason || null;
118+
const reason = req.body.reason || 'Suspended by an Administrator. Please contact support.';
119119
await suspendPteroServer(serverId);
120-
121-
if (reason) {
122-
await query('UPDATE server_meta SET status = ?, suspend_reason = ?, expires_at = ? WHERE ptero_server_id = ?', ['suspended', reason, '2020-01-01 00:00:00', serverId]);
123-
} else {
124-
await query('UPDATE server_meta SET status = ?, suspend_reason = NULL, expires_at = ? WHERE ptero_server_id = ?', ['suspended', '2020-01-01 00:00:00', serverId]);
125-
}
120+
await query('UPDATE server_meta SET status = ?, suspend_reason = ?, suspended_by = ? WHERE ptero_server_id = ?', ['suspended', reason, 'admin', serverId]);
126121

127122
await logActivity(req.user.userId, 'admin_suspend', `Admin suspended server #${serverId}${reason ? ': ' + reason : ''}`, serverId);
128123
res.json({ success: true });
@@ -140,7 +135,7 @@ router.post('/servers/:id/unsuspend', authenticateToken, requireAdmin, async (re
140135
}
141136

142137
await unsuspendPteroServer(serverId);
143-
await query('UPDATE server_meta SET status = ?, suspend_reason = NULL, expires_at = DATE_ADD(NOW(), INTERVAL 90 DAY) WHERE ptero_server_id = ?', ['active', serverId]);
138+
await query('UPDATE server_meta SET status = ?, suspend_reason = NULL, suspended_by = NULL WHERE ptero_server_id = ?', ['active', serverId]);
144139
await logActivity(req.user.userId, 'admin_unsuspend', `Admin unsuspended server #${serverId}`, serverId);
145140
res.json({ success: true });
146141
} catch (err) {
@@ -199,7 +194,7 @@ router.post('/servers/:id/renew-now', authenticateToken, requireAdmin, async (re
199194

200195
await suspendPteroServer(serverId);
201196
await query(
202-
'UPDATE server_meta SET expires_at = DATE_SUB(NOW(), INTERVAL 1 DAY), status = ?, suspend_reason = ? WHERE ptero_server_id = ?',
197+
'UPDATE server_meta SET expires_at = DATE_SUB(NOW(), INTERVAL 1 DAY), status = ?, suspend_reason = ?, suspended_by = NULL WHERE ptero_server_id = ?',
203198
['suspended', 'Expired by admin', serverId]
204199
);
205200

routes/servers.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,11 @@ router.post('/renew/:id', authenticateToken, async (req, res) => {
229229

230230
const row = meta[0];
231231

232+
// Block renewal if suspended by an admin
233+
if (row.suspended_by === 'admin') {
234+
return res.status(403).json({ error: 'Suspended by an Administrator. Please contact support.' });
235+
}
236+
232237
// Verify the server belongs to this user
233238
const servers = await getServersByUser(pteroId);
234239
const owned = servers.find(s => s.id === serverId);

0 commit comments

Comments
 (0)