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

Все примеры, используют `httpie <https://httpie.org>`_. Он удобнее чем 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, то создадутся две
          подписки и события будут приходить дважды.

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

          * https://st.yandex-team.ru/DIR-2234
          * https://st.yandex-team.ru/DIR-2233


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


Пока включение/выключение сервиса работает лишь со старыми
токенами. Можно использовать токен от 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
=======================================================

.. code:: python

          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',
              ]
          )

          



