2

Using Cognito user pools as my auth method, I am able to login verified users through the app and then those authenticated users can write to DynamoDB with an AppSync mutation just fine. The S3Object info is also populated in Dynamo as a JSON string like so:

"pdf": "{\"s3\":{\"key\":\"6_A_2018-04-26_etc.pdf\",\"bucket\":\"#####\",\"region\":\"us-west-2\"}}"

The request mapping template for the create mutation in AppSync is:

{
"version" : "2017-02-28",
"operation" : "PutItem",
"key" : {
    "id" : { "S" : "${util.autoId()}" }
},
#set( $attribs = $util.dynamodb.toMapValues($ctx.args.input) )
#if($util.isNull($ctx.args.input.pdf.version))
    #set( $attribs.pdf = $util.dynamodb.toS3Object($ctx.args.input.pdf.key, $ctx.args.input.pdf.bucket, $ctx.args.input.pdf.region))
#else
    #set( $attribs.pdf = $util.dynamodb.toS3Object($ctx.args.input.pdf.key, $ctx.args.input.pdf.bucket, $ctx.args.input.pdf.region, $ctx.args.input.pdf.version))
#end
"attributeValues" : $util.toJson($attribs)
}

Response mapping template:

$util.toJson($ctx.result)

pdf (S3Object) request mapping template (I've tried both the version and empty payload {} None resolver and this one):

{
  "version" : "2017-02-28",
  "operation" : "Query",
  "query" : {
      ## Provide a query expression. **
      "expression": "id = :id",
      "expressionValues" : {
          ":id" : {
              "S" : "${ctx.args.id}"
          }
      }
  }
}

Response mapping template for pdf:

$util.toJson($util.dynamodb.fromS3ObjectJson($context.source.pdf))

But NO S3 OBJECT is created in the bucket. However, if I use S3TransferUtility.default() on its own to send the upload request, it works perfectly fine, so I must have the correct permissions set for PutObject (also GetObject and ListObjects as I can also list / download objects from the bucket with s3TransferUtility).

Since AppSync is supposed to be using S3TransferUtility.default(), does anyone have any ideas for why the upload is not happening automatically? My view controller is dismissed afterwards, like in the tutorials, but that shouldn't be a problem because I am using the optimistic response method and it is not throwing any errors. I also tried simply using the perform mutation function without the optimistic response. Also I've tried NOT dismissing the view controller and waiting. Still no upload to S3, but the write to Dynamo never fails! Even optimistically updates to Dynamo when I return from airplane mode. File size for PDF doc is ~250KB.

By the way, the following also does work after pulling in my items from Dynamo using a graphql listAll query and only after uploading to S3 manually so it's actually in the bucket (I'm missing some optional chaining I am at work this part is from memory):

let s3Object = S3Object.init(snapshot: selectedItem.pdf.snapshot)
appSyncClient.s3ObjectManager.download(s3Object: s3Object, toURL: url) { ifSuccess, error in
})

Something like that. It does download the object, but it's because I called it manually. To be fair, I'm actually not sure what the intended functionality of a retrieved S3Object from a graphql query is (is it supposed to download it automatically...? Do I have access to that item as anything other than a AllPostsQuery.Data.ListPost.Item.Pdf or are we meant to download ourselves using the bucket, key, region as I have?) That's off topic, I suppose.

Any help would be much appreciated I'm really banging my head against the wall on this one.

EDIT: More / updated info here on the AWS Forums

EDIT: GitHub issue has elicited a response from AWS and they are looking into it

End3r117
  • 57
  • 1
  • 9
  • Have you considered using the IAM auth method for AppSync instead of user pools? You're going to have to either explicitly specify AWS credentials or fetch them via a Cognito Federated Identity associated with your user pool in the AppSync configuration to support S3 uploads anyway - might as well use the same credentials for IAM auth for AppSync at the same time. See my answer at https://stackoverflow.com/a/50244675/302804, in particular the part at the bottom regarding AWS credentials and AppSync. – hatboyzero May 13 '18 at 15:31
  • Yes I have tried both auth methods and both work perfectly fine except for the S3 automatic upload. AWS has replied to my GitHub issue post and are looking into it: https://github.com/awslabs/aws-mobile-appsync-sdk-ios/issues/25 – End3r117 May 21 '18 at 01:35
  • Hi Could you follow the latest instructions posted here: https://awslabs.github.io/aws-mobile-appsync-sdk-ios/#complex-objects It will walk through both the backend setup as well as client setup. – Rohan Dubal Jul 02 '18 at 02:42
  • Well, this is from a while ago. I'll just post what I have in case it is helpful. The generation of graphql results in encapsulation of input parameters. Neither iOS or Android will work if that is the case, has to be one of the input parameters like graphqlCall( file : S3ObjectInput). I've verified it in Android. Not sure it is an issue in web. – Bruce Jan 28 '19 at 19:51

0 Answers0