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

Commit 24fda98

Browse files
committed
feat: add auth_restriction separate from user restriction
1 parent 0f4b98f commit 24fda98

4 files changed

Lines changed: 49 additions & 4 deletions

File tree

config/migrate.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const tables = {
1414
{ name: 'password_set', def: 'TINYINT(1) NOT NULL DEFAULT 0' },
1515
{ name: 'is_admin', def: 'TINYINT(1) NOT NULL DEFAULT 0' },
1616
{ name: 'restricted', def: 'TINYINT(1) NOT NULL DEFAULT 0' },
17+
{ name: 'auth_restricted', def: 'TINYINT(1) NOT NULL DEFAULT 0' },
1718
{ name: 'avatar', def: 'VARCHAR(255) DEFAULT NULL' },
1819
{ name: 'ptero_client_api_key', def: 'VARCHAR(255) DEFAULT NULL' },
1920
{ name: 'created_at', def: 'TIMESTAMP DEFAULT CURRENT_TIMESTAMP' },

public/js/admin.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,7 @@ async function renderAdminUserDetail(userId) {
858858
<div class="detail-item"><span class="detail-label">Username</span><span class="detail-value">${u.username}</span></div>
859859
<div class="detail-item"><span class="detail-label">Email</span><span class="detail-value">${u.email}</span></div>
860860
<div class="detail-item"><span class="detail-label">Role</span><span class="detail-value">${u.is_admin ? '<span class="server-card-status status-active" style="font-size:0.75rem">Admin</span>' : '<span class="server-card-status status-installing" style="font-size:0.75rem">User</span>'}</span></div>
861-
<div class="detail-item"><span class="detail-label">Status</span><span class="detail-value">${u.restricted ? '<span class="server-card-status status-suspended" style="font-size:0.75rem">Restricted</span>' : '<span class="server-card-status status-active" style="font-size:0.75rem">Active</span>'}</span></div>
861+
<div class="detail-item"><span class="detail-label">Status</span><span class="detail-value">${u.restricted ? '<span class="server-card-status status-suspended" style="font-size:0.75rem">Restricted</span>' : '<span class="server-card-status status-active" style="font-size:0.75rem">Active</span>'} ${u.auth_restricted ? '<span class="server-card-status status-suspended" style="font-size:0.75rem">Auth Restricted</span>' : ''}</span></div>
862862
<div class="detail-item"><span class="detail-label">Ptero ID</span><span class="detail-value" style="font-family:monospace">${u.ptero_user_id || 'N/A'}</span></div>
863863
<div class="detail-item"><span class="detail-label">API Key Set</span><span class="detail-value">${u.ptero_client_api_key ? 'Yes' : 'No'}</span></div>
864864
<div class="detail-item"><span class="detail-label">Created</span><span class="detail-value">${formatDateWithTooltip(u.created_at)}</span></div>
@@ -916,6 +916,7 @@ async function renderAdminUserDetail(userId) {
916916
<div style="display:flex;gap:8px;flex-wrap:wrap">
917917
<button class="btn ${u.is_admin ? 'btn-warning' : 'btn-primary'}" id="admin-btn-toggle-admin" style="width:auto">${u.is_admin ? 'Remove Admin' : 'Make Admin'}</button>
918918
<button class="btn ${u.restricted ? 'btn-primary' : 'btn-warning'}" id="admin-btn-toggle-restriction" style="width:auto">${u.restricted ? 'Unrestrict User' : 'Restrict User'}</button>
919+
<button class="btn ${u.auth_restricted ? 'btn-primary' : 'btn-warning'}" id="admin-btn-toggle-auth-restriction" style="width:auto">${u.auth_restricted ? 'Unrestrict Auth' : 'Restrict Auth'}</button>
919920
<button class="btn btn-danger" id="admin-btn-delete-user" style="width:auto">Delete User</button>
920921
</div>
921922
<div id="admin-user-action-msg" style="margin-top:12px;display:none"></div>
@@ -980,6 +981,22 @@ function initUserActions(userId) {
980981
}
981982
});
982983

984+
$a('#admin-btn-toggle-auth-restriction')?.addEventListener('click', async () => {
985+
const btn = $a('#admin-btn-toggle-auth-restriction');
986+
btn.disabled = true;
987+
btn.innerHTML = '<span class="spinner"></span> Updating...';
988+
clearMsg();
989+
try {
990+
const data = await adminApi(`/users/${userId}/toggle-auth-restriction`, { method: 'POST' });
991+
showMsg(data.auth_restricted ? 'Auth restricted' : 'Auth unrestricted');
992+
setTimeout(() => renderAdminUserDetail(userId), 1500);
993+
} catch (err) {
994+
showMsg(err.message, 'error');
995+
btn.disabled = false;
996+
btn.innerHTML = 'Toggle Auth Restriction';
997+
}
998+
});
999+
9831000
$a('#admin-btn-delete-user')?.addEventListener('click', async () => {
9841001
if (!confirm('Are you sure you want to permanently delete this user? All their servers will be deleted. This action cannot be undone.')) return;
9851002
const btn = $a('#admin-btn-delete-user');

routes/admin.js

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ router.post('/login', async (req, res) => {
3636
}
3737

3838
const user = users[0];
39-
if (user.restricted) {
39+
if (user.auth_restricted) {
4040
return res.status(403).json({ error: 'Your account has been restricted. Contact support for assistance.' });
4141
}
4242
if (!user.is_admin) {
@@ -266,7 +266,7 @@ router.get('/users/:id', authenticateToken, requireAdmin, async (req, res) => {
266266
}
267267

268268
const users = await query(
269-
'SELECT id, email, username, is_admin, restricted, ptero_user_id, ptero_client_api_key, created_at FROM users WHERE id = ?',
269+
'SELECT id, email, username, is_admin, restricted, auth_restricted, ptero_user_id, ptero_client_api_key, created_at FROM users WHERE id = ?',
270270
[userId]
271271
);
272272
if (users.length === 0) {
@@ -331,6 +331,33 @@ router.post('/users/:id/toggle-restriction', authenticateToken, requireAdmin, as
331331
}
332332
});
333333

334+
router.post('/users/:id/toggle-auth-restriction', authenticateToken, requireAdmin, async (req, res) => {
335+
try {
336+
const userId = parseInt(req.params.id, 10);
337+
if (isNaN(userId)) {
338+
return res.status(400).json({ error: 'Invalid user ID' });
339+
}
340+
341+
if (userId === req.user.userId) {
342+
return res.status(400).json({ error: 'You cannot restrict your own auth' });
343+
}
344+
345+
const users = await query('SELECT auth_restricted FROM users WHERE id = ?', [userId]);
346+
if (users.length === 0) {
347+
return res.status(404).json({ error: 'User not found' });
348+
}
349+
350+
const newStatus = users[0].auth_restricted ? 0 : 1;
351+
await query('UPDATE users SET auth_restricted = ? WHERE id = ?', [newStatus, userId]);
352+
353+
await logActivity(req.user.userId, 'admin_toggle_auth_restriction', `${newStatus ? 'Auth restricted' : 'Auth unrestricted'} user #${userId}`);
354+
res.json({ success: true, auth_restricted: !!newStatus });
355+
} catch (err) {
356+
console.error('Admin toggle-auth-restriction error:', err.message);
357+
res.status(500).json({ error: 'Failed to toggle auth restriction status' });
358+
}
359+
});
360+
334361
router.post('/users/:id/toggle-admin', authenticateToken, requireAdmin, async (req, res) => {
335362
try {
336363
const userId = parseInt(req.params.id, 10);

routes/auth.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ router.post('/login', async (req, res) => {
198198

199199
if (process.env.NODE_ENV !== 'production') console.log('[LOGIN] User found:', { id: user.id, email: user.email });
200200

201-
if (user.restricted) {
201+
if (user.auth_restricted) {
202202
return res.status(403).json({ error: 'Your account has been restricted. Contact support for assistance.' });
203203
}
204204

0 commit comments

Comments
 (0)