如何在AWS AppSync创建Note前检查关联Entry的权限?
Great question! This is a common edge case when dealing with relational data in AppSync + Amplify—default @auth rules for child models don’t automatically validate permissions on their parent objects. Here are two solid approaches to lock down this scenario:
Method 1: Custom CreateNote Resolver (Recommended)
This approach adds a pre-check in the resolver logic for creating a Note to verify the user has access to the target Entry before allowing the association.
- Enable API overrides in your Amplify project:
amplify override api - Locate and edit the createNote resolver template:
Navigate toamplify/backend/api/<your-api-name>/resolvers/Mutation.createNote.req.vtland replace the content with this logic:# Extract the linked Entry ID from the input #set($entryId = $ctx.args.input.noteEntryId) #if($entryId) # Build a request to fetch the target Entry from DynamoDB #set($getEntryParams = { "version": "2018-05-29", "operation": "GetItem", "key": { "id": { "S": "$entryId" } }, "tableName": "Entry-${env}" }) # Execute the query and parse the result #set($entryResult = $util.dynamodb.fromDynamoDB($util.graphql($getEntryParams))) #set($entry = $entryResult.item) # Block if the Entry doesn't exist #if(!$entry) $util.unauthorized("The specified Entry does not exist.") #end # Validate user permissions: owner or shared user #set($isOwner = $util.equals($entry.owner, $ctx.identity.username)) #set($isShared = $util.isList($entry.shared) && $util.contains($entry.shared, $ctx.identity.username)) # Block if user has no access to the Entry #if(!$isOwner && !$isShared) $util.unauthorized("You don't have permission to add a Note to this Entry.") #end #end # Proceed with the original create logic #return($ctx.args) - Deploy the changes:
amplify push
This method directly enforces permission checks at the resolver level, preventing unauthorized users from linking Notes to Entries they can't access.
Method 2: Extend Note's @Auth Rules (With Redundant Fields)
If you prefer to leverage Amplify's built-in @auth system instead of custom resolvers, you can add redundant fields to the Note model that mirror the Entry's permission data, then use conditions to validate access.
- Update the Note model:
Add fields to store theEntry's owner and shared users, then add a conditional @auth rule:type Note @model @versioned @auth (rules: [ { allow: owner, conditions: { or: [ { "eq": ["$ctx.source.entryOwner", "$ctx.identity.username"] }, { "contains": ["$ctx.source.entryShared", "$ctx.identity.username"] } ] } } ]) { id: ID! text: String track: Track! diary: DiaryEntry @connection(name: "EntryNotes") entryOwner: String! entryShared: [String]! } - Enforce accurate redundant fields:
Modify thecreateNoteresolver to auto-populateentryOwnerandentrySharedfrom the targetEntry(so clients can't fake these values):#set($entryId = $ctx.args.input.noteEntryId) #if($entryId) #set($getEntryParams = { "version": "2018-05-29", "operation": "GetItem", "key": { "id": { "S": "$entryId" } }, "tableName": "Entry-${env}" }) #set($entry = $util.dynamodb.fromDynamoDB($util.graphql($getEntryParams)).item) #set($ctx.args.input.entryOwner = $entry.owner) #set($ctx.args.input.entryShared = $entry.shared) #end #return($ctx.args) - Deploy the changes:
amplify push
This approach uses Amplify's native auth system but requires maintaining redundant data—trade off between convenience and data normalization based on your needs.
Key Notes
- Double-check your DynamoDB table name in the resolver (it follows the format
Entry-${env}, e.g.,Entry-dev). - Both methods handle cases where the target
Entrydoesn't exist, returning an unauthorized error to avoid broken associations.
内容的提问来源于stack exchange,提问作者Jakub Juszczak

