// server/api/users/create.post.ts // Create new user (manual creation) import Database from 'better-sqlite3'; import { join } from 'path'; import { existsSync, mkdirSync } from 'fs'; const getDbPath = () => { const dbDir = join(process.cwd(), 'data'); if (!existsSync(dbDir)) { mkdirSync(dbDir, { recursive: true }); } return join(dbDir, 'users.db'); }; const initDb = () => { const dbPath = getDbPath(); const db = new Database(dbPath); // Create table if not exists db.exec(` CREATE TABLE IF NOT EXISTS users ( id TEXT PRIMARY KEY, namaLengkap TEXT NOT NULL, namaUser TEXT UNIQUE NOT NULL, email TEXT, tipeUser TEXT DEFAULT '', lastLogin INTEGER, roles TEXT DEFAULT '[]', realmRoles TEXT DEFAULT '[]', accountRoles TEXT DEFAULT '[]', resourceRoles TEXT DEFAULT '[]', groups TEXT DEFAULT '[]', given_name TEXT, family_name TEXT, createdAt INTEGER DEFAULT (strftime('%s', 'now')), updatedAt INTEGER DEFAULT (strftime('%s', 'now')) ) `); // Migration: Check and add missing columns one by one try { const tableInfo = db.prepare("PRAGMA table_info(users)").all() as any[]; const columnNames = tableInfo.map(col => col.name); // Add missing columns one by one if (!columnNames.includes('realmRoles')) { db.exec(`ALTER TABLE users ADD COLUMN realmRoles TEXT DEFAULT '[]'`); console.log('✅ Added column: realmRoles'); } if (!columnNames.includes('accountRoles')) { db.exec(`ALTER TABLE users ADD COLUMN accountRoles TEXT DEFAULT '[]'`); console.log('✅ Added column: accountRoles'); } if (!columnNames.includes('resourceRoles')) { db.exec(`ALTER TABLE users ADD COLUMN resourceRoles TEXT DEFAULT '[]'`); console.log('✅ Added column: resourceRoles'); } if (!columnNames.includes('lastLogin')) { db.exec(`ALTER TABLE users ADD COLUMN lastLogin INTEGER`); console.log('✅ Added column: lastLogin'); } if (!columnNames.includes('given_name')) { db.exec(`ALTER TABLE users ADD COLUMN given_name TEXT`); console.log('✅ Added column: given_name'); } if (!columnNames.includes('family_name')) { db.exec(`ALTER TABLE users ADD COLUMN family_name TEXT`); console.log('✅ Added column: family_name'); } } catch (e: any) { console.error('❌ Migration error:', e.message); // Don't throw, continue with existing schema } return db; }; export default defineEventHandler(async (event) => { const body = await readBody(event); console.log("➕ Create user endpoint called"); if (!body.namaLengkap || !body.username) { throw createError({ statusCode: 400, statusMessage: "namaLengkap and username are required", }); } try { const db = initDb(); // Generate ID if not provided (for manual creation) const userId = body.id || `manual-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; // Check if username already exists const existingUser = db.prepare('SELECT * FROM users WHERE namaUser = ?').get(body.username) as any; if (existingUser) { db.close(); throw createError({ statusCode: 409, statusMessage: "Username already exists", }); } // Insert new user db.prepare(` INSERT INTO users ( id, namaLengkap, namaUser, email, tipeUser, lastLogin, roles, realmRoles, accountRoles, resourceRoles, groups, given_name, family_name ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `).run( userId, body.namaLengkap, body.username, body.email || null, body.tipeUser || '', body.lastLogin || Math.floor(Date.now() / 1000), JSON.stringify(Array.isArray(body.roles) ? body.roles : []), JSON.stringify(Array.isArray(body.realmRoles) ? body.realmRoles : []), JSON.stringify(Array.isArray(body.accountRoles) ? body.accountRoles : []), JSON.stringify(Array.isArray(body.resourceRoles) ? body.resourceRoles : []), JSON.stringify(Array.isArray(body.groups) ? body.groups : []), body.given_name || null, body.family_name || null ); db.close(); console.log(`✅ User created: ${userId}`); return { success: true, message: 'User created successfully', id: userId }; } catch (error: any) { console.error("❌ Error creating user:", error); throw createError({ statusCode: error.statusCode || 500, statusMessage: error.message || "Failed to create user", }); } });