feat(invite-system): implement user invite functionality with registration mode control
This commit is contained in:
@@ -405,17 +405,52 @@ export async function initDatabase() {
|
||||
`);
|
||||
}
|
||||
|
||||
// ── Default admin ───────────────────────────────────────────────────────
|
||||
const adminEmail = process.env.ADMIN_EMAIL || 'admin@example.com';
|
||||
const adminPassword = process.env.ADMIN_PASSWORD || 'admin123';
|
||||
// User invite tokens (invite-only registration)
|
||||
if (isPostgres) {
|
||||
await db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS user_invites (
|
||||
id SERIAL PRIMARY KEY,
|
||||
token TEXT UNIQUE NOT NULL,
|
||||
email TEXT NOT NULL,
|
||||
created_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
used_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
||||
used_at TIMESTAMP,
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_invites_token ON user_invites(token);
|
||||
`);
|
||||
} else {
|
||||
await db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS user_invites (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
token TEXT UNIQUE NOT NULL,
|
||||
email TEXT NOT NULL,
|
||||
created_by INTEGER NOT NULL,
|
||||
used_by INTEGER,
|
||||
used_at DATETIME,
|
||||
expires_at DATETIME NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (used_by) REFERENCES users(id) ON DELETE SET NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_invites_token ON user_invites(token);
|
||||
`);
|
||||
}
|
||||
|
||||
// ── Default admin (only on very first start) ────────────────────────────
|
||||
const adminAlreadySeeded = await db.get("SELECT value FROM settings WHERE key = 'admin_seeded'");
|
||||
if (!adminAlreadySeeded) {
|
||||
const adminEmail = process.env.ADMIN_EMAIL || 'admin@example.com';
|
||||
const adminPassword = process.env.ADMIN_PASSWORD || 'admin123';
|
||||
|
||||
const existingAdmin = await db.get('SELECT id FROM users WHERE email = ?', [adminEmail]);
|
||||
if (!existingAdmin) {
|
||||
const hash = bcrypt.hashSync(adminPassword, 12);
|
||||
await db.run(
|
||||
'INSERT INTO users (name, display_name, email, password_hash, role, email_verified) VALUES (?, ?, ?, ?, ?, 1)',
|
||||
['Administrator', 'Administrator', adminEmail, hash, 'admin']
|
||||
);
|
||||
// Mark as seeded so it never runs again, even if the admin email is changed
|
||||
await db.run("INSERT INTO settings (key, value) VALUES ('admin_seeded', '1')");
|
||||
log.db.info(`Default admin created: ${adminEmail}`);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user