sbstjn / appsync-resolvers Goto Github PK
View Code? Open in Web Editor NEWAWS AppSync Resolvers for GraphQL using AWS Lambda functions in Go.
Home Page: https://sbstjn.com/serverless-graphql-with-appsync-and-lambda.html
License: MIT License
AWS AppSync Resolvers for GraphQL using AWS Lambda functions in Go.
Home Page: https://sbstjn.com/serverless-graphql-with-appsync-and-lambda.html
License: MIT License
Currently, resolver functions are invoked only with the GraphQL arguments or the resolved field. The identity
field or any other (possibly user-defined) field of the $context
object is dropped.
appsync-resolvers/repository.go
Line 27 in 08cb572
This makes it impossible to perform resource-based authorization based on $context.indentity.username
or $context.identity.cognitoIdentityId
(see AWS AppSync Developer Guide) in Lambda resolvers.
Hi guys. I have a question: Does AppSync support TransactWriteItems resolver?
Because I have such error on eu-central-1:
{
"data": {
"createMessage": null
},
"errors": [
{
"path": [
"createMessage"
],
"data": null,
"errorType": "MappingTemplate",
"errorInfo": null,
"locations": [
{
"line": 2,
"column": 3,
"sourceName": null
}
],
"message": "Unsupported operation 'TransactWriteItems'."
}
]
}
with the following request template:
## [Start] Determine request authentication mode **
#if( $util.isNullOrEmpty($authMode) && !$util.isNull($ctx.identity) && !$util.isNull($ctx.identity.sub) && !$util.isNull($ctx.identity.issuer) && !$util.isNull($ctx.identity.username) && !$util.isNull($ctx.identity.claims) && !$util.isNull($ctx.identity.sourceIp) && !$util.isNull($ctx.identity.defaultAuthStrategy) )
#set( $authMode = "userPools" )
#end
## [End] Determine request authentication mode **
## [Start] Check authMode and execute owner/group checks **
#if( $authMode == "userPools" )
## No Static Group Authorization Rules **
## No Dynamic Group Authorization Rules **
## [Start] Owner Authorization Checks **
#set( $isOwnerAuthorized = false )
## Authorization rule: { allow: owner, ownerField: "owner", identityClaim: "cognito:username" } **
#set( $allowedOwners0 = $util.defaultIfNull($ctx.args.input.owner, null) )
#set( $identityValue = $util.defaultIfNull($ctx.identity.claims.get("username"), $util.defaultIfNull($ctx.identity.claims.get("cognito:username"), "___xamznone____")) )
#if( $util.isList($allowedOwners0) )
#foreach( $allowedOwner in $allowedOwners0 )
#if( $allowedOwner == $identityValue )
#set( $isOwnerAuthorized = true )
#end
#end
#end
#if( $util.isString($allowedOwners0) )
#if( $allowedOwners0 == $identityValue )
#set( $isOwnerAuthorized = true )
#end
#end
#if( $util.isNull($allowedOwners0) && (! $ctx.args.input.containsKey("owner")) )
$util.qr($ctx.args.input.put("owner", $identityValue))
#set( $isOwnerAuthorized = true )
#end
## [End] Owner Authorization Checks **
## [Start] Throw if unauthorized **
#if( !($isStaticGroupAuthorized == true || $isDynamicGroupAuthorized == true || $isOwnerAuthorized == true) )
$util.unauthorized()
#end
## [End] Throw if unauthorized **
#end
## [End] Check authMode and execute owner/group checks **
#set($dateTime = $util.time.nowISO8601())
## [Start] Set the primary @key. **
#set( $modelObjectKey = {
"pk": $util.dynamodb.toDynamoDB($ctx.args.input.pk),
"sk": $util.dynamodb.toDynamoDB("M#${dateTime}#${identityValue}")
} )
## [End] Set the primary @key. **
## [Start] Prepare DynamoDB PutItem Request. **
$util.qr($context.args.input.put("createdAt", $util.defaultIfNull($ctx.args.input.createdAt, $util.time.nowISO8601())))
$util.qr($context.args.input.put("updatedAt", $util.defaultIfNull($ctx.args.input.updatedAt, $util.time.nowISO8601())))
$util.qr($context.args.input.put("__typename", "EntityItem"))
$util.qr($context.args.input.put("target", "Chat"))
#set( $condition = {
"expression": "attribute_not_exists(#pk)",
"expressionNames": {
"#pk": "pk"
}
} )
#if( $context.args.condition )
#set( $condition.expressionValues = {} )
#set( $conditionFilterExpressions = $util.parseJson($util.transform.toDynamoDBConditionExpression($context.args.condition)) )
$util.qr($condition.put("expression", "($condition.expression) AND $conditionFilterExpressions.expression"))
$util.qr($condition.expressionNames.putAll($conditionFilterExpressions.expressionNames))
$util.qr($condition.expressionValues.putAll($conditionFilterExpressions.expressionValues))
#end
#if( $condition.expressionValues && $condition.expressionValues.size() == 0 )
#set( $condition = {
"expression": $condition.expression,
"expressionNames": $condition.expressionNames
} )
#end
{
"version": "2018-05-29",
"operation": "TransactWriteItems",
"transactItems": [
{
"table": "EntityItem-bwwoag6fybal3d5y3wfirf7zru-dev",
"operation": "PutItem",
"key": $util.toJson($modelObjectKey),
"attributeValues": $util.dynamodb.toMapValuesJson($context.args.input),
"condition": $util.toJson({
"expression": $condition.expression,
"expressionNames": $condition.expressionNames,
"expressionValues": $condition.expressionValues,
"returnValuesOnConditionCheckFailure": false
})
}
]
}
## [End] Prepare DynamoDB PutItem Request. **
Ran into this case with a graphql schema I'm currently working on and have racked my brain for a bit to think up a good solution. Thought I'd post an issue here to see if there's any ideas on how to solve this problem without creating a custom fork ๐
Say you have this GraphQL schema (not the schema I'm using, but it's enough to show the problem):
type Query {
users: [User]
}
type User {
id ID!
name String!
role(company: ID!): String!
}
type Role {
id: ID!
name: String!
}
The users
field on the Query
type returns a list of User
types. However, the User
type also has a role
field that can take a company
arg. Currently, the role
field cannot be mapped to a lambda function using this library, which is due to (as best I can tell) these lines: https://github.com/sbstjn/appsync-resolvers/blob/master/invocation.go#L15-L25 . The payload
function appears to only return either the Source
field or the Arguments
field exclusively, meaning that the role
resolver wouldn't be able to access the company
arg at all.
I could solve this by making a more custom appsync resolver, i.e.
{
"version" : "2017-02-28",
"operation": "Invoke",
"payload": {
"resolve": "query.users.role",
"context": {
"source": null,
"arguments": $utils.toJson($context)
}
}
}
and then making my event structure parse out those properties, i.e.
type User struct {
ID string `json:"id"`
Name string `json:"name"`
}
type roleArgs struct {
Company string `json:"company"`
}
type event struct {
Source User `json:"source"`
Arguments roleArgs `json:"arguments"`
}
However, this does seem a bit more complicated than it needs to be, and I was wondering if there's a better way to solve combining the source & arguments together. I'm totally willing to work on implementing whatever solution is decided on (if any) ๐
How do we properly pass errors? Right now, all errors are returning as "Lambda:Unhandled"
.
Any way to customize errorType
, errorInfo
?
{
"data": null,
"errors": [
{
"path": [
"updateProject"
],
"data": null,
"errorType": "Lambda:Unhandled",
"errorInfo": null,
"locations": [
{
"line": 15,
"column": 3,
"sourceName": null
}
],
"message": "Name required"
}
]
}
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.