amplify-cli: update mutation with new cli does not work???
Note: If your issue/bug is regarding the AWS Amplify Console service, please log it in the Amplify Console GitHub Issue Tracker
Describe the bug A clear and concise description of what the bug is. Create a new project with schema. I am unable to update any of the values with generated mutation graphql mutations with cli. I make sure the required input values are included in the inputs to update the non-required values when I run my mutations but no change. I have also tried the appsync console with no avail. I have erased and tried a whole new environment in the cli but the bug keeps repeating. I am using 4.16.1. I have Merge enabled. The backend schema has
_version: Int!
_deleted: Boolean
_lastChangedAt: AWSTimestamp!
included. I also have iam provider and cognito user pools for auth rules. I am trying to update Profile table for my webapp.
here the VTL 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" )
## [Start] Static Group Authorization Checks **
#set($isStaticGroupAuthorized = $util.defaultIfNull(
$isStaticGroupAuthorized, false))
## Authorization rule: { allow: groups, groups: ["Users"], groupClaim: "cognito:groups" } **
#set( $userGroups = $util.defaultIfNull($ctx.identity.claims.get("cognito:groups"), []) )
#set( $allowedGroups = ["Users"] )
#foreach( $userGroup in $userGroups )
#if( $allowedGroups.contains($userGroup) )
#set( $isStaticGroupAuthorized = true )
#break
#end
#end
## [End] Static Group Authorization Checks **
#if( ! $isStaticGroupAuthorized )
## No dynamic group authorization rules **
## No owner authorization rules **
## [Start] Collect Auth Condition **
#set( $authCondition = $util.defaultIfNull($authCondition, {
"expression": "",
"expressionNames": {},
"expressionValues": {}
}) )
#set( $totalAuthExpression = "" )
## Add dynamic group auth conditions if they exist **
#if( $groupAuthExpressions )
#foreach( $authExpr in $groupAuthExpressions )
#set( $totalAuthExpression = "$totalAuthExpression $authExpr" )
#if( $foreach.hasNext )
#set( $totalAuthExpression = "$totalAuthExpression OR" )
#end
#end
#end
#if( $groupAuthExpressionNames )
$util.qr($authCondition.expressionNames.putAll($groupAuthExpressionNames))
#end
#if( $groupAuthExpressionValues )
$util.qr($authCondition.expressionValues.putAll($groupAuthExpressionValues))
#end
## Add owner auth conditions if they exist **
#if( $totalAuthExpression != "" && $ownerAuthExpressions && $ownerAuthExpressions.size() > 0 )
#set( $totalAuthExpression = "$totalAuthExpression OR" )
#end
#if( $ownerAuthExpressions )
#foreach( $authExpr in $ownerAuthExpressions )
#set( $totalAuthExpression = "$totalAuthExpression $authExpr" )
#if( $foreach.hasNext )
#set( $totalAuthExpression = "$totalAuthExpression OR" )
#end
#end
#end
#if( $ownerAuthExpressionNames )
$util.qr($authCondition.expressionNames.putAll($ownerAuthExpressionNames))
#end
#if( $ownerAuthExpressionValues )
$util.qr($authCondition.expressionValues.putAll($ownerAuthExpressionValues))
#end
## Set final expression if it has changed. **
#if( $totalAuthExpression != "" )
#if( $util.isNullOrEmpty($authCondition.expression) )
#set( $authCondition.expression = "($totalAuthExpression)" )
#else
#set( $authCondition.expression = "$authCondition.expression AND ($totalAuthExpression)" )
#end
#end
## [End] Collect Auth Condition **
#end
## [Start] Throw if unauthorized **
#if( !($isStaticGroupAuthorized == true || ($totalAuthExpression != "")) )
$util.unauthorized()
#end
## [End] Throw if unauthorized **
#end
## [End] Check authMode and execute owner/group checks **
#if( $authCondition && $authCondition.expression != "" )
#set( $condition = $authCondition )
#if( $modelObjectKey )
#foreach( $entry in $modelObjectKey.entrySet() )
$util.qr($condition.put("expression", "$condition.expression AND attribute_exists(#keyCondition$velocityCount)"))
$util.qr($condition.expressionNames.put("#keyCondition$velocityCount", "$entry.key"))
#end
#else
$util.qr($condition.put("expression", "$condition.expression AND attribute_exists(#id)"))
$util.qr($condition.expressionNames.put("#id", "id"))
#end
#else
#if( $modelObjectKey )
#set( $condition = {
"expression": "",
"expressionNames": {},
"expressionValues": {}
} )
#foreach( $entry in $modelObjectKey.entrySet() )
#if( $velocityCount == 1 )
$util.qr($condition.put("expression", "attribute_exists(#keyCondition$velocityCount)"))
#else
$util.qr($condition.put("expression", "$condition.expression AND attribute_exists(#keyCondition$velocityCount)"))
#end
$util.qr($condition.expressionNames.put("#keyCondition$velocityCount", "$entry.key"))
#end
#else
#set( $condition = {
"expression": "attribute_exists(#id)",
"expressionNames": {
"#id": "id"
},
"expressionValues": {}
} )
#end
#end
## Automatically set the updatedAt timestamp. **
$util.qr($context.args.input.put("updatedAt", $util.defaultIfNull($ctx.args.input.updatedAt, $util.time.nowISO8601())))
$util.qr($context.args.input.put("__typename", "Profile"))
## Update condition if type is @versioned **
#if( $versionedCondition )
$util.qr($condition.put("expression", "($condition.expression) AND $versionedCondition.expression"))
$util.qr($condition.expressionNames.putAll($versionedCondition.expressionNames))
$util.qr($condition.expressionValues.putAll($versionedCondition.expressionValues))
#end
#if( $context.args.condition )
#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
#set( $expNames = {} )
#set( $expValues = {} )
#set( $expSet = {} )
#set( $expAdd = {} )
#set( $expRemove = [] )
#if( $modelObjectKey )
#set( $keyFields = [] )
#foreach( $entry in $modelObjectKey.entrySet() )
$util.qr($keyFields.add("$entry.key"))
#end
#else
#set( $keyFields = ["id", "_version", "_deleted", "_lastChangedAt"] )
#end
#foreach( $entry in $util.map.copyAndRemoveAllKeys($context.args.input, $keyFields).entrySet() )
#if( !$util.isNull($dynamodbNameOverrideMap) && $dynamodbNameOverrideMap.containsKey("$entry.key") )
#set( $entryKeyAttributeName = $dynamodbNameOverrideMap.get("$entry.key") )
#else
#set( $entryKeyAttributeName = $entry.key )
#end
#if( $util.isNull($entry.value) )
#set( $discard = $expRemove.add("#$entryKeyAttributeName") )
$util.qr($expNames.put("#$entryKeyAttributeName", "$entry.key"))
#else
$util.qr($expSet.put("#$entryKeyAttributeName", ":$entryKeyAttributeName"))
$util.qr($expNames.put("#$entryKeyAttributeName", "$entry.key"))
$util.qr($expValues.put(":$entryKeyAttributeName", $util.dynamodb.toDynamoDB($entry.value)))
#end
#end
#set( $expression = "" )
#if( !$expSet.isEmpty() )
#set( $expression = "SET" )
#foreach( $entry in $expSet.entrySet() )
#set( $expression = "$expression $entry.key = $entry.value" )
#if( $foreach.hasNext() )
#set( $expression = "$expression," )
#end
#end
#end
#if( !$expAdd.isEmpty() )
#set( $expression = "$expression ADD" )
#foreach( $entry in $expAdd.entrySet() )
#set( $expression = "$expression $entry.key $entry.value" )
#if( $foreach.hasNext() )
#set( $expression = "$expression," )
#end
#end
#end
#if( !$expRemove.isEmpty() )
#set( $expression = "$expression REMOVE" )
#foreach( $entry in $expRemove )
#set( $expression = "$expression $entry" )
#if( $foreach.hasNext() )
#set( $expression = "$expression," )
#end
#end
#end
#set( $update = {} )
$util.qr($update.put("expression", "$expression"))
#if( !$expNames.isEmpty() )
$util.qr($update.put("expressionNames", $expNames))
#end
#if( !$expValues.isEmpty() )
$util.qr($update.put("expressionValues", $expValues))
#end
{
"version": "2018-05-29",
"operation": "UpdateItem",
"key": #if( $modelObjectKey ) $util.toJson($modelObjectKey) #else {
"id": {
"S": $util.toJson($context.args.input.id)
}
} #end,
"update": $util.toJson($update),
"condition": $util.toJson($condition),
"_version": $util.defaultIfNull($ctx.args.input["_version"], "0")
}
here’s schema for table
type Profile
@model
@auth(rules: [
{ allow: public, provider: iam, operations: [read] },
{allow: groups, groups: ["public"], operations: [read]},
{allow: groups, groups: ["Users"]},
])
{
id: ID!
userId: ID!
name: String!
aboutMe: String
profilePicture: String
following: [UserHost] @connection(keyName: "byUser", fields: ["id"])
followingCount: String
user: User @connection(fields: ["userId"])
stats: Stats @connection(fields: ["userId"])
}
here’s my react code:
const updateUserProfileForm = async (values) => {
try {
const {
files,
aboutMe,
} = values;
// upload picture
const filteredFiles = files.filter(file => file !== null);
console.log(values, ' this is the values object');
console.log(files, ' this is files');
if (filteredFiles
&& filteredFiles[0]
&& filteredFiles[0].name) await uploadPicture(filteredFiles[0]);
const params = (filteredFiles && filteredFiles[0] && filteredFiles[0].name)
? {
input: {
id: profileId,
aboutMe,
profilePicture: `${credId}/${profileId}/${escapeUnsafe(filteredFiles[0].name)}`,
userId: userProfile.userId,
name: userProfile.name,
},
}
: {
input: {
id: profileId,
aboutMe,
userId: userProfile.userId,
name: userProfile.name,
},
};
const userProfileData = await API
.graphql(
graphqlOperation(
UpdateUserProfile, params,
),
);
const { data: { updateProfile: newUserProfile } } = userProfileData;
setUserProfile(newUserProfile);
console.log(newUserProfile, ' this is NewUserProfile');
setSuccess({
header: 'Update successful!',
content: 'Profile updated successfully.',
});
setError(null);
} catch (e) {
setSuccess(null);
setError({
header: 'Oops...something went wrong',
content: 'Something went wrong with updating profile, please try again.',
});
}
};
Amplify CLI Version
You can use amplify -v to check the amplify cli version on your system
4.16.1
To Reproduce
Steps to reproduce the behavior or terminal output if applicable
- create new schema
- create values inside dynamodb table using appsync
- use update mutation while including the required fields.
Expected behavior A clear and concise description of what you expected to happen. The values should update.
Screenshots If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
- OS: [e.g. Mac/Windows/Ubuntu]
- Node Version. You can use
node -vto check the node version on your system
v12.13.1
Additional context Add any other context about the problem here.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 24 (5 by maintainers)
tl;dr: When you call the “updateProfile” mutation, because you have versioning turned on, you need to pass in the current _version number as part of the update input object. In your react code I can see you aren’t doing this.
To test this and show it working properly:
navigate to AppSync in your region, https://eu-west-2.console.aws.amazon.com/appsync/ . Select queries on left hand side. Login, use AppClientIDWeb from step 2.
execute the following mutations