Add calender support in server
This commit is contained in:
323
server/routes/calendar.js
Normal file
323
server/routes/calendar.js
Normal file
@@ -0,0 +1,323 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const { CalendarUser } = require('../models');
|
||||
const CalendarService = require('../services/CalendarService');
|
||||
|
||||
// Get all calendar users
|
||||
router.get('/users', async (req, res) => {
|
||||
try {
|
||||
const users = await CalendarUser.findAll({
|
||||
where: { isActive: true },
|
||||
attributes: ['id', 'name', 'nextcloudUrl', 'username', 'calendarName', 'isActive']
|
||||
});
|
||||
res.json(users);
|
||||
} catch (error) {
|
||||
console.error('Error fetching calendar users:', error);
|
||||
res.status(500).json({ error: 'Failed to fetch calendar users' });
|
||||
}
|
||||
});
|
||||
|
||||
// Add a new calendar user
|
||||
router.post('/users', async (req, res) => {
|
||||
try {
|
||||
const { name, nextcloudUrl, username, password, calendarName } = req.body;
|
||||
|
||||
if (!name || !nextcloudUrl || !username || !password) {
|
||||
return res.status(400).json({
|
||||
error: 'Missing required fields: name, nextcloudUrl, username, password'
|
||||
});
|
||||
}
|
||||
|
||||
// Test connection before saving
|
||||
const testConfig = { name, nextcloudUrl, username, password, calendarName };
|
||||
const connectionTest = await CalendarService.testConnection(testConfig);
|
||||
|
||||
if (!connectionTest) {
|
||||
return res.status(400).json({
|
||||
error: 'Failed to connect to Nextcloud instance. Please check your credentials.'
|
||||
});
|
||||
}
|
||||
|
||||
const user = await CalendarUser.create({
|
||||
name,
|
||||
nextcloudUrl,
|
||||
username,
|
||||
password,
|
||||
calendarName
|
||||
});
|
||||
|
||||
// Return user without password
|
||||
const { password: _, ...userWithoutPassword } = user.toJSON();
|
||||
res.status(201).json(userWithoutPassword);
|
||||
} catch (error) {
|
||||
console.error('Error creating calendar user:', error);
|
||||
if (error.name === 'SequelizeUniqueConstraintError') {
|
||||
res.status(400).json({ error: 'User name already exists' });
|
||||
} else {
|
||||
res.status(500).json({ error: 'Failed to create calendar user' });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Update a calendar user
|
||||
router.put('/users/:id', async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { name, nextcloudUrl, username, password, calendarName, isActive } = req.body;
|
||||
|
||||
const user = await CalendarUser.findByPk(id);
|
||||
if (!user) {
|
||||
return res.status(404).json({ error: 'Calendar user not found' });
|
||||
}
|
||||
|
||||
// Test connection if credentials are being updated
|
||||
if (nextcloudUrl || username || password) {
|
||||
const testConfig = {
|
||||
name: name || user.name,
|
||||
nextcloudUrl: nextcloudUrl || user.nextcloudUrl,
|
||||
username: username || user.username,
|
||||
password: password || user.password,
|
||||
calendarName: calendarName || user.calendarName
|
||||
};
|
||||
|
||||
const connectionTest = await CalendarService.testConnection(testConfig);
|
||||
if (!connectionTest) {
|
||||
return res.status(400).json({
|
||||
error: 'Failed to connect to Nextcloud instance. Please check your credentials.'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await user.update({
|
||||
...(name && { name }),
|
||||
...(nextcloudUrl && { nextcloudUrl }),
|
||||
...(username && { username }),
|
||||
...(password && { password }),
|
||||
...(calendarName !== undefined && { calendarName }),
|
||||
...(isActive !== undefined && { isActive })
|
||||
});
|
||||
|
||||
// Return user without password
|
||||
const { password: _, ...userWithoutPassword } = user.toJSON();
|
||||
res.json(userWithoutPassword);
|
||||
} catch (error) {
|
||||
console.error('Error updating calendar user:', error);
|
||||
res.status(500).json({ error: 'Failed to update calendar user' });
|
||||
}
|
||||
});
|
||||
|
||||
// Delete a calendar user
|
||||
router.delete('/users/:id', async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const user = await CalendarUser.findByPk(id);
|
||||
if (!user) {
|
||||
return res.status(404).json({ error: 'Calendar user not found' });
|
||||
}
|
||||
|
||||
await user.destroy();
|
||||
res.json({ message: 'Calendar user deleted successfully' });
|
||||
} catch (error) {
|
||||
console.error('Error deleting calendar user:', error);
|
||||
res.status(500).json({ error: 'Failed to delete calendar user' });
|
||||
}
|
||||
});
|
||||
|
||||
// Get calendar events for a specific month
|
||||
// GET /api/calendar/events/:year/:month?user=username&type=family|individual
|
||||
router.get('/events/:year/:month', async (req, res) => {
|
||||
try {
|
||||
const { year, month } = req.params;
|
||||
const { user, type } = req.query;
|
||||
|
||||
// Validate year and month
|
||||
if (!year || !month || !/^\d{4}$/.test(year) || !/^(0[1-9]|1[0-2])$/.test(month)) {
|
||||
return res.status(400).json({
|
||||
error: 'Invalid year or month format. Use YYYY for year and MM for month.'
|
||||
});
|
||||
}
|
||||
|
||||
if (type === 'family') {
|
||||
// Get events from all active users
|
||||
const users = await CalendarUser.findAll({
|
||||
where: { isActive: true },
|
||||
attributes: ['name', 'nextcloudUrl', 'username', 'password', 'calendarName']
|
||||
});
|
||||
|
||||
if (users.length === 0) {
|
||||
return res.json([]);
|
||||
}
|
||||
|
||||
const events = await CalendarService.getFamilyEventsForMonth(users, year, month);
|
||||
res.json(events);
|
||||
} else {
|
||||
// Get events for a specific user
|
||||
if (!user) {
|
||||
return res.status(400).json({
|
||||
error: 'User parameter required for individual calendar view'
|
||||
});
|
||||
}
|
||||
|
||||
const userConfig = await CalendarUser.findOne({
|
||||
where: { name: user, isActive: true },
|
||||
attributes: ['name', 'nextcloudUrl', 'username', 'password', 'calendarName']
|
||||
});
|
||||
|
||||
if (!userConfig) {
|
||||
return res.status(404).json({ error: 'User not found or inactive' });
|
||||
}
|
||||
|
||||
const events = await CalendarService.getEventsForMonth(userConfig, year, month);
|
||||
res.json(events);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error retrieving calendar events:', error);
|
||||
res.status(500).json({ error: 'Failed to retrieve calendar events' });
|
||||
}
|
||||
});
|
||||
|
||||
// Create a new calendar event
|
||||
// POST /api/calendar/events
|
||||
router.post('/events', async (req, res) => {
|
||||
try {
|
||||
const { user, date, text } = req.body;
|
||||
|
||||
if (!user || !date || !text) {
|
||||
return res.status(400).json({
|
||||
error: 'Missing required fields: user, date, text'
|
||||
});
|
||||
}
|
||||
|
||||
// Validate date format (YYYY-MM-DD)
|
||||
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
||||
return res.status(400).json({
|
||||
error: 'Invalid date format. Use YYYY-MM-DD.'
|
||||
});
|
||||
}
|
||||
|
||||
const userConfig = await CalendarUser.findOne({
|
||||
where: { name: user, isActive: true },
|
||||
attributes: ['name', 'nextcloudUrl', 'username', 'password', 'calendarName']
|
||||
});
|
||||
|
||||
if (!userConfig) {
|
||||
return res.status(404).json({ error: 'User not found or inactive' });
|
||||
}
|
||||
|
||||
const event = await CalendarService.createEvent(userConfig, date, text);
|
||||
res.status(201).json(event);
|
||||
} catch (error) {
|
||||
console.error('Error creating calendar event:', error);
|
||||
res.status(500).json({ error: 'Failed to create calendar event' });
|
||||
}
|
||||
});
|
||||
|
||||
// Update a calendar event
|
||||
// PUT /api/calendar/events/:eventId
|
||||
router.put('/events/:eventId', async (req, res) => {
|
||||
try {
|
||||
const { eventId } = req.params;
|
||||
const { user, date, text } = req.body;
|
||||
|
||||
if (!user || !date || !text) {
|
||||
return res.status(400).json({
|
||||
error: 'Missing required fields: user, date, text'
|
||||
});
|
||||
}
|
||||
|
||||
// Validate date format (YYYY-MM-DD)
|
||||
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
||||
return res.status(400).json({
|
||||
error: 'Invalid date format. Use YYYY-MM-DD.'
|
||||
});
|
||||
}
|
||||
|
||||
const userConfig = await CalendarUser.findOne({
|
||||
where: { name: user, isActive: true },
|
||||
attributes: ['name', 'nextcloudUrl', 'username', 'password', 'calendarName']
|
||||
});
|
||||
|
||||
if (!userConfig) {
|
||||
return res.status(404).json({ error: 'User not found or inactive' });
|
||||
}
|
||||
|
||||
const event = await CalendarService.updateEvent(userConfig, eventId, date, text);
|
||||
res.json(event);
|
||||
} catch (error) {
|
||||
console.error('Error updating calendar event:', error);
|
||||
if (error.message === 'Event not found') {
|
||||
res.status(404).json({ error: 'Event not found' });
|
||||
} else if (error.message.includes('Permission denied')) {
|
||||
res.status(403).json({ error: error.message });
|
||||
} else {
|
||||
res.status(500).json({ error: 'Failed to update calendar event' });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Delete a calendar event
|
||||
// DELETE /api/calendar/events/:eventId
|
||||
router.delete('/events/:eventId', async (req, res) => {
|
||||
try {
|
||||
const { eventId } = req.params;
|
||||
const { user } = req.body;
|
||||
|
||||
if (!user) {
|
||||
return res.status(400).json({
|
||||
error: 'Missing required field: user'
|
||||
});
|
||||
}
|
||||
|
||||
const userConfig = await CalendarUser.findOne({
|
||||
where: { name: user, isActive: true },
|
||||
attributes: ['name', 'nextcloudUrl', 'username', 'password', 'calendarName']
|
||||
});
|
||||
|
||||
if (!userConfig) {
|
||||
return res.status(404).json({ error: 'User not found or inactive' });
|
||||
}
|
||||
|
||||
await CalendarService.deleteEvent(userConfig, eventId);
|
||||
res.json({ message: 'Event deleted successfully' });
|
||||
} catch (error) {
|
||||
console.error('Error deleting calendar event:', error);
|
||||
if (error.message === 'Event not found') {
|
||||
res.status(404).json({ error: 'Event not found' });
|
||||
} else if (error.message.includes('Permission denied')) {
|
||||
res.status(403).json({ error: error.message });
|
||||
} else {
|
||||
res.status(500).json({ error: 'Failed to delete calendar event' });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Test Nextcloud connection for a user
|
||||
router.post('/users/:id/test-connection', async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const user = await CalendarUser.findByPk(id);
|
||||
if (!user) {
|
||||
return res.status(404).json({ error: 'Calendar user not found' });
|
||||
}
|
||||
|
||||
const connectionTest = await CalendarService.testConnection({
|
||||
name: user.name,
|
||||
nextcloudUrl: user.nextcloudUrl,
|
||||
username: user.username,
|
||||
password: user.password,
|
||||
calendarName: user.calendarName
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: connectionTest,
|
||||
message: connectionTest ? 'Connection successful' : 'Connection failed'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error testing connection:', error);
|
||||
res.status(500).json({ error: 'Failed to test connection' });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
Reference in New Issue
Block a user