aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.43k stars 2.13k forks source link

DataStore does not sync join tables for guest users #10636

Closed duranmla closed 1 year ago

duranmla commented 2 years ago

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

DataStore

Amplify Categories

api

Environment information

``` System: OS: macOS 13.0 CPU: (8) arm64 Apple M1 Memory: 128.09 MB / 16.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 16.16.0 - ~/.nvm/versions/node/v16.16.0/bin/node Yarn: 1.22.19 - ~/.nvm/versions/node/v16.16.0/bin/yarn npm: 8.15.1 - ~/.nvm/versions/node/v16.16.0/bin/npm Browsers: Chrome: 107.0.5304.87 Firefox: 106.0.5 Safari: 16.1 npmPackages: @aws-crypto/sha256-js: ^2.0.1 => 2.0.1 (1.0.0-alpha.0, 1.2.2, 2.0.0) @commitlint/cli: ^17.0.3 => 17.0.3 @commitlint/config-conventional: ^17.0.3 => 17.0.3 @craco/craco: ^6.4.5 => 6.4.5 @cypress/mount-utils: 0.0.0-development @cypress/react: 0.0.0-development @cypress/react18: 0.0.0-development @cypress/vue: 0.0.0-development @cypress/vue2: 0.0.0-development @jackfranklin/test-data-bot: ^2.0.0 => 2.0.0 @react-theming/storybook-addon: ^1.1.7 => 1.1.7 @reduxjs/toolkit: ^1.8.3 => 1.8.3 @reduxjs/toolkit-query: 1.0.0 @reduxjs/toolkit-query-react: 1.0.0 @sentry/react: ^7.8.1 => 7.8.1 @sentry/tracing: ^7.8.1 => 7.8.1 @sentry/webpack-plugin: ^1.19.0 => 1.19.0 @storybook/addon-essentials: ^6.5.9 => 6.5.9 @storybook/addon-links: ^6.5.9 => 6.5.9 @storybook/addons: ^6.5.9 => 6.5.9 @storybook/builder-webpack5: ^6.5.9 => 6.5.9 @storybook/manager-webpack5: ^6.5.9 => 6.5.9 @storybook/preset-create-react-app: ^4.1.2 => 4.1.2 @storybook/react: ^6.5.9 => 6.5.9 @storybook/theming: ^6.5.9 => 6.5.9 @svgr/plugin-prettier: 5.5.0 => 5.5.0 @testing-library/cypress: ^8.0.3 => 8.0.3 @testing-library/dom: ^8.16.0 => 8.16.0 @testing-library/jest-dom: ^5.16.4 => 5.16.4 @testing-library/react: ^13.3.0 => 13.3.0 @testing-library/user-event: ^14.4.1 => 14.4.1 @types/draft-js: ^0.11.9 => 0.11.9 @types/draftjs-to-html: ^0.8.1 => 0.8.1 @types/html-to-draftjs: ^1.4.0 => 1.4.0 @types/jest: ^28.1.6 => 28.1.6 @types/lodash: ^4.14.182 => 4.14.182 @types/mixpanel-browser: ^2.38.0 => 2.38.0 @types/node: ^18.6.3 => 18.6.3 (14.18.29, 16.11.46, 14.18.22) @types/react: ^18.0.15 => 18.0.15 @types/react-dom: ^18.0.6 => 18.0.6 @types/react-draft-wysiwyg: ^1.13.4 => 1.13.4 @types/react-html-parser: ^2.0.2 => 2.0.2 @types/react-redux: ^7.1.24 => 7.1.24 @types/react-router-dom: ^5.3.3 => 5.3.3 @types/react-slider: ^1.3.1 => 1.3.1 @types/redux-logger: ^3.0.9 => 3.0.9 @types/styled-components: ^5.1.25 => 5.1.25 @types/styled-system: ^5.1.15 => 5.1.15 @types/styled-system__css: ^5.0.17 => 5.0.17 @types/three: ^0.143.0 => 0.143.0 aws-amplify: ^4.3.30 => 4.3.30 aws-sdk: ^2.1187.0 => 2.1187.0 babel-plugin-styled-components: ^2.0.7 => 2.0.7 base64-js: ^1.5.1 => 1.5.1 cypress: ^10.4.0 => 10.4.0 cz-conventional-changelog: 3.3.0 => 3.3.0 dayjs: ^1.11.5 => 1.11.5 (1.11.4) easymde: ^2.18.0 => 2.18.0 eslint-config-prettier: ^8.5.0 => 8.5.0 eslint-plugin-cypress: ^2.12.1 => 2.12.1 eslint-plugin-prettier: ^4.2.1 => 4.2.1 formik: ^2.2.9 => 2.2.9 framer-motion: ^6.5.1 => 6.5.1 history: ^5.3.0 => 5.3.0 husky: ^8.0.1 => 8.0.1 lodash: ^4.17.21 => 4.17.21 mixpanel-browser: ^2.45.0 => 2.45.0 polished: ^4.2.2 => 4.2.2 postcss-normalize: ^10.0.1 => 10.0.1 prettier: ^2.7.1 => 2.7.1 (2.3.0) pretty-quick: ^3.1.3 => 3.1.3 react: ^18.2.0 => 18.2.0 react-accessible-dropdown-menu-hook: ^3.2.0 => 3.2.0 react-country-region-selector: ^3.6.1 => 3.6.1 react-dom: ^18.2.0 => 18.2.0 react-feather: ^2.0.10 => 2.0.10 react-feature-flags: ^1.0.0 => 1.0.0 react-graceful-image: ^1.5.0 => 1.5.0 react-helmet-async: ^1.3.0 => 1.3.0 react-hot-toast: ^2.3.0 => 2.3.0 react-html-parser: ^2.0.2 => 2.0.2 react-html-parser-demo: 0.0.0 react-loader-spinner: ^5.3.4 => 5.3.4 react-markdown: ^8.0.3 => 8.0.3 react-redux: ^8.0.2 => 8.0.2 react-router-dom: ^6.3.0 => 6.3.0 react-scripts: ^5.0.1 => 5.0.1 react-select: ^5.4.0 => 5.4.0 react-simplemde-editor: ^5.2.0 => 5.2.0 react-snap: ^1.23.0 => 1.23.0 redux-persist: ^6.0.0 => 6.0.0 redux-persist/integration/react: undefined () remark-gfm: ^3.0.1 => 3.0.1 sendbird-uikit: ^2.7.2 => 2.7.2 styled-components: ^5.3.5 => 5.3.5 styled-components/macro: undefined () styled-components/native: undefined () styled-components/primitives: undefined () styled-system: ^5.1.5 => 5.1.5 ts-morph: ^15.1.0 => 15.1.0 typescript: ^4.7.4 => 4.7.4 wait-on: ^6.0.1 => 6.0.1 web-vitals: ^2.1.4 => 2.1.4 webpack: 5 => 5.74.0 (4.46.0) npmGlobalPackages: @aws-amplify/cli: 10.3.0 @svgr/plugin-prettier: 6.3.1 commitizen: 4.2.5 corepack: 0.10.0 npm: 8.15.1 yarn: 1.22.19 ```

Describe the bug

When using the application from Incognito (empty local storage, simulate first time users) my join tables are not being sync as the sync requests are not being triggered (join tables are being created automatically using @manyToMany directive in my schema)

Once I login my user then I can see the sync requests being there.

Expected behavior

Sync requests to join table should always be trigger for guest and logged in users

Reproduction steps

  1. Create a project
  2. Create a relation manyToMany between two models
  3. Allow public access to both models
  4. Add one entry to each models and relate them
  5. Go incognito with application data empty
    • Request the join table using DataStore (retrieve empty)
    • Request the join table using AppSync (retrieve with data)

Code Snippet

The case of study is with Project model and their connected models, here I show you the Project model with Tag model, other relations follow the same pattern

type Project
  @model
  @auth(
    rules: [
      { allow: private }
      { allow: public, operations: [read], provider: apiKey }
    ]
  ) {
  id: ID!
  name: String!
  description: String!
  location: String!
  problem: String!
  solution: String!
  mediaHTML: String!
  image: String!
  launchPlan: String!
  status: ProjectStatus! @default(value: "DRAFT")
  tags: [Tag] @manyToMany(relationName: "ProjectTagConnection")
  organisers: [Organiser] @manyToMany(relationName: "ProjectOrganiserConnection")
  participants: [Participant]
    @manyToMany(relationName: "ProjectParticipantConnection")
  posts: [Post] @hasMany(indexName: "byProject", fields: ["id"])
}

type Tag
  @model
  @auth(
    rules: [
      { allow: private }
      # This allow lambda to make CRUD operations
      { allow: private, provider: iam }
      { allow: public, operations: [read], provider: apiKey }
    ]
  ) {
  id: ID!
  name: String!
  image: String!
  projects: [Project] @manyToMany(relationName: "ProjectTagConnection")
  # Tag with lower number will be shown first
  priority: Int @default(value: "1000")
}

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

https://www.loom.com/share/d4edda89883348ae826727796a6b8c24

Perhaps I am missing something and it is just a configuration thing. I am using Amplify CLI v10.2.3 in my CI due to https://github.com/aws-amplify/amplify-cli/issues/9508 and https://github.com/aws-amplify/amplify-js/discussions/10600

chrisbonifacio commented 1 year ago

Hey @duranmla when trying to sync as a guest user, are you seeing any errors in the console?

Also, can you share how you're configuring Amplify and/or DataStore?

Lastly, if you use the Hub utility listener, can you confirm if the ready event is being emitted by DataStore?

For info on the Hub listener: https://docs.amplify.aws/lib/utilities/hub/q/platform/js/

duranmla commented 1 year ago

👋 Hello @chrisbonifacio

My configuration looks like:

private setupAmplify(config: Object) {
    // Allow to connect application with AWS Amplify
    Amplify.configure({
      ...awsconfig,
      // https://docs.amplify.aws/lib/datastore/setup-auth-rules/q/platform/js/#configure-multiple-authorization-types
      DataStore: {
        authModeStrategyType: AuthModeStrategyType.MULTI_AUTH,
        errorHandler: (error: any) => {
          logger.debug('Unrecoverable error', error)
        },
      },
    })
  }

I have a class that then I call in the root of my application as below:

useEffect(() => {
    api
      .init()
      .then((synced) => {
        setReady(synced)
      })
      .catch((err) => {
        setError(err)
      })
  }, [api])

Full code of the class can be seeing at https://gist.github.com/duranmla/98e258a1fcb675984341bc54dd853ecf

Also, I can say that the 'ready' has been emitted cause I wait for that event before rendering the application. I actually suffer from another issue which is https://github.com/aws-amplify/amplify-js/issues/5963 but that's another subject completely different.

duranmla commented 1 year ago

Also, in my case this issue was hidden because once you use the app as a logged user the data is on the indexdb so it was available for DataStore, but when I enter to the app with incognito window with everything empty, the sync does not happen and DataStore resolves empty for join tables.

Today, it happens the same with another relation and the solution will be the same, using AppSync query instead

chrisbonifacio commented 1 year ago

I was able to reproduce this behavior with the reproduction steps given. Labeling as a bug for the team to investigate further.

dpilch commented 1 year ago

I wasn't able to reproduce this with the latest version (5.0.15). It appears this issue was fixed accidentally with the release of v5. It is unlikely that we will be backporting a fix to v4. Please comment if you are still experiencing this issue on v5.