Added tag and category API endpoints
This commit is contained in:
parent
f0ebd192a1
commit
6870d304b4
191
server/server.js
191
server/server.js
@ -15,7 +15,15 @@ const {
|
|||||||
getAllUsers,
|
getAllUsers,
|
||||||
updateUserRole,
|
updateUserRole,
|
||||||
deleteUser,
|
deleteUser,
|
||||||
getOwnedDrafts
|
getOwnedDrafts,
|
||||||
|
getAllCategories,
|
||||||
|
getAllTags,
|
||||||
|
getArticleCategories,
|
||||||
|
getArticleTags,
|
||||||
|
getOrCreateCategory,
|
||||||
|
getOrCreateTag,
|
||||||
|
setArticleCategories,
|
||||||
|
setArticleTags
|
||||||
} = require('./db');
|
} = require('./db');
|
||||||
const { generateToken, authenticateToken, authorizeRoles } = require('./auth');
|
const { generateToken, authenticateToken, authorizeRoles } = require('./auth');
|
||||||
const app = express();
|
const app = express();
|
||||||
@ -55,6 +63,12 @@ initDb().then(() => {
|
|||||||
app.get('/api/articles', authenticateToken, (req, res) => {
|
app.get('/api/articles', authenticateToken, (req, res) => {
|
||||||
try {
|
try {
|
||||||
const articles = getAllArticles();
|
const articles = getAllArticles();
|
||||||
|
|
||||||
|
articles.forEach(article => {
|
||||||
|
article.categories = getArticleCategories(article.id);
|
||||||
|
article.tags = getArticleTags(article.id);
|
||||||
|
});
|
||||||
|
|
||||||
res.json(articles);
|
res.json(articles);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching articles:', error);
|
console.error('Error fetching articles:', error);
|
||||||
@ -80,6 +94,9 @@ initDb().then(() => {
|
|||||||
return res.status(404).json({ error: 'Article not found' });
|
return res.status(404).json({ error: 'Article not found' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
article.categories = getArticleCategories(article.id);
|
||||||
|
article.tags = getArticleTags(article.id);
|
||||||
|
|
||||||
res.json(article);
|
res.json(article);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching article:', error);
|
console.error('Error fetching article:', error);
|
||||||
@ -162,6 +179,47 @@ initDb().then(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.get('/api/search/advanced', authenticateToken, (req, res) => {
|
||||||
|
try {
|
||||||
|
const { query, categories, tags } = req.query;
|
||||||
|
|
||||||
|
let articles = getAllArticles();
|
||||||
|
|
||||||
|
articles.forEach(article => {
|
||||||
|
article.categories = getArticleCategories(article.id);
|
||||||
|
article.tags = getArticleTags(article.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (query) {
|
||||||
|
const searchTerm = query.toLowerCase();
|
||||||
|
articles = articles.filter(article =>
|
||||||
|
article.title.toLowerCase().includes(searchTerm) ||
|
||||||
|
article.content.toLowerCase().includes(searchTerm) ||
|
||||||
|
article.ka_number.toLowerCase().includes(searchTerm)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (categories) {
|
||||||
|
const categoryList = categories.split(',').map(c => c.trim().toLowerCase());
|
||||||
|
articles = articles.filter(article =>
|
||||||
|
article.categories.some(cat => categoryList.includes(cat.toLowerCase()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tags) {
|
||||||
|
const tagList = tags.split(',').map(t => t.trim().toLowerCase());
|
||||||
|
articles = articles.filter(article =>
|
||||||
|
article.tags.some(tag => tagList.includes(tag.toLowerCase()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(articles);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error searching articles:', error);
|
||||||
|
res.status(500).json({ error: 'Failed to search articles', details: String(error) });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.post('/api/auth/register', async (req, res) => {
|
app.post('/api/auth/register', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { username, email, password, display_name } = req.body;
|
const { username, email, password, display_name } = req.body;
|
||||||
@ -473,6 +531,137 @@ initDb().then(() => {
|
|||||||
|
|
||||||
app.use('/media', express.static('./media'));
|
app.use('/media', express.static('./media'));
|
||||||
|
|
||||||
|
app.get('/api/categories', authenticateToken, (req, res) => {
|
||||||
|
try {
|
||||||
|
const categories = getAllCategories();
|
||||||
|
res.json(categories);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching categories:', error);
|
||||||
|
res.status(500).json({ error: 'Failed to fetch categories', details: String(error) });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post('/api/categories', authenticateToken, authorizeRoles('Admin', 'Editor'), (req, res) => {
|
||||||
|
try {
|
||||||
|
const { name } = req.body;
|
||||||
|
|
||||||
|
if (!name || !name.trim()) {
|
||||||
|
return res.status(400).json({ error: 'Category name is required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const category = getOrCreateCategory(name.trim());
|
||||||
|
res.status(201).json(category);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error creating category:', error);
|
||||||
|
res.status(500).json({ error: 'Failed to create category', details: String(error) });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
app.get('/api/tags', authenticateToken, (req, res) => {
|
||||||
|
try {
|
||||||
|
const tags = getAllTags();
|
||||||
|
res.json(tags);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching tags:', error);
|
||||||
|
res.status(500).json({ error: 'Failed to fetch tags', details: String(error) });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post('/api/tags', authenticateToken, authorizeRoles('Admin', 'Editor'), (req, res) => {
|
||||||
|
try {
|
||||||
|
const { name } = req.body;
|
||||||
|
|
||||||
|
if (!name || !name.trim()) {
|
||||||
|
return res.status(400).json({ error: 'Tag name is required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const tag = getOrCreateTag(name.trim());
|
||||||
|
res.status(201).json(tag);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error creating tag:', error);
|
||||||
|
res.status(500).json({ error: 'Failed to create tag', details: String(error) });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.put('/api/articles/:ka_number/categories', authenticateToken, authorizeRoles('Admin', 'Editor'), (req, res) => {
|
||||||
|
try {
|
||||||
|
const kaNumber = req.params.ka_number;
|
||||||
|
const { categories } = req.body;
|
||||||
|
|
||||||
|
if (!Array.isArray(categories)) {
|
||||||
|
return res.status(400).json({ error: 'Categories must be an array' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const article = getArticle(kaNumber);
|
||||||
|
if (!article) {
|
||||||
|
return res.status(404).json({ error: 'Article not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
setArticleCategories(article.id, categories);
|
||||||
|
res.json({ message: 'Categories updated successfully', categories });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating article categories:', error);
|
||||||
|
res.status(500).json({ error: 'Failed to update categories', details: String(error) });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.put('/api/articles/:ka_number/tags', authenticateToken, authorizeRoles('Admin', 'Editor'), (req, res) => {
|
||||||
|
try {
|
||||||
|
const kaNumber = req.params.ka_number;
|
||||||
|
const { tags } = req.body;
|
||||||
|
|
||||||
|
if (!Array.isArray(tags)) {
|
||||||
|
return res.status(400).json({ error: 'Tags must be an array' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const article = getArticle(kaNumber);
|
||||||
|
if (!article) {
|
||||||
|
return res.status(404).json({ error: 'Article not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
setArticleTags(article.id, tags);
|
||||||
|
res.json({ message: 'Tags updated successfully', tags });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating article tags:', error);
|
||||||
|
res.status(500).json({ error: 'Failed to update tags', details: String(error) });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/api/articles/:ka_number/categories', authenticateToken, (req, res) => {
|
||||||
|
try {
|
||||||
|
const article = getArticle(req.params.ka_number);
|
||||||
|
|
||||||
|
if (!article) {
|
||||||
|
return res.status(404).json({ error: 'Article not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const categories = getArticleCategories(article.id);
|
||||||
|
res.json(categories);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching article categories:', error);
|
||||||
|
res.status(500).json({ error: 'Failed to fetch categories', details: String(error) });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/api/articles/:ka_number/tags', authenticateToken, (req, res) => {
|
||||||
|
try {
|
||||||
|
const article = getArticle(req.params.ka_number);
|
||||||
|
|
||||||
|
if (!article) {
|
||||||
|
return res.status(404).json({ error: 'Article not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const tags = getArticleTags(article.id);
|
||||||
|
res.json(tags);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching article tags:', error);
|
||||||
|
res.status(500).json({ error: 'Failed to fetch tags', details: String(error) });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`Server running on http://localhost:${PORT}`);
|
console.log(`Server running on http://localhost:${PORT}`);
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user