Подключение node-приложения к Google Calendar API

от автора

Как-то неожиданно для меня подключение своего nodejs-приложения к Google Calendar API оказалось довольно нетривиальной задачей. Несмотря на подробное описание вариантов подключения на русском языке пришлось продираться через лес различных настроек и конфигураций. В статье подробно изложены шаги, которые приходится совершить, чтобы интеграция завершилась успехом.

Цель интеграции — дать возможность nodejs-приложению публиковать события в определённый календарь. В данном примере использовался обычная, персональная учётная запись в Google.

Создание календаря

Для начала нужно создать календарь, в который будем публиковать события. Идём в Google Calendar и нажимаем на кнопку «+» рядом с «Другие календари«, затем выбираем пункт «Создать календарь«:

заполняем форму и опять жмём «Создать календарь«, но уже синюю кнопку:

Гугл довольно долго шуршит мозгами, после чего радостно сообщает, что новый календарь готов. Доступ к настройкам нового календаря:

В настройках нас прежде всего интересует пункт «Интеграция календаря«:

в котором самое полезное — это «Идентификатор календаря«

c093hr4fqjuj5k9e6uvvac73ac@group.calendar.google.com

Этот значение наше nodejs-приложение будет использовать при подключении к API.

Регистрация приложения в Google

Управление приложениями находится в «Консоли API«.

Создать новое приложение можно через селектор текущего приложения — «Выберите проект«:

После создания проект становится доступным в списке проектов — «Habr Demo«:

Теперь нужно дать доступ этому проекту к соответствующим API Google’а:

Так как интерфейсов Google наплодил свыше 3 сотен, используем фильтр для поиска нужных:

Фильтрация по ключу «calend» оставляет всего два вариант, один из которых нам и нужен:

Заходим в «Google Calendar API» и включаем его для использования в нашем проекте:

После чего проваливаемся в dashboard использования этого API в нашем проекте (https://console.developers.google.com/apis/api/calendar-json.googleapis.com/overview?project=habr-demo-293107&supportedpurview=project), где нам сообщают, что для использования API мы должны создать учётные данные:

Жмём «СОЗДАТЬ УЧЁТНЫЕ ДАННЫЕ» и заполняем анкету, определяющую, какой тип учётных данных нам нужен для доступа к API:

вся анкета не влезла в один скрин, вот остаток:

По результатам анкетирования Google предлагает создать закрытый ключ в формате JSON, при помощи которого наше приложение будет подключаться к Google Calendar API:

Самую большую трудность для меня создал пункт «Роль«. Похоже, что ролей у Google’а даже больше, чем API, к которым можно подключаться:

В общем, если выбрать «Проект / Владелец«, то обещают предоставить полный доступ ко всем ресурсам. Жмём на кнопку «Продолжить» и получаем JSON-файл в каталог «Downloads» на своём компрьютере:

Содержимое JSON-файла примерно такое (ключ я вырезал):

{   "type": "service_account",   "project_id": "habr-demo-293107",   "private_key_id": "4ec17ea5f8b606e0535a0623a110111123fd3c33",   "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",   "client_email": "nodejs-app@habr-demo-293107.iam.gserviceaccount.com",   "client_id": "102219376121816220804",   "auth_uri": "https://accounts.google.com/o/oauth2/auth",   "token_uri": "https://oauth2.googleapis.com/token",   "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",   "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/nodejs-app%40habr-demo-293107.iam.gserviceaccount.com" }

В консоли API у приложения «Habr Demo» появляется новый сервис с email’ом «nodejs-app@habr-demo-293107.iam.gserviceaccount.com«:

Код

Для подключения к API из nodejs-приложения Google предлагает библиотеку googleapis и обзор её использования. В обзоре применяется OAuth2-аутентификация и получение из календаря списка событий, а нам нужна аутентификация по ключу в соответствующих scope’ах и добавление события в календарь. Поэтому код получается примерно такой:

const fs = require('fs'); const {google} = require('googleapis');  const CALENDAR_ID = 'c093hr4fqjuj5k9e6uvvac73ac@group.calendar.google.com'; const KEYFILE = 'Habr Demo-4ec17ea5f8b6.json'; // path to JSON with private key been downloaded from Google const SCOPE_CALENDAR = 'https://www.googleapis.com/auth/calendar'; // authorization scopes const SCOPE_EVENTS = 'https://www.googleapis.com/auth/calendar.events';  (async function run() {     // INNER FUNCTIONS     async function readPrivateKey() {         const content = fs.readFileSync(KEYFILE);         return JSON.parse(content.toString());     }      async function authenticate(key) {         const jwtClient = new google.auth.JWT(             key.client_email,             null,             key.private_key,             [SCOPE_CALENDAR, SCOPE_EVENTS]         );         await jwtClient.authorize();         return jwtClient;     }      async function createEvent(auth) {         const event = {             'summary': 'Habr Post Demo',             'description': 'Тест для демонстрации интеграции nodejs-приложения с Google Calendar API.',             'start': {                 'dateTime': '2020-10-20T16:00:00+02:00',                 'timeZone': 'Europe/Riga',             },             'end': {                 'dateTime': '2020-10-20T18:00:00+02:00',                 'timeZone': 'Europe/Riga',             }         };          let calendar = google.calendar('v3');         await calendar.events.insert({             auth: auth,             calendarId: CALENDAR_ID,             resource: event,         });     }      // MAIN     try {         const key = await readPrivateKey();         const auth = await authenticate(key);         await createEvent(auth);     } catch (e) {         console.log('Error: ' + e);     } })(); 

Запускаем код на выполнение и получаем ответ от Calendar API:

{   ...   "status": 404,   "statusText": "Not Found",   ... }

что и логично — наш новый календарь ничего не знает про наш новый сервис.

Настройка доступа сервиса к календарю

Заходим в наш календарь, созданный ранее, и в настройках жмём «Доступ для отдельных пользователей«, затем «Добавить пользователей» и вводим email-адрес нашего сервиса, который будет создавать события в нашем календаре:

После предоставления сервису доступа к календарю нужно настроить права:

Выбираем «Внесение изменений и предоставление доступа«, иначе будем иметь ошибку «You need to have writer access to this calendar.» при обращении к API:

Запускаем наш скрипт на выполнение ещё раз и фиксируем результат в календаре:

В коде я задавал время старта события в 16:00:

'start': {     'dateTime': '2020-10-20T16:00:00+02:00',     'timeZone': 'Europe/Riga', }

a по факту событие запланировано на 17:00, что вполне соответствует духу IT:

В программировании существует лишь два характерных затруднения: инвалидация кеша, наименование сущностей и ошибка на единицу

Резюме

Вот и всё, квест пройден. Хэппи, как говорится, кодинг.

Ссылки

ссылка на оригинал статьи https://habr.com/ru/post/524240/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *