From 632c92f3eee13ca4834bffd9be672749f7bba437 Mon Sep 17 00:00:00 2001 From: Joachim Hummel Date: Sat, 29 Nov 2025 13:37:01 +0000 Subject: [PATCH] Add MQTT tables and parent_user_id column to database schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added MQTT credentials, ACL rules, and sync status tables for broker integration. Added parent_user_id column to User table for hierarchical user management. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- scripts/init-database.js | 77 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/scripts/init-database.js b/scripts/init-database.js index a2a04de..fb007ab 100644 --- a/scripts/init-database.js +++ b/scripts/init-database.js @@ -33,6 +33,7 @@ db.exec(` email TEXT, passwordHash TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'VIEWER', + parent_user_id TEXT, createdAt TEXT DEFAULT (datetime('now')), updatedAt TEXT DEFAULT (datetime('now')), lastLoginAt TEXT, @@ -64,6 +65,7 @@ console.log('✓ Created Device table'); // Create indexes db.exec(` CREATE INDEX IF NOT EXISTS idx_user_username ON User(username); + CREATE INDEX IF NOT EXISTS idx_user_parent ON User(parent_user_id); CREATE INDEX IF NOT EXISTS idx_device_owner ON Device(ownerId); CREATE INDEX IF NOT EXISTS idx_device_active ON Device(isActive); `); @@ -99,6 +101,75 @@ db.exec(` `); console.log('✓ Created password reset tokens index'); +// Create MQTT credentials table +db.exec(` + CREATE TABLE IF NOT EXISTS mqtt_credentials ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + device_id TEXT NOT NULL UNIQUE, + mqtt_username TEXT NOT NULL UNIQUE, + mqtt_password_hash TEXT NOT NULL, + enabled INTEGER DEFAULT 1, + created_at TEXT DEFAULT (datetime('now')), + updated_at TEXT DEFAULT (datetime('now')), + + FOREIGN KEY (device_id) REFERENCES Device(id) ON DELETE CASCADE, + CHECK (enabled IN (0, 1)) + ); +`); +console.log('✓ Created mqtt_credentials table'); + +// Create MQTT ACL rules table +db.exec(` + CREATE TABLE IF NOT EXISTS mqtt_acl_rules ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + device_id TEXT NOT NULL, + topic_pattern TEXT NOT NULL, + permission TEXT NOT NULL CHECK(permission IN ('read', 'write', 'readwrite')), + created_at TEXT DEFAULT (datetime('now')), + + FOREIGN KEY (device_id) REFERENCES Device(id) ON DELETE CASCADE + ); +`); +console.log('✓ Created mqtt_acl_rules table'); + +// Create MQTT sync status table +db.exec(` + CREATE TABLE IF NOT EXISTS mqtt_sync_status ( + id INTEGER PRIMARY KEY CHECK (id = 1), + pending_changes INTEGER DEFAULT 0, + last_sync_at TEXT, + last_sync_status TEXT, + created_at TEXT DEFAULT (datetime('now')), + updated_at TEXT DEFAULT (datetime('now')) + ); +`); +console.log('✓ Created mqtt_sync_status table'); + +// Create MQTT indexes +db.exec(` + CREATE INDEX IF NOT EXISTS idx_mqtt_credentials_device + ON mqtt_credentials(device_id); + + CREATE INDEX IF NOT EXISTS idx_mqtt_credentials_username + ON mqtt_credentials(mqtt_username); + + CREATE INDEX IF NOT EXISTS idx_mqtt_acl_device + ON mqtt_acl_rules(device_id); +`); +console.log('✓ Created MQTT indexes'); + +// Initialize MQTT sync status +const syncStatus = db.prepare('SELECT * FROM mqtt_sync_status WHERE id = 1').get(); +if (!syncStatus) { + db.prepare(` + INSERT INTO mqtt_sync_status (id, pending_changes, last_sync_status) + VALUES (1, 0, 'never_synced') + `).run(); + console.log('✓ Initialized MQTT sync status'); +} else { + console.log('✓ MQTT sync status already exists'); +} + // Check if admin user exists const existingAdmin = db.prepare('SELECT * FROM User WHERE username = ?').get('admin'); @@ -106,9 +177,9 @@ if (!existingAdmin) { // Create default admin user const passwordHash = bcrypt.hashSync('admin123', 10); db.prepare(` - INSERT INTO User (id, username, email, passwordHash, role) - VALUES (?, ?, ?, ?, ?) - `).run('admin-001', 'admin', 'admin@example.com', passwordHash, 'ADMIN'); + INSERT INTO User (id, username, email, passwordHash, role, parent_user_id) + VALUES (?, ?, ?, ?, ?, ?) + `).run('admin-001', 'admin', 'admin@example.com', passwordHash, 'ADMIN', null); console.log('✓ Created default admin user (username: admin, password: admin123)'); } else { console.log('✓ Admin user already exists');