Skip to content

Commit c6e6ad3

Browse files
markcclaude
andcommitted
Add HCP database schema and QueryType enum
- 11-HCP/schema/hcp.sql: Unified schema for hosting control panel (users, posts, categories, vhosts, vmails, valias, vdns, ssl_certs) - app/lib/QueryType.php: Enum for database query result types Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c8ee3fa commit c6e6ad3

File tree

2 files changed

+196
-0
lines changed

2 files changed

+196
-0
lines changed

11-HCP/schema/hcp.sql

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
-- HCP Unified Database Schema
2+
-- Supports SQLite and MariaDB/MySQL
3+
4+
-- Users table (authentication & authorization)
5+
CREATE TABLE IF NOT EXISTS users (
6+
id INTEGER PRIMARY KEY AUTOINCREMENT,
7+
acl INTEGER NOT NULL DEFAULT 2, -- 0=SuperAdmin, 1=Admin, 2=User, 3=Suspended, 9=Anonymous
8+
login TEXT UNIQUE NOT NULL, -- Email address
9+
fname TEXT DEFAULT '',
10+
lname TEXT DEFAULT '',
11+
altemail TEXT DEFAULT '',
12+
webpw TEXT DEFAULT '', -- Password hash
13+
otp TEXT DEFAULT '', -- One-time password token
14+
otpttl INTEGER DEFAULT 0, -- OTP time-to-live
15+
cookie TEXT DEFAULT '', -- Remember me cookie
16+
anote TEXT DEFAULT '', -- Admin notes
17+
updated DATETIME DEFAULT CURRENT_TIMESTAMP,
18+
created DATETIME DEFAULT CURRENT_TIMESTAMP
19+
);
20+
21+
-- Categories for posts/docs
22+
CREATE TABLE IF NOT EXISTS categories (
23+
id INTEGER PRIMARY KEY AUTOINCREMENT,
24+
name TEXT NOT NULL UNIQUE,
25+
slug TEXT NOT NULL UNIQUE,
26+
description TEXT DEFAULT '',
27+
created DATETIME DEFAULT CURRENT_TIMESTAMP
28+
);
29+
30+
-- Posts table (pages, blog posts, docs)
31+
CREATE TABLE IF NOT EXISTS posts (
32+
id INTEGER PRIMARY KEY AUTOINCREMENT,
33+
author_id INTEGER NOT NULL,
34+
type TEXT NOT NULL DEFAULT 'post', -- 'page', 'post', 'doc'
35+
title TEXT NOT NULL,
36+
slug TEXT NOT NULL UNIQUE,
37+
icon TEXT DEFAULT '', -- Lucide icon name
38+
excerpt TEXT DEFAULT '',
39+
content TEXT DEFAULT '',
40+
featured_image TEXT DEFAULT '',
41+
status TEXT DEFAULT 'published', -- 'draft', 'published', 'archived'
42+
updated DATETIME DEFAULT CURRENT_TIMESTAMP,
43+
created DATETIME DEFAULT CURRENT_TIMESTAMP,
44+
FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE
45+
);
46+
47+
-- Post-Category junction table
48+
CREATE TABLE IF NOT EXISTS post_categories (
49+
post_id INTEGER NOT NULL,
50+
category_id INTEGER NOT NULL,
51+
PRIMARY KEY (post_id, category_id),
52+
FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
53+
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
54+
);
55+
56+
-- Virtual Hosts
57+
CREATE TABLE IF NOT EXISTS vhosts (
58+
id INTEGER PRIMARY KEY AUTOINCREMENT,
59+
user_id INTEGER, -- Owner (for multi-tenant)
60+
domain TEXT NOT NULL UNIQUE,
61+
aliases TEXT DEFAULT '', -- Space-separated alias domains
62+
docroot TEXT DEFAULT '',
63+
php_version TEXT DEFAULT '8.5',
64+
ssl_enabled INTEGER DEFAULT 0,
65+
active INTEGER DEFAULT 1,
66+
updated DATETIME DEFAULT CURRENT_TIMESTAMP,
67+
created DATETIME DEFAULT CURRENT_TIMESTAMP,
68+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
69+
);
70+
71+
-- Virtual Mail accounts
72+
CREATE TABLE IF NOT EXISTS vmails (
73+
id INTEGER PRIMARY KEY AUTOINCREMENT,
74+
user_id INTEGER, -- Owner
75+
email TEXT NOT NULL UNIQUE, -- Full email address
76+
password TEXT NOT NULL, -- Dovecot-compatible hash
77+
quota INTEGER DEFAULT 0, -- MB, 0 = unlimited
78+
active INTEGER DEFAULT 1,
79+
updated DATETIME DEFAULT CURRENT_TIMESTAMP,
80+
created DATETIME DEFAULT CURRENT_TIMESTAMP,
81+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
82+
);
83+
84+
-- Mail aliases
85+
CREATE TABLE IF NOT EXISTS valias (
86+
id INTEGER PRIMARY KEY AUTOINCREMENT,
87+
source TEXT NOT NULL, -- Alias address
88+
target TEXT NOT NULL, -- Destination(s)
89+
active INTEGER DEFAULT 1,
90+
updated DATETIME DEFAULT CURRENT_TIMESTAMP,
91+
created DATETIME DEFAULT CURRENT_TIMESTAMP,
92+
UNIQUE(source, target)
93+
);
94+
95+
-- DNS records
96+
CREATE TABLE IF NOT EXISTS vdns (
97+
id INTEGER PRIMARY KEY AUTOINCREMENT,
98+
vhost_id INTEGER, -- Related vhost
99+
name TEXT NOT NULL, -- Record name
100+
type TEXT NOT NULL DEFAULT 'A', -- A, AAAA, CNAME, MX, TXT, etc.
101+
content TEXT NOT NULL, -- Record value
102+
ttl INTEGER DEFAULT 3600,
103+
priority INTEGER DEFAULT 0, -- For MX records
104+
active INTEGER DEFAULT 1,
105+
updated DATETIME DEFAULT CURRENT_TIMESTAMP,
106+
created DATETIME DEFAULT CURRENT_TIMESTAMP,
107+
FOREIGN KEY (vhost_id) REFERENCES vhosts(id) ON DELETE CASCADE
108+
);
109+
110+
-- SSL certificates
111+
CREATE TABLE IF NOT EXISTS ssl_certs (
112+
id INTEGER PRIMARY KEY AUTOINCREMENT,
113+
vhost_id INTEGER NOT NULL,
114+
provider TEXT DEFAULT 'letsencrypt', -- 'letsencrypt', 'manual', 'selfsigned'
115+
expires DATETIME,
116+
auto_renew INTEGER DEFAULT 1,
117+
updated DATETIME DEFAULT CURRENT_TIMESTAMP,
118+
created DATETIME DEFAULT CURRENT_TIMESTAMP,
119+
FOREIGN KEY (vhost_id) REFERENCES vhosts(id) ON DELETE CASCADE
120+
);
121+
122+
-- Indexes for performance
123+
CREATE INDEX IF NOT EXISTS idx_posts_type ON posts(type);
124+
CREATE INDEX IF NOT EXISTS idx_posts_slug ON posts(slug);
125+
CREATE INDEX IF NOT EXISTS idx_posts_author ON posts(author_id);
126+
CREATE INDEX IF NOT EXISTS idx_vhosts_active ON vhosts(active);
127+
CREATE INDEX IF NOT EXISTS idx_vmails_active ON vmails(active);
128+
CREATE INDEX IF NOT EXISTS idx_users_acl ON users(acl);
129+
130+
-- Default super admin (password: Admin@123456)
131+
INSERT OR IGNORE INTO users (id, acl, login, fname, webpw, created, updated)
132+
VALUES (1, 0, 'admin@localhost', 'Admin', '$2y$10$ZletPP5fW0qHIhWCvbQGpOx4VXBH4NC0Y5HI42dkkV/jMBvY4wbxO', datetime('now'), datetime('now'));
133+
134+
-- Default categories
135+
INSERT OR IGNORE INTO categories (id, name, slug) VALUES
136+
(1, 'General', 'general'),
137+
(2, 'Documentation', 'documentation'),
138+
(3, 'Tutorials', 'tutorials');
139+
140+
-- Default pages
141+
INSERT OR IGNORE INTO posts (id, author_id, type, title, slug, icon, content, created, updated) VALUES
142+
(1, 1, 'page', 'Home', 'home', 'home', '# Welcome to HCP
143+
144+
This is your **Hosting Control Panel** homepage. Edit this page to customize your landing content.
145+
146+
## Features
147+
148+
- Manage virtual hosts
149+
- Configure email accounts
150+
- SSL certificate management
151+
- DNS zone editing
152+
- User administration', datetime('now'), datetime('now')),
153+
154+
(2, 1, 'page', 'About', 'about', 'book-open', '# About HCP
155+
156+
**HCP** (Hosting Control Panel) is a lightweight, self-hosted control panel built with PHP 8.5.
157+
158+
## Technology Stack
159+
160+
- PHP 8.5 with pipe operator
161+
- SQLite or MariaDB
162+
- HTMX for dynamic updates
163+
- Lucide icons', datetime('now'), datetime('now')),
164+
165+
(3, 1, 'page', 'Contact', 'contact', 'mail', '# Contact
166+
167+
For support, please email: **support@example.com**', datetime('now'), datetime('now'));
168+
169+
-- Sample blog post
170+
INSERT OR IGNORE INTO posts (id, author_id, type, title, slug, icon, excerpt, content, created, updated) VALUES
171+
(4, 1, 'post', 'Getting Started with HCP', 'getting-started', 'rocket', 'Learn how to set up and configure your Hosting Control Panel.', '# Getting Started with HCP
172+
173+
Welcome to HCP! This guide will help you get started.
174+
175+
## First Steps
176+
177+
1. Log in with your admin credentials
178+
2. Configure your first virtual host
179+
3. Set up email accounts
180+
4. Enable SSL certificates
181+
182+
## Need Help?
183+
184+
Check out the **Docs** section for detailed documentation.', datetime('now'), datetime('now'));

app/lib/QueryType.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php declare(strict_types=1);
2+
3+
// Copyright (C) 2015-2026 Mark Constable <mc@netserva.org> (MIT License)
4+
5+
namespace SPE\App;
6+
7+
enum QueryType: string
8+
{
9+
case All = 'all';
10+
case One = 'one';
11+
case Col = 'col';
12+
}

0 commit comments

Comments
 (0)