我可以在 AWS Amplify 的 Velocity 模板中获取用户电子邮件吗?

Can I get the user email within a Velocity template of AWS Amplify?

当我在我的 GraphQL API 中查询解析器时,我在其中添加了一个 $util.error($ctx) 到 return 上下文对象,我得到以下结果(删除了不必要的值)。

{
  "data": {
    "listXData": null
  },
  "errors": [
    {
      "message": {
        "arguments": {},
        "args": {},
        "info": {
          "fieldName": "listXData",
          "variables": {},
          "parentTypeName": "Query",
          "selectionSetList": [
            "items",
            "items/id",
            "items/createdAt",
            "items/updatedAt",
            "nextToken"
          ],
          "selectionSetGraphQL": "{\n  items {\n    id\n    createdAt\n    updatedAt\n  }\n  nextToken\n}"
        },
        "request": {...},
        "identity": {
          "sub": "",
          "issuer": "",
          "username": "013fe9d2-95f7-4885-83ec-b7e2e0a1423f",
          "sourceIp": "",
          "claims": {
            "origin_jti": "",
            "sub": "",
            "event_id": "",
            "token_use": "",
            "scope": "",
            "auth_time": ,
            "iss": "",
            "exp": ,
            "iat": ,
            "jti": "",
            "client_id": "",
            "username": "013fe9d2-95f7-4885-83ec-b7e2e0a1423f"
          },
          "defaultAuthStrategy": "ALLOW"
        },
        "stash": {},
        "source": null,
        "result": {
          "items": [],
          "scannedCount": 0,
          "nextToken": null
        },
        "error": null,
        "prev": {
          "result": {}
        }
      },
      "errorType": null,
      "data": null,
      "errorInfo": null,
      "path": [
        "listXData"
      ],
      "locations": [
        {
          "line": 2,
          "column": 3,
          "sourceName": "GraphQL request"
        }
      ]
    }
  ]
}

如您所见,用户名是一个 ID,但我更希望(也)有电子邮件。是否可以获取用户电子邮件(在 Velocity 模板中)?

如果我需要添加更多详细信息或者我的问题不清楚,请告诉我。

identity context only returns back the Cognito username for the user pool. You will need to setup pipeline functions to perform additional queries to get your user information. Here is one intro to setting them up.

至此看来,纯粹靠vtl是做不到的

我已经使用 lambda 函数实现了它,如下所示:

Lambda 函数(节点):

/* Amplify Params - DO NOT EDIT
    ENV
    REGION
Amplify Params - DO NOT EDIT */

const aws = require('aws-sdk')

const cognitoidentityserviceprovider = new aws.CognitoIdentityServiceProvider({
  apiVersion: '2016-04-18',
  region: 'eu-west-1'
})

exports.handler = async (context, event, callback) => {
  if (!context.identity?.username) {
    callback('Not signed in')
  }
  const params = {
    'AccessToken': context.request.headers.authorization
  }
  const result = await cognitoidentityserviceprovider.getUser(params).promise()
  const email = result.UserAttributes.find(attribute => attribute.Name === 'email')
  callback(null, JSON.stringify({ email }))
}

CustomResources.json

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "An auto-generated nested stack.",
  "Metadata": {...},
  "Parameters": {...},
  "Resources": {
    "GetEmailLambdaDataSourceRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "RoleName": {
          "Fn::If": [
            "HasEnvironmentParameter",
            {
              "Fn::Join": [
                "-",
                [
                  "GetEmail17ec",
                  {
                    "Ref": "GetAttGraphQLAPIApiId"
                  },
                  {
                    "Ref": "env"
                  }
                ]
              ]
            },
            {
              "Fn::Join": [
                "-",
                [
                  "GetEmail17ec",
                  {
                    "Ref": "GetAttGraphQLAPIApiId"
                  }
                ]
              ]
            }
          ]
        },
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": "appsync.amazonaws.com"
              },
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Policies": [
          {
            "PolicyName": "InvokeLambdaFunction",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "lambda:InvokeFunction"
                  ],
                  "Resource": {
                    "Fn::If": [
                      "HasEnvironmentParameter",
                      {
                        "Fn::Sub": [
                          "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:GetEmail-${env}",
                          {
                            "env": {
                              "Ref": "env"
                            }
                          }
                        ]
                      },
                      {
                        "Fn::Sub": [
                          "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:GetEmail",
                          {}
                        ]
                      }
                    ]
                  }
                }
              ]
            }
          }
        ]
      }
    },
    "GetEmailLambdaDataSource": {
      "Type": "AWS::AppSync::DataSource",
      "Properties": {
        "ApiId": {
          "Ref": "AppSyncApiId"
        },
        "Name": "GetEmailLambdaDataSource",
        "Type": "AWS_LAMBDA",
        "ServiceRoleArn": {
          "Fn::GetAtt": [
            "GetEmailLambdaDataSourceRole",
            "Arn"
          ]
        },
        "LambdaConfig": {
          "LambdaFunctionArn": {
            "Fn::If": [
              "HasEnvironmentParameter",
              {
                "Fn::Sub": [
                  "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:GetEmail-${env}",
                  {
                    "env": {
                      "Ref": "env"
                    }
                  }
                ]
              },
              {
                "Fn::Sub": [
                  "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:GetEmail",
                  {}
                ]
              }
            ]
          }
        }
      },
      "DependsOn": "GetEmailLambdaDataSourceRole"
    },
    "InvokeGetEmailLambdaDataSource": {
      "Type": "AWS::AppSync::FunctionConfiguration",
      "Properties": {
        "ApiId": {
          "Ref": "AppSyncApiId"
        },
        "Name": "InvokeGetEmailLambdaDataSource",
        "DataSourceName": "GetEmailLambdaDataSource",
        "FunctionVersion": "2018-05-29",
        "RequestMappingTemplateS3Location": {
          "Fn::Sub": [
            "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/pipelineFunctions/${ResolverFileName}",
            {
              "S3DeploymentBucket": {
                "Ref": "S3DeploymentBucket"
              },
              "S3DeploymentRootKey": {
                "Ref": "S3DeploymentRootKey"
              },
              "ResolverFileName": {
                "Fn::Join": [
                  ".",
                  [
                    "InvokeGetEmailLambdaDataSource",
                    "req",
                    "vtl"
                  ]
                ]
              }
            }
          ]
        },
        "ResponseMappingTemplateS3Location": {
          "Fn::Sub": [
            "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/pipelineFunctions/${ResolverFileName}",
            {
              "S3DeploymentBucket": {
                "Ref": "S3DeploymentBucket"
              },
              "S3DeploymentRootKey": {
                "Ref": "S3DeploymentRootKey"
              },
              "ResolverFileName": {
                "Fn::Join": [
                  ".",
                  [
                    "InvokeGetEmailLambdaDataSource",
                    "res",
                    "vtl"
                  ]
                ]
              }
            }
          ]
        }
      },
      "DependsOn": "GetEmailLambdaDataSource"
    },                
    "IsOrganizationMember": {
      "Type": "AWS::AppSync::FunctionConfiguration",
      "Properties": {
        "FunctionVersion": "2018-05-29",
        "ApiId": {
          "Ref": "AppSyncApiId"
        },
        "Name": "IsOrganizationMember",
        "DataSourceName": "PermissionsPerOrganizationTable",
        "RequestMappingTemplateS3Location": {
          "Fn::Sub": [
            "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/Query.isOrganizationMember.req.vtl",
            {
              "S3DeploymentBucket": {
                "Ref": "S3DeploymentBucket"
              },
              "S3DeploymentRootKey": {
                "Ref": "S3DeploymentRootKey"
              }
            }
          ]
        },
        "ResponseMappingTemplateS3Location": {
          "Fn::Sub": [
            "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/Query.isOrganizationMember.res.vtl",
            {
              "S3DeploymentBucket": {
                "Ref": "S3DeploymentBucket"
              },
              "S3DeploymentRootKey": {
                "Ref": "S3DeploymentRootKey"
              }
            }
          ]
        }
      }
    },
    "OrganizationAccessPipeline": {
      "Type": "AWS::AppSync::Resolver",
      "Properties": {
        "ApiId": {
          "Ref": "AppSyncApiId"
        },
        "TypeName": "Query",
        "Kind": "PIPELINE",
        "FieldName": "listXData",
        "PipelineConfig": {
          "Functions": [
            {
              "Fn::GetAtt": [
                "InvokeGetEmailLambdaDataSource",
                "FunctionId"
              ]
            },
            {
              "Fn::GetAtt": [
                "IsOrganizationMember",
                "FunctionId"
              ]
            }
          ]
        },
        "RequestMappingTemplate": "{}",
        "ResponseMappingTemplate": "$util.toJson($ctx.result)"
      }
    }
  },
  "Conditions": {...},
  "Outputs": {...}
}

lambda 是使用 CLI 创建的,IsOrganizationMember 是一个常规 VTL,它在 $context.prev.result.

中包含用户电子邮件