Как использовать атрибут groups подключенного / встроенного объекта для аутентификации родительской записи в AWS AppSync (Amplify)

#authentication #aws-lambda #aws-amplify #velocity #aws-appsync

#аутентификация #aws-lambda #aws-amplify #скорость #aws-appsync

Вопрос:

Справочная информация

В проекте, над которым я работаю, мы используем AWS в качестве поставщика облачных услуг и Amplify с AppSync GraphQL для быстрого создания серверной части. AppSync в Amplify по умолчанию использует базу данных DynamoDB, так что это то, что мы используем с ней.

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

Существует иерархия, в соответствии с которой объект проекта может содержать много других объектов, и нам нужно убедиться, что любой, кто имеет право просматривать проект, также может просматривать все, что он содержит.

Проблема

Для этого предполагалось, что у нас может быть Asset объект с projectId атрибутом и project подключением для заполнения сведений о проекте при чтении записи. Таблица / объект проекта содержит groups атрибут, который мы используем в директиве dynamic group security @auth .

вот пример схемы:

 type Project
  @model
  @auth(rules: [
    { allow: groups, groupsField: "groups" }
  ])
{
  id: ID!
  title: String!
  reference: String
  clientId: ID!
  client: Organisation!
    @connection(fields: ["clientId"])
  modifiedById: ID
  changeComment: String
  groups: [String!]
}

type Asset
  @model
  @key(name: "byProjectId", fields: ["projectId"])
{
  id: ID!
  name: String!
  projectId: ID!
  project: Project!
    @connection(fields: ["projectId"])
  completedAt: AWSDateTime
}
 

Это упрощено, поэтому не имеет большого смысла, как написано. В идеале мы бы использовали @auth директиву для указания поля для Asset типа, например

 @auth( allow: groups, groupsField: "project.groups" )
 

Мы также попытались сделать это вручную с помощью пользовательского преобразователя, написанного на Velocity (.vtl), который оказался почти таким же:

 #set( $allowedGroups = $util.defaultIfNull($item.project.groups, []) )
#set( $userGroups = $util.defaultIfNull($ctx.identity.claims.get("cognito:groups"), []) )
#foreach( $userGroup in $userGroups )
    #if( $util.isList($allowedGroups) )    
        #if( $allowedGroups.contains($userGroup) )
            #set( $isLocalDynamicGroupAuthorized = true )
        #end
    #end
    #if( $util.isString($allowedGroups) )
        #if( $allowedGroups == $userGroup )
            #set( $isLocalDynamicGroupAuthorized = true )
        #end
    #end
#end
 

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

Ответ?

Есть ли способ сделать это или более подходящая альтернатива? Меня беспокоит то, что очевидное решение, заключающееся в том, что все объекты имеют свой собственный атрибут groups, который содержит имя группы пользователей родительского проекта, может стать очень громоздким, поскольку в проекте более 10 тыс. ресурсов и нужно учитывать не только активы.

Я борюсь со своим желанием нормализовать данные, поскольку это база данных NoSQL, и мы должны просто дублировать значения и обрабатывать их в коде?

Будет ли таблица матрицы разрешений пользователя более разумной и будет ли ее достаточно легко встроить в AppSync с помощью Amplify?

Любые подсказки о том, как это сделать или реализовать более подходящее решение, были бы очень признательны.