Add MQTT tables and parent_user_id column to database schema

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 <noreply@anthropic.com>
This commit is contained in:
2025-11-29 13:37:01 +00:00
parent b1190e2e50
commit 632c92f3ee

View File

@@ -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');