- Login now uses username instead of email - DB migration renames email -> username on existing databases - Users can change their own password from the Stories page - Admin can reset any user's password from the admin panel Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
41 lines
1.5 KiB
JavaScript
41 lines
1.5 KiB
JavaScript
import { Router } from 'express'
|
|
import bcrypt from 'bcryptjs'
|
|
import jwt from 'jsonwebtoken'
|
|
import db from '../db.js'
|
|
import { auth, JWT_SECRET } from '../middleware/auth.js'
|
|
|
|
const router = Router()
|
|
|
|
router.post('/login', (req, res) => {
|
|
const { username, password } = req.body || {}
|
|
if (!username || !password) return res.status(400).json({ error: 'Username and password required' })
|
|
|
|
const user = db.prepare('SELECT * FROM users WHERE username = ?').get(username)
|
|
if (!user || !bcrypt.compareSync(password, user.password)) {
|
|
return res.status(401).json({ error: 'Wrong username or password' })
|
|
}
|
|
|
|
const token = jwt.sign(
|
|
{ id: user.id, username: user.username, name: user.name },
|
|
JWT_SECRET,
|
|
{ expiresIn: '30d' }
|
|
)
|
|
res.json({ token, user: { id: user.id, username: user.username, name: user.name } })
|
|
})
|
|
|
|
router.put('/password', auth, (req, res) => {
|
|
const { current, newPassword } = req.body || {}
|
|
if (!current || !newPassword) return res.status(400).json({ error: 'Current and new password required' })
|
|
if (newPassword.length < 6) return res.status(400).json({ error: 'New password must be at least 6 characters' })
|
|
|
|
const user = db.prepare('SELECT * FROM users WHERE id = ?').get(req.user.id)
|
|
if (!bcrypt.compareSync(current, user.password)) {
|
|
return res.status(401).json({ error: 'Current password is incorrect' })
|
|
}
|
|
|
|
db.prepare('UPDATE users SET password = ? WHERE id = ?').run(bcrypt.hashSync(newPassword, 10), req.user.id)
|
|
res.json({ ok: true })
|
|
})
|
|
|
|
export default router
|