84 lines
2.5 KiB
TypeScript
84 lines
2.5 KiB
TypeScript
import { NextResponse } from 'next/server';
|
|
import { db, writerDb } from "@/drizzle/db";
|
|
import { users, tenants } from "@/drizzle/schema";
|
|
import { eq } from 'drizzle-orm';
|
|
import jwt from 'jsonwebtoken';
|
|
import bcrypt from 'bcryptjs';
|
|
|
|
export async function POST(req: Request) {
|
|
try {
|
|
const { email, password } = await req.json();
|
|
|
|
if (!email || !password || password.length < 6) {
|
|
return NextResponse.json({ error: 'Email and password (min 6 chars) are required' }, { status: 400 });
|
|
}
|
|
|
|
// Check if email already exists
|
|
const existingUser = await db.select().from(users).where(eq(users.email, email)).limit(1);
|
|
if (existingUser.length > 0) {
|
|
return NextResponse.json({ error: 'Email sudah terdaftar.' }, { status: 409 });
|
|
}
|
|
|
|
// Create a new Tenant for the user
|
|
const tenantName = `Personal Workspace - ${email.split('@')[0]}`;
|
|
const newTenantResult = await writerDb.insert(tenants).values({
|
|
name: tenantName,
|
|
isActive: true
|
|
}).returning({ id: tenants.id, name: tenants.name });
|
|
|
|
const newTenant = newTenantResult[0];
|
|
|
|
// Create the user with bcrypt-hashed password (Kelas Militer)
|
|
const hashedPassword = await bcrypt.hash(password, 12);
|
|
const newUserResult = await writerDb.insert(users).values({
|
|
email: email,
|
|
passwordHash: hashedPassword,
|
|
tenantId: newTenant.id,
|
|
role: 'admin' // The creator of the personal tenant is an admin
|
|
}).returning({ id: users.id, email: users.email, role: users.role });
|
|
|
|
const user = newUserResult[0];
|
|
|
|
// Generate JWT Token
|
|
const token = jwt.sign(
|
|
{
|
|
userId: user.id,
|
|
email: user.email,
|
|
role: user.role,
|
|
tenantId: newTenant.id,
|
|
tenantName: newTenant.name,
|
|
licenses: {}
|
|
},
|
|
process.env.JWT_SECRET as string,
|
|
{ expiresIn: '8h' }
|
|
);
|
|
|
|
const response = NextResponse.json({
|
|
message: 'Registrasi Berhasil.',
|
|
user: {
|
|
email: user.email,
|
|
role: user.role,
|
|
tenantName: newTenant.name
|
|
}
|
|
}, { status: 201 });
|
|
|
|
// Set HttpOnly Cookie for SSO
|
|
response.cookies.set({
|
|
name: 'jumpa_token',
|
|
value: token,
|
|
httpOnly: true,
|
|
secure: true,
|
|
sameSite: 'lax',
|
|
path: '/',
|
|
domain: process.env.NEXT_PUBLIC_COOKIE_DOMAIN || undefined,
|
|
maxAge: 8 * 60 * 60
|
|
});
|
|
|
|
return response;
|
|
|
|
} catch (error) {
|
|
console.error('[API REGISTER ERROR]', error);
|
|
return NextResponse.json({ error: 'Kesalahan Sistem Internal PostgreSQL' }, { status: 500 });
|
|
}
|
|
}
|