Use user profile timezone from DB as fallback for CalDAV all-day events (#8755)

* adds timezone pull from user profile in DB

* minor fixes

* fixes promise return type

* comments and minor fixes

* minor improvement

* fix return type

* changes for help in debugging
pull/8810/head^2
Syed Ali Shahbaz 2023-05-10 14:14:15 +05:30 committed by GitHub
parent 2e686d03fa
commit 8ffb5529e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 59 additions and 18 deletions

View File

@ -276,6 +276,38 @@ export default abstract class BaseCalendarService implements Calendar {
} }
} }
/**
* getUserTimezoneFromDB() retrieves the timezone of a user from the database.
*
* @param {number} id - The user's unique identifier.
* @returns {Promise<string | undefined>} - A Promise that resolves to the user's timezone or "Europe/London" as a default value if the timezone is not found.
*/
getUserTimezoneFromDB = async (id: number): Promise<string | undefined> => {
const prisma = await import("@calcom/prisma").then((mod) => mod.default);
const user = await prisma.user.findUnique({
where: {
id,
},
select: {
timeZone: true,
},
});
return user?.timeZone;
};
/**
* getUserId() extracts the user ID from the first calendar in an array of IntegrationCalendars.
*
* @param {IntegrationCalendar[]} selectedCalendars - An array of IntegrationCalendars.
* @returns {number | null} - The user ID associated with the first calendar in the array, or null if the array is empty or the user ID is not found.
*/
getUserId = (selectedCalendars: IntegrationCalendar[]): number | null => {
if (selectedCalendars.length === 0) {
return null;
}
return selectedCalendars[0].userId || null;
};
isValidFormat = (url: string): boolean => { isValidFormat = (url: string): boolean => {
const allowedExtensions = ["eml", "ics"]; const allowedExtensions = ["eml", "ics"];
const urlExtension = getFileExtension(url); const urlExtension = getFileExtension(url);
@ -299,6 +331,10 @@ export default abstract class BaseCalendarService implements Calendar {
dateTo, dateTo,
headers: this.headers, headers: this.headers,
}); });
const userId = this.getUserId(selectedCalendars);
// we use the userId from selectedCalendars to fetch the user's timeZone from the database primarily for all-day events without any timezone information
const userTimeZone = userId ? await this.getUserTimezoneFromDB(userId) : "Europe/London";
const events: { start: string; end: string }[] = []; const events: { start: string; end: string }[] = [];
objects.forEach((object) => { objects.forEach((object) => {
if (object.data == null || JSON.stringify(object.data) == "{}") return; if (object.data == null || JSON.stringify(object.data) == "{}") return;
@ -322,26 +358,31 @@ export default abstract class BaseCalendarService implements Calendar {
const isUTC = timezone === "Z"; const isUTC = timezone === "Z";
const tzid: string | undefined = vevent?.getFirstPropertyValue("tzid") || isUTC ? "UTC" : timezone; const tzid: string | undefined = vevent?.getFirstPropertyValue("tzid") || isUTC ? "UTC" : timezone;
// In case of icalendar, when only tzid is available without vtimezone, we need to add vtimezone explicitly to take care of timezone diff // In case of icalendar, when only tzid is available without vtimezone, we need to add vtimezone explicitly to take care of timezone diff
if (!vcalendar.getFirstSubcomponent("vtimezone") && tzid) { if (!vcalendar.getFirstSubcomponent("vtimezone")) {
try { const timezoneToUse = tzid || userTimeZone;
const timezoneComp = new ICAL.Component("vtimezone"); if (timezoneToUse) {
timezoneComp.addPropertyWithValue("tzid", tzid); try {
const standard = new ICAL.Component("standard"); const timezoneComp = new ICAL.Component("vtimezone");
timezoneComp.addPropertyWithValue("tzid", timezoneToUse);
const standard = new ICAL.Component("standard");
// get timezone offset // get timezone offset
const tzoffsetfrom = dayjs(event.startDate.toJSDate()).tz(tzid).format("Z"); const tzoffsetfrom = dayjs(event.startDate.toJSDate()).tz(timezoneToUse).format("Z");
const tzoffsetto = dayjs(event.endDate.toJSDate()).tz(tzid).format("Z"); const tzoffsetto = dayjs(event.endDate.toJSDate()).tz(timezoneToUse).format("Z");
// set timezone offset // set timezone offset
standard.addPropertyWithValue("tzoffsetfrom", tzoffsetfrom); standard.addPropertyWithValue("tzoffsetfrom", tzoffsetfrom);
standard.addPropertyWithValue("tzoffsetto", tzoffsetto); standard.addPropertyWithValue("tzoffsetto", tzoffsetto);
// provide a standard dtstart // provide a standard dtstart
standard.addPropertyWithValue("dtstart", "1601-01-01T00:00:00"); standard.addPropertyWithValue("dtstart", "1601-01-01T00:00:00");
timezoneComp.addSubcomponent(standard); timezoneComp.addSubcomponent(standard);
vcalendar.addSubcomponent(timezoneComp); vcalendar.addSubcomponent(timezoneComp);
} catch (e) { } catch (e) {
// Adds try-catch to ensure the code proceeds when Apple Calendar provides non-standard TZIDs // Adds try-catch to ensure the code proceeds when Apple Calendar provides non-standard TZIDs
console.log("error in adding vtimezone", e); console.log("error in adding vtimezone", e);
}
} else {
console.error("No timezone found");
} }
} }
const vtimezone = vcalendar.getFirstSubcomponent("vtimezone"); const vtimezone = vcalendar.getFirstSubcomponent("vtimezone");