Files
ProjectE/apps/web/lib/auth-config.ts
T
mbatchelder b3ff23a5f0 feat: Phase 1 foundation - schema, auth, realtime, shell
- Rewrote Drizzle schema: 20 tables with enums, relations, indexes
- Generated migration with DROP TABLE records (v1 EAV removal)
- Added passkey auth routes (register/login)
- Added requireWorkspaceAccess helper
- Added seedDefaultData for Personal workspace + welcome note
- Updated SSE endpoint for v2 entities + workspace_id filtering
- Created recordActivity helper (insert + pg_notify)
- Updated sidebar: Graph replaces Reports, removed Analytics
- Updated command palette for v2 entities
- Created AGENTS.md with locked contract
- Created llm-wiki scaffold (5 stubs)
- Added inline AGENT INSTRUCTION comments to all 50 API route files
- Fixed globals.css border-border class conflict
- Updated database.ts stub for v1 compatibility
2026-07-29 05:53:13 -04:00

57 lines
2.0 KiB
TypeScript

import bcrypt from 'bcryptjs';
import { count, eq } from 'drizzle-orm';
import type { NextAuthOptions } from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import { db, users } from '@project-e/db';
import { seedDefaultData } from './seed';
export const authOptions: NextAuthOptions = {
session: { strategy: 'jwt' },
providers: [
CredentialsProvider({
name: 'Credentials',
credentials: {
email: { label: 'Email', type: 'email' },
password: { label: 'Password', type: 'password' },
},
async authorize(credentials) {
const email = credentials?.email?.trim().toLowerCase();
const password = credentials?.password;
if (!email || !password) return null;
let [user] = await db.select().from(users).where(eq(users.email, email)).limit(1);
if (!user) {
const [{ total }] = await db.select({ total: count() }).from(users);
const initialEmail = process.env.INITIAL_ADMIN_EMAIL?.trim().toLowerCase();
const initialPassword = process.env.INITIAL_ADMIN_PASSWORD;
if (total === 0 && email === initialEmail && password === initialPassword) {
[user] = await db.insert(users).values({
email,
name: process.env.INITIAL_ADMIN_NAME || email,
passwordHash: await bcrypt.hash(password, 12),
}).returning();
// Seed default workspace + welcome note on first user creation
await seedDefaultData();
}
}
if (!user || !(await bcrypt.compare(password, user.passwordHash))) return null;
return { id: user.id, email: user.email, name: user.name };
},
}),
],
callbacks: {
jwt({ token, user }) {
if (user) token.id = user.id;
return token;
},
session({ session, token }) {
if (session.user) session.user.id = token.id as string;
return session;
},
},
pages: { signIn: '/login' },
};