Владение ресурсами в REST API

В следующем сценарии:

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

Можно отправить запрос /game/{id} для получения данных игры, которые должны быть одинаковыми для каждого клиента, например:

{
   name: 'My Game',
   sport: 'Football'
   ...
}

Допустим, нам нужно показать ссылку «Настройки» для владельца игры на главном игровом экране. Эта ссылка «Настройки» не может отображаться для обычных игроков.

И игрок, и владелец могут видеть главный игровой экран.

Как я могу подтвердить право собственности на этот ресурс, чтобы показывать пользователям различные компоненты?

  • Я думаю, что добавление ownerId к ответу будет проблемой, поскольку можно изменить значение на стороне клиента, верно?
  • Кроме того, добавление поля isOwner сделает невозможным кэширование ответа.

person Felipe Francisco    schedule 08.06.2017    source источник


Ответы (3)


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

Кэширование: это проблема, но она решаема.

person Software Engineer    schedule 08.06.2017
comment
В таком случае, как это можно решить с точки зрения кэширования? При таком подходе ответ становится пользовательским. - person Felipe Francisco; 09.06.2017
comment
Проблема, как указано, на самом деле не кэшируется — вы получаете разные выходные данные в зависимости от пользователя, поэтому мы обычно не кэшируем данные. Вам придется разделить это на два запроса: один для объекта и один для его метаданных (включая ссылку на настройки). Исходный dto можно кэшировать, а пользовательские данные нельзя. - person Software Engineer; 09.06.2017

Давайте поговорим о серверном приложении и клиентском приложении. Клиентское приложение содержит главный экран игры и должно отображать или скрывать некоторые панели в зависимости от чего-то.

Серверное приложение должно предоставить это что-то. Поскольку серверное приложение является REST, оно должно предоставлять некоторую помощь. Что за ресурс и где он должен быть?

GET /games/{gameId}/users/{userId}/something
GET /users/{userId}/games/{gameId}/something

Это можно назвать что-то правами или разрешениями пользователя. Это отдельный ресурс? Наверное, нет. Таким образом, вы можете реализовать метод

GET /games/{gameId}/users/{userId}

Метод вернет профиль пользователя и соответствующие разрешения для игры с идентификатором {gameId}, как здесь:

{
    givenNames: 'Miguel de Cervantes',
    familyName: 'Saavedra',
    totalScore: 10342,

    permissions: {
        canClose: false,
        canSetup: false,
        . . .
    }
}

И, конечно же, серверное приложение должно проверять разрешения для каждого запроса клиента.

person Mark Shevchenko    schedule 08.06.2017
comment
Спасибо, я впервые вижу такой подход, поэтому у меня есть несколько вопросов о последствиях использования этого типа обработки разрешений в приложении: данные профиля текущих пользователей можно получить, запросив конечную точку /users/{id}. Можно ли также включить данные о пользователях в эту предлагаемую конечную точку (/games/{gameId}/users/{userId})? - person Felipe Francisco; 09.06.2017
comment
В данном случае это означает, что для получения разрешения пользователя необходимо будет сделать еще один запрос, не ухудшит ли это производительность приложения? И поскольку узел permissions будет стандартом для всего приложения, как лучше всего задокументировать ключи разрешений разных типов (canClose, canSetup...) в документации? - person Felipe Francisco; 09.06.2017
comment
По первому вопросу. Да, было бы нормально. Иногда подресурсы могут быть доступны по разным путям, особенно когда есть отношение многие-ко-многим. У вас есть игры, у вас есть пользователи и у вас есть все игры указанного пользователя. - person Mark Shevchenko; 09.06.2017
comment
По второму вопросу. Общее правило заключается в передаче как можно большего количества данных за раз (шаблон Remote Façade). Permissions — это простая небольшая коллекция, поэтому вы можете просто включить ее в пользовательский объект. В JSON API вы можете использовать параметр запроса include для передачи нужных необязательных полей. - person Mark Shevchenko; 09.06.2017

Я думаю, сначала вам нужно решить концептуальную проблему, связанную с ответственностью за ресурсы, потому что ресурс, который возвращает информацию об игре, не должен возвращать информацию о безопасности, такую ​​​​как «видеть или не видеть кнопку».

Итак, я бы создал специальный ресурс для возврата такой информации о безопасности. В этом конкретном ресурсе безопасности для упомянутого выше случая я бы не стал передавать какой-либо параметр по URL-адресу, а через хэш аутентификации я бы получил идентификатор пользователя, чтобы проверить, является ли он владельцем игры, возвращая простой ответ, например, true или false, чтобы узнать если этот пользователь может видеть эту кнопку.

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

Такой ресурс, как:

GET /security/buttons/{buttonId}

И в будущем:

GET /security/screens/{screenId}
GET /security/functionalities/{functionalityId}
GET /security/actions/{actionId}
.
.
.
person Leo Ramos    schedule 09.06.2017
comment
Кнопка была просто абстрактным примером, так как я не могу поделиться здесь реальным сценарием. Кнопка представляет информацию и действия, относящиеся исключительно к Владельцу игры. Что касается вашего ответа, разве это не противоречит концепции ресурса, а также RFC 3986? - person Felipe Francisco; 09.06.2017