- React + TipTap editor with formatting toolbar (bold, italic, underline, strikethrough, alignment, highlight, scene breaks) - Custom image node view with resize and alignment controls; server-side WebP conversion via sharp - Express + SQLite backend with JWT auth and admin user management - Export to PDF, EPUB, and ODT - Five themes (Midnight, Gothic Night, Enchanted Forest, Aged Manuscript, Neon Noir); Lora body font for readability - Writing streak, daily word goal, milestones, and Ollama writing prompts - Docker Compose setup for self-hosted deployment behind NPMplus Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
22 lines
704 B
JavaScript
22 lines
704 B
JavaScript
import jwt from 'jsonwebtoken'
|
|
|
|
export const JWT_SECRET = process.env.JWT_SECRET || 'dev-secret-change-in-production'
|
|
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || 'admin'
|
|
|
|
export function auth(req, res, next) {
|
|
const token = req.headers.authorization?.split(' ')[1]
|
|
if (!token) return res.status(401).json({ error: 'Not logged in' })
|
|
try {
|
|
req.user = jwt.verify(token, JWT_SECRET)
|
|
next()
|
|
} catch {
|
|
res.status(401).json({ error: 'Session expired, please log in again' })
|
|
}
|
|
}
|
|
|
|
export function adminAuth(req, res, next) {
|
|
const pw = req.headers['x-admin-password']
|
|
if (pw && pw === ADMIN_PASSWORD) return next()
|
|
res.status(401).json({ error: 'Wrong admin password' })
|
|
}
|