- Build complete Next.js CRM for commercial real estate - Add authentication with JWT sessions and role-based access - Add GoHighLevel API integration for contacts, conversations, opportunities - Add AI-powered Control Center with tool calling - Add Setup page with onboarding checklist (/setup) - Add sidebar navigation with Setup menu item - Fix type errors in onboarding API, GHL services, and control center tools - Add Prisma schema with SQLite for local development - Add UI components with clay morphism design system Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
65 lines
1.6 KiB
TypeScript
65 lines
1.6 KiB
TypeScript
import { cookies } from 'next/headers';
|
|
import { verifyToken, JWTPayload } from './jwt';
|
|
import { prisma } from '@/lib/db';
|
|
import { User, Role } from '@/types';
|
|
|
|
const SESSION_COOKIE_NAME = 'cresync_session';
|
|
|
|
export async function getSession(): Promise<{ user: User } | null> {
|
|
const cookieStore = await cookies();
|
|
const token = cookieStore.get(SESSION_COOKIE_NAME)?.value;
|
|
|
|
if (!token) return null;
|
|
|
|
try {
|
|
const payload = verifyToken(token);
|
|
|
|
const user = await prisma.user.findUnique({
|
|
where: { id: payload.userId },
|
|
select: {
|
|
id: true,
|
|
email: true,
|
|
role: true,
|
|
firstName: true,
|
|
lastName: true,
|
|
brokerage: true,
|
|
ghlLocationId: true,
|
|
createdAt: true,
|
|
},
|
|
});
|
|
|
|
if (!user) return null;
|
|
|
|
return {
|
|
user: {
|
|
id: user.id,
|
|
email: user.email,
|
|
role: user.role as Role,
|
|
firstName: user.firstName ?? undefined,
|
|
lastName: user.lastName ?? undefined,
|
|
brokerage: user.brokerage ?? undefined,
|
|
ghlLocationId: user.ghlLocationId ?? undefined,
|
|
createdAt: user.createdAt,
|
|
}
|
|
};
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function setSessionCookie(token: string): Promise<void> {
|
|
const cookieStore = await cookies();
|
|
cookieStore.set(SESSION_COOKIE_NAME, token, {
|
|
httpOnly: true,
|
|
secure: process.env.NODE_ENV === 'production',
|
|
sameSite: 'lax',
|
|
maxAge: 60 * 60 * 24 * 7, // 7 days
|
|
path: '/',
|
|
});
|
|
}
|
|
|
|
export async function clearSessionCookie(): Promise<void> {
|
|
const cookieStore = await cookies();
|
|
cookieStore.delete(SESSION_COOKIE_NAME);
|
|
}
|