How Would I Build This AWS Amplify GraphQL Functionality with AWS CDK? - graphql

I have decided to convert my AWS Amplify application to be built with the AWS CDK instead. I am now faced with converting my schema.graphql to something that can work with the AWS CDK.
I have created two tables below that offer a variety of functionality that comes out of the box with AWS Amplify.
Key Functionality I am stuck on building in the AWS CDK:
#hasMany
#auth
Adding resolvers for CRUD operations
What I have achieved already:
Creating DynamoDB Tables
Creating Global Secondary Indexes
Code:
type EmployerAccount
#model
#auth(
rules: [
{ allow: owner, operations: [create, update, delete, read] }
{ allow: private, operations: [read] }
{ allow: public, provider: iam, operations: [read] }
]
) {
id: ID!
owner: String!
group: String
#index(
name: "byEmployerGroup"
queryField: "byEmployerGroup"
)
images: [Image] #hasMany(indexName: "byEmployer", fields: ["id"])
}
type Image
#model
) {
id: ID! #primaryKey(sortKeyFields: ["employerID"]) #IMAGE-ksuid
employerID: ID! #index(name: "byEmployer", queryField: "byEmployer", sortKeyFields: ["id"])
}
I have decided to use:
#aws-cdk/aws-appsync-alpha module
aws-cdk-lib (V2 of the CDK)

Related

Amplify - Specify the Graphql Authoriser lambda on Amplify schema

Currently I'm on aws amplify and I have several authorizers (graphql lambda authorizer) but I can't specify the name of the one I want to use for my user table.
Anyone have an idea how to do it?
type User
#model
#auth(rules: [{ allow: custom }])
{
id: ID!
first_name: String
last_name: String
}

Amplify, Cognito authentication and GraphQL API

I am a bit confused about how authentication works using AWS Amplify (Cognito and AppSync bundle).
I have setup my authentication method to Cognito and I designed a datamodel using GraphQL API schema.
It looks almost like this (I skipped some elements has they are not relevant to my question):
type Grower #model
#auth(rules: [
{ allow: owner, ownerField: "admins" },
{ allow: owner, ownerField: "members", operations: [read, update, create]},
{ allow: owner, ownerField: "guests", operations: [read]}
]) {
code: String!
name: String!
admins: [String]
members: [String]
guests: [String]
workers: [Workers] #hasMany
orchards: [Orchard] #hasMany
}
type Orchard #model
#auth(rules: [
{ allow: owner }
]){
name: String!
location: String
grower: Grower! #belongsTo
harvests: [Harvest] #hasMany
visits: [Visit] #hasMany
}
Given this schema, will a user declared in the Grower.admins field be able to access an Orchard and its fields if it belongs to the Grower?
And, the opposite, will a user not declared as a member of this Grower (neither guests, member or admins) be able to see the Orchard?
Basically, I would like to understand if my authentication rules 'propagate' throught nested models.
Any comment about this datastructure is welcomed.

How to prevent access to certain fields in Amplify graphql public API

I have a graphql model in Amplify as follows:
type Blog #model #auth(rules: [
{ allow: owner },
{ allow: groups, groups: ["admins"] },
{ allow: public, provider: apiKey, operations: [read] }
]){
id: ID!
title: String!
content: String!
author: String
}
I would like all field to have read access via an API key except the 'author' field.It should only be readable by owner and the 'Admin' group.
I have tried all sorts of combinations of top level and field level #auth directives but it doesn't work.
Does anyone knows how to solve this.
Thank you
have you tried using the Field Level Authorization?
type User #model {
id: ID!
username: String
ssn: String #auth(rules: [{ allow: owner, ownerField: "username" }])
}
Update: My mistake, in your question it does say you tried this out.

Query and Mutate GraphQL from Lambda function in AWS-Amplify using Cognito for auth

I created a GraphQL api via the amplify api add command and added the schema below. I'm using cognito for auth.
type User #model
#auth(rules: [{ allow: owner }]) {
id: ID!
videos: [Video!] #connection(keyName: "videosByUser", fields: ["id"])
adverts: [Advert] #connection(keyName:"advertsByUser", fields: ["id"])
}
type Video #model
#key(name: "videosByUser", fields: ["userId"])
#auth(rules: [{ allow: owner, operations: [create, update, delete] }]) {
id: ID!
title: String!
description: String!
size: Float!
length: Float!
hashMarks: [Float!]!
userId: ID!
# bidrectional connection, if needed
# user: User! #connection(fields: ["userId"])
adverts: [VideoAdverts!] #connection(keyName: "advertsByVideo", fields: ["id"])
streamingLink: AWSURL
}
type VideoAdverts #model(queries: null)
#key(name: "advertsByVideo", fields: ["videoId", "advertId"])
#key(name: "videosByAdvert", fields: ["advertId", "videoId"]) {
id: ID!
videoId: ID!
advertId: ID!
video: Video! #connection(fields: ["videoId"])
advert: Advert! #connection(fields: ["advertId"])
}
type Advert #model
#key(name: "advertsByUser", fields: ["userId"])
#auth(rules: [{ allow: owner, operations: [create, update, delete] }]) {
id: ID!
title: String!
description: String!
size: Float!
length: Float!
creatorId: ID!
# bidrectional connection, if needed
# creator: Creator! #connection(fields: ["creatorId"])
videos: [VideoAdverts!] #connection(keyName: "videosByAdvert", fields: ["id"])
blacklist: [AdvertBlacklist!] #connection(keyName: "blacklistByAdvert", fields: ["id"])
startDate: AWSDateTime
endDate: AWSDateTime
}
This is my first amplify project and I'm having trouble figuring out how to implement the following use cases:
Use a lambda function to query data and return to a client.
Use a cron triggered lambda function to make an API call and use a mutation to update some fields.
All I have found so far from googling involves using lambdas to interact with data added via the amplify storage add command.
A few other examples I found here on Stackoverflow do not use cognito for auth.
Looks like I will be able to use cloudwatch to trigger lambdas, and so my main problem now is how to actually query and mutate a GraphQL api from a lambda, using cognito for authentication.
Any help would be super helpful, thanks :)
The key to authenticating your Lambda functions to interact with your AppSync API is to configure multiple authentication methods. You are using Cognito for your front end application users, however, you do not want to use that for your Lambda function authentication. AppSync supports multiple authentications mechanisms for your API. In your case, you will want to add IAM as the second authentication mechanism.
You can do this from the Amplify CLI:
$ amplify update api
Scanning for plugins...
Plugin scan successful
? Please select from one of the below mentioned services: GraphQL
? Choose the default authorization type for the API Amazon Cognito User Pool
Use a Cognito user pool configured as a part of this project.
? Do you want to configure advanced settings for the GraphQL API Yes, I want
to make some additional changes.
? Configure additional auth types? Yes
? Choose the additional authorization types you want to configure for the API IAM

In an AppSync #auth rule, how do I set an ownerField to a property in an array?

Imagine I have the following AppSync GraphQL schema with a User type, and a Post type with an editors field set to an array of Users:
type User
#model
#auth(rules: [
{ allow: owner }
])
{
id: ID!
owner: String!
username: String!
}
type Post
#model
#auth(rules: [
{ allow: owner },
# Can I do this?
# { allow: owner, ownerField: "editors.owner", operations: [update] }
])
{
id: ID!
owner: String!
title: String!
content: String
editors: [User]
}
How do I create an #auth rule to give update permissions to the Users in the editors array?
If you're using the amazon Cognito user pool you should set the editor type inside Post to be an array of String and set the values to the Cognito ids of the users that you want to have access. This is explained in the amplify cli documentation.
To have the editors to be of type User I suggest you to create another paramether named differently (for example editorUsers) and connect it to the User model as described here
Your schema should look like this:
type User
#model
#key(name: "byUser", fields: ["username"])
#auth(rules: [
{ allow: owner }
])
{
id: ID!
owner: String!
username: String!
}
type Post
#model
#auth(rules: [
{ allow: owner },
{ allow: owner, ownerField: "editors", operations: [update] }
])
{
id: ID!
owner: String!
title: String!
content: String
editors: [String]
editorsUsers: [User] #connection(keyName: "byUser", fields: ["id"])
}

Resources