- save refreshed tokens of both calendar integrations
- Office365 expiry check was off by *1000 - log errors from calendar integrations with console.error - improved google calendar integration performance further when calendars are selected
This commit is contained in:
parent
6d7ec7fa66
commit
ded27d17ea
1 changed files with 88 additions and 47 deletions
|
@ -1,14 +1,44 @@
|
|||
import prisma from "./prisma";
|
||||
|
||||
const {google} = require('googleapis');
|
||||
import createNewEventEmail from "./emails/new-event";
|
||||
|
||||
const googleAuth = () => {
|
||||
const googleAuth = (credential) => {
|
||||
const {client_secret, client_id, redirect_uris} = JSON.parse(process.env.GOOGLE_API_CREDENTIALS).web;
|
||||
return new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
|
||||
const myGoogleAuth = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
|
||||
myGoogleAuth.setCredentials(credential.key);
|
||||
|
||||
const isExpired = () => myGoogleAuth.isTokenExpiring();
|
||||
|
||||
const refreshAccessToken = () => myGoogleAuth.refreshToken(credential.key.refresh_token).then(res => {
|
||||
const token = res.res.data;
|
||||
credential.key.access_token = token.access_token;
|
||||
credential.key.expiry_date = token.expiry_date;
|
||||
return prisma.credential.update({
|
||||
where: {
|
||||
id: credential.id
|
||||
},
|
||||
data: {
|
||||
key: credential.key
|
||||
}
|
||||
}).then(() => {
|
||||
myGoogleAuth.setCredentials(credential.key);
|
||||
return myGoogleAuth;
|
||||
});
|
||||
}).catch(err => {
|
||||
console.error("Error refreshing google token", err);
|
||||
return myGoogleAuth;
|
||||
});
|
||||
|
||||
return {
|
||||
getToken: () => !isExpired() ? Promise.resolve(myGoogleAuth) : refreshAccessToken()
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
function handleErrorsJson(response) {
|
||||
if (!response.ok) {
|
||||
response.json().then(console.log);
|
||||
response.json().then(e => console.error("O365 Error", e));
|
||||
throw Error(response.statusText);
|
||||
}
|
||||
return response.json();
|
||||
|
@ -16,7 +46,7 @@ function handleErrorsJson(response) {
|
|||
|
||||
function handleErrorsRaw(response) {
|
||||
if (!response.ok) {
|
||||
response.text().then(console.log);
|
||||
response.text().then(e => console.error("O365 Error", e));
|
||||
throw Error(response.statusText);
|
||||
}
|
||||
return response.text();
|
||||
|
@ -24,25 +54,34 @@ function handleErrorsRaw(response) {
|
|||
|
||||
const o365Auth = (credential) => {
|
||||
|
||||
const isExpired = (expiryDate) => expiryDate < +(new Date());
|
||||
const isExpired = (expiryDate) => expiryDate < Math.round((+(new Date()) / 1000));
|
||||
|
||||
const refreshAccessToken = (refreshToken) => fetch('https://login.microsoftonline.com/common/oauth2/v2.0/token', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
'scope': 'User.Read Calendars.Read Calendars.ReadWrite',
|
||||
'client_id': process.env.MS_GRAPH_CLIENT_ID,
|
||||
'refresh_token': refreshToken,
|
||||
'grant_type': 'refresh_token',
|
||||
'client_secret': process.env.MS_GRAPH_CLIENT_SECRET,
|
||||
})
|
||||
})
|
||||
.then(handleErrorsJson)
|
||||
.then((responseBody) => {
|
||||
credential.key.access_token = responseBody.access_token;
|
||||
credential.key.expiry_date = Math.round((+(new Date()) / 1000) + responseBody.expires_in);
|
||||
return credential.key.access_token;
|
||||
const refreshAccessToken = (refreshToken) => {
|
||||
return fetch('https://login.microsoftonline.com/common/oauth2/v2.0/token', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({
|
||||
'scope': 'User.Read Calendars.Read Calendars.ReadWrite',
|
||||
'client_id': process.env.MS_GRAPH_CLIENT_ID,
|
||||
'refresh_token': refreshToken,
|
||||
'grant_type': 'refresh_token',
|
||||
'client_secret': process.env.MS_GRAPH_CLIENT_SECRET,
|
||||
})
|
||||
})
|
||||
.then(handleErrorsJson)
|
||||
.then((responseBody) => {
|
||||
credential.key.access_token = responseBody.access_token;
|
||||
credential.key.expiry_date = Math.round((+(new Date()) / 1000) + responseBody.expires_in);
|
||||
return prisma.credential.update({
|
||||
where: {
|
||||
id: credential.id
|
||||
},
|
||||
data: {
|
||||
key: credential.key
|
||||
}
|
||||
}).then(() => credential.key.access_token)
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
getToken: () => !isExpired(credential.key.expiry_date) ? Promise.resolve(credential.key.access_token) : refreshAccessToken(credential.key.refresh_token)
|
||||
|
@ -173,7 +212,7 @@ const MicrosoftOffice365Calendar = (credential): CalendarApiAdapter => {
|
|||
})
|
||||
}
|
||||
).catch((err) => {
|
||||
console.log(err);
|
||||
console.error(err);
|
||||
});
|
||||
},
|
||||
createEvent: (event: CalendarEvent) => auth.getToken().then(accessToken => fetch('https://graph.microsoft.com/v1.0/me/calendar/events', {
|
||||
|
@ -206,32 +245,32 @@ const MicrosoftOffice365Calendar = (credential): CalendarApiAdapter => {
|
|||
};
|
||||
|
||||
const GoogleCalendar = (credential): CalendarApiAdapter => {
|
||||
const myGoogleAuth = googleAuth();
|
||||
myGoogleAuth.setCredentials(credential.key);
|
||||
const auth = googleAuth(credential);
|
||||
const integrationType = "google_calendar";
|
||||
|
||||
return {
|
||||
getAvailability: (dateFrom, dateTo, selectedCalendars) => new Promise((resolve, reject) => {
|
||||
getAvailability: (dateFrom, dateTo, selectedCalendars) => new Promise((resolve, reject) => auth.getToken().then(myGoogleAuth => {
|
||||
const calendar = google.calendar({version: 'v3', auth: myGoogleAuth});
|
||||
calendar.calendarList
|
||||
.list()
|
||||
.then(cals => {
|
||||
const filteredItems = cals.data.items.filter(i => selectedCalendars.findIndex(e => e.externalId === i.id) > -1)
|
||||
if (filteredItems.length == 0 && selectedCalendars.length > 0){
|
||||
// Only calendars of other integrations selected
|
||||
resolve([]);
|
||||
}
|
||||
const selectedCalendarIds = selectedCalendars.filter(e => e.integration === integrationType).map(e => e.externalId);
|
||||
if (selectedCalendarIds.length == 0 && selectedCalendars.length > 0){
|
||||
// Only calendars of other integrations selected
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
(selectedCalendarIds.length == 0
|
||||
? calendar.calendarList.list().then(cals => cals.data.items.map(cal => cal.id))
|
||||
: Promise.resolve(selectedCalendarIds)).then(calsIds => {
|
||||
calendar.freebusy.query({
|
||||
requestBody: {
|
||||
timeMin: dateFrom,
|
||||
timeMax: dateTo,
|
||||
items: filteredItems.length > 0 ? filteredItems : cals.data.items
|
||||
items: calsIds.map(id => ({id: id}))
|
||||
}
|
||||
}, (err, apires) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
|
||||
resolve(
|
||||
Object.values(apires.data.calendars).flatMap(
|
||||
(item) => item["busy"]
|
||||
|
@ -240,11 +279,12 @@ const GoogleCalendar = (credential): CalendarApiAdapter => {
|
|||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('There was an error contacting google calendar service: ', err);
|
||||
reject(err);
|
||||
});
|
||||
|
||||
}),
|
||||
createEvent: (event: CalendarEvent) => new Promise((resolve, reject) => {
|
||||
})),
|
||||
createEvent: (event: CalendarEvent) => new Promise((resolve, reject) => auth.getToken().then(myGoogleAuth => {
|
||||
const payload = {
|
||||
summary: event.title,
|
||||
description: event.description,
|
||||
|
@ -276,13 +316,13 @@ const GoogleCalendar = (credential): CalendarApiAdapter => {
|
|||
resource: payload,
|
||||
}, function (err, event) {
|
||||
if (err) {
|
||||
console.log('There was an error contacting the Calendar service: ' + err);
|
||||
console.error('There was an error contacting google calendar service: ', err);
|
||||
return reject(err);
|
||||
}
|
||||
return resolve(event.data);
|
||||
});
|
||||
}),
|
||||
updateEvent: (uid: String, event: CalendarEvent) => new Promise((resolve, reject) => {
|
||||
})),
|
||||
updateEvent: (uid: String, event: CalendarEvent) => new Promise((resolve, reject) => auth.getToken().then(myGoogleAuth => {
|
||||
const payload = {
|
||||
summary: event.title,
|
||||
description: event.description,
|
||||
|
@ -317,13 +357,13 @@ const GoogleCalendar = (credential): CalendarApiAdapter => {
|
|||
resource: payload
|
||||
}, function (err, event) {
|
||||
if (err) {
|
||||
console.log('There was an error contacting the Calendar service: ' + err);
|
||||
console.error('There was an error contacting google calendar service: ', err);
|
||||
return reject(err);
|
||||
}
|
||||
return resolve(event.data);
|
||||
});
|
||||
}),
|
||||
deleteEvent: (uid: String) => new Promise( (resolve, reject) => {
|
||||
})),
|
||||
deleteEvent: (uid: String) => new Promise( (resolve, reject) => auth.getToken().then(myGoogleAuth => {
|
||||
const calendar = google.calendar({version: 'v3', auth: myGoogleAuth});
|
||||
calendar.events.delete({
|
||||
auth: myGoogleAuth,
|
||||
|
@ -333,13 +373,13 @@ const GoogleCalendar = (credential): CalendarApiAdapter => {
|
|||
sendUpdates: 'all',
|
||||
}, function (err, event) {
|
||||
if (err) {
|
||||
console.log('There was an error contacting the Calendar service: ' + err);
|
||||
console.error('There was an error contacting google calendar service: ', err);
|
||||
return reject(err);
|
||||
}
|
||||
return resolve(event.data);
|
||||
});
|
||||
}),
|
||||
listCalendars: () => new Promise((resolve, reject) => {
|
||||
})),
|
||||
listCalendars: () => new Promise((resolve, reject) => auth.getToken().then(myGoogleAuth => {
|
||||
const calendar = google.calendar({version: 'v3', auth: myGoogleAuth});
|
||||
calendar.calendarList
|
||||
.list()
|
||||
|
@ -352,9 +392,10 @@ const GoogleCalendar = (credential): CalendarApiAdapter => {
|
|||
}))
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('There was an error contacting google calendar service: ', err);
|
||||
reject(err);
|
||||
});
|
||||
})
|
||||
}))
|
||||
};
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue