From 92d08d7b79b9dd6c6e247d20abe5e1165ed082dd Mon Sep 17 00:00:00 2001 From: NixReaper Date: Sun, 5 Apr 2026 10:54:15 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20rename=20WHM=E2=86=92NixServer,=20cPane?= =?UTF-8?q?l=E2=86=92NixClient,=20bump=20v0.2.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename frontend workspaces: whm/ → nixserver/, cpanel/ → nixclient/ - Rename server route dirs: routes/whm/ → routes/nixserver/, routes/cpanel/ → routes/nixclient/ - Update all API prefixes: /api/whm → /api/nixserver, /api/cpanel → /api/nixclient - Rename env vars: WHM_PORT → NIXSERVER_PORT, CPANEL_PORT → NIXCLIENT_PORT - Update config properties: whmPort → nixserverPort, cpanelPort → nixclientPort - Update all UI labels, login pages, sidebar branding, and error messages - Update installer and update scripts to match new names - Add cpanel email route (missing from initial scaffold) - Add .gitattributes to enforce LF line endings - Bump version to 0.2.0 across all package.json files --- .env.example | 4 +-- .gitattributes | 9 +++++ {cpanel => nixclient}/index.html | 0 {cpanel => nixclient}/package.json | 2 +- {cpanel => nixclient}/postcss.config.js | 0 {cpanel => nixclient}/src/App.tsx | 0 {cpanel => nixclient}/src/api/client.ts | 0 .../src/components/Layout.tsx | 2 +- .../src/contexts/AuthContext.tsx | 2 +- {cpanel => nixclient}/src/index.css | 0 {cpanel => nixclient}/src/main.tsx | 0 {cpanel => nixclient}/src/pages/CronJobs.tsx | 8 ++--- {cpanel => nixclient}/src/pages/Databases.tsx | 10 +++--- {cpanel => nixclient}/src/pages/Domains.tsx | 14 ++++---- {cpanel => nixclient}/src/pages/Email.tsx | 10 +++--- {cpanel => nixclient}/src/pages/FTP.tsx | 6 ++-- .../src/pages/FileManager.tsx | 10 +++--- {cpanel => nixclient}/src/pages/Login.tsx | 4 +-- {cpanel => nixclient}/src/pages/Overview.tsx | 2 +- {cpanel => nixclient}/src/pages/SSL.tsx | 4 +-- {cpanel => nixclient}/src/pages/Stats.tsx | 2 +- {cpanel => nixclient}/tailwind.config.js | 0 {cpanel => nixclient}/tsconfig.json | 0 {cpanel => nixclient}/tsconfig.node.json | 0 {cpanel => nixclient}/vite.config.ts | 0 {whm => nixserver}/index.html | 0 {whm => nixserver}/package.json | 2 +- {whm => nixserver}/postcss.config.js | 0 {whm => nixserver}/src/App.tsx | 0 {whm => nixserver}/src/api/client.ts | 0 {whm => nixserver}/src/components/Layout.tsx | 4 +-- .../src/contexts/AuthContext.tsx | 2 +- {whm => nixserver}/src/index.css | 0 {whm => nixserver}/src/main.tsx | 0 {whm => nixserver}/src/pages/Accounts.tsx | 8 ++--- {whm => nixserver}/src/pages/Backup.tsx | 8 ++--- .../src/pages/CreateAccount.tsx | 6 ++-- {whm => nixserver}/src/pages/DNS.tsx | 8 ++--- {whm => nixserver}/src/pages/Dashboard.tsx | 4 +-- {whm => nixserver}/src/pages/Email.tsx | 6 ++-- {whm => nixserver}/src/pages/Login.tsx | 4 +-- {whm => nixserver}/src/pages/PHP.tsx | 4 +-- {whm => nixserver}/src/pages/Packages.tsx | 8 ++--- {whm => nixserver}/src/pages/Resellers.tsx | 10 +++--- {whm => nixserver}/src/pages/SSL.tsx | 8 ++--- {whm => nixserver}/src/pages/Security.tsx | 10 +++--- {whm => nixserver}/src/pages/Services.tsx | 4 +-- {whm => nixserver}/src/pages/Settings.tsx | 4 +-- {whm => nixserver}/src/pages/System.tsx | 4 +-- {whm => nixserver}/src/pages/WebServer.tsx | 10 +++--- {whm => nixserver}/tailwind.config.js | 0 {whm => nixserver}/tsconfig.json | 0 {whm => nixserver}/tsconfig.node.json | 0 {whm => nixserver}/vite.config.ts | 0 package.json | 14 ++++---- scripts/install.sh | 36 +++++++++---------- scripts/update.sh | 4 +-- server/package.json | 2 +- server/src/app.ts | 16 ++++----- server/src/config.ts | 4 +-- server/src/core/dns.ts | 2 +- server/src/index.ts | 8 ++--- server/src/routes/auth/index.ts | 4 +-- .../src/routes/{cpanel => nixclient}/cron.ts | 0 .../routes/{cpanel => nixclient}/databases.ts | 10 +++--- .../routes/{cpanel => nixclient}/domains.ts | 0 .../src/routes/{cpanel => nixclient}/email.ts | 12 +++---- .../src/routes/{cpanel => nixclient}/files.ts | 32 ++++++++--------- .../src/routes/{cpanel => nixclient}/ftp.ts | 0 .../src/routes/{cpanel => nixclient}/index.ts | 2 +- .../src/routes/{cpanel => nixclient}/stats.ts | 4 +-- .../src/routes/{whm => nixserver}/accounts.ts | 18 +++++----- .../src/routes/{whm => nixserver}/backup.ts | 10 +++--- server/src/routes/{whm => nixserver}/dns.ts | 12 +++---- server/src/routes/{whm => nixserver}/email.ts | 14 ++++---- server/src/routes/{whm => nixserver}/index.ts | 2 +- .../src/routes/{whm => nixserver}/packages.ts | 0 server/src/routes/{whm => nixserver}/php.ts | 8 ++--- .../routes/{whm => nixserver}/resellers.ts | 0 .../src/routes/{whm => nixserver}/security.ts | 20 +++++------ .../src/routes/{whm => nixserver}/services.ts | 6 ++-- server/src/routes/{whm => nixserver}/ssl.ts | 8 ++--- .../src/routes/{whm => nixserver}/system.ts | 14 ++++---- .../routes/{whm => nixserver}/webserver.ts | 12 +++---- 84 files changed, 243 insertions(+), 234 deletions(-) create mode 100644 .gitattributes rename {cpanel => nixclient}/index.html (100%) rename {cpanel => nixclient}/package.json (96%) rename {cpanel => nixclient}/postcss.config.js (100%) rename {cpanel => nixclient}/src/App.tsx (100%) rename {cpanel => nixclient}/src/api/client.ts (100%) rename {cpanel => nixclient}/src/components/Layout.tsx (99%) rename {cpanel => nixclient}/src/contexts/AuthContext.tsx (95%) rename {cpanel => nixclient}/src/index.css (100%) rename {cpanel => nixclient}/src/main.tsx (100%) rename {cpanel => nixclient}/src/pages/CronJobs.tsx (94%) rename {cpanel => nixclient}/src/pages/Databases.tsx (94%) rename {cpanel => nixclient}/src/pages/Domains.tsx (90%) rename {cpanel => nixclient}/src/pages/Email.tsx (95%) rename {cpanel => nixclient}/src/pages/FTP.tsx (95%) rename {cpanel => nixclient}/src/pages/FileManager.tsx (95%) rename {cpanel => nixclient}/src/pages/Login.tsx (96%) rename {cpanel => nixclient}/src/pages/Overview.tsx (98%) rename {cpanel => nixclient}/src/pages/SSL.tsx (96%) rename {cpanel => nixclient}/src/pages/Stats.tsx (97%) rename {cpanel => nixclient}/tailwind.config.js (100%) rename {cpanel => nixclient}/tsconfig.json (100%) rename {cpanel => nixclient}/tsconfig.node.json (100%) rename {cpanel => nixclient}/vite.config.ts (100%) rename {whm => nixserver}/index.html (100%) rename {whm => nixserver}/package.json (96%) rename {whm => nixserver}/postcss.config.js (100%) rename {whm => nixserver}/src/App.tsx (100%) rename {whm => nixserver}/src/api/client.ts (100%) rename {whm => nixserver}/src/components/Layout.tsx (97%) rename {whm => nixserver}/src/contexts/AuthContext.tsx (95%) rename {whm => nixserver}/src/index.css (100%) rename {whm => nixserver}/src/main.tsx (100%) rename {whm => nixserver}/src/pages/Accounts.tsx (96%) rename {whm => nixserver}/src/pages/Backup.tsx (93%) rename {whm => nixserver}/src/pages/CreateAccount.tsx (93%) rename {whm => nixserver}/src/pages/DNS.tsx (94%) rename {whm => nixserver}/src/pages/Dashboard.tsx (97%) rename {whm => nixserver}/src/pages/Email.tsx (95%) rename {whm => nixserver}/src/pages/Login.tsx (96%) rename {whm => nixserver}/src/pages/PHP.tsx (95%) rename {whm => nixserver}/src/pages/Packages.tsx (96%) rename {whm => nixserver}/src/pages/Resellers.tsx (94%) rename {whm => nixserver}/src/pages/SSL.tsx (95%) rename {whm => nixserver}/src/pages/Security.tsx (93%) rename {whm => nixserver}/src/pages/Services.tsx (96%) rename {whm => nixserver}/src/pages/Settings.tsx (90%) rename {whm => nixserver}/src/pages/System.tsx (96%) rename {whm => nixserver}/src/pages/WebServer.tsx (92%) rename {whm => nixserver}/tailwind.config.js (100%) rename {whm => nixserver}/tsconfig.json (100%) rename {whm => nixserver}/tsconfig.node.json (100%) rename {whm => nixserver}/vite.config.ts (100%) rename server/src/routes/{cpanel => nixclient}/cron.ts (100%) rename server/src/routes/{cpanel => nixclient}/databases.ts (96%) rename server/src/routes/{cpanel => nixclient}/domains.ts (100%) rename server/src/routes/{cpanel => nixclient}/email.ts (95%) rename server/src/routes/{cpanel => nixclient}/files.ts (92%) rename server/src/routes/{cpanel => nixclient}/ftp.ts (100%) rename server/src/routes/{cpanel => nixclient}/index.ts (90%) rename server/src/routes/{cpanel => nixclient}/stats.ts (94%) rename server/src/routes/{whm => nixserver}/accounts.ts (97%) rename server/src/routes/{whm => nixserver}/backup.ts (93%) rename server/src/routes/{whm => nixserver}/dns.ts (95%) rename server/src/routes/{whm => nixserver}/email.ts (94%) rename server/src/routes/{whm => nixserver}/index.ts (94%) rename server/src/routes/{whm => nixserver}/packages.ts (100%) rename server/src/routes/{whm => nixserver}/php.ts (93%) rename server/src/routes/{whm => nixserver}/resellers.ts (100%) rename server/src/routes/{whm => nixserver}/security.ts (90%) rename server/src/routes/{whm => nixserver}/services.ts (90%) rename server/src/routes/{whm => nixserver}/ssl.ts (96%) rename server/src/routes/{whm => nixserver}/system.ts (93%) rename server/src/routes/{whm => nixserver}/webserver.ts (90%) diff --git a/.env.example b/.env.example index ce39a6e..5f3279e 100644 --- a/.env.example +++ b/.env.example @@ -9,8 +9,8 @@ JWT_REFRESH_EXPIRES_IN="7d" # Server NODE_ENV="production" -WHM_PORT=2087 -CPANEL_PORT=2083 +NIXSERVER_PORT=2087 +NIXCLIENT_PORT=2083 HOST="0.0.0.0" # Admin diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3b456c9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +# Default — normalize to LF on commit +* text=auto eol=lf + +# Shell scripts must always be LF +*.sh text eol=lf + +# Windows-only files (if any) +*.bat text eol=crlf +*.cmd text eol=crlf diff --git a/cpanel/index.html b/nixclient/index.html similarity index 100% rename from cpanel/index.html rename to nixclient/index.html diff --git a/cpanel/package.json b/nixclient/package.json similarity index 96% rename from cpanel/package.json rename to nixclient/package.json index cdc56a6..2693ddf 100644 --- a/cpanel/package.json +++ b/nixclient/package.json @@ -1,6 +1,6 @@ { "name": "@nixpanel/cpanel", - "version": "0.1.0", + "version": "0.2.0", "private": true, "type": "module", "scripts": { diff --git a/cpanel/postcss.config.js b/nixclient/postcss.config.js similarity index 100% rename from cpanel/postcss.config.js rename to nixclient/postcss.config.js diff --git a/cpanel/src/App.tsx b/nixclient/src/App.tsx similarity index 100% rename from cpanel/src/App.tsx rename to nixclient/src/App.tsx diff --git a/cpanel/src/api/client.ts b/nixclient/src/api/client.ts similarity index 100% rename from cpanel/src/api/client.ts rename to nixclient/src/api/client.ts diff --git a/cpanel/src/components/Layout.tsx b/nixclient/src/components/Layout.tsx similarity index 99% rename from cpanel/src/components/Layout.tsx rename to nixclient/src/components/Layout.tsx index db6a9ee..b77c91f 100644 --- a/cpanel/src/components/Layout.tsx +++ b/nixclient/src/components/Layout.tsx @@ -34,7 +34,7 @@ export default function Layout() { {sidebarOpen && (
-

NixPanel

+

NixClient

{user?.domain}

)} diff --git a/cpanel/src/contexts/AuthContext.tsx b/nixclient/src/contexts/AuthContext.tsx similarity index 95% rename from cpanel/src/contexts/AuthContext.tsx rename to nixclient/src/contexts/AuthContext.tsx index 519bc57..622a27c 100644 --- a/cpanel/src/contexts/AuthContext.tsx +++ b/nixclient/src/contexts/AuthContext.tsx @@ -40,7 +40,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const login = async (username: string, password: string) => { const { data } = await api.post('/auth/login', { username, password }) - if (data.data.role !== 'user') throw new Error('Use WHM to log in as admin or reseller') + if (data.data.role !== 'user') throw new Error('Use NixServer to log in as admin or reseller') localStorage.setItem('access_token', data.data.accessToken) localStorage.setItem('refresh_token', data.data.refreshToken) setUser(data.data.user) diff --git a/cpanel/src/index.css b/nixclient/src/index.css similarity index 100% rename from cpanel/src/index.css rename to nixclient/src/index.css diff --git a/cpanel/src/main.tsx b/nixclient/src/main.tsx similarity index 100% rename from cpanel/src/main.tsx rename to nixclient/src/main.tsx diff --git a/cpanel/src/pages/CronJobs.tsx b/nixclient/src/pages/CronJobs.tsx similarity index 94% rename from cpanel/src/pages/CronJobs.tsx rename to nixclient/src/pages/CronJobs.tsx index c281024..7ff736e 100644 --- a/cpanel/src/pages/CronJobs.tsx +++ b/nixclient/src/pages/CronJobs.tsx @@ -22,7 +22,7 @@ export default function CronJobs() { const fetch = async () => { setLoading(true) - try { const r = await api.get('/cpanel/cron'); setJobs(r.data.data) } + try { const r = await api.get('/nixclient/cron'); setJobs(r.data.data) } finally { setLoading(false) } } @@ -30,18 +30,18 @@ export default function CronJobs() { const save = async (e: React.FormEvent) => { e.preventDefault(); setSaving(true); setError('') - try { await api.post('/cpanel/cron', form); setShowModal(false); setForm({ schedule: '0 * * * *', command: '', comment: '', enabled: true }); fetch() } + try { await api.post('/nixclient/cron', form); setShowModal(false); setForm({ schedule: '0 * * * *', command: '', comment: '', enabled: true }); fetch() } catch (err: unknown) { setError((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } finally { setSaving(false) } } const del = async (id: number) => { if (!confirm('Delete this cron job?')) return - try { await api.delete(`/cpanel/cron/${id}`); fetch() } catch {} + try { await api.delete(`/nixclient/cron/${id}`); fetch() } catch {} } const toggle = async (job: CronJob) => { - try { await api.put(`/cpanel/cron/${job.id}`, { enabled: !job.enabled }); fetch() } catch {} + try { await api.put(`/nixclient/cron/${job.id}`, { enabled: !job.enabled }); fetch() } catch {} } return ( diff --git a/cpanel/src/pages/Databases.tsx b/nixclient/src/pages/Databases.tsx similarity index 94% rename from cpanel/src/pages/Databases.tsx rename to nixclient/src/pages/Databases.tsx index 446065a..5cc6ca5 100644 --- a/cpanel/src/pages/Databases.tsx +++ b/nixclient/src/pages/Databases.tsx @@ -18,7 +18,7 @@ export default function Databases() { const fetch = async () => { setLoading(true) - try { const r = await api.get('/cpanel/databases'); setDbs(r.data.data) } + try { const r = await api.get('/nixclient/databases'); setDbs(r.data.data) } finally { setLoading(false) } } @@ -26,27 +26,27 @@ export default function Databases() { const createDb = async (e: React.FormEvent) => { e.preventDefault(); setSaving(true); setError('') - try { await api.post('/cpanel/databases', dbForm); setShowDbModal(false); setDbForm({ name: '' }); fetch() } + try { await api.post('/nixclient/databases', dbForm); setShowDbModal(false); setDbForm({ name: '' }); fetch() } catch (err: unknown) { setError((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } finally { setSaving(false) } } const deleteDb = async (id: number) => { if (!confirm('Delete this database and all its data?')) return - try { await api.delete(`/cpanel/databases/${id}`); fetch() } + try { await api.delete(`/nixclient/databases/${id}`); fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } } const createUser = async (e: React.FormEvent) => { e.preventDefault(); if (!showUserModal) return setSaving(true); setError('') - try { await api.post(`/cpanel/databases/${showUserModal}/users`, userForm); setShowUserModal(null); setUserForm({ username: '', password: '', privileges: 'ALL' }); fetch() } + try { await api.post(`/nixclient/databases/${showUserModal}/users`, userForm); setShowUserModal(null); setUserForm({ username: '', password: '', privileges: 'ALL' }); fetch() } catch (err: unknown) { setError((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } finally { setSaving(false) } } const deleteUser = async (dbId: number, userId: number) => { - try { await api.delete(`/cpanel/databases/${dbId}/users/${userId}`); fetch() } + try { await api.delete(`/nixclient/databases/${dbId}/users/${userId}`); fetch() } catch {} } diff --git a/cpanel/src/pages/Domains.tsx b/nixclient/src/pages/Domains.tsx similarity index 90% rename from cpanel/src/pages/Domains.tsx rename to nixclient/src/pages/Domains.tsx index a3a5014..9b7b39c 100644 --- a/cpanel/src/pages/Domains.tsx +++ b/nixclient/src/pages/Domains.tsx @@ -18,7 +18,7 @@ export default function Domains() { const fetch = async () => { setLoading(true) try { - const r = await api.get(`/cpanel/domains/${tab}`) + const r = await api.get(`/nixclient/domains/${tab}`) setItems(r.data.data) } finally { setLoading(false) } } @@ -28,9 +28,9 @@ export default function Domains() { const save = async (e: React.FormEvent) => { e.preventDefault(); setSaving(true); setError('') try { - if (tab === 'subdomains') await api.post('/cpanel/domains/subdomains', { subdomain: form.subdomain }) - else if (tab === 'addon') await api.post('/cpanel/domains/addon', { domain: form.domain }) - else await api.post('/cpanel/domains/parked', { domain: form.domain }) + if (tab === 'subdomains') await api.post('/nixclient/domains/subdomains', { subdomain: form.subdomain }) + else if (tab === 'addon') await api.post('/nixclient/domains/addon', { domain: form.domain }) + else await api.post('/nixclient/domains/parked', { domain: form.domain }) setShowModal(false); setForm({ subdomain: '', domain: '' }); fetch() } catch (err: unknown) { setError((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } finally { setSaving(false) } @@ -39,9 +39,9 @@ export default function Domains() { const del = async (id: number) => { if (!confirm('Remove this domain?')) return try { - if (tab === 'subdomains') await api.delete(`/cpanel/domains/subdomains/${id}`) - else if (tab === 'addon') await api.delete(`/cpanel/domains/addon/${id}`) - else await api.delete(`/cpanel/domains/parked/${id}`) + if (tab === 'subdomains') await api.delete(`/nixclient/domains/subdomains/${id}`) + else if (tab === 'addon') await api.delete(`/nixclient/domains/addon/${id}`) + else await api.delete(`/nixclient/domains/parked/${id}`) fetch() } catch {} } diff --git a/cpanel/src/pages/Email.tsx b/nixclient/src/pages/Email.tsx similarity index 95% rename from cpanel/src/pages/Email.tsx rename to nixclient/src/pages/Email.tsx index b727857..3eb55e3 100644 --- a/cpanel/src/pages/Email.tsx +++ b/nixclient/src/pages/Email.tsx @@ -20,7 +20,7 @@ export default function Email() { const fetch = async () => { setLoading(true) try { - const [em, fw] = await Promise.all([api.get('/cpanel/email'), api.get('/cpanel/email/forwarders')]) + const [em, fw] = await Promise.all([api.get('/nixclient/email'), api.get('/nixclient/email/forwarders')]) setAccounts(em.data.data) setForwarders(fw.data.data) } finally { setLoading(false) } @@ -31,7 +31,7 @@ export default function Email() { const createAccount = async (e: React.FormEvent) => { e.preventDefault(); setSaving(true); setError('') try { - await api.post('/cpanel/email', form) + await api.post('/nixclient/email', form) setShowModal(false); fetch() } catch (err: unknown) { setError((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } finally { setSaving(false) } @@ -39,18 +39,18 @@ export default function Email() { const del = async (id: number) => { if (!confirm('Delete this email account?')) return - try { await api.delete(`/cpanel/email/${id}`); fetch() } catch {} + try { await api.delete(`/nixclient/email/${id}`); fetch() } catch {} } const addForwarder = async (e: React.FormEvent) => { e.preventDefault(); setSaving(true); setError('') - try { await api.post('/cpanel/email/forwarders', fwdForm); setShowFwd(false); fetch() } + try { await api.post('/nixclient/email/forwarders', fwdForm); setShowFwd(false); fetch() } catch (err: unknown) { setError((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } finally { setSaving(false) } } const delFwd = async (id: number) => { - try { await api.delete(`/cpanel/email/forwarders/${id}`); fetch() } catch {} + try { await api.delete(`/nixclient/email/forwarders/${id}`); fetch() } catch {} } return ( diff --git a/cpanel/src/pages/FTP.tsx b/nixclient/src/pages/FTP.tsx similarity index 95% rename from cpanel/src/pages/FTP.tsx rename to nixclient/src/pages/FTP.tsx index 748fa04..fa94768 100644 --- a/cpanel/src/pages/FTP.tsx +++ b/nixclient/src/pages/FTP.tsx @@ -14,7 +14,7 @@ export default function FTP() { const fetch = async () => { setLoading(true) - try { const r = await api.get('/cpanel/ftp'); setAccounts(r.data.data) } + try { const r = await api.get('/nixclient/ftp'); setAccounts(r.data.data) } finally { setLoading(false) } } @@ -22,14 +22,14 @@ export default function FTP() { const save = async (e: React.FormEvent) => { e.preventDefault(); setSaving(true); setError('') - try { await api.post('/cpanel/ftp', form); setShowModal(false); fetch() } + try { await api.post('/nixclient/ftp', form); setShowModal(false); fetch() } catch (err: unknown) { setError((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } finally { setSaving(false) } } const del = async (id: number) => { if (!confirm('Delete this FTP account?')) return - try { await api.delete(`/cpanel/ftp/${id}`); fetch() } catch {} + try { await api.delete(`/nixclient/ftp/${id}`); fetch() } catch {} } return ( diff --git a/cpanel/src/pages/FileManager.tsx b/nixclient/src/pages/FileManager.tsx similarity index 95% rename from cpanel/src/pages/FileManager.tsx rename to nixclient/src/pages/FileManager.tsx index d2e06c1..1394730 100644 --- a/cpanel/src/pages/FileManager.tsx +++ b/nixclient/src/pages/FileManager.tsx @@ -19,7 +19,7 @@ export default function FileManager() { const loadDir = async (p: string) => { setLoading(true); setSelected(new Set()) try { - const r = await api.get(`/cpanel/files?path=${encodeURIComponent(p)}`) + const r = await api.get(`/nixclient/files?path=${encodeURIComponent(p)}`) setFiles(r.data.data.files); setPath(r.data.data.path) } catch (e: unknown) { alert((e as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed to load directory') @@ -35,7 +35,7 @@ export default function FileManager() { const openFile = async (filePath: string) => { try { - const r = await api.get(`/cpanel/files/content?path=${encodeURIComponent(filePath)}`) + const r = await api.get(`/nixclient/files/content?path=${encodeURIComponent(filePath)}`) setEditing({ path: filePath, content: r.data.data.content }) } catch (e: unknown) { alert((e as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Cannot open file') @@ -46,7 +46,7 @@ export default function FileManager() { if (!editing) return setSaving(true) try { - await api.put('/cpanel/files/content', { path: editing.path, content: editing.content }) + await api.put('/nixclient/files/content', { path: editing.path, content: editing.content }) setEditing(null) } catch (e: unknown) { alert((e as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Save failed') @@ -56,7 +56,7 @@ export default function FileManager() { const deleteSelected = async () => { if (!selected.size || !confirm(`Delete ${selected.size} item(s)?`)) return try { - await api.delete('/cpanel/files', { data: { paths: Array.from(selected) } }) + await api.delete('/nixclient/files', { data: { paths: Array.from(selected) } }) loadDir(path) } catch {} } @@ -64,7 +64,7 @@ export default function FileManager() { const createDir = async (e: React.FormEvent) => { e.preventDefault() try { - await api.post('/cpanel/files/mkdir', { path: `${path}/${newDir}` }) + await api.post('/nixclient/files/mkdir', { path: `${path}/${newDir}` }) setNewDir(''); setShowNewDir(false); loadDir(path) } catch (e: unknown) { alert((e as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') diff --git a/cpanel/src/pages/Login.tsx b/nixclient/src/pages/Login.tsx similarity index 96% rename from cpanel/src/pages/Login.tsx rename to nixclient/src/pages/Login.tsx index fdb62a9..f86d706 100644 --- a/cpanel/src/pages/Login.tsx +++ b/nixclient/src/pages/Login.tsx @@ -27,7 +27,7 @@ export default function Login() {
N
-

NixPanel

+

NixClient

Hosting Control Panel

@@ -49,7 +49,7 @@ export default function Login() { -

NixPanel v0.1.0 · Port 2083

+

NixClient v0.2.0 · Port 2083

) diff --git a/cpanel/src/pages/Overview.tsx b/nixclient/src/pages/Overview.tsx similarity index 98% rename from cpanel/src/pages/Overview.tsx rename to nixclient/src/pages/Overview.tsx index 1367b56..60d0144 100644 --- a/cpanel/src/pages/Overview.tsx +++ b/nixclient/src/pages/Overview.tsx @@ -53,7 +53,7 @@ export default function Overview() { const [stats, setStats] = useState(null) useEffect(() => { - api.get('/cpanel/stats').then(r => setStats(r.data.data)).catch(() => {}) + api.get('/nixclient/stats').then(r => setStats(r.data.data)).catch(() => {}) }, []) return ( diff --git a/cpanel/src/pages/SSL.tsx b/nixclient/src/pages/SSL.tsx similarity index 96% rename from cpanel/src/pages/SSL.tsx rename to nixclient/src/pages/SSL.tsx index 4d1054b..664ef35 100644 --- a/cpanel/src/pages/SSL.tsx +++ b/nixclient/src/pages/SSL.tsx @@ -10,14 +10,14 @@ export default function SSL() { const fetch = async () => { setLoading(true) - try { const r = await api.get('/whm/ssl'); setCerts(r.data.data) } + try { const r = await api.get('/nixserver/ssl'); setCerts(r.data.data) } finally { setLoading(false) } } useEffect(() => { fetch() }, []) const renew = async (id: number) => { - try { await api.post(`/whm/ssl/${id}/renew`); fetch() } + try { await api.post(`/nixserver/ssl/${id}/renew`); fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Renewal failed') } } diff --git a/cpanel/src/pages/Stats.tsx b/nixclient/src/pages/Stats.tsx similarity index 97% rename from cpanel/src/pages/Stats.tsx rename to nixclient/src/pages/Stats.tsx index 025713f..2b991eb 100644 --- a/cpanel/src/pages/Stats.tsx +++ b/nixclient/src/pages/Stats.tsx @@ -34,7 +34,7 @@ export default function Stats() { const fetch = async () => { setLoading(true) - try { const r = await api.get('/cpanel/stats'); setStats(r.data.data) } + try { const r = await api.get('/nixclient/stats'); setStats(r.data.data) } finally { setLoading(false) } } diff --git a/cpanel/tailwind.config.js b/nixclient/tailwind.config.js similarity index 100% rename from cpanel/tailwind.config.js rename to nixclient/tailwind.config.js diff --git a/cpanel/tsconfig.json b/nixclient/tsconfig.json similarity index 100% rename from cpanel/tsconfig.json rename to nixclient/tsconfig.json diff --git a/cpanel/tsconfig.node.json b/nixclient/tsconfig.node.json similarity index 100% rename from cpanel/tsconfig.node.json rename to nixclient/tsconfig.node.json diff --git a/cpanel/vite.config.ts b/nixclient/vite.config.ts similarity index 100% rename from cpanel/vite.config.ts rename to nixclient/vite.config.ts diff --git a/whm/index.html b/nixserver/index.html similarity index 100% rename from whm/index.html rename to nixserver/index.html diff --git a/whm/package.json b/nixserver/package.json similarity index 96% rename from whm/package.json rename to nixserver/package.json index c6b8bf4..8fca5ba 100644 --- a/whm/package.json +++ b/nixserver/package.json @@ -1,6 +1,6 @@ { "name": "@nixpanel/whm", - "version": "0.1.0", + "version": "0.2.0", "private": true, "type": "module", "scripts": { diff --git a/whm/postcss.config.js b/nixserver/postcss.config.js similarity index 100% rename from whm/postcss.config.js rename to nixserver/postcss.config.js diff --git a/whm/src/App.tsx b/nixserver/src/App.tsx similarity index 100% rename from whm/src/App.tsx rename to nixserver/src/App.tsx diff --git a/whm/src/api/client.ts b/nixserver/src/api/client.ts similarity index 100% rename from whm/src/api/client.ts rename to nixserver/src/api/client.ts diff --git a/whm/src/components/Layout.tsx b/nixserver/src/components/Layout.tsx similarity index 97% rename from whm/src/components/Layout.tsx rename to nixserver/src/components/Layout.tsx index 7454425..61a1085 100644 --- a/whm/src/components/Layout.tsx +++ b/nixserver/src/components/Layout.tsx @@ -49,8 +49,8 @@ export default function Layout() { {sidebarOpen && (
-

NixPanel

-

WHM

+

NixServer

+

Admin Panel

)} diff --git a/whm/src/contexts/AuthContext.tsx b/nixserver/src/contexts/AuthContext.tsx similarity index 95% rename from whm/src/contexts/AuthContext.tsx rename to nixserver/src/contexts/AuthContext.tsx index ef95abe..5065961 100644 --- a/whm/src/contexts/AuthContext.tsx +++ b/nixserver/src/contexts/AuthContext.tsx @@ -44,7 +44,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const login = async (username: string, password: string) => { const { data } = await api.post('/auth/login', { username, password }) if (data.data.role !== 'admin' && data.data.role !== 'reseller') { - throw new Error('Access denied — WHM is for administrators and resellers only') + throw new Error('Access denied — NixServer is for administrators and resellers only') } localStorage.setItem('access_token', data.data.accessToken) localStorage.setItem('refresh_token', data.data.refreshToken) diff --git a/whm/src/index.css b/nixserver/src/index.css similarity index 100% rename from whm/src/index.css rename to nixserver/src/index.css diff --git a/whm/src/main.tsx b/nixserver/src/main.tsx similarity index 100% rename from whm/src/main.tsx rename to nixserver/src/main.tsx diff --git a/whm/src/pages/Accounts.tsx b/nixserver/src/pages/Accounts.tsx similarity index 96% rename from whm/src/pages/Accounts.tsx rename to nixserver/src/pages/Accounts.tsx index 9327248..fd4d783 100644 --- a/whm/src/pages/Accounts.tsx +++ b/nixserver/src/pages/Accounts.tsx @@ -43,7 +43,7 @@ export default function Accounts() { const params = new URLSearchParams({ page: String(page), limit: '25' }) if (search) params.set('search', search) if (status) params.set('status', status) - const r = await api.get(`/whm/accounts?${params}`) + const r = await api.get(`/nixserver/accounts?${params}`) setData(r.data.data) } finally { setLoading(false) @@ -56,9 +56,9 @@ export default function Accounts() { setActionMenu(null) if (act === 'terminate' && !confirm('Terminate this account? This cannot be undone.')) return try { - if (act === 'suspend') await api.post(`/whm/accounts/${id}/suspend`) - else if (act === 'unsuspend') await api.post(`/whm/accounts/${id}/unsuspend`) - else await api.delete(`/whm/accounts/${id}`) + if (act === 'suspend') await api.post(`/nixserver/accounts/${id}/suspend`) + else if (act === 'unsuspend') await api.post(`/nixserver/accounts/${id}/unsuspend`) + else await api.delete(`/nixserver/accounts/${id}`) fetch() } catch (e: unknown) { alert((e as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Action failed') diff --git a/whm/src/pages/Backup.tsx b/nixserver/src/pages/Backup.tsx similarity index 93% rename from whm/src/pages/Backup.tsx rename to nixserver/src/pages/Backup.tsx index d016bd7..bc12af5 100644 --- a/whm/src/pages/Backup.tsx +++ b/nixserver/src/pages/Backup.tsx @@ -16,7 +16,7 @@ export default function Backup() { const fetch = async () => { setLoading(true) try { - const [b, a] = await Promise.all([api.get('/whm/backup/list'), api.get('/whm/accounts?limit=100')]) + const [b, a] = await Promise.all([api.get('/nixserver/backup/list'), api.get('/nixserver/accounts?limit=100')]) setBackups(b.data.data) setAccounts(a.data.data.items) } finally { setLoading(false) } @@ -27,7 +27,7 @@ export default function Backup() { const backupAccount = async () => { if (!selectedAccount) return alert('Select an account') setBacking(true) - try { await api.post(`/whm/backup/account/${selectedAccount}`); fetch() } + try { await api.post(`/nixserver/backup/account/${selectedAccount}`); fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Backup failed') } finally { setBacking(false) } } @@ -35,14 +35,14 @@ export default function Backup() { const backupServer = async () => { if (!confirm('Start a full server backup? This may take a while.')) return setBacking(true) - try { await api.post('/whm/backup/server'); fetch() } + try { await api.post('/nixserver/backup/server'); fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Backup failed') } finally { setBacking(false) } } const del = async (path: string) => { if (!confirm('Delete this backup?')) return - try { await api.delete('/whm/backup', { data: { path } }); fetch() } + try { await api.delete('/nixserver/backup', { data: { path } }); fetch() } catch {} } diff --git a/whm/src/pages/CreateAccount.tsx b/nixserver/src/pages/CreateAccount.tsx similarity index 93% rename from whm/src/pages/CreateAccount.tsx rename to nixserver/src/pages/CreateAccount.tsx index df361c1..7388cea 100644 --- a/whm/src/pages/CreateAccount.tsx +++ b/nixserver/src/pages/CreateAccount.tsx @@ -15,7 +15,7 @@ export default function CreateAccount() { }) useEffect(() => { - api.get('/whm/packages').then(r => setPackages(r.data.data)).catch(() => {}) + api.get('/nixserver/packages').then(r => setPackages(r.data.data)).catch(() => {}) }, []) const set = (k: keyof typeof form) => (e: React.ChangeEvent) => @@ -26,7 +26,7 @@ export default function CreateAccount() { setError('') setLoading(true) try { - await api.post('/whm/accounts', { + await api.post('/nixserver/accounts', { ...form, packageId: form.packageId ? parseInt(form.packageId, 10) : undefined, }) @@ -56,7 +56,7 @@ export default function CreateAccount() { { key: 'username', label: 'Username', type: 'text', placeholder: 'john', hint: 'Lowercase letters, numbers, hyphens' }, { key: 'domain', label: 'Primary Domain', type: 'text', placeholder: 'example.com' }, { key: 'email', label: 'Contact Email', type: 'email', placeholder: 'john@example.com' }, - { key: 'password', label: 'cPanel Password', type: 'password', placeholder: '••••••••', hint: 'Min 8 characters' }, + { key: 'password', label: 'NixClient Password', type: 'password', placeholder: '••••••••', hint: 'Min 8 characters' }, ].map(({ key, label, type, placeholder, hint }) => (
diff --git a/whm/src/pages/DNS.tsx b/nixserver/src/pages/DNS.tsx similarity index 94% rename from whm/src/pages/DNS.tsx rename to nixserver/src/pages/DNS.tsx index ed3169f..a60e7bb 100644 --- a/whm/src/pages/DNS.tsx +++ b/nixserver/src/pages/DNS.tsx @@ -16,13 +16,13 @@ export default function DNS() { const fetchZones = async () => { setLoading(true) - try { const r = await api.get('/whm/dns'); setZones(r.data.data) } + try { const r = await api.get('/nixserver/dns'); setZones(r.data.data) } finally { setLoading(false) } } const loadZone = async (zone: Zone) => { setSelected(zone) - const r = await api.get(`/whm/dns/${zone.id}`) + const r = await api.get(`/nixserver/dns/${zone.id}`) setRecords(r.data.data.records ?? []) } @@ -32,7 +32,7 @@ export default function DNS() { e.preventDefault(); if (!selected) return setSaving(true) try { - await api.post(`/whm/dns/${selected.id}/records`, { ...form, priority: form.priority ? parseInt(form.priority, 10) : undefined }) + await api.post(`/nixserver/dns/${selected.id}/records`, { ...form, priority: form.priority ? parseInt(form.priority, 10) : undefined }) setShowForm(false) loadZone(selected) } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } @@ -41,7 +41,7 @@ export default function DNS() { const deleteRecord = async (recordId: number) => { if (!selected || !confirm('Delete this DNS record?')) return - try { await api.delete(`/whm/dns/${selected.id}/records/${recordId}`); loadZone(selected) } + try { await api.delete(`/nixserver/dns/${selected.id}/records/${recordId}`); loadZone(selected) } catch {} } diff --git a/whm/src/pages/Dashboard.tsx b/nixserver/src/pages/Dashboard.tsx similarity index 97% rename from whm/src/pages/Dashboard.tsx rename to nixserver/src/pages/Dashboard.tsx index a699ce8..4e2a655 100644 --- a/whm/src/pages/Dashboard.tsx +++ b/nixserver/src/pages/Dashboard.tsx @@ -38,8 +38,8 @@ export default function Dashboard() { const wsRef = useRef(null) useEffect(() => { - api.get('/whm/accounts/stats').then(r => setAccountStats(r.data.data)).catch(() => {}) - api.get('/whm/system/stats').then(r => setStats(r.data.data)).catch(() => {}) + api.get('/nixserver/accounts/stats').then(r => setAccountStats(r.data.data)).catch(() => {}) + api.get('/nixserver/system/stats').then(r => setStats(r.data.data)).catch(() => {}) // WebSocket live stats const token = localStorage.getItem('access_token') diff --git a/whm/src/pages/Email.tsx b/nixserver/src/pages/Email.tsx similarity index 95% rename from whm/src/pages/Email.tsx rename to nixserver/src/pages/Email.tsx index dff6342..6a48332 100644 --- a/whm/src/pages/Email.tsx +++ b/nixserver/src/pages/Email.tsx @@ -16,7 +16,7 @@ export default function Email() { const fetch = async () => { setLoading(true) try { - const [em, acc] = await Promise.all([api.get('/whm/email'), api.get('/whm/accounts?limit=100')]) + const [em, acc] = await Promise.all([api.get('/nixserver/email'), api.get('/nixserver/accounts?limit=100')]) setAccounts(em.data.data) setHosting(acc.data.data.items) } finally { setLoading(false) } @@ -27,7 +27,7 @@ export default function Email() { const save = async (e: React.FormEvent) => { e.preventDefault(); setSaving(true); setError('') try { - await api.post('/whm/email', { ...form, accountId: parseInt(form.accountId, 10), quotaMb: form.quotaMb }) + await api.post('/nixserver/email', { ...form, accountId: parseInt(form.accountId, 10), quotaMb: form.quotaMb }) setShowModal(false); fetch() } catch (err: unknown) { setError((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } finally { setSaving(false) } @@ -35,7 +35,7 @@ export default function Email() { const del = async (id: number, address: string) => { if (!confirm(`Delete ${address}?`)) return - try { await api.delete(`/whm/email/${id}`); fetch() } + try { await api.delete(`/nixserver/email/${id}`); fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } } diff --git a/whm/src/pages/Login.tsx b/nixserver/src/pages/Login.tsx similarity index 96% rename from whm/src/pages/Login.tsx rename to nixserver/src/pages/Login.tsx index 0b561bd..d5cf668 100644 --- a/whm/src/pages/Login.tsx +++ b/nixserver/src/pages/Login.tsx @@ -34,7 +34,7 @@ export default function Login() {
-

NixPanel WHM

+

NixServer

Web Host Manager

@@ -81,7 +81,7 @@ export default function Login() {

- NixPanel v0.1.0 · WHM Port 2087 + NixServer v0.2.0 · Port 2087

diff --git a/whm/src/pages/PHP.tsx b/nixserver/src/pages/PHP.tsx similarity index 95% rename from whm/src/pages/PHP.tsx rename to nixserver/src/pages/PHP.tsx index 335cbeb..6167b26 100644 --- a/whm/src/pages/PHP.tsx +++ b/nixserver/src/pages/PHP.tsx @@ -13,7 +13,7 @@ export default function PHP() { const fetch = async () => { setLoading(true) try { - const [v, a] = await Promise.all([api.get('/whm/php/versions'), api.get('/whm/php/accounts')]) + const [v, a] = await Promise.all([api.get('/nixserver/php/versions'), api.get('/nixserver/php/accounts')]) setVersions(v.data.data) setAccounts(a.data.data) } finally { setLoading(false) } @@ -23,7 +23,7 @@ export default function PHP() { const changeVersion = async (accountId: number, phpVersion: string) => { try { - await api.put(`/whm/php/accounts/${accountId}`, { phpVersion }) + await api.put(`/nixserver/php/accounts/${accountId}`, { phpVersion }) fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } } diff --git a/whm/src/pages/Packages.tsx b/nixserver/src/pages/Packages.tsx similarity index 96% rename from whm/src/pages/Packages.tsx rename to nixserver/src/pages/Packages.tsx index b2aaed3..0e601d6 100644 --- a/whm/src/pages/Packages.tsx +++ b/nixserver/src/pages/Packages.tsx @@ -27,7 +27,7 @@ export default function Packages() { const fetch = async () => { setLoading(true) - try { const r = await api.get('/whm/packages'); setPackages(r.data.data) } + try { const r = await api.get('/nixserver/packages'); setPackages(r.data.data) } finally { setLoading(false) } } @@ -44,8 +44,8 @@ export default function Packages() { const save = async (e: React.FormEvent) => { e.preventDefault(); setSaving(true); setError('') try { - if (editing) await api.put(`/whm/packages/${editing.id}`, form) - else await api.post('/whm/packages', form) + if (editing) await api.put(`/nixserver/packages/${editing.id}`, form) + else await api.post('/nixserver/packages', form) setShowModal(false); fetch() } catch (err: unknown) { setError((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Save failed') @@ -54,7 +54,7 @@ export default function Packages() { const del = async (p: Package) => { if (!confirm(`Delete package "${p.name}"?`)) return - try { await api.delete(`/whm/packages/${p.id}`); fetch() } + try { await api.delete(`/nixserver/packages/${p.id}`); fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Delete failed') } diff --git a/whm/src/pages/Resellers.tsx b/nixserver/src/pages/Resellers.tsx similarity index 94% rename from whm/src/pages/Resellers.tsx rename to nixserver/src/pages/Resellers.tsx index c72b1de..38733e2 100644 --- a/whm/src/pages/Resellers.tsx +++ b/nixserver/src/pages/Resellers.tsx @@ -17,7 +17,7 @@ export default function Resellers() { setLoading(true) try { const params = search ? `?search=${encodeURIComponent(search)}` : '' - const r = await api.get(`/whm/resellers${params}`) + const r = await api.get(`/nixserver/resellers${params}`) setItems(r.data.data.items ?? r.data.data) } finally { setLoading(false) } }, [search]) @@ -26,7 +26,7 @@ export default function Resellers() { const save = async (e: React.FormEvent) => { e.preventDefault(); setSaving(true); setError('') - try { await api.post('/whm/resellers', form); setShowModal(false); fetch() } + try { await api.post('/nixserver/resellers', form); setShowModal(false); fetch() } catch (err: unknown) { setError((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } finally { setSaving(false) } } @@ -34,9 +34,9 @@ export default function Resellers() { const act = async (id: number, action: 'suspend' | 'unsuspend' | 'delete') => { if (action === 'delete' && !confirm('Delete this reseller?')) return try { - if (action === 'suspend') await api.post(`/whm/resellers/${id}/suspend`) - else if (action === 'unsuspend') await api.post(`/whm/resellers/${id}/unsuspend`) - else await api.delete(`/whm/resellers/${id}`) + if (action === 'suspend') await api.post(`/nixserver/resellers/${id}/suspend`) + else if (action === 'unsuspend') await api.post(`/nixserver/resellers/${id}/unsuspend`) + else await api.delete(`/nixserver/resellers/${id}`) fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } } diff --git a/whm/src/pages/SSL.tsx b/nixserver/src/pages/SSL.tsx similarity index 95% rename from whm/src/pages/SSL.tsx rename to nixserver/src/pages/SSL.tsx index b66c6b6..83a8b5e 100644 --- a/whm/src/pages/SSL.tsx +++ b/nixserver/src/pages/SSL.tsx @@ -23,7 +23,7 @@ export default function SSL() { const fetch = async () => { setLoading(true) try { - const [sl, acc] = await Promise.all([api.get('/whm/ssl'), api.get('/whm/accounts?limit=100')]) + const [sl, acc] = await Promise.all([api.get('/nixserver/ssl'), api.get('/nixserver/accounts?limit=100')]) setCerts(sl.data.data) setHosting(acc.data.data.items) } finally { setLoading(false) } @@ -34,20 +34,20 @@ export default function SSL() { const issue = async (e: React.FormEvent) => { e.preventDefault(); setSaving(true); setError('') try { - await api.post('/whm/ssl/issue', { ...form, accountId: parseInt(form.accountId, 10) }) + await api.post('/nixserver/ssl/issue', { ...form, accountId: parseInt(form.accountId, 10) }) setShowModal(false); fetch() } catch (err: unknown) { setError((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } finally { setSaving(false) } } const renew = async (id: number) => { - try { await api.post(`/whm/ssl/${id}/renew`); fetch() } + try { await api.post(`/nixserver/ssl/${id}/renew`); fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Renewal failed') } } const revoke = async (id: number) => { if (!confirm('Revoke this certificate?')) return - try { await api.post(`/whm/ssl/${id}/revoke`); fetch() } + try { await api.post(`/nixserver/ssl/${id}/revoke`); fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Revoke failed') } } diff --git a/whm/src/pages/Security.tsx b/nixserver/src/pages/Security.tsx similarity index 93% rename from whm/src/pages/Security.tsx rename to nixserver/src/pages/Security.tsx index c34c18c..d8e62c1 100644 --- a/whm/src/pages/Security.tsx +++ b/nixserver/src/pages/Security.tsx @@ -22,8 +22,8 @@ export default function Security() { setLoading(true) try { const [b, e] = await Promise.all([ - api.get('/whm/security/blocked-ips'), - api.get('/whm/security/events'), + api.get('/nixserver/security/blocked-ips'), + api.get('/nixserver/security/events'), ]) setBlocked(b.data.data) setEvents(e.data.data.items ?? e.data.data) @@ -34,17 +34,17 @@ export default function Security() { const block = async (e: React.FormEvent) => { e.preventDefault() - try { await api.post('/whm/security/blocked-ips', { ip: newIp, reason }); setNewIp(''); setReason(''); fetch() } + try { await api.post('/nixserver/security/blocked-ips', { ip: newIp, reason }); setNewIp(''); setReason(''); fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } } const unblock = async (id: number) => { - try { await api.delete(`/whm/security/blocked-ips/${id}`); fetch() } + try { await api.delete(`/nixserver/security/blocked-ips/${id}`); fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } } const resolve = async (id: number) => { - try { await api.post(`/whm/security/events/${id}/resolve`); fetch() } + try { await api.post(`/nixserver/security/events/${id}/resolve`); fetch() } catch {} } diff --git a/whm/src/pages/Services.tsx b/nixserver/src/pages/Services.tsx similarity index 96% rename from whm/src/pages/Services.tsx rename to nixserver/src/pages/Services.tsx index 012f0f6..80f0e1f 100644 --- a/whm/src/pages/Services.tsx +++ b/nixserver/src/pages/Services.tsx @@ -18,7 +18,7 @@ export default function Services() { const fetch = async () => { setLoading(true) - try { const r = await api.get('/whm/services'); setServices(r.data.data) } + try { const r = await api.get('/nixserver/services'); setServices(r.data.data) } finally { setLoading(false) } } @@ -26,7 +26,7 @@ export default function Services() { const act = async (name: string, action: string) => { setActing(name + action) - try { await api.post(`/whm/services/${name}`, { action }); fetch() } + try { await api.post(`/nixserver/services/${name}`, { action }); fetch() } catch (e: unknown) { alert((e as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } finally { setActing(null) } } diff --git a/whm/src/pages/Settings.tsx b/nixserver/src/pages/Settings.tsx similarity index 90% rename from whm/src/pages/Settings.tsx rename to nixserver/src/pages/Settings.tsx index bb375ce..931f78a 100644 --- a/whm/src/pages/Settings.tsx +++ b/nixserver/src/pages/Settings.tsx @@ -10,7 +10,7 @@ export default function Settings() { const fetch = async () => { setLoading(true) - try { const r = await api.get('/whm/system/settings'); setSettings(r.data.data) } + try { const r = await api.get('/nixserver/system/settings'); setSettings(r.data.data) } finally { setLoading(false) } } @@ -18,7 +18,7 @@ export default function Settings() { const save = async (e: React.FormEvent) => { e.preventDefault(); setSaving(true) - try { await api.put('/whm/system/settings', settings); setSaved(true); setTimeout(() => setSaved(false), 2000) } + try { await api.put('/nixserver/system/settings', settings); setSaved(true); setTimeout(() => setSaved(false), 2000) } finally { setSaving(false) } } diff --git a/whm/src/pages/System.tsx b/nixserver/src/pages/System.tsx similarity index 96% rename from whm/src/pages/System.tsx rename to nixserver/src/pages/System.tsx index d5a2aa2..c3f573a 100644 --- a/whm/src/pages/System.tsx +++ b/nixserver/src/pages/System.tsx @@ -14,8 +14,8 @@ export default function System() { setLoading(true) try { const [infoR, procR] = await Promise.all([ - api.get('/whm/system/info'), - api.get('/whm/system/processes'), + api.get('/nixserver/system/info'), + api.get('/nixserver/system/processes'), ]) setInfo(infoR.data.data) setProcesses(procR.data.data) diff --git a/whm/src/pages/WebServer.tsx b/nixserver/src/pages/WebServer.tsx similarity index 92% rename from whm/src/pages/WebServer.tsx rename to nixserver/src/pages/WebServer.tsx index 10e8bdf..bfe0522 100644 --- a/whm/src/pages/WebServer.tsx +++ b/nixserver/src/pages/WebServer.tsx @@ -14,9 +14,9 @@ export default function WebServer() { setLoading(true) try { const [s, v, l] = await Promise.all([ - api.get('/whm/webserver/status'), - api.get('/whm/webserver/vhosts'), - api.get(`/whm/webserver/logs/${logType}`), + api.get('/nixserver/webserver/status'), + api.get('/nixserver/webserver/vhosts'), + api.get(`/nixserver/webserver/logs/${logType}`), ]) setStatus(s.data.data); setVhosts(v.data.data); setLogs(l.data.data) } finally { setLoading(false) } @@ -25,12 +25,12 @@ export default function WebServer() { useEffect(() => { fetch() }, [logType]) const testConfig = async () => { - const r = await api.post('/whm/webserver/nginx/test') + const r = await api.post('/nixserver/webserver/nginx/test') setTestResult(r.data.data.output) } const reload = async () => { - try { await api.post('/whm/webserver/nginx/reload'); fetch() } + try { await api.post('/nixserver/webserver/nginx/reload'); fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Reload failed') } } diff --git a/whm/tailwind.config.js b/nixserver/tailwind.config.js similarity index 100% rename from whm/tailwind.config.js rename to nixserver/tailwind.config.js diff --git a/whm/tsconfig.json b/nixserver/tsconfig.json similarity index 100% rename from whm/tsconfig.json rename to nixserver/tsconfig.json diff --git a/whm/tsconfig.node.json b/nixserver/tsconfig.node.json similarity index 100% rename from whm/tsconfig.node.json rename to nixserver/tsconfig.node.json diff --git a/whm/vite.config.ts b/nixserver/vite.config.ts similarity index 100% rename from whm/vite.config.ts rename to nixserver/vite.config.ts diff --git a/package.json b/package.json index 3542b06..0b3497c 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,18 @@ { "name": "nixpanel-server", - "version": "0.1.0", + "version": "0.2.0", "private": true, "workspaces": [ "server", - "whm", - "cpanel" + "nixserver", + "nixclient" ], "scripts": { - "dev": "concurrently \"npm run dev --workspace=server\" \"npm run dev --workspace=whm\" \"npm run dev --workspace=cpanel\"", + "dev": "concurrently \"npm run dev --workspace=server\" \"npm run dev --workspace=nixserver\" \"npm run dev --workspace=nixclient\"", "dev:server": "npm run dev --workspace=server", - "dev:whm": "npm run dev --workspace=whm", - "dev:cpanel": "npm run dev --workspace=cpanel", - "build": "npm run build --workspace=server && npm run build --workspace=whm && npm run build --workspace=cpanel", + "dev:nixserver": "npm run dev --workspace=nixserver", + "dev:nixclient": "npm run dev --workspace=nixclient", + "build": "npm run build --workspace=server && npm run build --workspace=nixserver && npm run build --workspace=nixclient", "db:migrate": "npm run db:migrate --workspace=server", "db:studio": "npm run db:studio --workspace=server" }, diff --git a/scripts/install.sh b/scripts/install.sh index 9d97504..ecb09ea 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -30,8 +30,8 @@ EOF echo -e "${RESET}" echo -e " Version : ${BOLD}0.1.0${RESET}" echo -e " GitHub : ${BOLD}https://github.com/NixReaper/nixpanel-server${RESET}" -echo -e " WHM : ${BOLD}https://:2087${RESET}" -echo -e " cPanel : ${BOLD}https://:2083${RESET}" +echo -e " NixServer: ${BOLD}https://:2087${RESET}" +echo -e " NixClient: ${BOLD}https://:2083${RESET}" echo "" # ── Root check ──────────────────────────────────────────────────────────────── @@ -341,8 +341,8 @@ JWT_REFRESH_EXPIRES_IN="7d" # Server NODE_ENV="production" -WHM_PORT=2087 -CPANEL_PORT=2083 +NIXSERVER_PORT=2087 +NIXCLIENT_PORT=2083 HOST="0.0.0.0" # Admin credentials (used during initial seed only) @@ -398,11 +398,11 @@ ADMIN_EMAIL="${ADMIN_EMAIL}" \ success "Default admin, packages, and settings seeded" # ── Build frontends ─────────────────────────────────────────────────────────── -step "Building WHM + cPanel frontends" +step "Building NixServer + NixClient frontends" cd "$INSTALL_DIR" -npm run build --workspace=whm --silent -npm run build --workspace=cpanel --silent +npm run build --workspace=nixserver --silent +npm run build --workspace=nixclient --silent success "Frontends built" # ── systemd service ─────────────────────────────────────────────────────────── @@ -453,13 +453,13 @@ fi cat > /etc/nginx/sites-available/nixpanel.conf </dev/null ufw allow 80/tcp comment "HTTP" >/dev/null ufw allow 443/tcp comment "HTTPS" >/dev/null - ufw allow 2087/tcp comment "WHM" >/dev/null - ufw allow 2083/tcp comment "cPanel" >/dev/null + ufw allow 2087/tcp comment "NixServer" >/dev/null + ufw allow 2083/tcp comment "NixClient" >/dev/null ufw allow 21/tcp comment "FTP" >/dev/null ufw allow 25/tcp comment "SMTP" >/dev/null ufw allow 143/tcp comment "IMAP" >/dev/null @@ -637,12 +637,12 @@ echo -e "${BOLD}${GREEN}╔═════════════════ echo -e "${BOLD}${GREEN}║ NixPanel Installation Complete! ║${RESET}" echo -e "${BOLD}${GREEN}╚══════════════════════════════════════════════════════╝${RESET}" echo "" -echo -e " ${BOLD}WHM (Admin Panel)${RESET}" +echo -e " ${BOLD}NixServer (Admin Panel)${RESET}" echo -e " URL : ${CYAN}http://${SERVER_IP}:2087${RESET}" echo -e " Username : ${BOLD}${ADMIN_USER}${RESET}" echo -e " Password : ${BOLD}${ADMIN_PASS}${RESET}" echo "" -echo -e " ${BOLD}cPanel (User Panel)${RESET}" +echo -e " ${BOLD}NixClient (User Panel)${RESET}" echo -e " URL : ${CYAN}http://${SERVER_IP}:2083${RESET}" echo "" echo -e " ${BOLD}Database${RESET}" @@ -671,8 +671,8 @@ CRED_FILE="/root/.nixpanel_credentials" cat > "$CRED_FILE" < ({ status: 'ok', - version: '0.1.0', + version: '0.2.0', timestamp: new Date().toISOString(), })) diff --git a/server/src/config.ts b/server/src/config.ts index 5fb2626..18a6108 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -16,8 +16,8 @@ export const config = { server: { host: optional('HOST', '0.0.0.0'), - whmPort: parseInt(optional('WHM_PORT', '2087'), 10), - cpanelPort: parseInt(optional('CPANEL_PORT', '2083'), 10), + nixserverPort: parseInt(optional('NIXSERVER_PORT', '2087'), 10), + nixclientPort: parseInt(optional('NIXCLIENT_PORT', '2083'), 10), }, db: { diff --git a/server/src/core/dns.ts b/server/src/core/dns.ts index 4146346..dca4593 100644 --- a/server/src/core/dns.ts +++ b/server/src/core/dns.ts @@ -45,7 +45,7 @@ $TTL ${ttl} www IN A ${ip} mail IN A ${ip} ftp IN A ${ip} -cpanel IN A ${ip} +nixclient IN A ${ip} webmail IN A ${ip} ; MX record diff --git a/server/src/index.ts b/server/src/index.ts index dd0f494..90c4356 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -13,10 +13,10 @@ async function start() { app = await buildApp() - // WHM server on port 2087 - await app.listen({ port: config.server.whmPort, host: config.server.host }) - console.log(`NixPanel WHM running on port ${config.server.whmPort}`) - console.log(`NixPanel cPanel API running on port ${config.server.whmPort} (/api/cpanel)`) + // NixServer on port 2087 + await app.listen({ port: config.server.nixserverPort, host: config.server.host }) + console.log(`NixServer running on port ${config.server.nixserverPort}`) + console.log(`NixClient API running on port ${config.server.nixserverPort} (/api/cpanel)`) } catch (err) { console.error('Failed to start server:', err) diff --git a/server/src/routes/auth/index.ts b/server/src/routes/auth/index.ts index ced31a6..048e2e0 100644 --- a/server/src/routes/auth/index.ts +++ b/server/src/routes/auth/index.ts @@ -37,7 +37,7 @@ function signTokens( export default async function authRoutes(fastify: FastifyInstance) { /** * POST /api/auth/login - * Login for admin, reseller, or cPanel user. + * Login for admin, reseller, or NixClient user. * Body: { username, password } * Returns: { accessToken, refreshToken, role, user } */ @@ -111,7 +111,7 @@ export default async function authRoutes(fastify: FastifyInstance) { }) } - // Try hosting account (cPanel user) + // Try hosting account (NixClient user) const account = await prisma.account.findUnique({ where: { username } }) if (account) { if (account.status !== 'active') { diff --git a/server/src/routes/cpanel/cron.ts b/server/src/routes/nixclient/cron.ts similarity index 100% rename from server/src/routes/cpanel/cron.ts rename to server/src/routes/nixclient/cron.ts diff --git a/server/src/routes/cpanel/databases.ts b/server/src/routes/nixclient/databases.ts similarity index 96% rename from server/src/routes/cpanel/databases.ts rename to server/src/routes/nixclient/databases.ts index 0ca0a00..422083a 100644 --- a/server/src/routes/cpanel/databases.ts +++ b/server/src/routes/nixclient/databases.ts @@ -12,7 +12,7 @@ function mysqlEscape(s: string): string { export default async function databaseRoutes(fastify: FastifyInstance) { const preHandler = [requireAuth] - // GET /api/cpanel/databases + // GET /api/nixclient/databases fastify.get('/', { preHandler }, async (request, reply) => { const user = request.user! const accountId = user.role === 'user' ? user.sub : parseInt((request.query as Record).accountId ?? '0', 10) @@ -25,7 +25,7 @@ export default async function databaseRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: databases }) }) - // POST /api/cpanel/databases + // POST /api/nixclient/databases fastify.post('/', { preHandler }, async (request, reply) => { const user = request.user! const accountId = user.role === 'user' ? user.sub : parseInt((request.body as Record).accountId ?? '0', 10) @@ -74,7 +74,7 @@ export default async function databaseRoutes(fastify: FastifyInstance) { return reply.code(201).send({ success: true, data: db }) }) - // DELETE /api/cpanel/databases/:id + // DELETE /api/nixclient/databases/:id fastify.delete('/:id', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } const user = request.user! @@ -93,7 +93,7 @@ export default async function databaseRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: `Database ${db.name} deleted` } }) }) - // POST /api/cpanel/databases/:id/users + // POST /api/nixclient/databases/:id/users fastify.post('/:id/users', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } const user = request.user! @@ -139,7 +139,7 @@ export default async function databaseRoutes(fastify: FastifyInstance) { return reply.code(201).send({ success: true, data: safe }) }) - // DELETE /api/cpanel/databases/:id/users/:userId + // DELETE /api/nixclient/databases/:id/users/:userId fastify.delete('/:id/users/:userId', { preHandler }, async (request, reply) => { const { id, userId } = request.params as { id: string; userId: string } diff --git a/server/src/routes/cpanel/domains.ts b/server/src/routes/nixclient/domains.ts similarity index 100% rename from server/src/routes/cpanel/domains.ts rename to server/src/routes/nixclient/domains.ts diff --git a/server/src/routes/cpanel/email.ts b/server/src/routes/nixclient/email.ts similarity index 95% rename from server/src/routes/cpanel/email.ts rename to server/src/routes/nixclient/email.ts index 4385127..ce03d5d 100644 --- a/server/src/routes/cpanel/email.ts +++ b/server/src/routes/nixclient/email.ts @@ -8,7 +8,7 @@ import { exec } from '../../core/exec.js' export default async function cpanelEmailRoutes(fastify: FastifyInstance) { const preHandler = [requireAuth] - // GET /api/cpanel/email + // GET /api/nixclient/email fastify.get('/', { preHandler }, async (request, reply) => { const user = request.user! const accountId = user.role === 'user' ? user.sub : parseInt((request.query as Record).accountId ?? '0', 10) @@ -21,7 +21,7 @@ export default async function cpanelEmailRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: accounts }) }) - // POST /api/cpanel/email + // POST /api/nixclient/email fastify.post('/', { preHandler }, async (request, reply) => { const user = request.user! const accountId = user.role === 'user' ? user.sub : (request.body as Record).accountId as number @@ -62,7 +62,7 @@ export default async function cpanelEmailRoutes(fastify: FastifyInstance) { return reply.code(201).send({ success: true, data: safe }) }) - // DELETE /api/cpanel/email/:id + // DELETE /api/nixclient/email/:id fastify.delete('/:id', { preHandler }, async (request, reply) => { const user = request.user! const accountId = user.role === 'user' ? user.sub : 0 @@ -80,7 +80,7 @@ export default async function cpanelEmailRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: 'Email account deleted' } }) }) - // GET /api/cpanel/email/forwarders + // GET /api/nixclient/email/forwarders fastify.get('/forwarders', { preHandler }, async (request, reply) => { const user = request.user! const accountId = user.role === 'user' ? user.sub : parseInt((request.query as Record).accountId ?? '0', 10) @@ -89,7 +89,7 @@ export default async function cpanelEmailRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: forwarders }) }) - // POST /api/cpanel/email/forwarders + // POST /api/nixclient/email/forwarders fastify.post('/forwarders', { preHandler }, async (request, reply) => { const user = request.user! const accountId = user.role === 'user' ? user.sub : (request.body as Record).accountId as number @@ -107,7 +107,7 @@ export default async function cpanelEmailRoutes(fastify: FastifyInstance) { return reply.code(201).send({ success: true, data: forwarder }) }) - // DELETE /api/cpanel/email/forwarders/:id + // DELETE /api/nixclient/email/forwarders/:id fastify.delete('/forwarders/:id', { preHandler }, async (request, reply) => { const user = request.user! const accountId = user.role === 'user' ? user.sub : 0 diff --git a/server/src/routes/cpanel/files.ts b/server/src/routes/nixclient/files.ts similarity index 92% rename from server/src/routes/cpanel/files.ts rename to server/src/routes/nixclient/files.ts index e1298c8..243d8fc 100644 --- a/server/src/routes/cpanel/files.ts +++ b/server/src/routes/nixclient/files.ts @@ -26,10 +26,10 @@ async function getAccount(fastify: FastifyInstance, userId: number) { export default async function fileRoutes(fastify: FastifyInstance) { const preHandler = [requireAuth] - // GET /api/cpanel/files?path= + // GET /api/nixclient/files?path= fastify.get('/', { preHandler }, async (request, reply) => { const user = request.user! - if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'cPanel users only' }) + if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'NixClient users only' }) const account = await getAccount(fastify, user.sub) if (!account) return reply.code(404).send({ success: false, error: 'Account not found' }) @@ -73,10 +73,10 @@ export default async function fileRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { path: userPath, files } }) }) - // GET /api/cpanel/files/content?path= + // GET /api/nixclient/files/content?path= fastify.get('/content', { preHandler }, async (request, reply) => { const user = request.user! - if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'cPanel users only' }) + if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'NixClient users only' }) const account = await getAccount(fastify, user.sub) if (!account) return reply.code(404).send({ success: false, error: 'Account not found' }) @@ -102,10 +102,10 @@ export default async function fileRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { path: q.path, content } }) }) - // PUT /api/cpanel/files/content — save file content + // PUT /api/nixclient/files/content — save file content fastify.put('/content', { preHandler }, async (request, reply) => { const user = request.user! - if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'cPanel users only' }) + if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'NixClient users only' }) const account = await getAccount(fastify, user.sub) if (!account) return reply.code(404).send({ success: false, error: 'Account not found' }) @@ -133,10 +133,10 @@ export default async function fileRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: 'File saved' } }) }) - // POST /api/cpanel/files/mkdir + // POST /api/nixclient/files/mkdir fastify.post('/mkdir', { preHandler }, async (request, reply) => { const user = request.user! - if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'cPanel users only' }) + if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'NixClient users only' }) const account = await getAccount(fastify, user.sub) if (!account) return reply.code(404).send({ success: false, error: 'Account not found' }) @@ -157,10 +157,10 @@ export default async function fileRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: 'Directory created' } }) }) - // DELETE /api/cpanel/files + // DELETE /api/nixclient/files fastify.delete('/', { preHandler }, async (request, reply) => { const user = request.user! - if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'cPanel users only' }) + if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'NixClient users only' }) const account = await getAccount(fastify, user.sub) if (!account) return reply.code(404).send({ success: false, error: 'Account not found' }) @@ -189,10 +189,10 @@ export default async function fileRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { deleted, errors } }) }) - // POST /api/cpanel/files/rename + // POST /api/nixclient/files/rename fastify.post('/rename', { preHandler }, async (request, reply) => { const user = request.user! - if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'cPanel users only' }) + if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'NixClient users only' }) const account = await getAccount(fastify, user.sub) if (!account) return reply.code(404).send({ success: false, error: 'Account not found' }) @@ -207,10 +207,10 @@ export default async function fileRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: 'Renamed' } }) }) - // POST /api/cpanel/files/chmod + // POST /api/nixclient/files/chmod fastify.post('/chmod', { preHandler }, async (request, reply) => { const user = request.user! - if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'cPanel users only' }) + if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'NixClient users only' }) const account = await getAccount(fastify, user.sub) if (!account) return reply.code(404).send({ success: false, error: 'Account not found' }) @@ -228,10 +228,10 @@ export default async function fileRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: 'Permissions updated' } }) }) - // POST /api/cpanel/files/compress — zip files + // POST /api/nixclient/files/compress — zip files fastify.post('/compress', { preHandler }, async (request, reply) => { const user = request.user! - if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'cPanel users only' }) + if (user.role !== 'user') return reply.code(403).send({ success: false, error: 'NixClient users only' }) const account = await getAccount(fastify, user.sub) if (!account) return reply.code(404).send({ success: false, error: 'Account not found' }) diff --git a/server/src/routes/cpanel/ftp.ts b/server/src/routes/nixclient/ftp.ts similarity index 100% rename from server/src/routes/cpanel/ftp.ts rename to server/src/routes/nixclient/ftp.ts diff --git a/server/src/routes/cpanel/index.ts b/server/src/routes/nixclient/index.ts similarity index 90% rename from server/src/routes/cpanel/index.ts rename to server/src/routes/nixclient/index.ts index 2175e7c..d1a7a27 100644 --- a/server/src/routes/cpanel/index.ts +++ b/server/src/routes/nixclient/index.ts @@ -7,7 +7,7 @@ import ftpRoutes from './ftp.js' import cronRoutes from './cron.js' import statsRoutes from './stats.js' -export default async function cpanelRoutes(fastify: FastifyInstance) { +export default async function nixclientRoutes(fastify: FastifyInstance) { fastify.register(fileRoutes, { prefix: '/files' }) fastify.register(databaseRoutes, { prefix: '/databases' }) fastify.register(emailRoutes, { prefix: '/email' }) diff --git a/server/src/routes/cpanel/stats.ts b/server/src/routes/nixclient/stats.ts similarity index 94% rename from server/src/routes/cpanel/stats.ts rename to server/src/routes/nixclient/stats.ts index 0efd2f3..ae289d3 100644 --- a/server/src/routes/cpanel/stats.ts +++ b/server/src/routes/nixclient/stats.ts @@ -6,7 +6,7 @@ import { exec } from '../../core/exec.js' export default async function statsRoutes(fastify: FastifyInstance) { const preHandler = [requireAuth] - // GET /api/cpanel/stats — account resource usage summary + // GET /api/nixclient/stats — account resource usage summary fastify.get('/', { preHandler }, async (request, reply) => { const user = request.user! const accountId = user.role === 'user' ? user.sub : parseInt((request.query as Record).accountId ?? '0', 10) @@ -57,7 +57,7 @@ export default async function statsRoutes(fastify: FastifyInstance) { }) }) - // GET /api/cpanel/stats/bandwidth — bandwidth usage over time (placeholder for log parsing) + // GET /api/nixclient/stats/bandwidth — bandwidth usage over time (placeholder for log parsing) fastify.get('/bandwidth', { preHandler }, async (request, reply) => { const user = request.user! const accountId = user.role === 'user' ? user.sub : parseInt((request.query as Record).accountId ?? '0', 10) diff --git a/server/src/routes/whm/accounts.ts b/server/src/routes/nixserver/accounts.ts similarity index 97% rename from server/src/routes/whm/accounts.ts rename to server/src/routes/nixserver/accounts.ts index 3075f6f..f7734ed 100644 --- a/server/src/routes/whm/accounts.ts +++ b/server/src/routes/nixserver/accounts.ts @@ -28,7 +28,7 @@ const UpdateAccountSchema = z.object({ export default async function accountRoutes(fastify: FastifyInstance) { const preHandler = [requireAdminOrReseller] - // GET /api/whm/accounts + // GET /api/nixserver/accounts fastify.get('/', { preHandler }, async (request, reply) => { const q = request.query as Record const page = Math.max(1, parseInt(q.page ?? '1', 10)) @@ -69,7 +69,7 @@ export default async function accountRoutes(fastify: FastifyInstance) { }) }) - // GET /api/whm/accounts/stats + // GET /api/nixserver/accounts/stats fastify.get('/stats', { preHandler }, async (request, reply) => { const where = request.user!.role === 'reseller' ? { resellerId: request.user!.sub } : {} @@ -83,7 +83,7 @@ export default async function accountRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { total, active, suspended, terminated } }) }) - // GET /api/whm/accounts/:id + // GET /api/nixserver/accounts/:id fastify.get('/:id', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } const where: Record = { id: parseInt(id, 10) } @@ -111,7 +111,7 @@ export default async function accountRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: safe }) }) - // POST /api/whm/accounts + // POST /api/nixserver/accounts fastify.post('/', { preHandler }, async (request, reply) => { const body = CreateAccountSchema.safeParse(request.body) if (!body.success) { @@ -228,7 +228,7 @@ export default async function accountRoutes(fastify: FastifyInstance) { return reply.code(201).send({ success: true, data: safe }) }) - // PUT /api/whm/accounts/:id + // PUT /api/nixserver/accounts/:id fastify.put('/:id', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } const body = UpdateAccountSchema.safeParse(request.body) @@ -261,7 +261,7 @@ export default async function accountRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: safe }) }) - // POST /api/whm/accounts/:id/suspend + // POST /api/nixserver/accounts/:id/suspend fastify.post('/:id/suspend', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } const { reason } = (request.body as Record) ?? {} @@ -291,7 +291,7 @@ export default async function accountRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: `Account ${account.username} suspended` } }) }) - // POST /api/whm/accounts/:id/unsuspend + // POST /api/nixserver/accounts/:id/unsuspend fastify.post('/:id/unsuspend', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } @@ -319,7 +319,7 @@ export default async function accountRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: `Account ${account.username} unsuspended` } }) }) - // DELETE /api/whm/accounts/:id + // DELETE /api/nixserver/accounts/:id fastify.delete('/:id', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } const { removeFiles } = (request.body as Record) ?? {} @@ -364,7 +364,7 @@ export default async function accountRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: `Account ${account.username} terminated` } }) }) - // POST /api/whm/accounts/bulk + // POST /api/nixserver/accounts/bulk fastify.post('/bulk', { preHandler }, async (request, reply) => { const body = z.object({ action: z.enum(['suspend', 'unsuspend', 'terminate']), diff --git a/server/src/routes/whm/backup.ts b/server/src/routes/nixserver/backup.ts similarity index 93% rename from server/src/routes/whm/backup.ts rename to server/src/routes/nixserver/backup.ts index 9fc1d86..dc44c38 100644 --- a/server/src/routes/whm/backup.ts +++ b/server/src/routes/nixserver/backup.ts @@ -9,7 +9,7 @@ import { config } from '../../config.js' const BACKUP_DIR = '/var/nixpanel/backups' export default async function backupRoutes(fastify: FastifyInstance) { - // POST /api/whm/backup/account/:id — backup a single account + // POST /api/nixserver/backup/account/:id — backup a single account fastify.post('/account/:id', { preHandler: [requireAdmin] }, async (request, reply) => { const { id } = request.params as { id: string } const account = await prisma.account.findUnique({ where: { id: parseInt(id, 10) } }) @@ -39,7 +39,7 @@ export default async function backupRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { filename, path: dest, size, createdAt: new Date() } }) }) - // POST /api/whm/backup/server — full server backup + // POST /api/nixserver/backup/server — full server backup fastify.post('/server', { preHandler: [requireAdmin] }, async (request, reply) => { const timestamp = new Date().toISOString().replace(/[:.]/g, '-') const filename = `server-backup-${timestamp}.tar.gz` @@ -61,7 +61,7 @@ export default async function backupRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { filename, path: dest, createdAt: new Date() } }) }) - // GET /api/whm/backup/list — list available backups + // GET /api/nixserver/backup/list — list available backups fastify.get('/list', { preHandler: [requireAdmin] }, async (request, reply) => { const result = await exec('find', [BACKUP_DIR, '-name', '*.tar.gz', '-printf', '%p %s %T@\n']) if (result.exitCode !== 0 && !result.stdout) { @@ -81,7 +81,7 @@ export default async function backupRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: backups }) }) - // DELETE /api/whm/backup — delete a backup file + // DELETE /api/nixserver/backup — delete a backup file fastify.delete('/', { preHandler: [requireAdmin] }, async (request, reply) => { const body = z.object({ path: z.string() }).safeParse(request.body) if (!body.success) { @@ -96,7 +96,7 @@ export default async function backupRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: 'Backup deleted' } }) }) - // POST /api/whm/backup/restore/:filename + // POST /api/nixserver/backup/restore/:filename fastify.post('/restore/:filename', { preHandler: [requireAdmin] }, async (request, reply) => { const { filename } = request.params as { filename: string } // Sanitize — no path traversal diff --git a/server/src/routes/whm/dns.ts b/server/src/routes/nixserver/dns.ts similarity index 95% rename from server/src/routes/whm/dns.ts rename to server/src/routes/nixserver/dns.ts index eeb482d..3ed02fd 100644 --- a/server/src/routes/whm/dns.ts +++ b/server/src/routes/nixserver/dns.ts @@ -16,7 +16,7 @@ const DnsRecordSchema = z.object({ export default async function dnsRoutes(fastify: FastifyInstance) { const preHandler = [requireAdminOrReseller] - // GET /api/whm/dns + // GET /api/nixserver/dns fastify.get('/', { preHandler }, async (request, reply) => { const q = request.query as Record const where: Record = {} @@ -34,7 +34,7 @@ export default async function dnsRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: zones }) }) - // GET /api/whm/dns/:id + // GET /api/nixserver/dns/:id fastify.get('/:id', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } const zone = await prisma.dnsZone.findUnique({ @@ -48,7 +48,7 @@ export default async function dnsRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: zone }) }) - // POST /api/whm/dns/:id/records + // POST /api/nixserver/dns/:id/records fastify.post('/:id/records', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } const body = DnsRecordSchema.safeParse(request.body) @@ -72,7 +72,7 @@ export default async function dnsRoutes(fastify: FastifyInstance) { return reply.code(201).send({ success: true, data: record }) }) - // PUT /api/whm/dns/:zoneId/records/:recordId + // PUT /api/nixserver/dns/:zoneId/records/:recordId fastify.put('/:zoneId/records/:recordId', { preHandler }, async (request, reply) => { const { zoneId, recordId } = request.params as { zoneId: string; recordId: string } const body = DnsRecordSchema.partial().safeParse(request.body) @@ -95,7 +95,7 @@ export default async function dnsRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: updated }) }) - // DELETE /api/whm/dns/:zoneId/records/:recordId + // DELETE /api/nixserver/dns/:zoneId/records/:recordId fastify.delete('/:zoneId/records/:recordId', { preHandler }, async (request, reply) => { const { zoneId, recordId } = request.params as { zoneId: string; recordId: string } @@ -110,7 +110,7 @@ export default async function dnsRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: 'Record deleted' } }) }) - // POST /api/whm/dns/:id/reload + // POST /api/nixserver/dns/:id/reload fastify.post('/:id/reload', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } await rebuildZone(parseInt(id, 10)) diff --git a/server/src/routes/whm/email.ts b/server/src/routes/nixserver/email.ts similarity index 94% rename from server/src/routes/whm/email.ts rename to server/src/routes/nixserver/email.ts index dbffd62..1df1f50 100644 --- a/server/src/routes/whm/email.ts +++ b/server/src/routes/nixserver/email.ts @@ -8,7 +8,7 @@ import { exec } from '../../core/exec.js' export default async function emailRoutes(fastify: FastifyInstance) { const preHandler = [requireAdminOrReseller] - // GET /api/whm/email?accountId= + // GET /api/nixserver/email?accountId= fastify.get('/', { preHandler }, async (request, reply) => { const q = request.query as Record const where: Record = {} @@ -27,7 +27,7 @@ export default async function emailRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: accounts }) }) - // POST /api/whm/email + // POST /api/nixserver/email fastify.post('/', { preHandler }, async (request, reply) => { const body = z.object({ accountId: z.number().int().positive(), @@ -81,7 +81,7 @@ export default async function emailRoutes(fastify: FastifyInstance) { return reply.code(201).send({ success: true, data: safe }) }) - // DELETE /api/whm/email/:id + // DELETE /api/nixserver/email/:id fastify.delete('/:id', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } const emailAccount = await prisma.emailAccount.findUnique({ where: { id: parseInt(id, 10) } }) @@ -93,7 +93,7 @@ export default async function emailRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: 'Email account deleted' } }) }) - // POST /api/whm/email/:id/password + // POST /api/nixserver/email/:id/password fastify.post('/:id/password', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } const body = z.object({ password: z.string().min(8) }).safeParse(request.body) @@ -110,7 +110,7 @@ export default async function emailRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: 'Password updated' } }) }) - // GET /api/whm/email/forwarders?accountId= + // GET /api/nixserver/email/forwarders?accountId= fastify.get('/forwarders', { preHandler }, async (request, reply) => { const q = request.query as Record const where: Record = {} @@ -120,7 +120,7 @@ export default async function emailRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: forwarders }) }) - // POST /api/whm/email/forwarders + // POST /api/nixserver/email/forwarders fastify.post('/forwarders', { preHandler }, async (request, reply) => { const body = z.object({ accountId: z.number().int().positive(), @@ -136,7 +136,7 @@ export default async function emailRoutes(fastify: FastifyInstance) { return reply.code(201).send({ success: true, data: forwarder }) }) - // DELETE /api/whm/email/forwarders/:id + // DELETE /api/nixserver/email/forwarders/:id fastify.delete('/forwarders/:id', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } await prisma.emailForwarder.delete({ where: { id: parseInt(id, 10) } }) diff --git a/server/src/routes/whm/index.ts b/server/src/routes/nixserver/index.ts similarity index 94% rename from server/src/routes/whm/index.ts rename to server/src/routes/nixserver/index.ts index cad6040..48f067e 100644 --- a/server/src/routes/whm/index.ts +++ b/server/src/routes/nixserver/index.ts @@ -12,7 +12,7 @@ import securityRoutes from './security.js' import backupRoutes from './backup.js' import webserverRoutes from './webserver.js' -export default async function whmRoutes(fastify: FastifyInstance) { +export default async function nixserverRoutes(fastify: FastifyInstance) { fastify.register(accountRoutes, { prefix: '/accounts' }) fastify.register(packageRoutes, { prefix: '/packages' }) fastify.register(resellerRoutes, { prefix: '/resellers' }) diff --git a/server/src/routes/whm/packages.ts b/server/src/routes/nixserver/packages.ts similarity index 100% rename from server/src/routes/whm/packages.ts rename to server/src/routes/nixserver/packages.ts diff --git a/server/src/routes/whm/php.ts b/server/src/routes/nixserver/php.ts similarity index 93% rename from server/src/routes/whm/php.ts rename to server/src/routes/nixserver/php.ts index 872e1eb..dc78881 100644 --- a/server/src/routes/whm/php.ts +++ b/server/src/routes/nixserver/php.ts @@ -8,7 +8,7 @@ import { writeFile } from '../../core/exec.js' const SUPPORTED_PHP_VERSIONS = ['7.4', '8.0', '8.1', '8.2', '8.3'] export default async function phpRoutes(fastify: FastifyInstance) { - // GET /api/whm/php/versions — list installed PHP versions + // GET /api/nixserver/php/versions — list installed PHP versions fastify.get('/versions', { preHandler: [requireAdmin] }, async (request, reply) => { const versions: { version: string; installed: boolean; active: boolean }[] = [] @@ -21,7 +21,7 @@ export default async function phpRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: versions }) }) - // GET /api/whm/php/accounts — list which PHP version each account uses + // GET /api/nixserver/php/accounts — list which PHP version each account uses fastify.get('/accounts', { preHandler: [requireAdmin] }, async (request, reply) => { const accounts = await prisma.account.findMany({ where: { status: 'active' }, @@ -33,7 +33,7 @@ export default async function phpRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: accounts }) }) - // PUT /api/whm/php/accounts/:id — change PHP version for account + // PUT /api/nixserver/php/accounts/:id — change PHP version for account fastify.put('/accounts/:id', { preHandler: [requireAdmin] }, async (request, reply) => { const { id } = request.params as { id: string } const body = z.object({ @@ -82,7 +82,7 @@ php_admin_value[error_log] = ${account.homedir}/logs/php_errors.log return reply.send({ success: true, data: { message: `PHP version set to ${body.data.phpVersion}` } }) }) - // GET /api/whm/php/ini/:version — get php.ini settings + // GET /api/nixserver/php/ini/:version — get php.ini settings fastify.get('/ini/:version', { preHandler: [requireAdmin] }, async (request, reply) => { const { version } = request.params as { version: string } if (!SUPPORTED_PHP_VERSIONS.includes(version)) { diff --git a/server/src/routes/whm/resellers.ts b/server/src/routes/nixserver/resellers.ts similarity index 100% rename from server/src/routes/whm/resellers.ts rename to server/src/routes/nixserver/resellers.ts diff --git a/server/src/routes/whm/security.ts b/server/src/routes/nixserver/security.ts similarity index 90% rename from server/src/routes/whm/security.ts rename to server/src/routes/nixserver/security.ts index 57d9ff4..a5f95c3 100644 --- a/server/src/routes/whm/security.ts +++ b/server/src/routes/nixserver/security.ts @@ -5,7 +5,7 @@ import { requireAdmin } from '../../middleware/auth.js' import { exec } from '../../core/exec.js' export default async function securityRoutes(fastify: FastifyInstance) { - // GET /api/whm/security/events + // GET /api/nixserver/security/events fastify.get('/events', { preHandler: [requireAdmin] }, async (request, reply) => { const q = request.query as Record const page = Math.max(1, parseInt(q.page ?? '1', 10)) @@ -25,7 +25,7 @@ export default async function securityRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { items, total, page, limit, totalPages: Math.ceil(total / limit) } }) }) - // POST /api/whm/security/events/:id/resolve + // POST /api/nixserver/security/events/:id/resolve fastify.post('/events/:id/resolve', { preHandler: [requireAdmin] }, async (request, reply) => { const { id } = request.params as { id: string } await prisma.securityEvent.update({ @@ -35,13 +35,13 @@ export default async function securityRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: 'Event resolved' } }) }) - // GET /api/whm/security/blocked-ips + // GET /api/nixserver/security/blocked-ips fastify.get('/blocked-ips', { preHandler: [requireAdmin] }, async (request, reply) => { const blocked = await prisma.blockedIp.findMany({ orderBy: { createdAt: 'desc' } }) return reply.send({ success: true, data: blocked }) }) - // POST /api/whm/security/blocked-ips + // POST /api/nixserver/security/blocked-ips fastify.post('/blocked-ips', { preHandler: [requireAdmin] }, async (request, reply) => { const body = z.object({ ip: z.string().ip(), @@ -69,7 +69,7 @@ export default async function securityRoutes(fastify: FastifyInstance) { return reply.code(201).send({ success: true, data: blocked }) }) - // DELETE /api/whm/security/blocked-ips/:id + // DELETE /api/nixserver/security/blocked-ips/:id fastify.delete('/blocked-ips/:id', { preHandler: [requireAdmin] }, async (request, reply) => { const { id } = request.params as { id: string } const blocked = await prisma.blockedIp.findUnique({ where: { id: parseInt(id, 10) } }) @@ -81,13 +81,13 @@ export default async function securityRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: `${blocked.ip} unblocked` } }) }) - // GET /api/whm/security/whitelisted-ips + // GET /api/nixserver/security/whitelisted-ips fastify.get('/whitelisted-ips', { preHandler: [requireAdmin] }, async (request, reply) => { const list = await prisma.whitelistedIp.findMany({ orderBy: { createdAt: 'desc' } }) return reply.send({ success: true, data: list }) }) - // POST /api/whm/security/whitelisted-ips + // POST /api/nixserver/security/whitelisted-ips fastify.post('/whitelisted-ips', { preHandler: [requireAdmin] }, async (request, reply) => { const body = z.object({ ip: z.string().ip(), @@ -102,20 +102,20 @@ export default async function securityRoutes(fastify: FastifyInstance) { return reply.code(201).send({ success: true, data: entry }) }) - // DELETE /api/whm/security/whitelisted-ips/:id + // DELETE /api/nixserver/security/whitelisted-ips/:id fastify.delete('/whitelisted-ips/:id', { preHandler: [requireAdmin] }, async (request, reply) => { const { id } = request.params as { id: string } await prisma.whitelistedIp.delete({ where: { id: parseInt(id, 10) } }) return reply.send({ success: true, data: { message: 'Removed from whitelist' } }) }) - // GET /api/whm/security/fail2ban + // GET /api/nixserver/security/fail2ban fastify.get('/fail2ban', { preHandler: [requireAdmin] }, async (request, reply) => { const result = await exec('fail2ban-client', ['status']) return reply.send({ success: true, data: { output: result.stdout } }) }) - // GET /api/whm/security/fail2ban/:jail + // GET /api/nixserver/security/fail2ban/:jail fastify.get('/fail2ban/:jail', { preHandler: [requireAdmin] }, async (request, reply) => { const { jail } = request.params as { jail: string } const result = await exec('fail2ban-client', ['status', jail]) diff --git a/server/src/routes/whm/services.ts b/server/src/routes/nixserver/services.ts similarity index 90% rename from server/src/routes/whm/services.ts rename to server/src/routes/nixserver/services.ts index 8859019..9fca6c5 100644 --- a/server/src/routes/whm/services.ts +++ b/server/src/routes/nixserver/services.ts @@ -9,13 +9,13 @@ const ServiceActionSchema = z.object({ }) export default async function serviceRoutes(fastify: FastifyInstance) { - // GET /api/whm/services — list all managed services and their status + // GET /api/nixserver/services — list all managed services and their status fastify.get('/', { preHandler: [requireAdmin] }, async (request, reply) => { const statuses = await Promise.all(MANAGED_SERVICES.map(getServiceStatus)) return reply.send({ success: true, data: statuses }) }) - // GET /api/whm/services/:name + // GET /api/nixserver/services/:name fastify.get('/:name', { preHandler: [requireAdmin] }, async (request, reply) => { const { name } = request.params as { name: string } if (!MANAGED_SERVICES.includes(name)) { @@ -25,7 +25,7 @@ export default async function serviceRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: status }) }) - // POST /api/whm/services/:name — start/stop/restart/reload/enable/disable + // POST /api/nixserver/services/:name — start/stop/restart/reload/enable/disable fastify.post('/:name', { preHandler: [requireAdmin] }, async (request, reply) => { const { name } = request.params as { name: string } const body = ServiceActionSchema.safeParse(request.body) diff --git a/server/src/routes/whm/ssl.ts b/server/src/routes/nixserver/ssl.ts similarity index 96% rename from server/src/routes/whm/ssl.ts rename to server/src/routes/nixserver/ssl.ts index 9105b6a..bb32c6a 100644 --- a/server/src/routes/whm/ssl.ts +++ b/server/src/routes/nixserver/ssl.ts @@ -10,7 +10,7 @@ import { config } from '../../config.js' export default async function sslRoutes(fastify: FastifyInstance) { const preHandler = [requireAdminOrReseller] - // GET /api/whm/ssl + // GET /api/nixserver/ssl fastify.get('/', { preHandler }, async (request, reply) => { const q = request.query as Record const where: Record = {} @@ -25,7 +25,7 @@ export default async function sslRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: certs }) }) - // POST /api/whm/ssl/issue — issue Let's Encrypt cert via certbot + // POST /api/nixserver/ssl/issue — issue Let's Encrypt cert via certbot fastify.post('/issue', { preHandler }, async (request, reply) => { const body = z.object({ accountId: z.number().int().positive(), @@ -100,7 +100,7 @@ export default async function sslRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: cert }) }) - // POST /api/whm/ssl/revoke + // POST /api/nixserver/ssl/revoke fastify.post('/:id/revoke', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } const cert = await prisma.sslCertificate.findUnique({ where: { id: parseInt(id, 10) } }) @@ -121,7 +121,7 @@ export default async function sslRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: 'Certificate revoked' } }) }) - // POST /api/whm/ssl/:id/renew + // POST /api/nixserver/ssl/:id/renew fastify.post('/:id/renew', { preHandler }, async (request, reply) => { const { id } = request.params as { id: string } const cert = await prisma.sslCertificate.findUnique({ where: { id: parseInt(id, 10) } }) diff --git a/server/src/routes/whm/system.ts b/server/src/routes/nixserver/system.ts similarity index 93% rename from server/src/routes/whm/system.ts rename to server/src/routes/nixserver/system.ts index 6594eb7..cef6e3c 100644 --- a/server/src/routes/whm/system.ts +++ b/server/src/routes/nixserver/system.ts @@ -6,13 +6,13 @@ import { exec } from '../../core/exec.js' import { readFile } from 'fs/promises' export default async function systemRoutes(fastify: FastifyInstance) { - // GET /api/whm/system/stats + // GET /api/nixserver/system/stats fastify.get('/stats', { preHandler: [requireAdmin] }, async (request, reply) => { const stats = await getSystemStats() return reply.send({ success: true, data: stats }) }) - // GET /api/whm/system/info + // GET /api/nixserver/system/info fastify.get('/info', { preHandler: [requireAdmin] }, async (request, reply) => { const [hostname, osRelease, kernel, uptime] = await Promise.all([ exec('hostname', ['-f']), @@ -39,7 +39,7 @@ export default async function systemRoutes(fastify: FastifyInstance) { }) }) - // GET /api/whm/system/processes + // GET /api/nixserver/system/processes fastify.get('/processes', { preHandler: [requireAdmin] }, async (request, reply) => { const result = await exec('ps', ['aux', '--sort=-%cpu']) if (result.exitCode !== 0) { @@ -61,7 +61,7 @@ export default async function systemRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: processes }) }) - // POST /api/whm/system/processes/:pid/kill + // POST /api/nixserver/system/processes/:pid/kill fastify.post('/processes/:pid/kill', { preHandler: [requireAdmin] }, async (request, reply) => { const { pid } = request.params as { pid: string } if (!/^\d+$/.test(pid) || parseInt(pid, 10) <= 1) { @@ -74,7 +74,7 @@ export default async function systemRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: { message: `Process ${pid} killed` } }) }) - // GET /api/whm/system/audit-log + // GET /api/nixserver/system/audit-log fastify.get('/audit-log', { preHandler: [requireAdmin] }, async (request, reply) => { const q = request.query as Record const page = Math.max(1, parseInt(q.page ?? '1', 10)) @@ -96,7 +96,7 @@ export default async function systemRoutes(fastify: FastifyInstance) { }) }) - // GET /api/whm/system/settings + // GET /api/nixserver/system/settings fastify.get('/settings', { preHandler: [requireAdmin] }, async (request, reply) => { const settings = await prisma.setting.findMany({ orderBy: { key: 'asc' } }) const map: Record = {} @@ -104,7 +104,7 @@ export default async function systemRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: map }) }) - // PUT /api/whm/system/settings + // PUT /api/nixserver/system/settings fastify.put('/settings', { preHandler: [requireAdmin] }, async (request, reply) => { const body = request.body as Record if (typeof body !== 'object' || Array.isArray(body)) { diff --git a/server/src/routes/whm/webserver.ts b/server/src/routes/nixserver/webserver.ts similarity index 90% rename from server/src/routes/whm/webserver.ts rename to server/src/routes/nixserver/webserver.ts index 39d72bf..e2d5d44 100644 --- a/server/src/routes/whm/webserver.ts +++ b/server/src/routes/nixserver/webserver.ts @@ -5,7 +5,7 @@ import { exec } from '../../core/exec.js' import { readFile } from 'fs/promises' export default async function webserverRoutes(fastify: FastifyInstance) { - // GET /api/whm/webserver/status + // GET /api/nixserver/webserver/status fastify.get('/status', { preHandler: [requireAdmin] }, async (request, reply) => { const [nginx, apache] = await Promise.all([ exec('systemctl', ['is-active', 'nginx']), @@ -20,7 +20,7 @@ export default async function webserverRoutes(fastify: FastifyInstance) { }) }) - // GET /api/whm/webserver/vhosts + // GET /api/nixserver/webserver/vhosts fastify.get('/vhosts', { preHandler: [requireAdmin] }, async (request, reply) => { const result = await exec('find', ['/etc/nginx/sites-enabled', '-name', '*.conf', '-type', 'f']) const files = result.stdout.split('\n').filter(Boolean) @@ -31,7 +31,7 @@ export default async function webserverRoutes(fastify: FastifyInstance) { return reply.send({ success: true, data: vhosts }) }) - // GET /api/whm/webserver/vhosts/:domain + // GET /api/nixserver/webserver/vhosts/:domain fastify.get('/vhosts/:domain', { preHandler: [requireAdmin] }, async (request, reply) => { const { domain } = request.params as { domain: string } if (domain.includes('/') || domain.includes('..')) { @@ -45,7 +45,7 @@ export default async function webserverRoutes(fastify: FastifyInstance) { } }) - // POST /api/whm/webserver/nginx/test + // POST /api/nixserver/webserver/nginx/test fastify.post('/nginx/test', { preHandler: [requireAdmin] }, async (request, reply) => { const result = await exec('nginx', ['-t']) return reply.send({ @@ -54,7 +54,7 @@ export default async function webserverRoutes(fastify: FastifyInstance) { }) }) - // POST /api/whm/webserver/nginx/reload + // POST /api/nixserver/webserver/nginx/reload fastify.post('/nginx/reload', { preHandler: [requireAdmin] }, async (request, reply) => { const test = await exec('nginx', ['-t']) if (test.exitCode !== 0) { @@ -64,7 +64,7 @@ export default async function webserverRoutes(fastify: FastifyInstance) { return reply.send({ success: result.exitCode === 0, data: { output: result.stdout } }) }) - // GET /api/whm/webserver/logs/:type — access or error log (last 200 lines) + // GET /api/nixserver/webserver/logs/:type — access or error log (last 200 lines) fastify.get('/logs/:type', { preHandler: [requireAdmin] }, async (request, reply) => { const { type } = request.params as { type: string } const logFile = type === 'error' ? '/var/log/nginx/error.log' : '/var/log/nginx/access.log'