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 Subscriptions by Argument #9413

Open cyim02 opened 2 years ago

cyim02 commented 2 years ago

Is this related to a new or existing framework?

React Native

Is this related to a new or existing API?

DataStore

Is this related to another service?

AppSync

Describe the feature you'd like to request

Was looking at Subscriptions by Argument used in Amplify API GraphQL (https://docs.amplify.aws/guides/api-graphql/subscriptions-by-id/q/platform/js/).

Didn't find a way to do it using DataStore, and the underlying observeQuery API (https://docs.amplify.aws/lib/datastore/real-time/q/platform/js/#observe-query-results-in-real-time).

type Comment @model {
  id: ID!
  content: String
  postCommentsId: ID!
}

type Subscription {
  onCommentByPostId(postCommentsId: ID!): Comment
    @aws_subscribe(mutations: ["createComment"])
}
import { API } from 'aws-amplify';
import { onCommentByPostId } from './graphql/subscriptions';

API.graphql({
  query: onCommentByPostId,
  variables: {
    postCommentsId: "12345"
  }
})
.subscribe({
  next: data => {
    console.log('data: ', data)
  }
})

Describe the solution you'd like

I am hoping to see if developers are able to send argument (such as user_id) to the subscription so I can have fine grained auth control for GraphQL subscription as mentioned in the Amplify API GraphQL (Subscription by id guide above).

and with AppSync Lambda Authorizer, I can do the following request mapping for subscription:

## [Start] Subscription Request template. **
#if(${ctx.identity.resolverContext.uid} == ${context.args.uid})
  $util.toJson({
    "version": "2018-05-29",
    "payload": {}
  })
#else
  $utils.unauthorized()
#end
## [End] Subscription Request template. **

Describe alternatives you've considered

I do consider predicates, but it does not apply to auth scenario at subscription https://docs.amplify.aws/lib/datastore/data-access/q/platform/js/#predicates

I also consider using the Amplify GraphQL API (Subscription by id guide), but then I will need to build my own datastore, which cannot leverage the Amplify DataStore.

I think if Amplify GraphQL API can do this, DataStore feature request should have a chance :)

Additional context

No response

Is this something that you'd be interested in working on?

civicevolution commented 2 years ago

I am trying to implement this now. At least for my case, it would be an easy modification to the buildSubscriptionGraphQLOperation function in @aws-amplify/datastore/lib-esm/sync/utils.js. But I cannot fork the aws-amplify code and just install my modified version of DataStore.

I will try to add an interceptor that can add arguments to the subscription requests to enabled Enhanced filtering on the back end.

D'oh, an HTTP interceptor cannot work because the subscriptions are made through websockets.

It would be ideal if there was a DataStore.configure option that would allow me to set the arguments and variables to be applied as each model's optional filter arguments.

Selective syncing was a critical improvement, but without enhanced filtering through DataStore, we're right back to the same limitations and challenges in a multi-tenant application.

civicevolution commented 2 years ago

Are there any instructions available for building a custom version of amplify DataStore from a fork of the official versions?

undefobj commented 2 years ago

This functionality wasn't possible until the recent release of Enhanced Filtering in AppSync: https://aws.amazon.com/about-aws/whats-new/2022/04/aws-appsync-enhanced-filtering-graphql-subscriptions/ Now that the service functionality has been released we have been integrating it into Amplify. It requires both client and changes to your backend GraphQL resolver logic to achieve this use case. The initial changes for resolver code in the GraphQL Transform will be released in the coming weeks as part of the CLI release cycles. After that the library changes will roll out. Please stay tuned to the Amplify release cycles via AWS Blogs and CHANGELOG for more information.

civicevolution commented 2 years ago

Thanks for the prompt update.

I build my backend with CDK and I already prototyped the changes I need on the backend.

I successfully tested the enhanced filtering in the AppSync query console. It is a great (critical) new feature. Thanks.

My last challenge is to modify the subscription requests generated by the DataStore utility function buildSubscriptionGraphQLOperation.

I have forked the amplify-js repo and I'm trying to understand how to build with my modified code and integrate the modified code into my app, I'm assuming through a custom npm package.

Again, are there any instructions available for building a custom version of amplify DataStore from a fork of the official versions?

Thanks