Ver código fonte

Add auth routes (register, login, me)

k4be 7 horas atrás
pai
commit
0efb8ab7fb
1 arquivos alterados com 76 adições e 0 exclusões
  1. 76 0
      gpx-vis-backend/src/routes/auth.js

+ 76 - 0
gpx-vis-backend/src/routes/auth.js

@@ -0,0 +1,76 @@
+const router = require('express').Router();
+const bcrypt = require('bcryptjs');
+const jwt = require('jsonwebtoken');
+const { User } = require('../models');
+let config;
+try { config = require('../../config'); } catch(e) { config = { jwt: { secret: 'dev', expiresIn: '7d' } }; }
+const { requireAuth } = require('../middleware/auth');
+
+router.post('/register', async (req, res) => {
+  try {
+    const { login, email, password } = req.body;
+    if (!login || !/^[a-zA-Z0-9_]{3,32}$/.test(login)) {
+      return res.status(400).json({ error: 'Login must be 3-32 alphanumeric characters or underscores' });
+    }
+    if (!password || password.length < 6) {
+      return res.status(400).json({ error: 'Password must be at least 6 characters' });
+    }
+    const existing = await User.findOne({ where: { login } });
+    if (existing) return res.status(409).json({ error: 'Login already taken' });
+
+    const count = await User.count();
+    const isAdmin = count === 0;
+    const isActive = count === 0;
+
+    const passwordHash = await bcrypt.hash(password, 12);
+    const user = await User.create({
+      login, email: email || null, passwordHash, isAdmin, isActive
+    });
+
+    res.status(201).json({
+      id: user.id, login: user.login, email: user.email,
+      isAdmin: user.isAdmin, isActive: user.isActive
+    });
+  } catch (e) {
+    console.error(e);
+    res.status(500).json({ error: 'Server error' });
+  }
+});
+
+router.post('/login', async (req, res) => {
+  try {
+    const { login, password } = req.body;
+    const user = await User.findOne({ where: { login } });
+    if (!user) return res.status(401).json({ error: 'Invalid credentials' });
+
+    const valid = await bcrypt.compare(password, user.passwordHash);
+    if (!valid) return res.status(401).json({ error: 'Invalid credentials' });
+
+    if (!user.isActive) return res.status(403).json({ error: 'Account not yet activated by admin' });
+
+    const token = jwt.sign(
+      { id: user.id, login: user.login, isAdmin: user.isAdmin },
+      config.jwt.secret,
+      { expiresIn: config.jwt.expiresIn }
+    );
+
+    res.json({ token, user: { id: user.id, login: user.login, isAdmin: user.isAdmin, isActive: user.isActive } });
+  } catch (e) {
+    console.error(e);
+    res.status(500).json({ error: 'Server error' });
+  }
+});
+
+router.get('/me', requireAuth, async (req, res) => {
+  try {
+    const user = await User.findByPk(req.user.id, {
+      attributes: ['id', 'login', 'email', 'isAdmin', 'isActive', 'createdAt']
+    });
+    if (!user) return res.status(404).json({ error: 'User not found' });
+    res.json(user);
+  } catch (e) {
+    res.status(500).json({ error: 'Server error' });
+  }
+});
+
+module.exports = router;