write/server/routes/admin.js
chris 1f51504de9 Add story writer app with editor, auth, export, and polish features
- 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>
2026-05-11 11:47:55 -04:00

38 lines
1.1 KiB
JavaScript

import { Router } from 'express'
import bcrypt from 'bcryptjs'
import db from '../db.js'
import { adminAuth } from '../middleware/auth.js'
const router = Router()
router.use(adminAuth)
router.get('/users', (req, res) => {
const users = db.prepare(
'SELECT id, name, email, created_at FROM users ORDER BY created_at DESC'
).all()
res.json(users)
})
router.post('/users', (req, res) => {
const { name, email, password } = req.body || {}
if (!name || !email || !password)
return res.status(400).json({ error: 'Name, email, and password are all required' })
try {
const hash = bcrypt.hashSync(password, 10)
const { lastInsertRowid } = db.prepare(
'INSERT INTO users (name, email, password) VALUES (?, ?, ?)'
).run(name, email.toLowerCase(), hash)
res.json({ id: lastInsertRowid, name, email })
} catch {
res.status(400).json({ error: 'That email is already in use' })
}
})
router.delete('/users/:id', (req, res) => {
db.prepare('DELETE FROM users WHERE id = ?').run(req.params.id)
res.json({ ok: true })
})
export default router