Files
CaseGambling/server/src/routes/auth.js
T
2026-07-16 20:23:58 +02:00

118 lines
3.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Router } from 'express';
import bcrypt from 'bcrypt';
import { prisma } from '../db.js';
import { publicUser, requireAuth } from '../middleware.js';
const router = Router();
const STARTING_BALANCE = Number(process.env.STARTING_BALANCE || 10000);
const STARTING_OSU = Number(process.env.STARTING_OSU || 100);
router.post('/register', async (req, res) => {
try {
const username = String(req.body.username || '').trim();
const password = String(req.body.password || '');
if (username.length < 3 || username.length > 32) {
return res.status(400).json({ error: 'Username must be 332 characters' });
}
if (!/^[a-zA-Z0-9_]+$/.test(username)) {
return res.status(400).json({ error: 'Username may only contain letters, numbers, and underscores' });
}
if (password.length < 6) {
return res.status(400).json({ error: 'Password must be at least 6 characters' });
}
const existing = await prisma.user.findUnique({ where: { username } });
if (existing) {
return res.status(409).json({ error: 'Username already taken' });
}
const passwordHash = await bcrypt.hash(password, 10);
const user = await prisma.user.create({
data: {
username,
passwordHash,
balance: STARTING_BALANCE,
osuBalance: STARTING_OSU,
role: 'user',
},
});
await prisma.transaction.create({
data: {
userId: user.id,
type: 'seed_credit',
amount: STARTING_BALANCE,
meta: JSON.stringify({ reason: 'starting_balance' }),
},
});
await prisma.transaction.create({
data: {
userId: user.id,
type: 'seed_osu',
amount: STARTING_OSU,
meta: JSON.stringify({ reason: 'starting_osu' }),
},
});
req.session.userId = user.id;
req.session.role = user.role;
res.status(201).json({ user: publicUser(user) });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Registration failed' });
}
});
router.post('/login', async (req, res) => {
try {
const username = String(req.body.username || '').trim();
const password = String(req.body.password || '');
const user = await prisma.user.findUnique({ where: { username } });
if (!user) {
return res.status(401).json({ error: 'Invalid username or password' });
}
const ok = await bcrypt.compare(password, user.passwordHash);
if (!ok) {
return res.status(401).json({ error: 'Invalid username or password' });
}
req.session.userId = user.id;
req.session.role = user.role;
res.json({ user: publicUser(user) });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Login failed' });
}
});
router.post('/logout', (req, res) => {
req.session.destroy((err) => {
if (err) {
return res.status(500).json({ error: 'Logout failed' });
}
res.clearCookie('connect.sid');
res.json({ ok: true });
});
});
router.get('/me', requireAuth, async (req, res) => {
try {
const user = await prisma.user.findUnique({ where: { id: req.session.userId } });
if (!user) {
return res.status(401).json({ error: 'User not found' });
}
res.json({ user: publicUser(user) });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Failed to load user' });
}
});
export default router;