Amplify-cli: Dynamic runtime subscription support

Created on 11 Mar 2019  路  8Comments  路  Source: aws-amplify/amplify-cli

I need some help here.
The APIService generated by codegen has generated this function.

SubscribeToNewMessageListener: Observable<SubscribeToNewMessageSubscription> = API.graphql(
    graphqlOperation(
      `subscription SubscribeToNewMessage($conversationId: ID!) {
        subscribeToNewMessage(conversationId: $conversationId) {
          __typename
          author {
            __typename
            cognitoId
            id
            username
            registered
          }
          content
          conversationId
          createdAt
          id
          isSent
          recipient {
            __typename
            cognitoId
            id
            username
            registered
          }
          sender
        }
      }`
    )
  ) as Observable<SubscribeToNewMessageSubscription>;

I'm trying to call this listener from an angular page but I can not pass the parameter to the function
always get "Variable 'conversationId' has coerced Null value for NonNull type 'ID!'".
I have tried in all ways but I can not send it.

This is more or less my code.

constructor(
        private api: APIService
    ) {}

    ngOnInit() {
        this.api.SubscribeToNewMessageListener
        .map(msg => msg.conversationId = 'randomGUID')
        .subscribe({
            next: (x) => {console.log('Next',x)},
            error: (e) => {console.log('Error', e)},
            complete: () => {}
        })
    }

Another subscription without parameters, however, it works for me simply by subscribing to it.

Please need help.
Thanks you.

code-gen enhancement pending-review

Most helpful comment

@yuth If I'm subscribed to onCreateSomething and something gets created, I get an event to all my clients, whether I am authorized to see the data or not. It seems that this is the expected behavior. If so it's a big hole. This should be prioritized as a critical bug I would say because the default subscriptions compromise data privacy.

Btw - my auth flow is pretty complicated. I override the claims pre token generation and I assign the permissions there and then. After that, users are supposed to see what they're supposed to see only.

The same auth rules that apply to read should apply to subscriptions.

https://github.com/aws-amplify/amplify-cli/issues/1766

All 8 comments

Hey @RidClick,

Can you include the version of aws-amplify you are using?

Actually this seems related to the Amplify CLI codegen. I will pass this back to the CLI repo.

Hey @RidClick,

Can you include the version of aws-amplify you are using?

I am using the latest versions of npm aws
"aws-amplify": "^1.1.22",
"aws-amplify-angular": "^2.1.9"
and global aws-amplify/cli 1.1.7

But I did not think it was an error in the generation of the code, I think my problem is that I do not know how to use it, because I understand how to pass the parameter to an observable, since for it to work, I must pass to the listener the coversationId.

As I said, other listeners without parameters if they work like ...

APIService.ts

SubscribeToNewUsersListener: Observable<SubscribeToNewUsersSubscription> = API.graphql(
    graphqlOperation(
      `subscription SubscribeToNewUsers {
        subscribeToNewUsers {
          __typename
          id
          cognitoId
          username
          registered
          conversations {
            userConversations {
              conversationId
            }
          }
        }
      }`
    )
  ) as Observable<SubscribeToNewUsersSubscription>;

Angular page...

ngOninit() {
       this.subscription = this.api.SubscribeToNewUsersListener.subscribe({
            next(x) { console.log('next',x) },
            error(err) { console.log(`Finished with error: ${ err }`) },
            complete() { console.log('Finished') }
        });
}

This listener, when I create a new user, returns me in the next statement the new user created,
since the subscription does not receive any parameters.

@RidClick Thank you for reporting this. Codegen doesn't have the support to pass arguments to subscription yet. We will add this to our backlog and get it prioritized.

I am having this exact problem with subscriptions - any updates on this?

I am having this exact problem with subscriptions - any updates on this?

I found a momentary solution that I hope will work for you. You must modify your API.service and try that the subscription functions have more or less this structure.

  SubscribeToNewMessageListener(conversationId: string): Observable<SubscribeToNewMessageSubscription> {
    const statement = `subscription SubscribeToNewMessage($conversationId: ID!) {
      subscribeToNewMessage(conversationId: $conversationId) {
        __typename
        id
        content
        isSent
        conversationId
        createdAt
        sender
      }
    }`;
    const gqlAPIServiceArguments: any = {
      conversationId
    };
    return (API.graphql(
      graphqlOperation(statement, gqlAPIServiceArguments)
    )) as Observable<SubscribeToNewMessageSubscription>;
  }

And then on the ngOnInit of your page, you would call it that way, the .map is necessary because if you do not filter the subscription it is called multiple times when you receive a new message,
newMessageId is a global var but can be local, is another filter for the multiple callings.

    this.api.SubscribeToNewMessageListener(this.conversationId)
    .map((response:any) => {
         let message = response.value.data.subscribeToNewMessage;
         return message;
    })
    .subscribe(message => {
        console.log('subscription', message)
            if(message != null && this.newMessageId != message.id) {
                this.newMessageId = message.id;
                this.messages.push(message);
                this.scrollBottom(100);
            }
    })

Hey @yuth,

As the solution given by @RidClick isn't compliant with CI/CD and multiple branches/environments workflow, do we have any update on this point?

@yuth If I'm subscribed to onCreateSomething and something gets created, I get an event to all my clients, whether I am authorized to see the data or not. It seems that this is the expected behavior. If so it's a big hole. This should be prioritized as a critical bug I would say because the default subscriptions compromise data privacy.

Btw - my auth flow is pretty complicated. I override the claims pre token generation and I assign the permissions there and then. After that, users are supposed to see what they're supposed to see only.

The same auth rules that apply to read should apply to subscriptions.

https://github.com/aws-amplify/amplify-cli/issues/1766

Was this page helpful?
0 / 5 - 0 ratings