amplify-category-api icon indicating copy to clipboard operation
amplify-category-api copied to clipboard

Relation ship when authorization is owner cannot access a parent upon creation

Open ipodishima opened this issue 1 year ago • 10 comments

How did you install the Amplify CLI?

npx

If applicable, what version of Node.js are you using?

v20.6.1

Amplify CLI Version

npx ampx --version 1.2.5

What operating system are you using?

Mac

Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes made.

No

Describe the bug

I took the example given in the documentation and just changed the authorization to owner

const schema = a.schema({
  Member: a.model({
    name: a.string().required(),
    // 1. Create a reference field
    teamId: a.id(),
    // 2. Create a belongsTo relationship with the reference field
    team: a.belongsTo('Team', 'teamId'),
  })
  .authorization(allow => [allow.owner()]),

  Team: a.model({
    mantra: a.string().required(),
    // 3. Create a hasMany relationship with the reference field
    //    from the `Member`s model.
    members: a.hasMany('Member', 'teamId'),
  })
  .authorization(allow => [allow.owner()])
});

I can run a mutation for creating a team with success.

mutation CreateTestTeam {
  createTeam(input: {mantra: "Test"}) {
    id
  }
}

But when I run this mutation

mutation CreateJohn {
  createMember(input: {name: "John", teamId: "c0da8ec0-5fe9-4125-b62c-1b0dbcb4a557"}) {
    id
    name
    team {
      id
      mantra
    }
  }
}

This is what I get

{
  "data": {
    "createMember": {
      "id": "16827537-b102-40f5-83e9-252a65872cda",
      "name": "John",
      "team": null
    }
  },
  "errors": [
    {
      "path": [
        "createMember",
        "team",
        "id"
      ],
      "locations": null,
      "message": "Cannot return null for non-nullable type: 'ID' within parent 'Team' (/createMember/team/id)"
    },
    {
      "path": [
        "createMember",
        "team",
        "mantra"
      ],
      "locations": null,
      "message": "Cannot return null for non-nullable type: 'String' within parent 'Team' (/createMember/team/mantra)"
    }
  ]
}

Note: Running the query just after

query GetTeam {
  getTeam(id: "c0da8ec0-5fe9-4125-b62c-1b0dbcb4a557") {
    id
    mantra
    members {
      items {
        id
        name
      }
    }
  }
}

works (aka John was created, but the response had an error)

{
  "data": {
    "getTeam": {
      "id": "c0da8ec0-5fe9-4125-b62c-1b0dbcb4a557",
      "mantra": "Test",
      "members": {
        "items": [
          {
            "id": "16827537-b102-40f5-83e9-252a65872cda",
            "name": "John"
          }
        ]
      }
    }
  }
}

Also, when I run

query GetJohn {
  getMember(id: "16827537-b102-40f5-83e9-252a65872cda") {
    id
    name
    team {
      id
      mantra
    }
  }
}

There are no issues

{
  "data": {
    "getMember": {
      "id": "16827537-b102-40f5-83e9-252a65872cda",
      "name": "John",
      "team": {
        "id": "c0da8ec0-5fe9-4125-b62c-1b0dbcb4a557",
        "mantra": "Test"
      }
    }
  }
}

Expected behavior

When using allow.authenticated() I do not have this issue. I expect the same behavior when auth is owner()

Reproduction steps

Simply creating a new model with team and member like in the documentation, but with owner for the auth for both team and member

Project Identifier

No response

Log output

# Put your logs below this line


Additional information

No response

Before submitting, please confirm:

  • [X] I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
  • [X] I have removed any sensitive information from my code snippets and submission.

ipodishima avatar Sep 10 '24 08:09 ipodishima

Hey,👋 thanks for raising this! I'm going to transfer this over to our API repository for better assistance 🙂

ykethan avatar Sep 10 '24 14:09 ykethan

Perfect thanks

I’m just seeing this in the documentation

IMG_6949

maybe it’s kinda related

ipodishima avatar Sep 10 '24 16:09 ipodishima

Hey @ipodishima, Thanks for raising this. As mentioned in the documentation, you need to query the relation data separately.

AnilMaktala avatar Sep 10 '24 18:09 AnilMaktala

Ok @AnilMaktala It’s a bit weird though, because the documentation is not really clear about this nor does it specify how you can create a member in this case. By default, the mutation query to create a member tries to return the team. So maybe that it shouldn’t be the case somehow?

ipodishima avatar Sep 10 '24 18:09 ipodishima

Hey @ipodishima, Are you using subscriptions in your app? If not, you can disable them to resolve this issue.

AnilMaktala avatar Sep 11 '24 18:09 AnilMaktala

Hey @AnilMaktala no I'm not using subscriptions. I mean now yes, but not when I opened the bug. My workaround for now is to not have relation ships. I just store the parent ID and fetches all objects with a specific parent ID

ipodishima avatar Sep 12 '24 07:09 ipodishima

@AnilMaktala I am also running into this issue. I'm not using subscriptions either. Interestingly creating my object with nil for all the relationships it has in the appSync console works, I just get the following error in in my frontend:

message	String	"Cannot return null for non-nullable type: \'ID\' within parent \'MyParentModel\' (/createMyParentModel/myRelationField/id)"

Are there any updates here?

Edit:

Some context: This query to create a model in the AppSync console works:

mutation MyMutation {
  createMyModel(input: {}) {
    id
    myRelationId
  }
}

However, in my iOS app,

        let newModel = MyModel()
        let result = try await Amplify.API.mutate(
            request: .create(newModel, authMode: .amazonCognitoUserPools)
        )
        switch result {
        case .success(let amplifyResponseModel):
            // ...
        case .failure(let error):
            print("Failed to create in cloud \(error)")
            throw error
        }

shows the error I described.

concavegit avatar Sep 29 '24 00:09 concavegit

My workaround is to grab the returned MyModel from the partial in the result.

concavegit avatar Sep 29 '24 23:09 concavegit

Hey @ipodishima and @concavegit, Our team will work on modifying the default mutation logic in the codegen to eliminate the inclusion of child models.

AnilMaktala avatar Sep 30 '24 18:09 AnilMaktala

Hi there, is there something happening with this issue? It's very inconvenient when a successful create or update returns this error and requires doing an additional query. 🧐

marcoboerner avatar Mar 23 '25 11:03 marcoboerner

My workaround is to grab the returned MyModel from the partial in the result.

I've been using the same workaround, but encountered issues when trying to update the same model again. The model in the partial result, as it says in the error, does not contain the ID field of the parent. If you then modify this child model, the relation to the parent gets lost! This caused me a big headache. I now have to catch the specific error, ignore the partial result, and instead fetch the model again.

@AnilMaktala it's been a while, just want to tag you and ask if there is any progress with this?

marcoboerner avatar Mar 28 '25 09:03 marcoboerner

It would be nice if the error messages were more descriptive here.

chrisl777 avatar Jul 18 '25 20:07 chrisl777