Files
neta/server/auth/auth.ts
T
Poyraz 24fcdf9a77 feat: add new UI components and improve existing ones
- Introduced `Field` and `Label` components for better form handling.
- Refactored `Input` and `Textarea` components to use forward refs and improved styling.
- Updated `PendingSubmitButton` to use the new `Button` component.
- Enhanced `Skeleton` component for better layout handling.
- Revamped `Toast` component to support live regions and improved accessibility.
- Updated sidebar configuration to use typed icons.
- Added phase 3 UI boundary checks to prevent usage of deprecated imports.
- Implemented new authentication action handler for better cookie management.
- Improved setup logic for freelancer accounts with repair functionality.
2026-07-10 22:47:02 +03:00

95 lines
2.2 KiB
TypeScript

import "server-only";
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { nextCookies } from "better-auth/next-js";
import { getServerConfig } from "@/server/config";
import { getSqliteConnection } from "@/server/db/client";
import * as schema from "@/server/db/schema";
import {
completeFirstFreelancerSetup,
recordAuthAuditEvent,
reserveFirstFreelancerSetup,
} from "@/server/auth/setup";
const config = getServerConfig();
export const auth = betterAuth({
appName: "Neta",
baseURL: config.appUrl,
trustedOrigins: config.trustedOrigins,
secret: config.betterAuthSecret,
database: drizzleAdapter(getSqliteConnection().db, {
provider: "sqlite",
schema,
transaction: false,
}),
emailAndPassword: {
enabled: true,
minPasswordLength: 8,
maxPasswordLength: 128,
requireEmailVerification: false,
},
rateLimit: {
enabled: true,
window: 60,
max: 60,
customRules: {
"/sign-in/email": {
window: 60,
max: 10,
},
"/sign-up/email": {
window: 300,
max: 3,
},
},
},
advanced: {
useSecureCookies: config.nodeEnv === "production",
cookiePrefix: "neta",
defaultCookieAttributes: {
httpOnly: true,
sameSite: "lax",
secure: config.nodeEnv === "production",
path: "/",
},
},
databaseHooks: {
user: {
create: {
before: async (user) => {
const isReserved = await reserveFirstFreelancerSetup(user.email);
return isReserved;
},
after: async (user) => {
await completeFirstFreelancerSetup(user);
},
},
},
session: {
create: {
after: async (session) => {
await recordAuthAuditEvent({
type: "login_succeeded",
authUserId: session.userId,
metadata: { source: "session_create" },
});
},
},
delete: {
after: async (session) => {
await recordAuthAuditEvent({
type: "logout_succeeded",
authUserId: session.userId,
metadata: { source: "session_delete" },
});
},
},
},
},
plugins: [nextCookies()],
});
export type Auth = typeof auth;