Files
crates/crates/routes/api/auth/login.ts
T
2025-05-02 01:07:56 +10:00

90 lines
2.8 KiB
TypeScript

import { Handlers } from "$fresh/server.ts"
import { setCookie } from "$std/http/cookie.ts"
import * as bcrypt from "https://deno.land/x/bcrypt@v0.4.1/mod.ts"
import { z } from "npm:zod"
import { zx } from "npm:zodix"
import { createSession } from "api/mw.auth.ts"
import {
ValidationError,
InvalidCredentialsError,
NotLoggedInError,
ServerError
} from "api/errors.ts"
import { CratesState } from 'api/mw.service.ts'
const LoginSchema = z.object({
email: z.string().email("Invalid email format"),
password: z.string().min(1)
})
export const handler: Handlers<{email: string}, CratesState> = {
async POST(req, ctx) {
try {
const { email, password } = await zx.parseForm(req, LoginSchema)
// Create pg instance for database operations
const { pg } = ctx.state
// Find user by email
const user = await pg.userFindEmail(email)
if (!user) throw new InvalidCredentialsError()
// Verify password
const match = await bcrypt.compare(password, user.password)
if (!match) throw new InvalidCredentialsError()
// Create session using Deno KV
const { sessionId, expiresAt } = await createSession(user.id, 24 * 7) // 7 days in hours
// Set cookie
const headers = new Headers({ "Content-Type": "application/json" })
setCookie(headers, {
name: "session",
value: sessionId,
expires: expiresAt,
path: "/",
httpOnly: true,
secure: true,
sameSite: "Lax"
})
// Return user data
return new Response(JSON.stringify({
email: user.email
}), {
status: 200,
headers
})
} catch (error) {
// Let the error middleware handle custom errors
if (error instanceof ValidationError ||
error instanceof InvalidCredentialsError) {
throw error
}
console.error("Login error:", error)
throw new ServerError("An error occurred during login")
}
},
// GET handler to check login status
async GET(req, ctx) {
// This would be handled by the auth middleware
// If the request reaches here, the user is authenticated
const user = ctx.state.user
if (!user) {
throw new NotLoggedInError()
}
return new Response(JSON.stringify({
id: user.id,
email: user.email
}), {
status: 200,
headers: { "Content-Type": "application/json" }
})
}
}