RANGE //4,200M
STATUS //INBOUND
route.ts — cimlas-bespoke
// auth/session.ts — JWT-backed session management with secure cookie storage and 7-day expiry sliding window
import { jwtVerify, SignJWT, type JWTPayload } from 'jose'
import { cookies } from 'next/headers'
import type { NextRequest } from 'next/server'
const SECRET = new TextEncoder().encode(process.env.JWT_SECRET!)
const SESSION_TTL_DAYS = 7
type SessionPayload = JWTPayload & { sub: string; role: 'admin' | 'user' | 'guest' }
export async function createSession(userId: string, role: SessionPayload['role'] = 'user'): Promise<string> {
const expiresAt = new Date(Date.now() + SESSION_TTL_DAYS * 86_400_000)
const token = await new SignJWT({ sub: userId, role })
.setProtectedHeader({ alg: 'HS256', typ: 'JWT' })
.setIssuedAt()
.setExpirationTime(expiresAt)
.setIssuer('app.example.com')
.sign(SECRET)
cookies().set('app_session', token, { httpOnly: true, secure: true, sameSite: 'lax', expires: expiresAt, path: '/' })
return token
}
export async function getSession(req: NextRequest): Promise<SessionPayload | null> {
const token = req.cookies.get('app_session')?.value
if (!token) return null
try {
const { payload } = await jwtVerify<SessionPayload>(token, SECRET, { issuer: 'app.example.com' })
return payload
} catch {
return null
}
}
// db/users.ts — Drizzle ORM with full type-safe CRUD operations and indexed lookups
import { db } from '@/db'
import { users, sessions } from '@/db/schema'
import { eq, and, gt, desc } from 'drizzle-orm'
export type User = typeof users.$inferSelect
export type NewUser = typeof users.$inferInsert
export async function findUserByEmail(email: string): Promise<User | null> {
const [user] = await db.select().from(users).where(eq(users.email, email)).limit(1)
return user ?? null
}
export async function createUser(data: NewUser): Promise<User> {
const [user] = await db.insert(users).values({ ...data, createdAt: new Date(), updatedAt: new Date() }).returning()
return user
}
export async function listActiveSessions(userId: string) {
return db.select().from(sessions).where(and(eq(sessions.userId, userId), gt(sessions.expiresAt, new Date()))).orderBy(desc(sessions.createdAt))
}
// middleware.ts — protected-route gating with redirect to login and `next` query param for return-to-flow
import { NextResponse, type NextRequest } from 'next/server'
import { getSession } from '@/auth/session'
const PROTECTED_ROUTES = ['/dashboard', '/settings', '/billing', '/account']
const PUBLIC_API_ROUTES = ['/api/health', '/api/webhook/stripe', '/api/auth/callback']
export async function middleware(req: NextRequest) {
const path = req.nextUrl.pathname
const requiresAuth = PROTECTED_ROUTES.some(p => path.startsWith(p))
if (!requiresAuth) return NextResponse.next()
const session = await getSession(req)
if (!session) {
const url = new URL('/login', req.url)
url.searchParams.set('next', path)
return NextResponse.redirect(url)
}
return NextResponse.next()
}
export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico|public/).*)'] }
// db/schema.sql — Postgres tables with row-level security, cascading deletes, and partial indexes for active records
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
name TEXT,
role TEXT NOT NULL DEFAULT 'user' CHECK (role IN ('admin', 'user', 'guest')),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
expires_at TIMESTAMPTZ NOT NULL,
user_agent TEXT,
ip_address INET,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_sessions_user_id ON sessions(user_id);
CREATE INDEX idx_sessions_active ON sessions(expires_at) WHERE expires_at > now();
CREATE INDEX idx_users_email_lower ON users(LOWER(email));
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE sessions ENABLE ROW LEVEL SECURITY;
// auth/session.ts — JWT-backed session management with secure cookie storage and 7-day expiry sliding window
import { jwtVerify, SignJWT, type JWTPayload } from 'jose'
import { cookies } from 'next/headers'
import type { NextRequest } from 'next/server'
const SECRET = new TextEncoder().encode(process.env.JWT_SECRET!)
const SESSION_TTL_DAYS = 7
type SessionPayload = JWTPayload & { sub: string; role: 'admin' | 'user' | 'guest' }
export async function createSession(userId: string, role: SessionPayload['role'] = 'user'): Promise<string> {
const expiresAt = new Date(Date.now() + SESSION_TTL_DAYS * 86_400_000)
const token = await new SignJWT({ sub: userId, role })
.setProtectedHeader({ alg: 'HS256', typ: 'JWT' })
.setIssuedAt()
.setExpirationTime(expiresAt)
.setIssuer('app.example.com')
.sign(SECRET)
cookies().set('app_session', token, { httpOnly: true, secure: true, sameSite: 'lax', expires: expiresAt, path: '/' })
return token
}
export async function getSession(req: NextRequest): Promise<SessionPayload | null> {
const token = req.cookies.get('app_session')?.value
if (!token) return null
try {
const { payload } = await jwtVerify<SessionPayload>(token, SECRET, { issuer: 'app.example.com' })
return payload
} catch {
return null
}
}
// db/users.ts — Drizzle ORM with full type-safe CRUD operations and indexed lookups
import { db } from '@/db'
import { users, sessions } from '@/db/schema'
import { eq, and, gt, desc } from 'drizzle-orm'
export type User = typeof users.$inferSelect
export type NewUser = typeof users.$inferInsert
export async function findUserByEmail(email: string): Promise<User | null> {
const [user] = await db.select().from(users).where(eq(users.email, email)).limit(1)
return user ?? null
}
export async function createUser(data: NewUser): Promise<User> {
const [user] = await db.insert(users).values({ ...data, createdAt: new Date(), updatedAt: new Date() }).returning()
return user
}
export async function listActiveSessions(userId: string) {
return db.select().from(sessions).where(and(eq(sessions.userId, userId), gt(sessions.expiresAt, new Date()))).orderBy(desc(sessions.createdAt))
}
// middleware.ts — protected-route gating with redirect to login and `next` query param for return-to-flow
import { NextResponse, type NextRequest } from 'next/server'
import { getSession } from '@/auth/session'
const PROTECTED_ROUTES = ['/dashboard', '/settings', '/billing', '/account']
const PUBLIC_API_ROUTES = ['/api/health', '/api/webhook/stripe', '/api/auth/callback']
export async function middleware(req: NextRequest) {
const path = req.nextUrl.pathname
const requiresAuth = PROTECTED_ROUTES.some(p => path.startsWith(p))
if (!requiresAuth) return NextResponse.next()
const session = await getSession(req)
if (!session) {
const url = new URL('/login', req.url)
url.searchParams.set('next', path)
return NextResponse.redirect(url)
}
return NextResponse.next()
}
export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico|public/).*)'] }
// db/schema.sql — Postgres tables with row-level security, cascading deletes, and partial indexes for active records
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
name TEXT,
role TEXT NOT NULL DEFAULT 'user' CHECK (role IN ('admin', 'user', 'guest')),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
expires_at TIMESTAMPTZ NOT NULL,
user_agent TEXT,
ip_address INET,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_sessions_user_id ON sessions(user_id);
CREATE INDEX idx_sessions_active ON sessions(expires_at) WHERE expires_at > now();
CREATE INDEX idx_users_email_lower ON users(LOWER(email));
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE sessions ENABLE ROW LEVEL SECURITY;
BUILT FORYOU
route.ts — cimlas-bespoke
// auth/session.ts — JWT-backed session management with secure cookie storage and 7-day expiry sliding window
import { jwtVerify, SignJWT, type JWTPayload } from 'jose'
import { cookies } from 'next/headers'
import type { NextRequest } from 'next/server'
const SECRET = new TextEncoder().encode(process.env.JWT_SECRET!)
const SESSION_TTL_DAYS = 7
type SessionPayload = JWTPayload & { sub: string; role: 'admin' | 'user' | 'guest' }
export async function createSession(userId: string, role: SessionPayload['role'] = 'user'): Promise<string> {
const expiresAt = new Date(Date.now() + SESSION_TTL_DAYS * 86_400_000)
const token = await new SignJWT({ sub: userId, role })
.setProtectedHeader({ alg: 'HS256', typ: 'JWT' })
.setIssuedAt()
.setExpirationTime(expiresAt)
.setIssuer('app.example.com')
.sign(SECRET)
cookies().set('app_session', token, { httpOnly: true, secure: true, sameSite: 'lax', expires: expiresAt, path: '/' })
return token
}
export async function getSession(req: NextRequest): Promise<SessionPayload | null> {
const token = req.cookies.get('app_session')?.value
if (!token) return null
try {
const { payload } = await jwtVerify<SessionPayload>(token, SECRET, { issuer: 'app.example.com' })
return payload
} catch {
return null
}
}
// db/users.ts — Drizzle ORM with full type-safe CRUD operations and indexed lookups
import { db } from '@/db'
import { users, sessions } from '@/db/schema'
import { eq, and, gt, desc } from 'drizzle-orm'
export type User = typeof users.$inferSelect
export type NewUser = typeof users.$inferInsert
export async function findUserByEmail(email: string): Promise<User | null> {
const [user] = await db.select().from(users).where(eq(users.email, email)).limit(1)
return user ?? null
}
export async function createUser(data: NewUser): Promise<User> {
const [user] = await db.insert(users).values({ ...data, createdAt: new Date(), updatedAt: new Date() }).returning()
return user
}
export async function listActiveSessions(userId: string) {
return db.select().from(sessions).where(and(eq(sessions.userId, userId), gt(sessions.expiresAt, new Date()))).orderBy(desc(sessions.createdAt))
}
// middleware.ts — protected-route gating with redirect to login and `next` query param for return-to-flow
import { NextResponse, type NextRequest } from 'next/server'
import { getSession } from '@/auth/session'
const PROTECTED_ROUTES = ['/dashboard', '/settings', '/billing', '/account']
const PUBLIC_API_ROUTES = ['/api/health', '/api/webhook/stripe', '/api/auth/callback']
export async function middleware(req: NextRequest) {
const path = req.nextUrl.pathname
const requiresAuth = PROTECTED_ROUTES.some(p => path.startsWith(p))
if (!requiresAuth) return NextResponse.next()
const session = await getSession(req)
if (!session) {
const url = new URL('/login', req.url)
url.searchParams.set('next', path)
return NextResponse.redirect(url)
}
return NextResponse.next()
}
export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico|public/).*)'] }
// db/schema.sql — Postgres tables with row-level security, cascading deletes, and partial indexes for active records
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
name TEXT,
role TEXT NOT NULL DEFAULT 'user' CHECK (role IN ('admin', 'user', 'guest')),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
expires_at TIMESTAMPTZ NOT NULL,
user_agent TEXT,
ip_address INET,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_sessions_user_id ON sessions(user_id);
CREATE INDEX idx_sessions_active ON sessions(expires_at) WHERE expires_at > now();
CREATE INDEX idx_users_email_lower ON users(LOWER(email));
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE sessions ENABLE ROW LEVEL SECURITY;
// auth/session.ts — JWT-backed session management with secure cookie storage and 7-day expiry sliding window
import { jwtVerify, SignJWT, type JWTPayload } from 'jose'
import { cookies } from 'next/headers'
import type { NextRequest } from 'next/server'
const SECRET = new TextEncoder().encode(process.env.JWT_SECRET!)
const SESSION_TTL_DAYS = 7
type SessionPayload = JWTPayload & { sub: string; role: 'admin' | 'user' | 'guest' }
export async function createSession(userId: string, role: SessionPayload['role'] = 'user'): Promise<string> {
const expiresAt = new Date(Date.now() + SESSION_TTL_DAYS * 86_400_000)
const token = await new SignJWT({ sub: userId, role })
.setProtectedHeader({ alg: 'HS256', typ: 'JWT' })
.setIssuedAt()
.setExpirationTime(expiresAt)
.setIssuer('app.example.com')
.sign(SECRET)
cookies().set('app_session', token, { httpOnly: true, secure: true, sameSite: 'lax', expires: expiresAt, path: '/' })
return token
}
export async function getSession(req: NextRequest): Promise<SessionPayload | null> {
const token = req.cookies.get('app_session')?.value
if (!token) return null
try {
const { payload } = await jwtVerify<SessionPayload>(token, SECRET, { issuer: 'app.example.com' })
return payload
} catch {
return null
}
}
// db/users.ts — Drizzle ORM with full type-safe CRUD operations and indexed lookups
import { db } from '@/db'
import { users, sessions } from '@/db/schema'
import { eq, and, gt, desc } from 'drizzle-orm'
export type User = typeof users.$inferSelect
export type NewUser = typeof users.$inferInsert
export async function findUserByEmail(email: string): Promise<User | null> {
const [user] = await db.select().from(users).where(eq(users.email, email)).limit(1)
return user ?? null
}
export async function createUser(data: NewUser): Promise<User> {
const [user] = await db.insert(users).values({ ...data, createdAt: new Date(), updatedAt: new Date() }).returning()
return user
}
export async function listActiveSessions(userId: string) {
return db.select().from(sessions).where(and(eq(sessions.userId, userId), gt(sessions.expiresAt, new Date()))).orderBy(desc(sessions.createdAt))
}
// middleware.ts — protected-route gating with redirect to login and `next` query param for return-to-flow
import { NextResponse, type NextRequest } from 'next/server'
import { getSession } from '@/auth/session'
const PROTECTED_ROUTES = ['/dashboard', '/settings', '/billing', '/account']
const PUBLIC_API_ROUTES = ['/api/health', '/api/webhook/stripe', '/api/auth/callback']
export async function middleware(req: NextRequest) {
const path = req.nextUrl.pathname
const requiresAuth = PROTECTED_ROUTES.some(p => path.startsWith(p))
if (!requiresAuth) return NextResponse.next()
const session = await getSession(req)
if (!session) {
const url = new URL('/login', req.url)
url.searchParams.set('next', path)
return NextResponse.redirect(url)
}
return NextResponse.next()
}
export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico|public/).*)'] }
// db/schema.sql — Postgres tables with row-level security, cascading deletes, and partial indexes for active records
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
name TEXT,
role TEXT NOT NULL DEFAULT 'user' CHECK (role IN ('admin', 'user', 'guest')),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
expires_at TIMESTAMPTZ NOT NULL,
user_agent TEXT,
ip_address INET,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_sessions_user_id ON sessions(user_id);
CREATE INDEX idx_sessions_active ON sessions(expires_at) WHERE expires_at > now();
CREATE INDEX idx_users_email_lower ON users(LOWER(email));
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE sessions ENABLE ROW LEVEL SECURITY;
BUILT FORYOU
route.ts — cimlas-bespoke
// auth/session.ts — JWT-backed session management with secure cookie storage and 7-day expiry sliding window
import { jwtVerify, SignJWT, type JWTPayload } from 'jose'
import { cookies } from 'next/headers'
import type { NextRequest } from 'next/server'
const SECRET = new TextEncoder().encode(process.env.JWT_SECRET!)
const SESSION_TTL_DAYS = 7
type SessionPayload = JWTPayload & { sub: string; role: 'admin' | 'user' | 'guest' }
export async function createSession(userId: string, role: SessionPayload['role'] = 'user'): Promise<string> {
const expiresAt = new Date(Date.now() + SESSION_TTL_DAYS * 86_400_000)
const token = await new SignJWT({ sub: userId, role })
.setProtectedHeader({ alg: 'HS256', typ: 'JWT' })
.setIssuedAt()
.setExpirationTime(expiresAt)
.setIssuer('app.example.com')
.sign(SECRET)
cookies().set('app_session', token, { httpOnly: true, secure: true, sameSite: 'lax', expires: expiresAt, path: '/' })
return token
}
export async function getSession(req: NextRequest): Promise<SessionPayload | null> {
const token = req.cookies.get('app_session')?.value
if (!token) return null
try {
const { payload } = await jwtVerify<SessionPayload>(token, SECRET, { issuer: 'app.example.com' })
return payload
} catch {
return null
}
}
// db/users.ts — Drizzle ORM with full type-safe CRUD operations and indexed lookups
import { db } from '@/db'
import { users, sessions } from '@/db/schema'
import { eq, and, gt, desc } from 'drizzle-orm'
export type User = typeof users.$inferSelect
export type NewUser = typeof users.$inferInsert
export async function findUserByEmail(email: string): Promise<User | null> {
const [user] = await db.select().from(users).where(eq(users.email, email)).limit(1)
return user ?? null
}
export async function createUser(data: NewUser): Promise<User> {
const [user] = await db.insert(users).values({ ...data, createdAt: new Date(), updatedAt: new Date() }).returning()
return user
}
export async function listActiveSessions(userId: string) {
return db.select().from(sessions).where(and(eq(sessions.userId, userId), gt(sessions.expiresAt, new Date()))).orderBy(desc(sessions.createdAt))
}
// middleware.ts — protected-route gating with redirect to login and `next` query param for return-to-flow
import { NextResponse, type NextRequest } from 'next/server'
import { getSession } from '@/auth/session'
const PROTECTED_ROUTES = ['/dashboard', '/settings', '/billing', '/account']
const PUBLIC_API_ROUTES = ['/api/health', '/api/webhook/stripe', '/api/auth/callback']
export async function middleware(req: NextRequest) {
const path = req.nextUrl.pathname
const requiresAuth = PROTECTED_ROUTES.some(p => path.startsWith(p))
if (!requiresAuth) return NextResponse.next()
const session = await getSession(req)
if (!session) {
const url = new URL('/login', req.url)
url.searchParams.set('next', path)
return NextResponse.redirect(url)
}
return NextResponse.next()
}
export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico|public/).*)'] }
// db/schema.sql — Postgres tables with row-level security, cascading deletes, and partial indexes for active records
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
name TEXT,
role TEXT NOT NULL DEFAULT 'user' CHECK (role IN ('admin', 'user', 'guest')),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
expires_at TIMESTAMPTZ NOT NULL,
user_agent TEXT,
ip_address INET,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_sessions_user_id ON sessions(user_id);
CREATE INDEX idx_sessions_active ON sessions(expires_at) WHERE expires_at > now();
CREATE INDEX idx_users_email_lower ON users(LOWER(email));
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE sessions ENABLE ROW LEVEL SECURITY;
// auth/session.ts — JWT-backed session management with secure cookie storage and 7-day expiry sliding window
import { jwtVerify, SignJWT, type JWTPayload } from 'jose'
import { cookies } from 'next/headers'
import type { NextRequest } from 'next/server'
const SECRET = new TextEncoder().encode(process.env.JWT_SECRET!)
const SESSION_TTL_DAYS = 7
type SessionPayload = JWTPayload & { sub: string; role: 'admin' | 'user' | 'guest' }
export async function createSession(userId: string, role: SessionPayload['role'] = 'user'): Promise<string> {
const expiresAt = new Date(Date.now() + SESSION_TTL_DAYS * 86_400_000)
const token = await new SignJWT({ sub: userId, role })
.setProtectedHeader({ alg: 'HS256', typ: 'JWT' })
.setIssuedAt()
.setExpirationTime(expiresAt)
.setIssuer('app.example.com')
.sign(SECRET)
cookies().set('app_session', token, { httpOnly: true, secure: true, sameSite: 'lax', expires: expiresAt, path: '/' })
return token
}
export async function getSession(req: NextRequest): Promise<SessionPayload | null> {
const token = req.cookies.get('app_session')?.value
if (!token) return null
try {
const { payload } = await jwtVerify<SessionPayload>(token, SECRET, { issuer: 'app.example.com' })
return payload
} catch {
return null
}
}
// db/users.ts — Drizzle ORM with full type-safe CRUD operations and indexed lookups
import { db } from '@/db'
import { users, sessions } from '@/db/schema'
import { eq, and, gt, desc } from 'drizzle-orm'
export type User = typeof users.$inferSelect
export type NewUser = typeof users.$inferInsert
export async function findUserByEmail(email: string): Promise<User | null> {
const [user] = await db.select().from(users).where(eq(users.email, email)).limit(1)
return user ?? null
}
export async function createUser(data: NewUser): Promise<User> {
const [user] = await db.insert(users).values({ ...data, createdAt: new Date(), updatedAt: new Date() }).returning()
return user
}
export async function listActiveSessions(userId: string) {
return db.select().from(sessions).where(and(eq(sessions.userId, userId), gt(sessions.expiresAt, new Date()))).orderBy(desc(sessions.createdAt))
}
// middleware.ts — protected-route gating with redirect to login and `next` query param for return-to-flow
import { NextResponse, type NextRequest } from 'next/server'
import { getSession } from '@/auth/session'
const PROTECTED_ROUTES = ['/dashboard', '/settings', '/billing', '/account']
const PUBLIC_API_ROUTES = ['/api/health', '/api/webhook/stripe', '/api/auth/callback']
export async function middleware(req: NextRequest) {
const path = req.nextUrl.pathname
const requiresAuth = PROTECTED_ROUTES.some(p => path.startsWith(p))
if (!requiresAuth) return NextResponse.next()
const session = await getSession(req)
if (!session) {
const url = new URL('/login', req.url)
url.searchParams.set('next', path)
return NextResponse.redirect(url)
}
return NextResponse.next()
}
export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico|public/).*)'] }
// db/schema.sql — Postgres tables with row-level security, cascading deletes, and partial indexes for active records
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
name TEXT,
role TEXT NOT NULL DEFAULT 'user' CHECK (role IN ('admin', 'user', 'guest')),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
expires_at TIMESTAMPTZ NOT NULL,
user_agent TEXT,
ip_address INET,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_sessions_user_id ON sessions(user_id);
CREATE INDEX idx_sessions_active ON sessions(expires_at) WHERE expires_at > now();
CREATE INDEX idx_users_email_lower ON users(LOWER(email));
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE sessions ENABLE ROW LEVEL SECURITY;
BUILT FORYOU
route.ts — cimlas-bespoke
// auth/session.ts — JWT-backed session management with secure cookie storage and 7-day expiry sliding window
import { jwtVerify, SignJWT, type JWTPayload } from 'jose'
import { cookies } from 'next/headers'
import type { NextRequest } from 'next/server'
const SECRET = new TextEncoder().encode(process.env.JWT_SECRET!)
const SESSION_TTL_DAYS = 7
type SessionPayload = JWTPayload & { sub: string; role: 'admin' | 'user' | 'guest' }
export async function createSession(userId: string, role: SessionPayload['role'] = 'user'): Promise<string> {
const expiresAt = new Date(Date.now() + SESSION_TTL_DAYS * 86_400_000)
const token = await new SignJWT({ sub: userId, role })
.setProtectedHeader({ alg: 'HS256', typ: 'JWT' })
.setIssuedAt()
.setExpirationTime(expiresAt)
.setIssuer('app.example.com')
.sign(SECRET)
cookies().set('app_session', token, { httpOnly: true, secure: true, sameSite: 'lax', expires: expiresAt, path: '/' })
return token
}
export async function getSession(req: NextRequest): Promise<SessionPayload | null> {
const token = req.cookies.get('app_session')?.value
if (!token) return null
try {
const { payload } = await jwtVerify<SessionPayload>(token, SECRET, { issuer: 'app.example.com' })
return payload
} catch {
return null
}
}
// db/users.ts — Drizzle ORM with full type-safe CRUD operations and indexed lookups
import { db } from '@/db'
import { users, sessions } from '@/db/schema'
import { eq, and, gt, desc } from 'drizzle-orm'
export type User = typeof users.$inferSelect
export type NewUser = typeof users.$inferInsert
export async function findUserByEmail(email: string): Promise<User | null> {
const [user] = await db.select().from(users).where(eq(users.email, email)).limit(1)
return user ?? null
}
export async function createUser(data: NewUser): Promise<User> {
const [user] = await db.insert(users).values({ ...data, createdAt: new Date(), updatedAt: new Date() }).returning()
return user
}
export async function listActiveSessions(userId: string) {
return db.select().from(sessions).where(and(eq(sessions.userId, userId), gt(sessions.expiresAt, new Date()))).orderBy(desc(sessions.createdAt))
}
// middleware.ts — protected-route gating with redirect to login and `next` query param for return-to-flow
import { NextResponse, type NextRequest } from 'next/server'
import { getSession } from '@/auth/session'
const PROTECTED_ROUTES = ['/dashboard', '/settings', '/billing', '/account']
const PUBLIC_API_ROUTES = ['/api/health', '/api/webhook/stripe', '/api/auth/callback']
export async function middleware(req: NextRequest) {
const path = req.nextUrl.pathname
const requiresAuth = PROTECTED_ROUTES.some(p => path.startsWith(p))
if (!requiresAuth) return NextResponse.next()
const session = await getSession(req)
if (!session) {
const url = new URL('/login', req.url)
url.searchParams.set('next', path)
return NextResponse.redirect(url)
}
return NextResponse.next()
}
export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico|public/).*)'] }
// db/schema.sql — Postgres tables with row-level security, cascading deletes, and partial indexes for active records
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
name TEXT,
role TEXT NOT NULL DEFAULT 'user' CHECK (role IN ('admin', 'user', 'guest')),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
expires_at TIMESTAMPTZ NOT NULL,
user_agent TEXT,
ip_address INET,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_sessions_user_id ON sessions(user_id);
CREATE INDEX idx_sessions_active ON sessions(expires_at) WHERE expires_at > now();
CREATE INDEX idx_users_email_lower ON users(LOWER(email));
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE sessions ENABLE ROW LEVEL SECURITY;
// auth/session.ts — JWT-backed session management with secure cookie storage and 7-day expiry sliding window
import { jwtVerify, SignJWT, type JWTPayload } from 'jose'
import { cookies } from 'next/headers'
import type { NextRequest } from 'next/server'
const SECRET = new TextEncoder().encode(process.env.JWT_SECRET!)
const SESSION_TTL_DAYS = 7
type SessionPayload = JWTPayload & { sub: string; role: 'admin' | 'user' | 'guest' }
export async function createSession(userId: string, role: SessionPayload['role'] = 'user'): Promise<string> {
const expiresAt = new Date(Date.now() + SESSION_TTL_DAYS * 86_400_000)
const token = await new SignJWT({ sub: userId, role })
.setProtectedHeader({ alg: 'HS256', typ: 'JWT' })
.setIssuedAt()
.setExpirationTime(expiresAt)
.setIssuer('app.example.com')
.sign(SECRET)
cookies().set('app_session', token, { httpOnly: true, secure: true, sameSite: 'lax', expires: expiresAt, path: '/' })
return token
}
export async function getSession(req: NextRequest): Promise<SessionPayload | null> {
const token = req.cookies.get('app_session')?.value
if (!token) return null
try {
const { payload } = await jwtVerify<SessionPayload>(token, SECRET, { issuer: 'app.example.com' })
return payload
} catch {
return null
}
}
// db/users.ts — Drizzle ORM with full type-safe CRUD operations and indexed lookups
import { db } from '@/db'
import { users, sessions } from '@/db/schema'
import { eq, and, gt, desc } from 'drizzle-orm'
export type User = typeof users.$inferSelect
export type NewUser = typeof users.$inferInsert
export async function findUserByEmail(email: string): Promise<User | null> {
const [user] = await db.select().from(users).where(eq(users.email, email)).limit(1)
return user ?? null
}
export async function createUser(data: NewUser): Promise<User> {
const [user] = await db.insert(users).values({ ...data, createdAt: new Date(), updatedAt: new Date() }).returning()
return user
}
export async function listActiveSessions(userId: string) {
return db.select().from(sessions).where(and(eq(sessions.userId, userId), gt(sessions.expiresAt, new Date()))).orderBy(desc(sessions.createdAt))
}
// middleware.ts — protected-route gating with redirect to login and `next` query param for return-to-flow
import { NextResponse, type NextRequest } from 'next/server'
import { getSession } from '@/auth/session'
const PROTECTED_ROUTES = ['/dashboard', '/settings', '/billing', '/account']
const PUBLIC_API_ROUTES = ['/api/health', '/api/webhook/stripe', '/api/auth/callback']
export async function middleware(req: NextRequest) {
const path = req.nextUrl.pathname
const requiresAuth = PROTECTED_ROUTES.some(p => path.startsWith(p))
if (!requiresAuth) return NextResponse.next()
const session = await getSession(req)
if (!session) {
const url = new URL('/login', req.url)
url.searchParams.set('next', path)
return NextResponse.redirect(url)
}
return NextResponse.next()
}
export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico|public/).*)'] }
// db/schema.sql — Postgres tables with row-level security, cascading deletes, and partial indexes for active records
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
name TEXT,
role TEXT NOT NULL DEFAULT 'user' CHECK (role IN ('admin', 'user', 'guest')),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
expires_at TIMESTAMPTZ NOT NULL,
user_agent TEXT,
ip_address INET,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_sessions_user_id ON sessions(user_id);
CREATE INDEX idx_sessions_active ON sessions(expires_at) WHERE expires_at > now();
CREATE INDEX idx_users_email_lower ON users(LOWER(email));
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE sessions ENABLE ROW LEVEL SECURITY;
BUILT FORYOU
scroll
The Engineer · AI Reel · 2026
Tap to explore

01 ▸▸▸
MY STORY
02 ▸▸▸
PHILOSOPHY
◂◂◂ 03
TECH STACK
◂◂◂ 04
BEYOND CODE

Now you know who's building your product. Ready to start?
Now that you know me — it's time for me to know you and your web design needs.