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

Commit 6048ef2

Browse files
authored
Merge pull request #4 from ZeroHost-Code/beta
Beta
2 parents aabbad1 + 98cacaf commit 6048ef2

7 files changed

Lines changed: 28 additions & 123 deletions

File tree

config/db.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,4 @@ export async function query(sql, params = []) {
4040
throw lastErr;
4141
}
4242

43-
export async function getConnection() {
44-
return await pool.getConnection();
45-
}
4643

47-
export default pool;

package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,13 @@
99
},
1010
"dependencies": {
1111
"argon2": "^0.41.1",
12-
"better-sqlite3": "^11.7.0",
1312
"cookie-parser": "^1.4.7",
1413
"cors": "^2.8.5",
1514
"dotenv": "^16.4.7",
1615
"express": "^4.21.1",
1716
"express-rate-limit": "^7.4.1",
1817
"helmet": "^8.0.0",
1918
"jsonwebtoken": "^9.0.2",
20-
"mariadb": "^3.4.0",
21-
"uuid": "^11.0.3",
22-
"zod": "^3.24.1"
19+
"mariadb": "^3.4.0"
2320
}
2421
}

public/css/style.css

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,6 @@ html, body {
4747
a { color: var(--accent-3); text-decoration: none; }
4848
a:hover { color: var(--accent-1); }
4949

50-
.gradient-text {
51-
background: linear-gradient(135deg, var(--accent-1), var(--accent-2), var(--accent-cyan));
52-
-webkit-background-clip: text;
53-
background-clip: text;
54-
-webkit-text-fill-color: transparent;
55-
background-size: 200% 200%;
56-
animation: gradientShift 4s ease infinite;
57-
}
58-
59-
@keyframes gradientShift {
60-
0% { background-position: 0% 50%; }
61-
50% { background-position: 100% 50%; }
62-
100% { background-position: 0% 50%; }
63-
}
64-
6550
/* ===== AUTH PAGES ===== */
6651
.auth-page {
6752
min-height: 100vh;
@@ -969,34 +954,6 @@ tbody tr:hover {
969954
transition: width 0.5s ease;
970955
}
971956

972-
/* ===== LOADING SCREEN ===== */
973-
.loading-screen {
974-
display: flex;
975-
align-items: center;
976-
justify-content: center;
977-
min-height: 100vh;
978-
background: var(--bg-primary);
979-
}
980-
981-
.loading-content {
982-
text-align: center;
983-
}
984-
985-
.loading-spinner {
986-
width: 40px;
987-
height: 40px;
988-
border: 3px solid rgba(99, 102, 241, 0.15);
989-
border-top-color: var(--accent-1);
990-
border-radius: 50%;
991-
animation: spin 0.7s linear infinite;
992-
margin: 0 auto 16px;
993-
}
994-
995-
.loading-text {
996-
font-size: 0.95rem;
997-
color: var(--text-secondary);
998-
}
999-
1000957
/* ===== RESPONSIVE ===== */
1001958
.hamburger-toggle {
1002959
display: none;
@@ -1189,26 +1146,6 @@ tbody tr:hover {
11891146
color: var(--accent-orange);
11901147
}
11911148

1192-
.exp-col {
1193-
font-size: 0.82rem;
1194-
display: flex;
1195-
gap: 4px;
1196-
align-items: center;
1197-
}
1198-
1199-
.exp-col.expired {
1200-
color: var(--accent-red);
1201-
}
1202-
1203-
.exp-col.expiring {
1204-
color: var(--accent-orange);
1205-
}
1206-
1207-
.exp-days {
1208-
font-size: 0.75rem;
1209-
opacity: 0.8;
1210-
}
1211-
12121149
/* ===== SERVER DETAIL PAGE ===== */
12131150
.server-detail-grid {
12141151
display: grid;
@@ -1317,20 +1254,6 @@ tbody tr:hover {
13171254
gap: 10px;
13181255
}
13191256

1320-
.input-readonly {
1321-
width: 100%;
1322-
padding: 12px 16px;
1323-
background: var(--bg-secondary);
1324-
border: 1px solid var(--border);
1325-
border-radius: var(--radius-sm);
1326-
color: var(--text-muted);
1327-
font-family: 'Inter', sans-serif;
1328-
font-size: 0.95rem;
1329-
outline: none;
1330-
cursor: default;
1331-
opacity: 0.7;
1332-
}
1333-
13341257
.consent-group input[type="checkbox"] {
13351258
width: 18px;
13361259
height: 18px;
@@ -1352,5 +1275,4 @@ tbody tr:hover {
13521275
text-decoration: underline;
13531276
}
13541277

1355-
/* ===== PRIVACY / LEGAL PAGES ===== */
13561278

public/js/app.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ const state = {
99
serverDetailTab: 'info',
1010
};
1111

12-
function getRgpdConsent() {
13-
return state.rgpdConsent;
14-
}
15-
1612
function setRgpdConsent(preferences) {
1713
state.rgpdConsent = preferences;
1814
localStorage.setItem('zh_rgpd_consent', JSON.stringify(preferences));
@@ -50,8 +46,6 @@ function renderCookieBanner() {
5046
}
5147

5248
function $(sel) { return document.querySelector(sel); }
53-
function $$(sel) { return document.querySelectorAll(sel); }
54-
5549
function md5(s) {
5650
function F(x,y,z) { return (x & y) | (~x & z); }
5751
function G(x,y,z) { return (x & z) | (y & ~z); }
@@ -404,7 +398,7 @@ async function renderDashboard() {
404398
<div style="padding:8px 12px 0;display:flex;gap:16px;justify-content:center;flex-wrap:wrap">
405399
406400
</div>
407-
<div style="padding:4px 0 8px;text-align:center;font-size:0.7rem;color:var(--text-muted);letter-spacing:0.05em">v0.9.5 BETA</div>
401+
<div style="padding:4px 0 8px;text-align:center;font-size:0.7rem;color:var(--text-muted);letter-spacing:0.05em">v0.9.6 BETA</div>
408402
</div>
409403
</aside>
410404

routes/auth.js

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
import { Router } from 'express';
22
import jwt from 'jsonwebtoken';
33
import argon2 from 'argon2';
4-
import { randomBytes } from 'crypto';
54
import { query } from '../config/db.js';
6-
import { generateToken } from '../middleware/auth.js';
7-
import { createPteroUser, getPteroUserByEmail, updatePteroPassword, updatePteroEmail, deletePteroUser, getServersByUser, deletePteroServer } from '../services/pterodactyl.js';
8-
import { authenticateToken } from '../middleware/auth.js';
5+
import { generateToken, authenticateToken } from '../middleware/auth.js';
6+
import { createPteroUser, updatePteroPassword, updatePteroEmail, deletePteroUser, getServersByUser, deletePteroServer } from '../services/pterodactyl.js';
7+
import { verifyTurnstile } from '../config/turnstile.js';
98

109
const router = Router();
1110

12-
import { verifyTurnstile } from '../config/turnstile.js';
13-
import { v4 as uuidv4 } from 'uuid';
14-
1511
function getClientIp(req) {
1612
const forwarded = req.headers['x-forwarded-for'];
1713
if (forwarded) return forwarded.split(',')[0].trim();
@@ -344,13 +340,14 @@ router.post('/change-email', authenticateToken, async (req, res) => {
344340
router.post('/delete-account', authenticateToken, async (req, res) => {
345341
try {
346342
const { password } = req.body;
343+
const userId = req.user?.userId;
347344
const pteroId = req.user?.pteroId;
348345

349346
if (!password) {
350347
return res.status(400).json({ error: 'Password is required' });
351348
}
352349

353-
const users = await query('SELECT * FROM users WHERE ptero_user_id = ?', [pteroId]);
350+
const users = await query('SELECT * FROM users WHERE id = ?', [userId]);
354351
if (users.length === 0) {
355352
return res.status(404).json({ error: 'User not found' });
356353
}
@@ -362,30 +359,31 @@ router.post('/delete-account', authenticateToken, async (req, res) => {
362359
return res.status(401).json({ error: 'Password is incorrect' });
363360
}
364361

365-
// Delete all Pterodactyl servers first
366-
try {
367-
const servers = await getServersByUser(pteroId);
368-
for (const server of servers) {
369-
try {
370-
await deletePteroServer(server.id);
371-
} catch (err) {
372-
console.error(`Failed to delete server ${server.id}:`, err.message);
362+
// Delete from local DB first (cascades to user_ips)
363+
await query('DELETE FROM users WHERE id = ?', [user.id]);
364+
365+
// Then try to clean up Pterodactyl (best effort)
366+
if (pteroId) {
367+
try {
368+
const servers = await getServersByUser(pteroId);
369+
for (const server of servers) {
370+
try {
371+
await deletePteroServer(server.id);
372+
} catch (err) {
373+
console.error(`Failed to delete server ${server.id}:`, err.message);
374+
}
373375
}
376+
} catch (err) {
377+
console.error('Failed to fetch servers for deletion:', err.message);
374378
}
375-
} catch (err) {
376-
console.error('Failed to fetch servers for deletion:', err.message);
377-
}
378379

379-
// Delete Pterodactyl user
380-
try {
381-
await deletePteroUser(pteroId);
382-
} catch (err) {
383-
console.error('Failed to delete Pterodactyl user:', err.message);
380+
try {
381+
await deletePteroUser(pteroId);
382+
} catch (err) {
383+
console.error('Failed to delete Pterodactyl user:', err.message);
384+
}
384385
}
385386

386-
// Delete from local DB (cascades to user_ips)
387-
await query('DELETE FROM users WHERE id = ?', [user.id]);
388-
389387
res.json({ message: 'Account deleted successfully' });
390388
} catch (err) {
391389
console.error('Delete account error:', err.message);

routes/servers.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ import {
77
deletePteroServer,
88
reinstallPteroServer,
99
renamePteroServer,
10-
suspendPteroServer,
1110
unsuspendPteroServer,
1211
getEgg,
1312
getAllEggs,
14-
getPteroUserById,
1513
} from '../services/pterodactyl.js';
1614
import { query } from '../config/db.js';
1715
import { verifyTurnstile } from '../config/turnstile.js';

services/pterodactyl.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export async function createPteroUser({ email, username, firstName, lastName, pa
5151
return data.attributes;
5252
}
5353

54-
export async function getPteroUserByEmail(email) {
54+
async function getPteroUserByEmail(email) {
5555
const data = await pteroFetch(`/users?filter[email]=${encodeURIComponent(email)}`);
5656
if (data.data.length > 0) {
5757
return data.data[0].attributes;

0 commit comments

Comments
 (0)