134 lines
3.3 KiB
JavaScript
134 lines
3.3 KiB
JavaScript
|
const acl = {
|
||
|
'/login': {
|
||
|
roles: ['*'],
|
||
|
methods: ['GET'],
|
||
|
template: 'login.ejs'
|
||
|
},
|
||
|
'/api/login': {
|
||
|
roles: ['*'],
|
||
|
methods: ['POST']
|
||
|
},
|
||
|
'/register': {
|
||
|
roles: ['*'],
|
||
|
methods: ['GET'],
|
||
|
template: 'register.ejs'
|
||
|
},
|
||
|
'/api/register': {
|
||
|
roles: ['*'],
|
||
|
methods: ['POST']
|
||
|
},
|
||
|
'/portfolio': {
|
||
|
roles: ['*'],
|
||
|
methods: ['GET'],
|
||
|
template: 'portfolio.ejs'
|
||
|
},
|
||
|
'/api/secure-data': {
|
||
|
roles: ['admin', 'user'],
|
||
|
methods: ['GET']
|
||
|
},
|
||
|
'/api/admin-data': {
|
||
|
roles: ['admin'],
|
||
|
methods: ['GET']
|
||
|
},
|
||
|
'/api/user': {
|
||
|
roles: ['admin'],
|
||
|
methods: ['POST', 'PUT', 'DELETE']
|
||
|
},
|
||
|
'/api/achievements': {
|
||
|
roles: ['*'],
|
||
|
methods: ['GET', 'POST', 'PUT', 'DELETE']
|
||
|
},
|
||
|
'/api/learning-content': {
|
||
|
roles: ['user'],
|
||
|
methods: ['GET', 'POST', 'PUT', 'DELETE']
|
||
|
},
|
||
|
'/': {
|
||
|
roles: ['*'],
|
||
|
methods: ['GET'],
|
||
|
template: 'index.ejs'
|
||
|
},
|
||
|
'/mobile': {
|
||
|
roles: ['*'],
|
||
|
methods: ['GET'],
|
||
|
template: 'mobile.ejs'
|
||
|
},
|
||
|
'/admin': {
|
||
|
roles: ['admin'],
|
||
|
methods: ['GET'],
|
||
|
template: 'admin.ejs'
|
||
|
},
|
||
|
'/about': {
|
||
|
roles: ['*'],
|
||
|
methods: ['GET'],
|
||
|
template: 'about.ejs'
|
||
|
},
|
||
|
'/contact': {
|
||
|
roles: ['*'],
|
||
|
methods: ['GET'],
|
||
|
template: 'contact.ejs'
|
||
|
},
|
||
|
'/sessions': {
|
||
|
roles: ['admin'],
|
||
|
methods: ['GET'],
|
||
|
template: 'sessions.ejs'
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const { v4: uuidv4 } = require('uuid');
|
||
|
const { Op } = require('sequelize');
|
||
|
const { User, Session } = require('./models');
|
||
|
const bcrypt = require('bcrypt');
|
||
|
const users = require('./users'); // Hardcoded users
|
||
|
|
||
|
const authenticate = async (username, password) => {
|
||
|
const user = users[username] || await User.findOne({ where: { username } });
|
||
|
if (user && bcrypt.compareSync(password, user.password)) {
|
||
|
return user;
|
||
|
}
|
||
|
return null;
|
||
|
};
|
||
|
|
||
|
const authorize = (path, method, role) => {
|
||
|
const permissions = acl[path];
|
||
|
if (!permissions) return false;
|
||
|
const { roles, methods, template } = permissions;
|
||
|
if (methods && !methods.includes(method)) return false;
|
||
|
if (roles && !roles.includes('*') && !roles.includes(role)) return false;
|
||
|
return template || true;
|
||
|
};
|
||
|
|
||
|
const createSession = async (username) => {
|
||
|
const user = users[username] || await User.findOne({ where: { username } });
|
||
|
const token = uuidv4();
|
||
|
const expiresAt = new Date();
|
||
|
expiresAt.setHours(expiresAt.getHours() + 1); // Session expires in 1 hour
|
||
|
|
||
|
await Session.create({
|
||
|
token,
|
||
|
username,
|
||
|
data: JSON.stringify({ user: { username: username, role: user.role, id: user.id } }),
|
||
|
expiresAt
|
||
|
});
|
||
|
|
||
|
return token;
|
||
|
};
|
||
|
|
||
|
const validateSession = async (token) => {
|
||
|
if (!token) {
|
||
|
return null;
|
||
|
}
|
||
|
const session = await Session.findOne({
|
||
|
where: { token, expiresAt: { [Op.gt]: new Date() } }
|
||
|
});
|
||
|
if (session) {
|
||
|
return { username: session.username, data: session.data ? JSON.parse(session.data) : {} };
|
||
|
}
|
||
|
return null;
|
||
|
};
|
||
|
|
||
|
const getUser = (username) => {
|
||
|
return users[username] || User.findOne({ where: { username } });
|
||
|
};
|
||
|
|
||
|
module.exports = { authenticate, authorize, createSession, validateSession, getUser, acl };
|