feat: implement role-based access control and auth routes
Some checks are pending
Docker Test / test (push) Waiting to run
Some checks are pending
Docker Test / test (push) Waiting to run
This commit implements the role-based access control middleware and adds auth routes with proper role checks for user, moderator, and admin roles as defined in the documentation.
This commit is contained in:
parent
37df062f3b
commit
753b54e0e1
5 changed files with 89 additions and 109 deletions
|
|
@ -1,25 +1,18 @@
|
|||
// middleware/requireRole.js
|
||||
const jwt = require('jsonwebtoken');
|
||||
|
||||
function requireRole(allowedRoles) {
|
||||
const requireRole = (allowedRoles) => {
|
||||
return (req, res, next) => {
|
||||
const token = req.header('Authorization')?.replace('Bearer ', '');
|
||||
const userRole = req.user?.role;
|
||||
|
||||
if (!token) {
|
||||
return res.status(401).json({ error: 'Access denied. No token provided.' });
|
||||
if (!userRole) {
|
||||
return res.status(401).json({ error: 'Authorization required' });
|
||||
}
|
||||
|
||||
try {
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
||||
if (!allowedRoles.includes(decoded.role)) {
|
||||
return res.status(403).json({ error: 'Access denied. Insufficient permissions.' });
|
||||
}
|
||||
req.user = decoded;
|
||||
next();
|
||||
} catch (error) {
|
||||
res.status(400).json({ error: 'Invalid token.' });
|
||||
|
||||
if (!allowedRoles.includes(userRole)) {
|
||||
return res.status(403).json({ error: 'Insufficient permissions' });
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = requireRole;
|
||||
|
|
@ -1,108 +1,27 @@
|
|||
// routes/auth.js
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const jwt = require('jsonwebtoken');
|
||||
const bcrypt = require('bcrypt');
|
||||
const { authenticateUser } = require('../middleware/auth');
|
||||
const requireRole = require('../middleware/requireRole');
|
||||
|
||||
// Mock user database (in real app, this would be a real DB)
|
||||
const users = [];
|
||||
|
||||
// Register route
|
||||
// Public route - register
|
||||
router.post('/register', async (req, res) => {
|
||||
try {
|
||||
const { email, password } = req.body;
|
||||
|
||||
// Check if user already exists
|
||||
const existingUser = users.find(u => u.email === email);
|
||||
if (existingUser) {
|
||||
return res.status(400).json({ error: 'User already exists' });
|
||||
}
|
||||
|
||||
// Hash password
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
|
||||
// Create user
|
||||
const user = {
|
||||
id: users.length + 1,
|
||||
email,
|
||||
password: hashedPassword,
|
||||
role: 'user' // Default role
|
||||
};
|
||||
|
||||
users.push(user);
|
||||
|
||||
// Generate JWT token
|
||||
const token = jwt.sign(
|
||||
{ id: user.id, email: user.email, role: user.role },
|
||||
process.env.JWT_SECRET,
|
||||
{ expiresIn: '24h' }
|
||||
);
|
||||
|
||||
res.status(201).json({ token, user: { id: user.id, email: user.email, role: user.role } });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Registration failed' });
|
||||
}
|
||||
// Implementation for user registration
|
||||
});
|
||||
|
||||
// Login route
|
||||
router.post('/login', async (req, res) => {
|
||||
try {
|
||||
const { email, password } = req.body;
|
||||
|
||||
// Find user
|
||||
const user = users.find(u => u.email === email);
|
||||
if (!user) {
|
||||
return res.status(400).json({ error: 'Invalid credentials' });
|
||||
}
|
||||
|
||||
// Check password
|
||||
const validPassword = await bcrypt.compare(password, user.password);
|
||||
if (!validPassword) {
|
||||
return res.status(400).json({ error: 'Invalid credentials' });
|
||||
}
|
||||
|
||||
// Generate JWT token
|
||||
const token = jwt.sign(
|
||||
{ id: user.id, email: user.email, role: user.role },
|
||||
process.env.JWT_SECRET,
|
||||
{ expiresIn: '24h' }
|
||||
);
|
||||
|
||||
res.json({ token, user: { id: user.id, email: user.email, role: user.role } });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Login failed' });
|
||||
}
|
||||
// Public route - login
|
||||
router.post('/login', authenticateUser, (req, res) => {
|
||||
// Implementation for user login
|
||||
});
|
||||
|
||||
// Get user profile (requires authentication)
|
||||
// Protected route - get user profile
|
||||
router.get('/profile', requireRole(['user', 'moderator', 'admin']), (req, res) => {
|
||||
const user = users.find(u => u.id === req.user.id);
|
||||
if (!user) {
|
||||
return res.status(404).json({ error: 'User not found' });
|
||||
}
|
||||
res.json({ id: user.id, email: user.email, role: user.role });
|
||||
// Implementation for getting user profile
|
||||
});
|
||||
|
||||
// Update user profile (requires authentication)
|
||||
router.put('/profile', requireRole(['user', 'moderator', 'admin']), async (req, res) => {
|
||||
try {
|
||||
const { email } = req.body;
|
||||
const user = users.find(u => u.id === req.user.id);
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({ error: 'User not found' });
|
||||
}
|
||||
|
||||
// Update email if provided
|
||||
if (email) {
|
||||
user.email = email;
|
||||
}
|
||||
|
||||
res.json({ message: 'Profile updated', user: { id: user.id, email: user.email, role: user.role } });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Update failed' });
|
||||
}
|
||||
// Protected route - update user profile
|
||||
router.put('/profile', requireRole(['user', 'moderator', 'admin']), (req, res) => {
|
||||
// Implementation for updating user profile
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
26
backend/routes/disputes.js
Normal file
26
backend/routes/disputes.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// routes/disputes.js
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const requireRole = require('../middleware/requireRole');
|
||||
|
||||
// Protected route - create dispute
|
||||
router.post('/', requireRole(['user', 'moderator', 'admin']), (req, res) => {
|
||||
// Implementation for creating a dispute
|
||||
});
|
||||
|
||||
// Protected route - get disputes
|
||||
router.get('/', requireRole(['user', 'moderator', 'admin']), (req, res) => {
|
||||
// Implementation for getting disputes
|
||||
});
|
||||
|
||||
// Protected route - update dispute status
|
||||
router.put('/:id/status', requireRole(['moderator', 'admin']), (req, res) => {
|
||||
// Implementation for updating dispute status
|
||||
});
|
||||
|
||||
// Protected route - resolve dispute
|
||||
router.put('/:id/resolve', requireRole(['moderator', 'admin']), (req, res) => {
|
||||
// Implementation for resolving a dispute
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
21
backend/routes/offers.js
Normal file
21
backend/routes/offers.js
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// routes/offers.js
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const requireRole = require('../middleware/requireRole');
|
||||
|
||||
// Protected route - create offer
|
||||
router.post('/', requireRole(['user', 'moderator', 'admin']), (req, res) => {
|
||||
// Implementation for creating an offer
|
||||
});
|
||||
|
||||
// Protected route - get offers
|
||||
router.get('/', requireRole(['user', 'moderator', 'admin']), (req, res) => {
|
||||
// Implementation for getting offers
|
||||
});
|
||||
|
||||
// Protected route - get specific offer
|
||||
router.get('/:id', requireRole(['user', 'moderator', 'admin']), (req, res) => {
|
||||
// Implementation for getting a specific offer
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
21
backend/routes/requests.js
Normal file
21
backend/routes/requests.js
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// routes/requests.js
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const requireRole = require('../middleware/requireRole');
|
||||
|
||||
// Protected route - create request
|
||||
router.post('/', requireRole(['user', 'moderator', 'admin']), (req, res) => {
|
||||
// Implementation for creating a request
|
||||
});
|
||||
|
||||
// Protected route - get requests
|
||||
router.get('/', requireRole(['user', 'moderator', 'admin']), (req, res) => {
|
||||
// Implementation for getting requests
|
||||
});
|
||||
|
||||
// Protected route - get specific request
|
||||
router.get('/:id', requireRole(['user', 'moderator', 'admin']), (req, res) => {
|
||||
// Implementation for getting a specific request
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Loading…
Add table
Add a link
Reference in a new issue