159 lines
6.1 KiB
JavaScript
159 lines
6.1 KiB
JavaScript
|
const { authenticate, createSession, validateSession } = require('../acl');
|
||
|
const cookie = require('cookie');
|
||
|
const users = require('../users'); // Hardcoded users
|
||
|
const { User, Achievement } = require('../models'); // Sequelize models
|
||
|
const { getLearningContent } = require('../openai');
|
||
|
const bcrypt = require('bcrypt');
|
||
|
|
||
|
// Function to handle user login
|
||
|
const loginUser = async (req, res) => {
|
||
|
let body = '';
|
||
|
req.on('data', chunk => {
|
||
|
body += chunk.toString();
|
||
|
});
|
||
|
req.on('end', async () => {
|
||
|
try {
|
||
|
const { username, password } = JSON.parse(body);
|
||
|
let user = await User.findOne({ where: { username } });
|
||
|
if (!user && users[username]) {
|
||
|
user = { username, password: users[username].password, role: users[username].role };
|
||
|
}
|
||
|
|
||
|
if (user && bcrypt.compareSync(password, user.password)) {
|
||
|
const token = await createSession(username);
|
||
|
res.setHeader('Set-Cookie', cookie.serialize('token', token, {
|
||
|
httpOnly: true,
|
||
|
maxAge: 3600 // 1 hour
|
||
|
}));
|
||
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ message: 'Login successful', token }));
|
||
|
} else {
|
||
|
res.writeHead(401, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ error: 'Invalid username or password' }));
|
||
|
}
|
||
|
} catch (err) {
|
||
|
res.writeHead(400, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ error: 'Invalid request format - ' + err }));
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
// Function to handle user registration
|
||
|
const registerUser = async (req, res) => {
|
||
|
let body = '';
|
||
|
req.on('data', chunk => {
|
||
|
body += chunk.toString();
|
||
|
});
|
||
|
req.on('end', async () => {
|
||
|
try {
|
||
|
const { username, password, role } = JSON.parse(body);
|
||
|
if (!username || !password || !role) {
|
||
|
res.writeHead(400, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ error: 'Missing required fields' }));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const existingUser = await User.findOne({ where: { username } });
|
||
|
if (existingUser || users[username]) {
|
||
|
res.writeHead(409, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ error: 'User already exists' }));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Save user to the database
|
||
|
await User.create({ username, password, role });
|
||
|
|
||
|
// Save user to the hardcoded users list
|
||
|
users[username] = { password, role };
|
||
|
|
||
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ message: 'User registered successfully' }));
|
||
|
} catch (err) {
|
||
|
res.writeHead(400, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ error: 'Invalid request format' }));
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
// Function to fetch user achievements
|
||
|
const fetchAchievements = async (req, res) => {
|
||
|
try {
|
||
|
const session = await validateSession(req.cookies.token);
|
||
|
if (session && session.data.user) {
|
||
|
const achievements = await Achievement.findAll({ where: { userId: session.data.user.id } });
|
||
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify(achievements));
|
||
|
} else {
|
||
|
res.writeHead(401, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ error: 'Unauthorized' }));
|
||
|
}
|
||
|
} catch (err) {
|
||
|
res.writeHead(500, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ error: 'Failed to fetch achievements' }));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Function to fetch learning content from OpenAI
|
||
|
const fetchLearningContent = async (req, res) => {
|
||
|
let body = '';
|
||
|
req.on('data', chunk => {
|
||
|
body += chunk.toString();
|
||
|
});
|
||
|
req.on('end', async () => {
|
||
|
try {
|
||
|
const { prompt } = JSON.parse(body);
|
||
|
const content = await getLearningContent(prompt);
|
||
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ content }));
|
||
|
} catch (err) {
|
||
|
res.writeHead(500, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ error: 'Failed to fetch learning content' }));
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
// Function to handle adding achievements
|
||
|
const addAchievement = async (req, res) => {
|
||
|
let body = '';
|
||
|
req.on('data', chunk => {
|
||
|
body += chunk.toString();
|
||
|
});
|
||
|
req.on('end', async () => {
|
||
|
try {
|
||
|
const { userId, badge } = JSON.parse(body);
|
||
|
if (!userId || !badge) {
|
||
|
res.writeHead(400, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ error: 'Missing required fields' }));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
await Achievement.create({ userId, badge });
|
||
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ message: 'Achievement added successfully' }));
|
||
|
} catch (err) {
|
||
|
res.writeHead(500, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ error: 'Failed to add achievement' }));
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
// Export the API request handler
|
||
|
const handleApiRequest = (req, res) => {
|
||
|
if (req.url === '/api/login' && req.method === 'POST') {
|
||
|
loginUser(req, res);
|
||
|
} else if (req.url === '/api/register' && req.method === 'POST') {
|
||
|
registerUser(req, res);
|
||
|
} else if (req.url === '/api/achievements' && req.method === 'GET') {
|
||
|
fetchAchievements(req, res);
|
||
|
} else if (req.url === '/api/achievements' && req.method === 'POST') {
|
||
|
addAchievement(req, res);
|
||
|
} else if (req.url === '/api/learning-content' && req.method === 'POST') {
|
||
|
fetchLearningContent(req, res);
|
||
|
} else {
|
||
|
res.writeHead(404, { 'Content-Type': 'application/json' });
|
||
|
res.end(JSON.stringify({ error: 'Not Found' }));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
module.exports = { handleApiRequest };
|