Skip to content

Datastore: Support Multi-user data access #3388

Open
@dgagnon

Description

@dgagnon

Description

By following the Getting started instructions and setting up the datastore Cloud Feature at this page: https://docs.amplify.aws/lib/datastore/sync/q/platform/flutter/#setup-cloud-sync

We can read this line: "DataStore's cloud synchronization uses the API category behind the scenes. Therefore, the first step is to add the API plugin."

This leads people to believing that they can use the documentation at the linked page.

In the same manner, the Setup authorization rules page (at https://docs.amplify.aws/lib/datastore/setup-auth-rules/q/platform/flutter/ ) refers a few times to the AppSync cli page (at https://docs.amplify.aws/cli/graphql/authorization-rules/#per-user--owner-based-data-access ).

On this page, a section is name "Multi-user data access". I can attest that the code in this section will not work with Datastore, I suspect due to the limitation on subscription and multi-owner models.

I tried all possible configuration (transformer v1, removing multi auth, experimental pipeline, other feature flags, as a single model, etc) and all tests were done with an empty datastore. After working 3 days on this, I am convinced there is no way to have this working in a native way.

Having a documentation that is representative of the available feature is of paramount importance to us.

Note: While this could be framed as a bug in the datastore/appsync plugins for this specific example, this is a recurring theme with these two plugins. See #1566 (comment) for technical details.

Categories

  • Analytics
  • API (REST)
  • API (GraphQL)
  • Auth
  • Authenticator
  • DataStore
  • Notifications (Push)
  • Storage

Steps to Reproduce

  1. Follow the getting started instructions and create a new project
  2. Add auth (default settings without social + iam as secondary auth)
  3. Add api and datastore as per the documentation
  4. Add a multi-owner model
  5. Try to start the app.

Screenshots

Relevant Logs:

[  +45 ms] E/amplify:aws-datastore( 6140): Failure encountered while attempting to start API sync.
[        ] E/amplify:aws-datastore( 6140): DataStoreException{message=DataStore subscriptionProcessor failed to start., cause=GraphQLResponseException{message=Subscription error for Task: [GraphQLResponse.Error{message='Validation error of type UnknownArgument: Unknown field argument authors @ 'onCreateTask'', locations='null', path='null', extensions='null'}], errors=[GraphQLResponse.Error{message='Validation error of type UnknownArgument: Unknown field argument authors @ 'onCreateTask'', locations='null', path='null', extensions='null'}], recoverySuggestion=See attached list of GraphQLResponse.Error objects.}, recoverySuggestion=Check your internet.}
[        ] E/amplify:aws-datastore( 6140): 	at com.amplifyframework.datastore.syncengine.Orchestrator.lambda$startApiSync$3$com-amplifyframework-datastore-syncengine-Orchestrator(Orchestrator.java:306)
[        ] E/amplify:aws-datastore( 6140): 	at com.amplifyframework.datastore.syncengine.Orchestrator$$ExternalSyntheticLambda6.subscribe(Unknown Source:2)
[        ] E/amplify:aws-datastore( 6140): 	at io.reactivex.rxjava3.internal.operators.completable.CompletableCreate.subscribeActual(CompletableCreate.java:40)
[        ] E/amplify:aws-datastore( 6140): 	at io.reactivex.rxjava3.core.Completable.subscribe(Completable.java:2850)
[        ] E/amplify:aws-datastore( 6140): 	at io.reactivex.rxjava3.internal.operators.completable.CompletablePeek.subscribeActual(CompletablePeek.java:51)
[        ] E/amplify:aws-datastore( 6140): 	at io.reactivex.rxjava3.core.Completable.subscribe(Completable.java:2850)
[        ] E/amplify:aws-datastore( 6140): 	at io.reactivex.rxjava3.internal.operators.completable.CompletablePeek.subscribeActual(CompletablePeek.java:51)
[        ] E/amplify:aws-datastore( 6140): 	at io.reactivex.rxjava3.core.Completable.subscribe(Completable.java:2850)
[        ] E/amplify:aws-datastore( 6140): 	at io.reactivex.rxjava3.internal.operators.completable.CompletablePeek.subscribeActual(CompletablePeek.java:51)
[        ] E/amplify:aws-datastore( 6140): 	at io.reactivex.rxjava3.core.Completable.subscribe(Completable.java:2850)
[        ] E/amplify:aws-datastore( 6140): 	at io.reactivex.rxjava3.internal.operators.completable.CompletableSubscribeOn$SubscribeOnObserver.run(CompletableSubscribeOn.java:64)
[        ] E/amplify:aws-datastore( 6140): 	at io.reactivex.rxjava3.core.Scheduler$DisposeTask.run(Scheduler.java:614)
[        ] E/amplify:aws-datastore( 6140): 	at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:65)
[        ] E/amplify:aws-datastore( 6140): 	at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:56)
[        ] E/amplify:aws-datastore( 6140): 	at java.util.concurrent.FutureTask.run(FutureTask.java:264)
[        ] E/amplify:aws-datastore( 6140): 	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:307)
[        ] E/amplify:aws-datastore( 6140): 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
[        ] E/amplify:aws-datastore( 6140): 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
[        ] E/amplify:aws-datastore( 6140): 	at java.lang.Thread.run(Thread.java:1012)
[        ] E/amplify:aws-datastore( 6140): Caused by: GraphQLResponseException{message=Subscription error for Task: [GraphQLResponse.Error{message='Validation error of type UnknownArgument: Unknown field argument authors @ 'onCreateTask'', locations='null', path='null', extensions='null'}], errors=[GraphQLResponse.Error{message='Validation error of type UnknownArgument: Unknown field argument authors @ 'onCreateTask'', locations='null', path='null', extensions='null'}], recoverySuggestion=See attached list of GraphQLResponse.Error objects.}

Generated code:

input ModelSubscriptionTaskFilterInput {
  content: ModelSubscriptionStringInput
  and: [ModelSubscriptionTaskFilterInput]
  or: [ModelSubscriptionTaskFilterInput]
  _deleted: ModelBooleanInput
}

type Subscription {
  onCreateTask(filter: ModelSubscriptionTaskFilterInput): Task @aws_subscribe(mutations: ["createTask"]) @aws_iam @aws_cognito_user_pools
  onUpdateTask(filter: ModelSubscriptionTaskFilterInput): Task @aws_subscribe(mutations: ["updateTask"]) @aws_iam @aws_cognito_user_pools
  onDeleteTask(filter: ModelSubscriptionTaskFilterInput): Task @aws_subscribe(mutations: ["deleteTask"]) @aws_iam @aws_cognito_user_pools
}

Code to replicate:

  Future<void> configureAmplify() async {
    // Add any Amplify plugins you want to use
    final authPlugin = AmplifyAuthCognito();
    // await Amplify.addPlugin(authPlugin);

    // Add the following lines to your app initialization to add the DataStore plugin
    final datastorePlugin = AmplifyDataStore(
      modelProvider: ModelProvider.instance,
      // Be sure to add the authModeStrategy
      authModeStrategy: AuthModeStrategy.multiAuth,
    );
    // await Amplify.addPlugin(datastorePlugin);

    final api = AmplifyAPI();

    // You can use addPlugins if you are going to be adding multiple plugins
    await Amplify.addPlugins([authPlugin, api, datastorePlugin]);
    // await Amplify.addPlugins([authPlugin]);

    // Once Plugins are added, configure Amplify
    // Note: Amplify can only be configured once.
    try {
      await Amplify.configure(amplifyconfig);
    } on AmplifyAlreadyConfiguredException {
      safePrint("Tried to reconfigure Amplify; this can occur when your app restarts on Android.");
    }
  }

Platforms

  • iOS
  • Android
  • Web
  • macOS
  • Windows
  • Linux

Flutter Version

3.10.5

Amplify Flutter Version

1.2.0

Deployment Method

Amplify CLI

Schema

type Task @model @auth(rules: [{ allow: owner, ownerField: "authors" }]) {
    content: String
    authors: [String]
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    DocumentationImprovements or fixes to public documentation (docs.amplify.aws, pub.dev, readmes).datastoreIssues related to the DataStore Categoryfeature-requestA request for a new feature or an enhancement to an existing API or category.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions