Как работать с API через сервисные OAuth токены

Все примеры, используют httpie. Он удобнее чем curl.

Обмен client_id и секрета на OAuth токен

Для работы c API Директории прежде всего нужно получить обезличенный OAuth токен:

$ http --form \
       POST https://oauth-test.yandex.ru/token \
       grant_type=client_credentials \
       client_id=$WIKI_CLIENT_ID \
       client_secret=$WIKI_SECRET

{
    "access_token": "AQAAAAAAAAAAAAAK8F2ePE9-hEXMukJUypXpuOD",
    "expires_in": 31536000,
    "token_type": "bearer"
}

Запрос организаций, в которых подключен сервис

Пока не поддерживается. Работы ведутся в тикете: https://st.yandex-team.ru/DIR-2427

Запрос списка сотрудников организации

Зная org_id, можно запросить всех сотрудников организации:

$ http GET https://api-internal-test.directory.ws.yandex.net/users/ \
       "Authorization: OAuth $TOKEN" \
       "X-Org-ID: 108"

{
  "links": {
      "last": "https://api.test.directory.ws.yandex.ru/users/?page=5",
      "next": "https://api.test.directory.ws.yandex.ru/users/?page=2"
  },
  "page": 1,
  "pages": 5,
  "per_page": 20,
  "result": [
      {
          "about": null,
          "aliases": [],
          "birthday": "1968-08-11",
          "contacts": [
              {
                  "alias": false,
                  "main": false,
                  "synthetic": false,
                  "type": "phone",
                  "value": "+7 397 884 30 72"
              },
              {
                  "alias": false,
                  "main": true,
                  "synthetic": true,
                  "type": "email",
                  "value": "ebogdanova@mockorg.yaserv.biz"
              }
          ],
...

Если запросить без указания X-Org-ID, то будет 403 ошибка:

{
  "message": "Organization is required for this operation"
}

Note

Пока сервис может передавать id любой организации, даже той, для которой он не подключен. Но это баг, который мы исправим, и для случаев, когда сервис пытается получить доступ к организации в которой не подключен, он будет получать 403 ошибку.

https://st.yandex-team.ru/DIR-2463

Как подписаться на события

Для подписки на все события, достаточно передать в ручку /webhooks урл, куда присылать данные:

$ http POST 'https://api-internal-test.directory.ws.yandex.net/webhooks/' \
       "Authorization: OAuth $WIKI_TOKEN"
       "url=http://requestb.in/q2u3c9q2"

{
    "event_names": [],
    "expand_content": false,
    "fields_filter": {},
    "id": 5,
    "service_id": 1,
    "url": "http://requestb.in/q2u3c9q2"
}

Чтобы подписаться на конкретные события:

$ http POST 'https://api-internal-test.directory.ws.yandex.net/webhooks/' \
       "Authorization: OAuth $WIKI_TOKEN"
       "url=http://requestb.in/q2u3c9q2"
       'event_names:=["user_added", "department_added", "group_added"]'

{
    "event_names": ["user_added", "department_added", "group_added"],
    "expand_content": false,
    "fields_filter": {},
    "id": 5,
    "service_id": 1,
    "url": "http://requestb.in/q2u3c9q2"
}

Note

Если вы дважды сделаете один и тот же POST, то создадутся две подписки и события будут приходить дважды.

Способы получить список текущих подписок и удалить подписку, мы скоро сделаем, следите за тикетами:

Как потестировать включение/выключение сервиса

Пока включение/выключение сервиса работает лишь со старыми токенами. Можно использовать токен от Playground, чтобы включить Wiki:

$ http POST 'https://api-internal-test.directory.ws.yandex.net/services/wiki/enable/'
       "Authorization: token dsJdfdfdsadsaGH67b"
       "X-ORG-ID: 108"
       "X-UID: 1130000000203701"
       "X-User-IP: 127.0.0.1"

Note

Надо обязательно предоставить UID администратора, так как мы сохраняем запись о включении или отключении сервиса в логе действий над организацией.

Отключается сервис так же, только надо заменить enable на disable.

Работа от имени робота

Если у сервиса проставлена галка, что ему требуется робот, то после включения, в организации заведётся учётка робота. Логин робота будет какой-то такой: robot-wiki или robot-tracker.

Чтобы работать от имени робота, вам надо обменять обезличенный токен на токен робота, для этого надо узнать uid робота в организации.

Как узнать UID робота

Чтобы сделать это просто, мы планируем поддержать ручку /users/?service=startrek. Работы ведутся в тикете: https://st.yandex-team.ru/DIR-2324. А пока её нет, можно находить робота по логину: /users/?nickname=robot-startrek.

Как обменять обезличеный токен на токен робота

Note

Эта фича пока в разработке:

https://st.yandex-team.ru/DIR-2325

Работать ручка должна как-то так:

$ http GET https://api.directory.yandex.ru/users/100500/token/ \
       "Authorization: OAuth $WIKI_TOKEN"

{
  "token": "435ref3242r32143"
}

Как всё это будет выглядеть при работе через Python SDK

import os

from yad.api import Directory

# Получим обезличенный токен сервиса.
token = Directory.get_service_token(
    os.environ['CLIENT_ID'],
    os.environ['SECRET'],
)

# Используем обезличенный токен.
api = Directory(token)

# Пройдём по всем организациям, где подключен сервис
# (пока не работает, ждем https://st.yandex-team.ru/DIR-2427).
for organization in api.organizations:
    api.org_id = organization['id']

    # Пройдём по всем сотрудникам организации
    # библиотека сама позаботится о пейджинации.
    # Если во время обхода произойдёт инкремент
    # ревизии организации, то будет выброшено исключение
    # RevisionIncrement
    for user in api.users:
        do_something_with(user)

    # Чтобы не фейлиться из-за частых смен ревизии,
    # можно задать список событий, которые существенны
    # для вашей бизнес-логики. Тогда RevisionIncremented
    # будет бросаться только в том случае, если увеличению
    # ревизии сопутствуют события указанного типа:
    with vital_events('user_.*', 'department_.*'):
        for user in api.users:
            do_something_with(user)
        for dep in api.departments:
            do_something_with(dep)
    # Этот код пройдётся по всем пользователям и отделам,
    # и только если в процессе обхода было изменение
    # в пользователях или отделах, процесс прервётся.

    # Далее.
    # Получим обезличенный токен бота.
    # (пока не работает, ждем https://st.yandex-team.ru/DIR-2325)
    bot_api = api.as_bot()

    # Создадим команду от имени робота.
    bot_api.groups.create(name="Команда роботов", members=...)

# Подпишемся на события о подключении сервиса к организации
# (пока не реализована фильтрация по сервису, так что будут
# прилетать все события).
api.webhooks.create(
    url='https://some.wiki.url/',
    event_names=[
        'organization_service_enabled',
        'organization_service_disabled',
    ]
)