202 lines
6.6 KiB
JavaScript
202 lines
6.6 KiB
JavaScript
const express = require('express');
|
|
const argon2 = require('argon2');
|
|
const {
|
|
initDb,
|
|
getAllArticles,
|
|
getArticle,
|
|
createArticle,
|
|
updateArticle,
|
|
deleteArticle,
|
|
searchArticles,
|
|
createUser,
|
|
getUserByUsername,
|
|
getUserByEmail
|
|
} = require('./db');
|
|
const { generateToken, authenticateToken } = require('./auth');
|
|
const app = express();
|
|
const cors = require('cors');
|
|
const PORT = 9000;
|
|
|
|
app.use(cors())
|
|
app.use(express.json());
|
|
|
|
initDb().then(() => {
|
|
|
|
app.get('/', (req, res) => {
|
|
res.json({message : 'Server is running'});
|
|
});
|
|
|
|
app.get('/api/articles', authenticateToken, (req, res) => {
|
|
try {
|
|
const articles = getAllArticles();
|
|
res.json(articles);
|
|
} catch (error) {
|
|
console.error('Error fetching articles:', error);
|
|
res.status(500).json({error: 'Failed to fetch articles', 'details': String(error)});
|
|
}
|
|
});
|
|
|
|
app.get('/api/articles/:ka_number', authenticateToken, (req, res) => {
|
|
try {
|
|
const article = getArticle(req.params.ka_number);
|
|
|
|
if (!article) {
|
|
return res.status(404).json({ error: 'Article not found' });
|
|
}
|
|
|
|
res.json(article);
|
|
} catch (error) {
|
|
console.error('Error fetching article:', error);
|
|
res.status(500).json({error: 'Failed to fetch article', 'details': String(error)});
|
|
}
|
|
});
|
|
|
|
app.post('/api/articles', authenticateToken, (req, res) => {
|
|
try {
|
|
const { title, content } = req.body;
|
|
|
|
if (!title) {
|
|
return res.status(400).json({error: 'Title is required' });
|
|
}
|
|
|
|
const article = createArticle(title, content, req.user.display_name);
|
|
res.status(201).json(article);
|
|
|
|
} catch (error) {
|
|
console.error('Error creating article:', error);
|
|
res.status(500).json({error: 'Failed to create article', 'details': String(error)});
|
|
}
|
|
});
|
|
|
|
app.put('/api/articles/:ka_number', authenticateToken, (req, res) => {
|
|
try {
|
|
const { title, content } = req.body;
|
|
|
|
if (!title) {
|
|
return res.status(400).json({error: 'Title is required' });
|
|
}
|
|
|
|
const article = updateArticle(req.params.ka_number, title, content, req.user.display_name);
|
|
|
|
if (!article) {
|
|
return res.status(404).json({error: 'Article not found'});
|
|
}
|
|
|
|
res.json(article);
|
|
} catch (error) {
|
|
console.error('Error updating article:', error);
|
|
return res.status(500).json({error: 'Error while updating article', 'details': String(error)});
|
|
}
|
|
});
|
|
|
|
app.delete('/api/articles/:ka_number', authenticateToken, (req, res) => {
|
|
try {
|
|
deleteArticle(req.params.ka_number);
|
|
return res.status(200).json({'message': 'Successfully deleted article'});
|
|
|
|
} catch (error) {
|
|
console.error('Error when deleting article:', error);
|
|
return res.status(500).json({error: 'Failed to delete article', 'details': String(error)});
|
|
}
|
|
});
|
|
|
|
app.get('/api/search', authenticateToken, (req, res) => {
|
|
try {
|
|
const query = req.query.q;
|
|
|
|
if (!query) {
|
|
return res.status(400).json({error: 'Search query is required'});
|
|
}
|
|
|
|
const results = searchArticles(query);
|
|
res.json(results);
|
|
} catch (error) {
|
|
console.error('Error when searching articles:', error);
|
|
return res.status(500).json({error: 'Failed to search articles', 'details': String(error)});
|
|
}
|
|
});
|
|
|
|
app.post('/api/auth/register', async (req, res) => {
|
|
try {
|
|
const {username, email, password, displayName} = req.body;
|
|
|
|
if (!username || !email || !password || !displayName) {
|
|
return res.status(400).json({error: 'Username, email, password, and display name are required'});
|
|
}
|
|
|
|
const cur_user_username = getUserByUsername(username);
|
|
if (cur_user_username) {
|
|
return res.status(400).json({error: 'Username already exists'});
|
|
}
|
|
|
|
const cur_user_email = getUserByEmail(email);
|
|
if(cur_user_email) {
|
|
return res.status(400).json({error: 'email address already in use'});
|
|
}
|
|
|
|
const pass_hash = await argon2.hash(password);
|
|
const newUser = createUser(username, email, pass_hash, displayName);
|
|
const token = generateToken(newUser);
|
|
|
|
return res.status(201).json({
|
|
user: {
|
|
id: newUser.id,
|
|
username: newUser.username,
|
|
email: newUser.email,
|
|
display_name: newUser.display_name,
|
|
auth_provider: newUser.auth_provider,
|
|
created_at: newUser.created_at
|
|
},
|
|
token
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Error when registering new user: ', error);
|
|
return res.status(500).json({error: 'Failed to create user', 'details': String(error)});
|
|
}
|
|
});
|
|
|
|
app.post('/api/auth/login', async (req, res) => {
|
|
try {
|
|
const {username, email, password} = req.body;
|
|
|
|
if (!password || (!username && !email)) {
|
|
return res.status(400).json({error: 'Username/email & password are required'});
|
|
}
|
|
|
|
let user;
|
|
if (!username) {
|
|
user = getUserByEmail(email);
|
|
} else {
|
|
user = getUserByUsername(username);
|
|
}
|
|
|
|
if (!user || !await argon2.verify(user.pass_hash, password)) {
|
|
return res.status(401).json({error: 'Invalid credentials'});
|
|
}
|
|
|
|
const token = generateToken(user);
|
|
|
|
return res.status(200).json({
|
|
user: {
|
|
id: user.id,
|
|
username: user.username,
|
|
email: user.email,
|
|
display_name: user.display_name,
|
|
auth_provider: user.auth_provider,
|
|
created_at: user.created_at
|
|
},
|
|
token
|
|
});
|
|
} catch (error) {
|
|
console.log('Failed to log user in:', error);
|
|
return res.status(500).json({error: 'Failed to login', 'details': String(error)});
|
|
}
|
|
});
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`Server running on http://localhost:${PORT}`);
|
|
});
|
|
}).catch(err => {
|
|
console.error('Failed to initialize database:', err);
|
|
}); |