added webdav time off add calendar
This commit is contained in:
parent
9445e9e624
commit
0f2bfbb6a0
@ -1,3 +1,7 @@
|
||||
ADMIN_USERNAME="admin"
|
||||
ADMIN_PASSWORD="adminpassword"
|
||||
JWT_SECRET="" ##random number string
|
||||
NEXTCLOUD_URL=
|
||||
NEXTCLOUD_USER=
|
||||
NEXTCLOUD_APP_PASSWORD=
|
||||
NEXTCLOUD_CALENDAR_URL=
|
||||
@ -1,10 +1,12 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"axios": "^1.11.0",
|
||||
"bcryptjs": "^3.0.2",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^17.2.1",
|
||||
"express": "^5.1.0",
|
||||
"ics": "^3.8.1",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"pm2": "^6.0.8",
|
||||
"sqlite": "^5.1.1",
|
||||
|
||||
113
server.js
113
server.js
@ -6,6 +6,8 @@ const bcrypt = require('bcryptjs');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const cors = require('cors');
|
||||
const path = require('path');
|
||||
const axios = require('axios');
|
||||
const ics = require('ics');
|
||||
|
||||
const PORT = process.env.PORT || 3000;
|
||||
const JWT_SECRET = process.env.JWT_SECRET || 'default_secret_key';
|
||||
@ -86,6 +88,94 @@ async function initializeDatabase() {
|
||||
console.log("Database initialization complete.");
|
||||
}
|
||||
|
||||
// In server.js
|
||||
|
||||
async function addEventToNextcloud(request) {
|
||||
// Ensure we have the required config from the .env file
|
||||
if (!process.env.NEXTCLOUD_URL) {
|
||||
console.log("Nextcloud integration is not configured. Skipping calendar event creation.");
|
||||
return;
|
||||
}
|
||||
|
||||
// The ics library expects date parts in an array: [YYYY, MM, DD]
|
||||
const start = request.start_date.split('-').map(Number);
|
||||
|
||||
// For an all-day event, the end date is the day *after* the last day.
|
||||
const endDate = new Date(request.end_date);
|
||||
endDate.setDate(endDate.getDate() + 1);
|
||||
const end = [endDate.getFullYear(), endDate.getMonth() + 1, endDate.getDate()];
|
||||
|
||||
// Create the event object for the ics library
|
||||
const event = {
|
||||
start: start,
|
||||
end: end,
|
||||
title: `${request.username} - Time Off`,
|
||||
description: `Reason: ${request.reason || 'Not specified'}`,
|
||||
status: 'CONFIRMED',
|
||||
busyStatus: 'BUSY',
|
||||
};
|
||||
|
||||
// Generate the raw .ics file content
|
||||
const { error, value: icsFileContent } = ics.createEvent(event);
|
||||
if (error) {
|
||||
console.error("Could not create .ics file:", error);
|
||||
return;
|
||||
}
|
||||
|
||||
// --- THIS IS THE FIX ---
|
||||
// Remove the METHOD:PUBLISH line that Nextcloud/SabreDAV rejects.
|
||||
const finalIcsContent = icsFileContent.replace('METHOD:PUBLISH\r\n', '');
|
||||
|
||||
// Each calendar event is a unique .ics file on the WebDAV server.
|
||||
// We use the request ID to ensure a unique filename.
|
||||
const eventUrl = `${process.env.NEXTCLOUD_URL}${process.env.NEXTCLOUD_CALENDAR_URL}time-off-${request.id}.ics`;
|
||||
|
||||
try {
|
||||
// Send the corrected .ics content to the Nextcloud server
|
||||
await axios.put(eventUrl, finalIcsContent, {
|
||||
auth: {
|
||||
username: process.env.NEXTCLOUD_USER,
|
||||
password: process.env.NEXTCLOUD_APP_PASSWORD
|
||||
},
|
||||
headers: {
|
||||
'Content-Type': 'text/calendar; charset=utf-8'
|
||||
}
|
||||
});
|
||||
console.log(`Successfully added time-off request ${request.id} to Nextcloud calendar.`);
|
||||
} catch (err) {
|
||||
console.error("Error sending event to Nextcloud:", err.response ? err.response.data : err.message);
|
||||
}
|
||||
}
|
||||
|
||||
// In server.js
|
||||
|
||||
async function removeEventFromNextcloud(requestId) {
|
||||
if (!process.env.NEXTCLOUD_URL) {
|
||||
console.log("Nextcloud integration is not configured. Skipping calendar event removal.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Construct the exact URL for the event's .ics file
|
||||
const eventUrl = `${process.env.NEXTCLOUD_URL}${process.env.NEXTCLOUD_CALENDAR_URL}time-off-${requestId}.ics`;
|
||||
|
||||
try {
|
||||
await axios.delete(eventUrl, {
|
||||
auth: {
|
||||
username: process.env.NEXTCLOUD_USER,
|
||||
password: process.env.NEXTCLOUD_APP_PASSWORD
|
||||
}
|
||||
});
|
||||
console.log(`Successfully removed time-off request ${requestId} from Nextcloud calendar.`);
|
||||
} catch (err) {
|
||||
// A 404 error is okay here; it just means the event wasn't on the calendar to begin with.
|
||||
if (err.response && err.response.status === 404) {
|
||||
console.log(`Event for request ${requestId} not found on calendar. Nothing to remove.`);
|
||||
} else {
|
||||
console.error("Error removing event from Nextcloud:", err.response ? err.response.data : err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setupRoutes() {
|
||||
const authenticateToken = (req, res, next) => {
|
||||
const token = req.headers['authorization']?.split(' ')[1];
|
||||
@ -377,11 +467,26 @@ function setupRoutes() {
|
||||
|
||||
app.post('/api/admin/update-time-off-status', authenticateToken, requireRole('admin'), async (req, res) => {
|
||||
try {
|
||||
const { requestId, status } = req.body;
|
||||
await db.run('UPDATE time_off_requests SET status = ? WHERE id = ?', [status, requestId]);
|
||||
res.json({ message: `Request status updated to ${status}.` });
|
||||
const { requestId, status } = req.body;
|
||||
await db.run('UPDATE time_off_requests SET status = ? WHERE id = ?', [status, requestId]);
|
||||
|
||||
// Get the details of the request we're updating
|
||||
const requestDetails = await db.get("SELECT * FROM time_off_requests WHERE id = ?", [requestId]);
|
||||
|
||||
if (requestDetails) {
|
||||
if (status === 'approved') {
|
||||
// If approved, add it to the calendar
|
||||
await addEventToNextcloud(requestDetails);
|
||||
} else if (status === 'pending' || status === 'denied') {
|
||||
// If pushed back to pending or denied, remove it from the calendar
|
||||
await removeEventFromNextcloud(requestId);
|
||||
}
|
||||
}
|
||||
|
||||
res.json({ message: `Request status updated to ${status}.` });
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to update request status.' });
|
||||
console.error("Error in update-time-off-status route:", err); // Added better logging
|
||||
res.status(500).json({ message: 'Failed to update request status.' });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user