fix: use private helcimApiToken for all server-side Helcim API calls
This commit is contained in:
parent
ccd1d0783a
commit
d31b5b4dac
53 changed files with 1755 additions and 572 deletions
|
|
@ -1,114 +1,94 @@
|
|||
import Event from "../../models/event";
|
||||
import Member from "../../models/member";
|
||||
import { connectDB } from '../../utils/mongoose.js'
|
||||
import Event from '../../models/event'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const query = getQuery(event);
|
||||
const { memberId } = query;
|
||||
|
||||
if (!memberId) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "Member ID is required",
|
||||
});
|
||||
}
|
||||
await connectDB()
|
||||
const member = await requireAuth(event)
|
||||
|
||||
try {
|
||||
// Verify member exists
|
||||
const member = await Member.findById(memberId);
|
||||
if (!member) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
statusMessage: "Member not found",
|
||||
});
|
||||
}
|
||||
|
||||
// Find all events where the user is registered
|
||||
const events = await Event.find({
|
||||
"registrations.memberId": memberId,
|
||||
'registrations.memberId': member._id,
|
||||
isCancelled: { $ne: true },
|
||||
})
|
||||
.select("title slug description startDate endDate location")
|
||||
.sort({ startDate: 1 });
|
||||
.select('title slug description startDate endDate location')
|
||||
.sort({ startDate: 1 })
|
||||
|
||||
// Generate iCal format
|
||||
const ical = generateICalendar(events, member);
|
||||
const ical = generateICalendar(events, member)
|
||||
|
||||
// Set headers for calendar subscription (not download)
|
||||
setHeader(event, "Content-Type", "text/calendar; charset=utf-8");
|
||||
setHeader(event, "Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
setHeader(event, "Pragma", "no-cache");
|
||||
setHeader(event, "Expires", "0");
|
||||
setHeader(event, 'Content-Type', 'text/calendar; charset=utf-8')
|
||||
setHeader(event, 'Cache-Control', 'no-cache, no-store, must-revalidate')
|
||||
setHeader(event, 'Pragma', 'no-cache')
|
||||
setHeader(event, 'Expires', '0')
|
||||
|
||||
return ical;
|
||||
return ical
|
||||
} catch (error) {
|
||||
console.error("Error generating calendar:", error);
|
||||
console.error('Error generating calendar:', error)
|
||||
|
||||
if (error.statusCode) {
|
||||
throw error;
|
||||
throw error
|
||||
}
|
||||
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
statusMessage: "Failed to generate calendar",
|
||||
});
|
||||
statusMessage: 'Failed to generate calendar',
|
||||
})
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
function generateICalendar(events, member) {
|
||||
const now = new Date();
|
||||
const now = new Date()
|
||||
const timestamp = now
|
||||
.toISOString()
|
||||
.replace(/[-:]/g, "")
|
||||
.replace(/\.\d{3}/, "");
|
||||
.replace(/[-:]/g, '')
|
||||
.replace(/\.\d{3}/, '')
|
||||
|
||||
let ical = [
|
||||
"BEGIN:VCALENDAR",
|
||||
"VERSION:2.0",
|
||||
"PRODID:-//Ghost Guild//Events Calendar//EN",
|
||||
"CALSCALE:GREGORIAN",
|
||||
"METHOD:PUBLISH",
|
||||
"X-WR-CALNAME:Ghost Guild - My Events",
|
||||
"X-WR-TIMEZONE:UTC",
|
||||
"X-WR-CALDESC:Your registered Ghost Guild events",
|
||||
"REFRESH-INTERVAL;VALUE=DURATION:PT1H",
|
||||
"X-PUBLISHED-TTL:PT1H",
|
||||
];
|
||||
'BEGIN:VCALENDAR',
|
||||
'VERSION:2.0',
|
||||
'PRODID:-//Ghost Guild//Events Calendar//EN',
|
||||
'CALSCALE:GREGORIAN',
|
||||
'METHOD:PUBLISH',
|
||||
'X-WR-CALNAME:Ghost Guild - My Events',
|
||||
'X-WR-TIMEZONE:UTC',
|
||||
'X-WR-CALDESC:Your registered Ghost Guild events',
|
||||
'REFRESH-INTERVAL;VALUE=DURATION:PT1H',
|
||||
'X-PUBLISHED-TTL:PT1H',
|
||||
]
|
||||
|
||||
events.forEach((evt) => {
|
||||
const eventStart = new Date(evt.startDate);
|
||||
const eventEnd = new Date(evt.endDate);
|
||||
const eventStart = new Date(evt.startDate)
|
||||
const eventEnd = new Date(evt.endDate)
|
||||
|
||||
const dtstart = eventStart
|
||||
.toISOString()
|
||||
.replace(/[-:]/g, "")
|
||||
.replace(/\.\d{3}/, "");
|
||||
.replace(/[-:]/g, '')
|
||||
.replace(/\.\d{3}/, '')
|
||||
const dtend = eventEnd
|
||||
.toISOString()
|
||||
.replace(/[-:]/g, "")
|
||||
.replace(/\.\d{3}/, "");
|
||||
const dtstamp = timestamp;
|
||||
.replace(/[-:]/g, '')
|
||||
.replace(/\.\d{3}/, '')
|
||||
const dtstamp = timestamp
|
||||
|
||||
// Clean description for iCal format
|
||||
const description = (evt.description || "")
|
||||
.replace(/\n/g, "\\n")
|
||||
.replace(/,/g, "\\,");
|
||||
const description = (evt.description || '')
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/,/g, '\\,')
|
||||
|
||||
const eventUrl = `https://ghostguild.org/events/${evt.slug || evt._id}`;
|
||||
const eventUrl = `https://ghostguild.org/events/${evt.slug || evt._id}`
|
||||
|
||||
ical.push("BEGIN:VEVENT");
|
||||
ical.push(`UID:${evt._id}@ghostguild.org`);
|
||||
ical.push(`DTSTAMP:${dtstamp}`);
|
||||
ical.push(`DTSTART:${dtstart}`);
|
||||
ical.push(`DTEND:${dtend}`);
|
||||
ical.push(`SUMMARY:${evt.title}`);
|
||||
ical.push(`DESCRIPTION:${description}\\n\\nView event: ${eventUrl}`);
|
||||
ical.push(`LOCATION:${evt.location || "Online"}`);
|
||||
ical.push(`URL:${eventUrl}`);
|
||||
ical.push(`STATUS:CONFIRMED`);
|
||||
ical.push("END:VEVENT");
|
||||
});
|
||||
ical.push('BEGIN:VEVENT')
|
||||
ical.push(`UID:${evt._id}@ghostguild.org`)
|
||||
ical.push(`DTSTAMP:${dtstamp}`)
|
||||
ical.push(`DTSTART:${dtstart}`)
|
||||
ical.push(`DTEND:${dtend}`)
|
||||
ical.push(`SUMMARY:${evt.title}`)
|
||||
ical.push(`DESCRIPTION:${description}\\n\\nView event: ${eventUrl}`)
|
||||
ical.push(`LOCATION:${evt.location || 'Online'}`)
|
||||
ical.push(`URL:${eventUrl}`)
|
||||
ical.push('STATUS:CONFIRMED')
|
||||
ical.push('END:VEVENT')
|
||||
})
|
||||
|
||||
ical.push("END:VCALENDAR");
|
||||
ical.push('END:VCALENDAR')
|
||||
|
||||
return ical.join("\r\n");
|
||||
return ical.join('\r\n')
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue