Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataStore query on many-to-many join table, using @manyToMany, not working, source tables are using owner auth. GraphQL create join table object, not working, due to missing owner field in Input model. #473

Closed
3 tasks done
ecc7220 opened this issue Mar 28, 2022 · 4 comments
Assignees
Labels

Comments

@ecc7220
Copy link

ecc7220 commented Mar 28, 2022

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

DataStore

Amplify Categories

api

Environment information

# Put output below this line


Describe the bug

Using GraphQL transformer V2.

Following the examples on many-to-many queries from:

Amplify Docs - DataSore - Many-to-many

With a graphql.schema like this:

type User @model @auth(rules: [{allow: owner, operations: [read]}]) {
  id: ID!
  name: String @index(name: "byName", queryField: "userByName")
  cars: [Car] @manyToMany(relationName: "UserCar")
  owner: String!
}

type Car @model @auth(rules: [{allow: owner, operations: [read]}]) {
  id: ID!
  name: String @index(name: "byName", queryField: "carByName")
  users: [User] @manyToMany(relationName: "UserCar"),
  owner: String
}

Query on UserCar like this (notice no filter):

const result = await DataStore.query(UserCar);

Gives an empty array as result.

Query results on User or Car deliver the right objects.
If I look in Amplify Studio, I see the many-to-many relationships, when I load a User or Car.

The corresponding join table object was inserted using GraphQL in a Lambda function, but it was not possible to provide the owner field for the join object, due to missing definition in the AppSync CreateUserCarInput, although the type in AppSync for UserCar contains the owner field. Just for a test I populated the owner field using DynamoDB console, but without any success. The local storage on the browser client for the UserCar is always empty.

Please advice on how to proceed from here, because the only thing I can think about now, is to not use @manytomany at all, because it seems to be not working as it should, even using GraphQL instead of DataStore, due to the fact, that the CreateUserCarInput is missing the owner field, which is present in the type definition of UserCar in AppSync.

If you link a Car to a User in Amplify Studio, the owner field is obviously also missing the DynamoDB data.
So this lets me think, that owner auth is not supported on many-to-many relationships.

Please confirm, so I can start removing DataStore immediately to start making some progress on my project.

Expected behavior

To be able to fetch join table object with owner auth.

Reproduction steps

See the description:

  1. Create the model as shown in the description.

  2. Create test data in Amplify Studio.

  3. Try to fetch join table object using DataStore in the client.

  4. Try to create a join table object with GraphQL, with and without owner field set.

Code Snippet

// Put your code below this line.

Log output

// Put your logs below this line


aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

@chrisbonifacio chrisbonifacio added the pending-triage Issues that need further discussion to determine label Mar 29, 2022
@benjeater
Copy link

+1

I have the same issue when using dynamic group rules on a GraphQL API (@auth rules below)

@auth(
  rules: [
    { allow: groups, groupsField: "groupsCanRead", operations: [read] },
    { allow: groups, groupsField: "groupsCanUpdate", operations: [read, update] },
    { allow: groups, groupsField: "groupsFullControl", operations: [read, update, delete] },
    { allow: groups, groups: ["ADMINISTRATOR"], operations: [create, read, update, delete] }
  ]
)

Looking at the relevant .vtl templates for the generated join table in the api/[api-name]/build/resolvers folder, it appears that the authorization checks are inherited from the parent table.

In ecc7220's case, it is looking for an owner field on the join table and not finding one. In my case, it's looking for fields called groupsCanRead, groupsCanUpdate, groupsFullControl and not finding them.

There is certainly a requirement to define the auth rules for the join table, but I can find no documentation for how to do this.

To get around this problem I am going to go back to the V1 transformer method of creating many-to-many connections (i.e. defining my own join tables).

@chrisbonifacio chrisbonifacio added to-be-reproduced and removed pending-triage Issues that need further discussion to determine labels Aug 8, 2022
@titiloxx
Copy link

Can I work on this?

@dpilch dpilch transferred this issue from aws-amplify/amplify-js Aug 15, 2022
@RikiZimbakov
Copy link

Any update here? I also face a similar problem!

@alharris-at alharris-at added bug Something isn't working p2 labels Mar 21, 2023
@olliethedev
Copy link
Contributor

olliethedev commented Oct 20, 2023

Same issue here!

Here is my graqhQL schema:

type Post @model @auth(rules: [
  { allow: groups, groups: ["Admins"] },
  { allow: public, operations: [read] }
  ]){
  slug: ID! @primaryKey
  title: String!
  description: String!
  content: String!
  image: String!
  published: Boolean!
  tags: [Tag] @manyToMany(relationName: "PostTag")
}

type Tag @model  @auth(rules: [
  { allow: groups, groups: ["Admins"] },
  { allow: public, operations: [read] }
  ]){
  name: ID! @primaryKey
  posts: [Post] @manyToMany(relationName: "PostTag")
}

The generated code in the /model/schema.js relational table looks like this:

"PostTag": {
            "name": "PostTag",
            "fields": {
                "id": {
                    "name": "id",
                    "isArray": false,
                    "type": "ID",
                    "isRequired": true,
                    "attributes": []
                },
                "postSlug": {
                    "name": "postSlug",
                    "isArray": false,
                    "type": "ID",
                    "isRequired": false,
                    "attributes": []
                },
                "tagName": {
                    "name": "tagName",
                    "isArray": false,
                    "type": "ID",
                    "isRequired": false,
                    "attributes": []
                },
                "post": {
                    "name": "post",
                    "isArray": false,
                    "type": {
                        "model": "Post"
                    },
                    "isRequired": true,
                    "attributes": [],
                    "association": {
                        "connectionType": "BELONGS_TO",
                        "targetNames": [
                            "postSlug"
                        ]
                    }
                },
                "tag": {
                    "name": "tag",
                    "isArray": false,
                    "type": {
                        "model": "Tag"
                    },
                    "isRequired": true,
                    "attributes": [],
                    "association": {
                        "connectionType": "BELONGS_TO",
                        "targetNames": [
                            "tagName"
                        ]
                    }
                },
                "createdAt": {
                    "name": "createdAt",
                    "isArray": false,
                    "type": "AWSDateTime",
                    "isRequired": false,
                    "attributes": [],
                    "isReadOnly": true
                },
                "updatedAt": {
                    "name": "updatedAt",
                    "isArray": false,
                    "type": "AWSDateTime",
                    "isRequired": false,
                    "attributes": [],
                    "isReadOnly": true
                }
            },
            "syncable": true,
            "pluralName": "PostTags",
            "attributes": [
                {
                    "type": "model",
                    "properties": {}
                },
                {
                    "type": "key",
                    "properties": {
                        "name": "byPost",
                        "fields": [
                            "postSlug"
                        ]
                    }
                },
                {
                    "type": "key",
                    "properties": {
                        "name": "byTag",
                        "fields": [
                            "tagName"
                        ]
                    }
                }
            ]
        }
    }

As you can see its missing an Auth attribute.

To fix the issue I just added the same auth attribute from the Post (or Tag) model. Its a temporary solution since next codegen will probably override the changes.

    {
                    "type": "auth",
                    "properties": {
                        "rules": [
                            {
                                "groupClaim": "cognito:groups",
                                "provider": "userPools",
                                "allow": "groups",
                                "groups": [
                                    "Admins"
                                ],
                                "operations": [
                                    "create",
                                    "update",
                                    "delete",
                                    "read"
                                ]
                            },
                            {
                                "allow": "public",
                                "operations": [
                                    "read"
                                ]
                            }
                        ]
                    }
                }

Hopefully this helps anyone who is stuck with many-to-many Datastore unauthorized error!

This seems like a simple issue to solve for anyone who might want to give it a shot over a weekend. This line here is probably a good place to start.

@olliethedev olliethedev mentioned this issue Oct 20, 2023
3 tasks
@dpilch dpilch closed this as completed Feb 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

10 participants