Skip to content

Commit ee417f2

Browse files
committed
add admin panel (/admin) with login, servers list & detail; admin-cli script; noindex on admin routes
1 parent 3ed7a32 commit ee417f2

11 files changed

Lines changed: 934 additions & 1 deletion

File tree

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/migrate.js

Lines changed: 1 addition & 0 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
],

public/css/style.css

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,4 +1917,152 @@ tbody tr:hover {
19171917
}
19181918
}
19191919

1920+
/* ===== ADMIN PANEL ===== */
1921+
.admin-layout {
1922+
min-height: 100vh;
1923+
display: flex;
1924+
flex-direction: column;
1925+
position: relative;
1926+
}
1927+
1928+
.admin-navbar {
1929+
display: flex;
1930+
align-items: center;
1931+
padding: 0 24px;
1932+
height: 60px;
1933+
background: var(--bg-sidebar);
1934+
border-bottom: 1px solid var(--border);
1935+
position: sticky;
1936+
top: 0;
1937+
z-index: 100;
1938+
gap: 16px;
1939+
}
1940+
1941+
.admin-navbar-left {
1942+
display: flex;
1943+
align-items: center;
1944+
gap: 10px;
1945+
flex-shrink: 0;
1946+
}
1947+
1948+
.admin-navbar-logo {
1949+
width: 28px;
1950+
height: 28px;
1951+
border-radius: 6px;
1952+
}
1953+
1954+
.admin-navbar-brand {
1955+
font-size: 1rem;
1956+
font-weight: 800;
1957+
letter-spacing: -0.02em;
1958+
display: flex;
1959+
align-items: center;
1960+
gap: 6px;
1961+
}
1962+
1963+
.admin-badge {
1964+
font-size: 0.6rem;
1965+
font-weight: 700;
1966+
text-transform: uppercase;
1967+
letter-spacing: 0.08em;
1968+
color: var(--accent-1);
1969+
border: 1px solid var(--accent-1);
1970+
padding: 2px 6px;
1971+
border-radius: 4px;
1972+
}
1973+
1974+
.admin-navbar-center {
1975+
display: flex;
1976+
align-items: center;
1977+
gap: 4px;
1978+
flex: 1;
1979+
justify-content: center;
1980+
}
1981+
1982+
.admin-nav-link {
1983+
display: flex;
1984+
align-items: center;
1985+
gap: 8px;
1986+
padding: 8px 16px;
1987+
border-radius: var(--radius-sm);
1988+
color: var(--text-secondary);
1989+
font-size: 0.88rem;
1990+
font-weight: 500;
1991+
text-decoration: none;
1992+
transition: all var(--transition);
1993+
}
1994+
1995+
.admin-nav-link:hover {
1996+
color: var(--text-primary);
1997+
background: rgba(238, 129, 50, 0.08);
1998+
}
1999+
2000+
.admin-nav-link.active {
2001+
color: var(--accent-1);
2002+
background: rgba(238, 129, 50, 0.12);
2003+
}
2004+
2005+
.admin-navbar-right {
2006+
display: flex;
2007+
align-items: center;
2008+
gap: 12px;
2009+
flex-shrink: 0;
2010+
}
2011+
2012+
.admin-navbar-user {
2013+
font-size: 0.85rem;
2014+
font-weight: 600;
2015+
color: var(--text-primary);
2016+
}
2017+
2018+
.admin-content {
2019+
flex: 1;
2020+
padding: 32px;
2021+
position: relative;
2022+
z-index: 1;
2023+
}
2024+
2025+
.admin-page {
2026+
display: none;
2027+
}
2028+
2029+
.admin-page.active {
2030+
display: block;
2031+
}
2032+
2033+
.admin-layout::before {
2034+
content: '';
2035+
position: fixed;
2036+
inset: 0;
2037+
z-index: 0;
2038+
pointer-events: none;
2039+
background-image:
2040+
linear-gradient(rgba(238, 129, 50, 0.05) 1px, transparent 1px),
2041+
linear-gradient(90deg, rgba(238, 129, 50, 0.05) 1px, transparent 1px);
2042+
background-size: 24px 24px;
2043+
mask-image: radial-gradient(ellipse 90% 80% at 50% 30%, black 30%, transparent 80%);
2044+
-webkit-mask-image: radial-gradient(ellipse 90% 80% at 50% 30%, black 30%, transparent 80%);
2045+
}
2046+
2047+
.admin-content > * {
2048+
position: relative;
2049+
z-index: 1;
2050+
}
2051+
2052+
@media (max-width: 768px) {
2053+
.admin-navbar {
2054+
padding: 0 12px;
2055+
gap: 8px;
2056+
}
2057+
.admin-navbar-brand {
2058+
font-size: 0.85rem;
2059+
}
2060+
.admin-navbar-user {
2061+
display: none;
2062+
}
2063+
.admin-content {
2064+
padding: 20px;
2065+
}
2066+
}
2067+
19202068

public/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
<div id="app"></div>
1717

18-
<script src="/js/app.js"></script>
18+
<script src="/js/app.js"></script>
19+
<script src="/js/admin.js"></script>
1920
</body>
2021
</html>

0 commit comments

Comments
 (0)