Browse Source
- Create API route structure (auth, health, internal) - Add authentication middleware for internal pages - Add database connection utilities - Implement health check endpointmain
2 changed files with 87 additions and 0 deletions
@ -0,0 +1,53 @@ |
|||
/** |
|||
* Basic Authentication Middleware for /internal/* routes |
|||
* Protects internal pages (styleguide, admin tools) with HTTP Basic Auth |
|||
*/ |
|||
|
|||
export default defineEventHandler((event) => { |
|||
const path = event.path |
|||
|
|||
// Only protect /internal/* routes
|
|||
if (!path.startsWith('/internal')) { |
|||
return |
|||
} |
|||
|
|||
const config = useRuntimeConfig() |
|||
|
|||
// Get credentials from environment variables
|
|||
const validUsername = config.internalAuthUsername |
|||
const validPassword = config.internalAuthPassword |
|||
|
|||
// Skip auth if credentials are not configured (development convenience)
|
|||
if (!validUsername || !validPassword) { |
|||
console.warn('⚠️ INTERNAL_AUTH_USERNAME or INTERNAL_AUTH_PASSWORD not set. /internal routes are unprotected!') |
|||
return |
|||
} |
|||
|
|||
// Get Authorization header
|
|||
const authHeader = getHeader(event, 'authorization') |
|||
|
|||
if (!authHeader || !authHeader.startsWith('Basic ')) { |
|||
// Request authentication
|
|||
setHeader(event, 'WWW-Authenticate', 'Basic realm="Internal Area"') |
|||
throw createError({ |
|||
statusCode: 401, |
|||
statusMessage: 'Authentication required', |
|||
}) |
|||
} |
|||
|
|||
// Decode credentials
|
|||
const base64Credentials = authHeader.split(' ')[1] |
|||
const credentials = Buffer.from(base64Credentials, 'base64').toString('utf-8') |
|||
const [username, password] = credentials.split(':') |
|||
|
|||
// Validate credentials
|
|||
if (username !== validUsername || password !== validPassword) { |
|||
setHeader(event, 'WWW-Authenticate', 'Basic realm="Internal Area"') |
|||
throw createError({ |
|||
statusCode: 401, |
|||
statusMessage: 'Invalid credentials', |
|||
}) |
|||
} |
|||
|
|||
// Authentication successful, continue
|
|||
}) |
|||
@ -0,0 +1,34 @@ |
|||
import { drizzle } from 'drizzle-orm/postgres-js' |
|||
import postgres from 'postgres' |
|||
import * as schema from '../database/schema' |
|||
|
|||
/** |
|||
* Database connection utility |
|||
* |
|||
* Creates a singleton Drizzle ORM instance with the complete schema. |
|||
* This allows for type-safe database queries throughout the application. |
|||
* |
|||
* Usage: |
|||
* ```typescript
|
|||
* import { db } from '~/server/utils/db' |
|||
* |
|||
* // Query with relations
|
|||
* const users = await db.query.users.findMany({ |
|||
* with: { orders: true } |
|||
* }) |
|||
* |
|||
* // Raw SQL with type safety
|
|||
* import { users } from '~/server/database/schema' |
|||
* import { eq } from 'drizzle-orm' |
|||
* |
|||
* const user = await db.select().from(users).where(eq(users.id, userId)) |
|||
* ``` |
|||
*/ |
|||
|
|||
const config = useRuntimeConfig() |
|||
|
|||
// Create postgres.js client
|
|||
const client = postgres(config.databaseUrl) |
|||
|
|||
// Create Drizzle ORM instance with schema
|
|||
export const db = drizzle(client, { schema }) |
|||
Loading…
Reference in new issue