Skip to content

Commit e746ff7

Browse files
authored
Merge pull request #8 from ZeroHost-Code/beta
Beta
2 parents 65ca41c + e190426 commit e746ff7

21 files changed

Lines changed: 1840 additions & 141 deletions

File tree

.env.example

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ DB_NAME=zerohost_dashboard
1717
PTERO_URL=https://panel.your-domain.com
1818
PTERO_API_KEY=change_me
1919

20-
# Encryption key for sensitive data — Generate with: openssl rand -hex 32
21-
ENCRYPTION_KEY=change_me_to_a_random_hex_string
20+
# Panel database name (for egg variable lookup)
21+
PANEL_DB_NAME=panel
2222

2323
# Cap CAPTCHA (self-hosted alternative to Turnstile)
2424
CAP_ENDPOINT=https://cap.zero-host.org/f6c8171b08/

.github/workflows/deploy-beta.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ jobs:
1818
script: |
1919
cd ${{ secrets.BETA_PATH }}
2020
cp .env /tmp/beta.env 2>/dev/null; cp port.txt /tmp/beta.port.txt 2>/dev/null
21-
git fetch origin
22-
git reset --hard origin/beta
23-
git checkout -B beta
21+
git fetch origin --prune
22+
git checkout beta
23+
git merge --ff-only origin/beta
2424
cp /tmp/beta.env .env 2>/dev/null; cp /tmp/beta.port.txt port.txt 2>/dev/null
2525
grep 'discord.zero-host.org' public/js/app.js || echo "⚠ DISCORD LINK NOT FOUND IN FILE"
2626
head -20 port.txt 2>/dev/null || echo "⚠ port.txt missing or empty"

.github/workflows/deploy-main.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ jobs:
1818
script: |
1919
cd ${{ secrets.MAIN_PATH }}
2020
cp .env /tmp/main.env 2>/dev/null; cp port.txt /tmp/main.port.txt 2>/dev/null
21-
git fetch origin
22-
git reset --hard origin/main
23-
git checkout -B main
21+
git fetch origin --prune
22+
git checkout main
23+
git merge --ff-only origin/main
2424
cp /tmp/main.env .env 2>/dev/null; cp /tmp/main.port.txt port.txt 2>/dev/null
2525
npm install
2626
pm2 restart zerohost-dashboard

admin.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
# ZeroHost Dashboard - Admin Account Management
3+
#
4+
# Usage:
5+
# ./admin.sh create <email> <username> <password>
6+
# Create a new admin account
7+
#
8+
# ./admin.sh set-admin <email>
9+
# Set an existing user as admin by email
10+
#
11+
# ./admin.sh set-admin-by-username <username>
12+
# Set an existing user as admin by username
13+
#
14+
# ./admin.sh list
15+
# List all admin users
16+
#
17+
# ./admin.sh remove-admin <email>
18+
# Remove admin privileges from a user
19+
20+
cd "$(dirname "$0")"
21+
node scripts/admin-cli.js "$@"

config/cap.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,26 @@ async function fetchWithTimeout(url, options = {}, timeout = 10000) {
1919
}
2020
}
2121

22+
function normalizeUrl(base) {
23+
return base.endsWith('/') ? base : base + '/';
24+
}
25+
2226
export async function verifyCap(token) {
2327
if (!token) return false;
28+
const url = `${normalizeUrl(CAP_ENDPOINT)}siteverify`;
2429
try {
25-
const res = await fetchWithTimeout(`${CAP_ENDPOINT}siteverify`, {
30+
const res = await fetchWithTimeout(url, {
2631
method: 'POST',
2732
headers: { 'Content-Type': 'application/json' },
2833
body: JSON.stringify({ secret: CAP_SECRET, response: token }),
2934
});
3035
const data = await res.json();
36+
if (data.success !== true) {
37+
console.error('[CAP] Verification failed:', JSON.stringify(data));
38+
}
3139
return data.success === true;
32-
} catch {
40+
} catch (err) {
41+
console.error('[CAP] Service unreachable at', url, ':', err.message);
3342
return false;
3443
}
3544
}

config/db.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ const pool = mariadb.createPool({
1313
password: process.env.DB_PASSWORD,
1414
database: process.env.DB_NAME,
1515
connectionLimit: 10,
16+
connectTimeout: 5000,
1617
acquireTimeout: 10000,
18+
idleTimeout: 30000,
1719
insertIdAsNumber: true,
1820
});
1921

config/migrate.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const tables = {
1212
{ name: 'first_name', def: 'VARCHAR(255)' },
1313
{ name: 'last_name', def: 'VARCHAR(255)' },
1414
{ name: 'password_set', def: 'TINYINT(1) NOT NULL DEFAULT 0' },
15+
{ name: 'is_admin', def: 'TINYINT(1) NOT NULL DEFAULT 0' },
1516
{ name: 'ptero_client_api_key', def: 'VARCHAR(255) DEFAULT NULL' },
1617
{ name: 'created_at', def: 'TIMESTAMP DEFAULT CURRENT_TIMESTAMP' },
1718
],
@@ -24,6 +25,8 @@ const tables = {
2425
{ name: 'created_at', def: 'TIMESTAMP DEFAULT CURRENT_TIMESTAMP' },
2526
{ name: 'expires_at', def: 'TIMESTAMP NOT NULL' },
2627
{ name: 'status', def: "ENUM('active', 'suspended', 'expired') DEFAULT 'active'" },
28+
{ name: 'suspend_reason', def: 'TEXT DEFAULT NULL' },
29+
{ name: 'suspended_by', def: "VARCHAR(20) DEFAULT NULL" },
2730
],
2831
},
2932
user_ips: {
@@ -99,8 +102,10 @@ export async function migrate() {
99102
try {
100103
await query(c.sql);
101104
console.log(`Applied constraint: ${c.name}`);
102-
} catch {
103-
// Constraint already exists or table missing — safe to ignore
105+
} catch (err) {
106+
if (process.env.NODE_ENV !== 'production') {
107+
console.log(`Skipped constraint ${c.name}: ${err.message}`);
108+
}
104109
}
105110
}
106111
}

config/pyrodactyl.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export const PTERO_URL = process.env.PTERO_URL || 'https://panel.zero-host.org';
22
export const PTERO_API_KEY = process.env.PTERO_API_KEY || '';
3+
export const PANEL_DB_NAME = process.env.PANEL_DB_NAME || 'panel';
34

45
export const SERVER_LIMITS = {
56
memory: 512,

middleware/auth.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ const JWT_SECRET = process.env.JWT_SECRET;
44

55
if (!JWT_SECRET) {
66
console.error('Missing JWT_SECRET environment variable');
7+
} else if (/[\$\(\)]/.test(JWT_SECRET)) {
8+
console.error('JWT_SECRET contains unresolved shell expansion characters ($(), backticks). Generate a proper random key (e.g. openssl rand -hex 32) and hardcode it in .env');
79
}
810

911
export function authenticateToken(req, res, next) {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "zerohost-dashboard",
3-
"version": "0.9.9",
3+
"version": "1.0.0",
44
"private": true,
55
"type": "module",
66
"scripts": {

0 commit comments

Comments
 (0)