Commit Graph

7 Commits

Author SHA1 Message Date
myron f75f124725 Fix login and panel visibility for user and reseller portals
- initUser/initReseller: show main-layout and hide auth-check on
  successful auth (was never shown, causing blank page after login)
- Fix login form IDs in user/index.php and reseller/index.php:
  changed l-user/l-pass/login-err to li-user/li-pass/li-err to
  match what doLogin() reads; add onsubmit handler so form works
  immediately without waiting for JS to replace it
- Wire logout button in both boot sequences
- Fix data.accounts → data in reseller.js (same paginate() bug as admin)
- Reset myron user password to Joker1974!!!

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 22:50:28 +00:00
myron 33c36ffc65 Add #18 reseller white-label branding + #24 audit log UI with filters
#18: reseller_branding table (migration 008). branding.php endpoint: get/save/
     upload-logo/delete-logo/resellers. _branding.php server-side helper injects
     CSS vars (--primary, --accent), custom CSS, favicon, and panel name into
     <head> of reseller + user portals at page-load time (no flash of unbranded
     content). NOVACPX_BRANDING JS global carries panel_name/support_email/
     support_url/hide_powered_by for runtime use. Reseller panel gets a new
     "White Label" sidebar page with logo upload, color pickers with live preview,
     support contact fields, powered-by toggle, and custom CSS textarea.

#24: audit-log backend now accepts user/action/date_from/date_to filter params.
     auditLog() JS rebuilt: filter bar at top, paginated table, expandable detail
     rows (click row to show JSON detail), total entry count, page buttons.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 03:51:45 +00:00
myron aa93695459 Merge branch 'main' of https://github.com/myronblair/novacpx
# Conflicts:
#	db/migrations/002_features_14_17.sql
2026-06-08 01:22:31 +00:00
myron 6fdccc6dbd feat: items #9-13 — password change, webmail SSO, DKIM live, file manager security, cache busting
#9  auth.php: add self-service change-password action (current+new+confirm)
    accounts.php: fix admin change-password — accept account_id, fetch username
    for chpasswd (was using int ID), add Auth::require('admin') guard
    user.js: add Change Password page + navItem + submitChangePassword()

#10 EmailManager: store AES-256-CBC enc_password alongside SHA512-CRYPT hash
    webmail.php: rewrite login-url to use webmail_sso_tokens table
    novacpx-sso.php: Roundcube SSO bridge (validate token, decrypt, autosubmit)
    Migration 005: add enc_password column + webmail_sso_tokens table

#11 opendkim: installed, configured (/etc/opendkim.conf, signing.table,
    key.table, trusted.hosts), socket at /var/spool/postfix/opendkim/,
    Postfix milter wired, service enabled+running, key generation verified

#12 files.php: fix safe_path() for non-existent paths (write/mkdir),
    add safe_path_new() helper using parent-dir realpath check,
    fix delete guard (block deleting account root dirs),
    fix rename destination, clamp chmod to 0777

#13 nova.js: api() handles network errors, 429 rate-limit with retry-after,
    non-JSON responses (PHP fatal pages) — graceful error instead of throw
    admin/user/reseller index.php: filemtime-based cache-busting on all assets

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 01:19:33 +00:00
myron 88e98b4727 feat: polish items #26-29 — mobile CSS, error pages, rate limiting, session manager
#26 Mobile responsive:
- Hamburger button (SVG) in topbar for all three panels (admin/user/reseller)
- Sidebar overlay div for click-outside-to-close on mobile
- nova.js: DOMContentLoaded toggle handler with overlay and auto-close on nav click
- nova.css: sidebar-overlay, page-header, panel/panel-header, table, btn-success/warning/danger/secondary/xs,
  badge-muted; mobile media query shows toggle, fixes stats-grid/modal/panel-header layout

#27 Custom error pages:
- /errors/404.php and /errors/500.php with NovaCPX dark theme matching panel design
- Apache ErrorDocument 400/401/403/404/500/503 for ports 8880/8881/8882 with Alias /errors

#28 API rate limiting:
- api_rate_limits table (migration 004) with per-IP per-bucket counters
- api/index.php: 10 req/min for auth endpoint, 120 req/min for all others
- Returns X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset headers
- Returns 429 Too Many Requests when exceeded; rate limit failure is non-fatal

#29 Session Manager:
- sessions.php endpoint: list/revoke/revoke-user/revoke-all
- Admin panel Sessions page: table of active sessions with user, role, IP, browser, timestamps
- Revoke single session, revoke all for user, revoke all sessions (self-evicts)
2026-06-08 00:50:21 +00:00
myron 870ec062f0 Add complete user and reseller panel JS — all pages fully implemented
User panel (user.js): dashboard with usage rings, domains+SSL, email accounts+forwarders, databases, FTP, SSL manager, PHP switcher, cron jobs, file manager (edit/upload/chmod), stats
Reseller panel (reseller.js): dashboard, accounts list+search+suspend/terminate, create account form, packages CRUD, DNS zones editor
Both panels: dynamic sidebar nav using nova-icons.svg sprite, inline auth guard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 06:08:32 +00:00
myron 716d292e77 feat: dedicated ports per panel tier (8880/8881/8882)
Each panel now has its own dedicated port and is fully self-contained:
- Port 8880: User panel (end-user hosting dashboard)
- Port 8881: Reseller panel (account/package management)
- Port 8882: Admin panel (datacenter/server manager)

Changes:
- install.sh: PORT_USER/PORT_RESELLER/PORT_ADMIN constants; three separate
  nginx/Apache vhosts; UFW opens all three ports; Fail2Ban jail per port;
  credentials file shows all three URLs
- config.ini: stores port_user/port_reseller/port_admin
- Core.php: defines PORT_USER/RESELLER/ADMIN, detects CURRENT_PORTAL from
  SERVER_PORT so the API knows which tier is being accessed
- Auth.php: portalUrl() maps role → correct port for cross-portal redirects
- auth.php endpoint: returns portal_url on login so JS redirects to right port
- index.php login: uses portal_url from API response (no hardcoded paths)
- admin/index.php: inline login form (port 8882 is self-contained, no redirect)
- user/index.php: inline login form (port 8880 self-contained)
- reseller/index.php: new full reseller panel with inline login (port 8881);
  sidebar with accounts, packages, DNS, branding, bandwidth report sections

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 05:35:48 +00:00