Эта функциональность пока в разработке. Meta может изменить или удалить ее в любой момент.

Расширения для публикации контента в Workplace

Обзор

Расширения для публикации контента в Workplace позволяют людям легко и безопасно делиться информацией с соблюдением конфиденциальности исходного материала.

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

Публикация частных URL

В Workplace пользователи часто делятся ссылками на внутренние ресурсы компании, которые должны быть видны не всем. Этим Workplace отличается от Facebook, где люди обычно публикуют общедоступный контент, например новости или записи в блоге.

Общедоступные и частные URL в Workplace

Чтобы платформа Workplace могла сгенерировать предпросмотр для конфиденциального контента компании, необходимо предоставить определенные метаданные. Вы как поставщик услуг должны определить, разрешено ли текущему пользователю Workplace просматривать контент и, соответственно, следует ли предоставить ему метаданные.

Содержание

В этом документе рассматриваются различные аспекты реализации расширений для публикации контента:

В этом документе также рассказывается, как добавить в приложение поддержку расширений для публикации контента.

Настройка приложения

Чтобы настроить поддержку расширений для публикации контента в приложении, нужно предоставить три перечисленных далее поля.

  • Домен или группа доменов, выступающих в качестве корневых в каждом URL, для которого предоставляется авторизованный предпросмотр.
    • В домен (например, example.com) также включаются все поддомены (например, acme.example.com).
  • Регулярное выражение для сопоставления относительного пути каждого URL, поддерживаемого интеграцией.
    • Например, для сопоставления с www.example.com/download?id=123 или www.example.com/file/456, но не с www.example.com/blog выражение может быть таким: \/(download?|file\/).+/
    • Если домен или группа доменов охватывают все URL, можно оставить это поле пустым или указать универсальное выражение (например, /.*/).
  • Конечная точка для сопоставления идентификационных данных пользователей Workplace, которые должны видеть предварительный просмотр.

Приложение следует подписать на тему Webhooks Link и поле preview. Кроме того, ему нужно предоставить разрешение на развертывание ссылок.

Эта функция находится на стадии бета-тестирования, поэтому настроить приложение на панели разработчика на сайте developers.facebook.com пока нельзя.

Чтобы настроить или обновить эти поля, обратитесь к закрепленному за вами партнеру Meta.

Авторизованный предпросмотр

Главное назначение расширений для публикации контента — корректный предварительный просмотр в Workplace. Для этого требуются метаданные в определенном формате: при публикации URL вашего контента Workplace получает их и формирует предварительный просмотр. Этот процесс часто называют развертыванием ссылок.

Meta может получать метаданные для развертывания общедоступного URL с помощью протокола Open Graph и краулера Facebook, но для частных URL, которые обычно публикуются в Workplace, такой метод не подходит. Вместо этого на указанный вами URL обратного вызова отправляется уведомление Webhooks, в ответе на которое можно передать метаданные с описанием URL для человека, который его опубликовал, чтобы отобразить предпросмотр ссылки.

Этот процесс повторяется для каждого пользователя, просматривающего опубликованный URL в Workplace, что позволяет контролировать видимость предварительного просмотра для отдельных пользователей.

Конфигурация

Чтобы включить авторизованные предпросмотры, необходимо настроить приложение следующим образом:

  • установить его в сообществе Workplace либо в одной или нескольких группах;
  • предоставить разрешение на развертывание ссылок (в настоящее время включено в список разрешенных);
  • указать домен или группу доменов, содержащие URL, которые будет развертывать ваша интеграция;
  • подписаться на тему Webhooks Link для предпросмотра полей и указать URL обратного вызова для предоставления метаданных.

Webhooks

Получение Webhooks

Мы отправляем запрос поставщику услуг в различных ситуациях:

  1. при публикации нового URL, который нам ещё не известен (из поля для публикаций);
  2. если мы не знаем, есть ли у нового пользователя доступ к контенту, который он пытается просмотреть (из ленты);
  3. при репосте контента (из поля для публикаций или ленты) или истечении срока его действия.

Формат запроса Webhooks

Во всех описанных выше случаях Webhooks отправляется как запрос POST в следующем формате:

{
  "object": "link",
  "entry": [
    {
      "time": int,
      "changes": [
        {
          "field": "preview",
          "value": {
            "community": {
              "id": string,
            },
            "user": {
              "id": string,
            },
            "link": string,
          }
        }
      ]
    }
  ]
}
    

Полезные данные содержат следующие поля:

Имя поляОписание

object

Тема Webhooks. В данном контексте это всегда link.

entry

Список запросов. Необходимо одно и только одно такое поле.

entry.time

Время отправки запроса.

entry.changes

Список изменений в запросе. Необходимо одно и только одно такое поле.

entry.changes.field

Поле Webhooks. Всегда имеет значение preview.

entry.changes.value

Фактический объект, содержащий контекст запроса.

entry.changes.value.field.community

Сообщество, к которому относится пользователь, инициировавший запрос.

entry.changes.value.field.user

Пользователь, инициировавший запрос.

entry.changes.value.field.link

Ссылка, которую пытается отобразить Workplace. Соответствует домену и регулярному выражению, настроенным в приложении.

Пример

POST /callback HTTP/1.1
Host: third-party.com
Accept: application/json
Content-Type: application/json
User-Agent: Webhooks/1.0 (https://fb.me/webhooks)
X-Hub-Signature: sha1=bf3102e52efd0fd4bd26277030aa180d7b5cf587
...

{
    "object": "link",
    "entry": [{
        "time": 1501515097793,
        "changes": [{
            "field": "preview",
            "value": {
                "community": {
                    "id": "138169208138649"
                },
                "user": {
                    "id": "88575656148087"
                }
                "link": "https://company.third-party.com/document-about-this"
            }
        }]
    }]
}
    

Формат ответа Webhooks

Ответ на запрос Webhooks должен содержать метаданные в определенном формате:

{
  "data": [
    {
      "link": string,
      ?"canonical_link": string,
      ?"title": string,
      ?"description": string,
      ?"icon": string,
      ?"download_url": string,
      "privacy": 'organization' | 'accessible' | 'inaccessible',
      ?"type": 'document' | 'folder' | 'task' | 'link',
      ?"additional_data": [
        {
          "title" => string,
          "format" => 'text' | 'date' | 'datetime' | 'user',
          "value" => string | number,
          ?"color" => 'blue' | 'green' | 'yellow' | orange' | 'red',
        },
      ],
    }
  ],
  ?"linked_user": boolean
}

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

Имя поляОписание

data

Подборка объектов, доступных пользователю. Может быть пустой, если приложение вообще не развертывает ссылку для этого пользователя.

linked_user

Поле с логическим значением, указывающее, известен ли пользователь третьей стороне. Если задано значение false, выводится диалог привязки аккаунта.

data.link

Ссылка, уникальным образом идентифицирующая объект. Должна совпадать со ссылкой в запросе.

data.canonical_link

Каноническое представление URL контента. Если отличается от ссылки, то контент ассоциируется с каноническим контентом, что упрощает запрос связанных публикаций.

data.title

Название объекта. Не требуется только для объектов со значением inaccessible в поле privacy.

data.description

Краткое описание объекта, которое будет отображаться в расширенном предпросмотре.

data.icon

Объект, используемый в Workplace в качестве значка для контента. Это должен быть общедоступный URL. Лучше всего использовать объект размером 16 x 16 пикселей.

data.download_url

URL, по которому Workplace может скачать представление объекта в формате PDF для преобразования в публикацию с изображением. Игнорируется для всех типов объектов, кроме document и link.

data.privacy

Уровень конфиденциальности объекта. Возможные значения: organization, accessible и inaccessible. Значение organization означает, что объект можно показывать любому участнику сообщества Workplace, даже если его аккаунт не привязан, значение accessible — что объект доступен вошедшему пользователю, а остальным необязательно, и, наконец, значение inaccessible — что этот документ недоступен данному пользователю.

data.type

Возможные значения: document, folder, task и link. Папка — это набор документов или других папок. Не требуется только для объектов со значением inaccessible в поле privacy.

data.additional_data

Набор метаданных, отображаемых в расширенном предпросмотре. Игнорируется для document и folder. Используются только три первых элемента. Подробные сведения о формате этих полей см. в разделе Дополнительные данные.

Пример полного ответа

HTTP/1.1 200 OK
Content-Type: application/json
X-Hub-Signature: sha1=b5a6f32f084100ae5b355174b9bb8398f5fbe983
...

{
  "data": [
    {
      "link": "https://taaskly.herokuapp.com/task/4",
      "title": "Launch Workplace Integration for F8",
      "privacy": "organization",
      "type": "task",
      "additional_data": [
        {
          "title": "Owner",
          "format": "user",
          "value": "319922278498384"
        },
        {
          "title": "Created",
          "format": "datetime",
          "value": "2018-02-28T03:35:40.827Z"
        },
        {
          "title": "Priority",
          "format": "text",
          "value": "high",
          "color": "red"
        }
      ]
    }
  ],
  "linked_user": true
}
    

Режимы конфиденциальности

Режим конфиденциальности определяет видимость контента и необходимость аутентификации текущего и последующих пользователей.

  1. organization: контент виден пользователю, аутентификация не требуется
    В этом случае мы можем сразу показывать контент пользователю. Используется для контента, который должен быть доступен всем пользователям в домене (компании). Для каждого нового пользователя отправлять Webhooks нет необходимости.
  2. accessible: контент виден текущему пользователю, но для остальных может требоваться сопоставление идентификационных данных.
    Поставщику услуг известно, что данному пользователю разрешен просмотр этого контента, но это не значит, что просмотр разрешен всем. Мы показываем предпросмотр, но для остальных пользователей будем по-прежнему отправлять Webhooks.
  3. inaccessible: контент не виден пользователю
    Поставщику услуг известен этот пользователь, а также то, что ему запрещен просмотр этого контента. Мы отображаем уведомление о конфиденциальности (недоступности и т. п.).

Дополнительные данные

Вы можете отправить до **трех** объектов с дополнительными данными для предварительного просмотра ссылки. Такой объект состоит из набора элементов "ключ — значение". Значения могут иметь разный формат.

В настоящее время поддерживаются четыре формата.

  • text: значение отображается как есть; должно быть строкой. Дополнительные данные в этом формате также могут содержать свойство color с одним из следующих значений: blue, green, yellow, orange или red. В этом случае значение отображается на фоне указанного цвета.
  • date: значение интерпретируется и отображается как дата в формате ISO-8601 без указания времени.
  • datetime: значение интерпретируется и отображается как дата в формате ISO-8601 с указанием времени в часовом поясе пользователя.
  • user: значение интерпретируется как ID пользователя и отображается как его имя.

Отображение предварительного просмотра файлов (необязательно)

Если для документа установлен режим конфиденциальности organization или accessible и указан URL для скачивания, мы отправим дополнительный запрос на скачивание данных.

GET /download/super-fancy-document HTTP/1.1
Host: provider.com
Accept: <some mime types>
User-Agent: Webhooks/1.0 (https://fb.me/webhooks)
X-Hub-Signature: sha1=bf3102e52efd0fd4bd26277030aa180d7b5cf587

Workplace преобразует этот файл в фотографии, чтобы создать публикацию с несколькими фото.

Сопоставление идентификационных данных

Как упоминалось выше, для авторизованного предпросмотра требуется сопоставление идентификационных данных. Оно позволяет убедиться в том, что у пользователя Workplace есть разрешение на просмотр контента из предпросмотра, и обеспечить соблюдение правил доступа в Workplace.

Сопоставление на уровне компании

Это простейший способ сопоставления идентификационных данных: для показа предпросмотров пользователям достаточно того, чтобы они были участниками сообщества Workplace. Это обычная ситуация при предпросмотре ссылок в интрасети компании или любом сервисе, в котором все объекты (или по крайней мере их метаданные) видны всей компании.

Если интеграция установлена в сообществе Workplace, ID сообщества можно проверить через конечную точку /community с использованием маркера доступа, полученного при установке. Этот ID можно хранить вместе с маркером и сопоставлять его с идентификатором организации в вашем сервисе. Таким образом создается связь между сообществом Workplace и организацией в вашем сервисе.

Получив запрос Webhooks авторизованного предпросмотра, вы можете проверить, совпадает ли указанный в его полезных данных ID сообщества с ID сообщества, связанным с организацией, и решить, можно ли вернуть метаданные в ответе. Если указать в ответе уровень конфиденциальности ORGANIZATION, мы не будем отправлять дополнительные Webhooks для каждого участника этого сообщества Workplace.

Сопоставление на уровне пользователя

Этот способ подходит, когда требуется более детальная настройка разрешений: вы решаете, следует ли показывать метаданные каждому отдельному пользователю в Workplace. Workplace передает ID пользователя в каждом запросе Webhooks на авторизованный предпросмотр. Для сопоставления на уровне пользователя необходимо знать, какой пользователь в вашей системе соответствует ID пользователя, переданному из Workplace в полезных данных запроса Webhooks.

Если данный ID пользователя Workplace встречается впервые, можно передать в ответе логическое поле linked_user со значением false. В результате в Workplace будет показана кнопка Включить предпросмотр, позволяющая пользователю привязать свой аккаунт.

По нажатию этой кнопки в Workplace открывается диалог, позволяющий подтвердить сеанс пользователя в вашем сервисе. Для этого используется указанная вами конечная точка привязки аккаунта. Чтобы открыть этот URL, Workplace отправляет запрос POST, в котором передает параметр signed_request, содержащий ID текущего пользователя и ID сообщества.

POST https://www.example.com/account_linking?redirect_uri=https%3A%2F%2Ffoxfabrics.facebook.com%2Flink_complete HTTP/1.1
Host: foxfabrics.third-party.com
Origin: http://www.facebook.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 Gecko/20100101 Firefox/57.0
...

signed_request=238fsdfsd.oijdoifjsidf899
    

Параметр signed_request в полезных данных содержит информацию о пользователе. Этот запрос декодируется следующим образом:

  1. Значение делится на две части, разделенные символом ".".
  2. Первая часть — подпись — декодируется из base64url.
  3. Вторая часть — полезные данные — декодируется из base64url, после чего декодируется полученный объект JSON.
  4. Подпись проверяется на соответствие HMAC закодированных полезных данных с использованием секрета приложения.

Полезные данные содержат следующие поля:

{
  "algorithm": "HMAC-SHA256",
  "user_id": "88575656148087",
  "community_id": "138169208138649"
}
    

В итоге вы получаете ID пользователя Workplace и ID сообщества, а также подтвержденный сеанс пользователя в вашем сервисе, и можете сопоставить ID пользователя в Workplace с его ID в вашем сервисе. По завершении необходимо перенаправить пользователя на URL, указанный в исходном запросе в параметре redirect_uri.

GET {$redirect_uri} HTTP/1.1
Host: foxfabrics.facebook.com
User-Agent: Mozilla/5.0 Gecko/20100101 Firefox/57.0
Referer: https://www.example.com/account_linking
...
    

Workplace определит, что сопоставление идентификационных данных завершено, и вновь попытается запросить метаданные для авторизованного предпросмотра. На этот раз вы сможете передать в ответе поле linked_user со значением true и необходимые метаданные.

Примечание.

Весь этот цикл обмена данными требуется только один раз, когда неизвестный пользователь впервые пытается выполнить предпросмотр контента. Для последующих предварительных просмотров после сопоставления идентификационные данные не требуются.

Расширения для редактора

Авторизованный предпросмотр для ссылок, публикуемых в Workplace, сам по себе очень полезен. Но чтобы людям было ещё проще делиться контентом из вашего приложения прямо в Workplace, можно включить расширения для редактора.

Если ваша интеграция поддерживает эти расширения, вы можете предоставить список актуальных документов. Когда пользователь начнет создавать публикацию в соответствующей группе Workplace, он увидит этот список и сможет поделиться им, не копируя URL. Объект такой публикации ничем не отличается от объекта, опубликованного вручную. В том числе он учитывает разрешения функции авторизованного предпросмотра.

Для использования расширений для редактора идентификационные данные пользователя должны быть сопоставлены, иначе он не сможет получить персонализированный список документов.

Конфигурация

Чтобы включить расширения для редактора, необходимо настроить приложение следующим образом:

  • подписаться на тему Webhooks link и поле collection;
  • указать URL связывания аккаунтов, заданный во время настройки приложения.

Формат запроса Webhooks

Когда связанный пользователь вызывает расширение для редактора, Workplace отправляет уведомление Webhooks для получения списка документов в следующем формате:

{
  "object": "link",
  "entry": [
    {
      "time": int,
      "changes": [
        {
          "field": "collection",
          "value": {
            "community": {
              "id": string,
            },
            "user": {
              "id": string,
            },
            ?"link": string,
          }
        }
      ]
    }
  ]
}
    

Полезные данные содержат следующие поля:

Имя поляОписание

object

Тема Webhooks. В данном контексте это всегда link.

entry

Список запросов. Необходимо одно и только одно такое поле.

entry.time

Время отправки запроса.

entry.changes

Список изменений в запросе. Необходимо одно и только одно такое поле.

entry.changes.field

Поле Webhooks. Всегда имеет значение collection.

entry.changes.value

Фактический объект, содержащий контекст запроса.

entry.changes.value.field.community

Сообщество, к которому относится пользователь, инициировавший запрос.

entry.changes.value.field.user

Пользователь, инициировавший запрос.

entry.changes.value.field.link

Если пользователь переходит во вложенные папки, это значение задается для последующих запросов, но отсутствует для корневых.

Пример:

POST /callback HTTP/1.1
Host: third-party.com
Accept: application/json
Content-Type: application/json
User-Agent: Webhooks/1.0 (https://fb.me/webhooks)
X-Hub-Signature: sha1=bf3102e52efd0fd4bd26277030aa180d7b5cf587
...

{
    "object": "link",
    "entry": [{
        "time": 1501515097793,
        "changes": [{
            "field": "collection",
            "value": {
                "community": {
                    "id": "138169208138649"
                },
                "user": {
                    "id": "88575656148087"
                }
            }
        }]
    }]
}
    

Формат ответа

Получив запрос, URL обратного вызова должен проверить заголовок X-Hub-Signature и вернуть группу объектов для отображения в редакторе в следующем формате:

{
  "data": [
    {
      "link": string,
      "title": string,
      ?"description": string,
      ?"icon": string,
      ?"download_url": string,
      "privacy": ORGANIZATION | ACCESSIBLE,
      "type": DOCUMENT | FOLDER | TASK | LINK,
      ?"additional_data": [
        {
          "title" => string,
          "format" => 'text' | 'date' | 'datetime' | 'user',
          "value" => string | number,
        },
      ],
    }
  ],
  ?"linked_user": boolean
}

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

Имя поляОписание

data

Подборка доступных пользователю объектов.

linked_user

Поле с логическим значением, указывающее, известен ли пользователь третьей стороне. Если задано значение false, выводится диалог привязки аккаунта.

data.link

Ссылка, уникальным образом идентифицирующая объект.

data.title

Название объекта. Не требуется только для объектов со значением inaccessible в поле privacy.

data.description

Краткое описание объекта, которое будет отображаться в расширенном предпросмотре.

data.icon

Объект, используемый в Workplace в качестве значка для контента. Это должен быть общедоступный URL. Лучше всего использовать объект размером 16 x 16 пикселей.

data.download_url

URL, по которому Workplace может скачать представление объекта в формате PDF для преобразования в публикацию с изображением. Игнорируется для всех типов объектов, кроме document и link.

data.privacy

Уровень конфиденциальности объекта. Возможные значения: organization, accessible и inaccessible. Значение organization означает, что объект можно показывать любому участнику сообщества Workplace, даже если его аккаунт не привязан, значение accessible — что объект доступен вошедшему пользователю, а остальным необязательно, и, наконец, значение inaccessible — что этот документ недоступен данному пользователю.

data.type

Возможные значения: document, folder, task и link. Папка — это набор документов или других папок. Не требуется только для объектов со значением inaccessible в поле privacy.

data.additional_data

Набор метаданных, отображаемых в расширенном предпросмотре. Игнорируется для document и folder. Используются только три первых элемента. Подробные сведения о формате этих полей см. в разделе Дополнительные данные.

Пример:

HTTP/1.1 200 OK
Content-Type: application/json
X-Hub-Signature: sha1=b5a6f32f084100ae5b355174b9bb8398f5fbe983
...

{
  "data": [
    {
      "link": "https://company.third-party.com/document-A",
      "title": "Slides for Project A",
      "description": "Short summary of the slides.",
      "download_url": "https://company.provider.com/download/document-A",
      "privacy": "accessible",
      "type": "document"
    },
    {
      "link": "https://company.third-party.com/folder-B",
      "title": "Folder B",
      "privacy": "public",
      "type": "folder",
    }
  ],
  "linked_user": true
}