feat: implement GHL webhook endpoint for auto account + license key creation
POST /api/v1/automations/create/account accepts JSON with email, name, and subscription_level. Creates a Better Auth user via signUpEmail with a temporary password, sends a password reset email so the user can set their own password, generates and persists a license key, and emails the key to the user. Returns success/error as JSON.
This commit is contained in:
@@ -1,21 +1,91 @@
|
|||||||
import type { RequestHandler } from './$types';
|
import type { RequestHandler } from './$types';
|
||||||
|
import { json, error } from '@sveltejs/kit';
|
||||||
|
import { auth } from '$lib/auth';
|
||||||
|
import { prisma } from '$lib/db';
|
||||||
|
import { sendMail } from '$lib/server/resend';
|
||||||
|
|
||||||
export const POST: RequestHandler = async () => {
|
function generateLicenseKey(): string {
|
||||||
// Request validation (400)
|
const hex = crypto.randomUUID().replace(/-/g, '').slice(0, 16).toUpperCase();
|
||||||
// 1. Validate and extract information
|
return `${hex.slice(0, 4)}-${hex.slice(4, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}`;
|
||||||
|
}
|
||||||
|
|
||||||
// Business rule validation (409)
|
export const POST: RequestHandler = async ({ request }) => {
|
||||||
// 2. Check for existing entries
|
const body = await request.json();
|
||||||
|
const { email, name, subscription_level } = body;
|
||||||
|
|
||||||
// Resource creation (500 on unexpected failures)
|
if (!email || typeof email !== 'string') {
|
||||||
// 3. Create new entries
|
error(400, 'email is required');
|
||||||
// 5. Create license key
|
}
|
||||||
|
if (!subscription_level || typeof subscription_level !== 'string') {
|
||||||
|
error(400, 'subscription_level is required');
|
||||||
|
}
|
||||||
|
|
||||||
// External operations (502/503/504 or 500, depending on your API)
|
const level = await prisma.subscriptionLevel.findFirst({
|
||||||
// 4. Send profile setup email
|
where: { name: subscription_level }
|
||||||
// 6. Send license key email
|
});
|
||||||
|
if (!level) {
|
||||||
|
error(400, `subscription_level "${subscription_level}" not found`);
|
||||||
|
}
|
||||||
|
|
||||||
// Success (200/201)
|
let user = await prisma.user.findUnique({ where: { email } });
|
||||||
// 7. Send response
|
|
||||||
return new Response(JSON.stringify({ msg: 'success' }));
|
if (!user) {
|
||||||
|
const tempPassword = crypto.randomUUID().replace(/-/g, '').slice(0, 20);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await auth.api.signUpEmail({
|
||||||
|
body: {
|
||||||
|
email,
|
||||||
|
password: tempPassword,
|
||||||
|
name: name ?? email.split('@')[0]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
user = await prisma.user.findUnique({ where: { email } });
|
||||||
|
|
||||||
|
await auth.api.requestPasswordReset({
|
||||||
|
body: {
|
||||||
|
email,
|
||||||
|
redirectTo: '/reset-password'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to create user:', err);
|
||||||
|
error(500, 'Failed to create account');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
error(500, 'Failed to find or create user');
|
||||||
|
}
|
||||||
|
|
||||||
|
const key = generateLicenseKey();
|
||||||
|
|
||||||
|
await prisma.licenseKey.create({
|
||||||
|
data: {
|
||||||
|
key,
|
||||||
|
active: true,
|
||||||
|
level: subscription_level,
|
||||||
|
userId: user.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sendMail({
|
||||||
|
to: email,
|
||||||
|
subject: 'Your License Key',
|
||||||
|
data: {
|
||||||
|
firstName: name ?? 'Valued Customer',
|
||||||
|
licenseKey: key
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to send license key email:', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json({
|
||||||
|
success: true,
|
||||||
|
message: 'Account and license key created',
|
||||||
|
user_id: user.id
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user