Фильтрация подписки на события AWS AppSync для пользователя Cognito - PullRequest
0 голосов
/ 30 октября 2018

У меня есть следующая схема:

input CreateEventInput {
    userID: String!
    eventID: ID!
    type: String!
    data: String
    dateTime: AWSDateTime!
}

type Mutation {
    createEvent(input: CreateEventInput!): event
}

type Subscription {
    onCreateEvent(): event
        @aws_subscribe(mutations: ["createEvent"])

Резолвер createEvent устанавливает userID как:

"key" : {
        "userID" : $util.dynamodb.toDynamoDBJson($context.identity.username),
        "eventID" : $util.dynamodb.toDynamoDBJson($util.autoId())
    }

Я бы хотел ограничить подписку, чтобы только записи, в которых userID = $context.identity.username возвращались пользователю.

Кто-нибудь знает, как это настроить? Я думаю, что мне нужен распознаватель на подписку, но я не могу найти четкий пример этого, где у вас есть первичный ключ раздела (userID) и первичный ключ сортировки (eventID).

Буду очень признателен за любую помощь или руководство. При необходимости я могу изменить схему или БД.

Обновление

Полагаю, я могу установить для шаблона сопоставления ответов подписки что-то вроде:

#if(${context.identity.username} != ${context.arguments.userID})
    $utils.unauthorized()
#else
##User is authorized, but we return null to continue
    null
#end

Однако я не знаю, что добавить в шаблон сопоставления запросов.

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

Пока не улучшится Appsync, вот как я выполнил подписку, которая позволяет пользователю подписываться только на события, которые соответствуют его собственному userID, используя схему, которую я разместил выше:

Шаблон отображения запроса:

{
    "version": "2017-02-28",
    "operation": "GetItem",
    "key": {
        "userID": $util.dynamodb.toDynamoDBJson($ctx.identity.username),
        "eventID": { "S" : "0bfe0d7c-b469-441e-95f6-788fe300f76d" }
    },
}

Шаблон сопоставления запросов предназначен только для внешнего вида (веб-консоль Appsync не позволит вам сохранить, не заполнив его чем-либо допустимым). Он выполняет поиск в жестком коде каждый раз, когда кто-то делает запрос на подписку. Это ничего, кроме успеха, и данные выбрасываются. Так работает подписка в Appsync.

Шаблон отображения ответов подписки:

#if(${context.identity.username} != ${context.arguments.userID})
    $utils.unauthorized()
#else
##User is authorized, but we return null to continue
    null
#end

Здесь происходит волшебство. В основном это говорит о том, что если пользователь не запрашивал подписку на события с тем же именем пользователя, что и у них, - возвращать unauthorized. Если пользователь запросил подписку на события с тем же идентификатором пользователя, что и вошедшая в систему учетная запись, null (null - это способ успешного отображения шаблона сопоставления ответов (т. Е. Без ошибок).

Тщательно, вот как выглядит запрос клиента:

const eventSub = `subscription eventSub($userID: String!) {
  onCreateEvent(userID: $userID) {
    userID
    email_hash
    eventID
    type
    data
    dateTime
  }
}`;
0 голосов
/ 30 октября 2018

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

type mutation {
  createEvent(userID: String!, eventID: ID!, type: String!, 
    data: String, dateTime: AWSDateTime!): event
}
... other stuff...
type Subscription {
  onCreateEvent(userId: String!): event
  @aws_subscribe(mutations: ["createEvent"])
}

Несколько замечаний по этому поводу:

1) Предполагается, что вы хотите, чтобы это было требованием для подписки. Если нет, если вы хотите, чтобы это было необязательное правило, удалите!. По твоему комментарию, я думаю, ты бы этого хотел.

2) Фильтры подписки (что является параметром userId в операции подписки) требуют, чтобы фильтры были в ответе на мутацию. Поэтому убедитесь, что когда вы определяете операцию на своем клиенте, вы включаете туда userId в ответ.

3) Это необходимо для применения фильтра подписки. Служба не будет знать, что такое userId, если это не прямой ввод в мутацию, если он внутри и форма ввода не будет работать.

Теперь, насколько это возможно, пользователь не может просто подписаться на чужое имя пользователя. Я полагаю, что вы просматривали эту страницу документации . Это будет работать, полностью допустимо и может быть дополнено чем-то похожим на пример на этой странице документации, но оно основано на наличии таблицы поиска разрешений и распознавателя Dynamo. Если у вас его нет или вы предпочитаете избегать его использования, небольшая настройка должна помочь ему работать с не / локальным распознавателем. Без таблицы разрешений или чего-либо, с чем можно было бы проверить, я настоятельно рекомендовал бы локальный / без разрешения.

В частности, я считаю, что вы можете переместить то, что у вас есть в шаблоне отображения ответов, в новый шаблон отображения вашего нет / локального преобразователя ...

#if(${context.identity.username} != ${context.arguments.userID})
    $utils.unauthorized()
#else
##User is authorized, but we return null to continue
    null
#end

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...