Is there an alternative to work with union types and Amplify Graphql Api? - graphql

I want to create a Type on my schema that has a Union type as a type in a field. for example:
union Member = User | Professional | Orgs
type Conversation #model #auth(rules: [{ allow: public }]) {
conversationID: ID! #primaryKey
messages: [Message] #hasMany
members: [Member]
}
However reading the documentation I realized that I can't use unions this way, is there another way to allow user professionals and orgs to be in the member's field?
I am open to any workaround

Related

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.

Can the 'ownerField' of an #auth directive be based on the field of a different document?

Using AWS AppSync GraphQL, I want to be able to have the #auth ownership of one type of document to be based on another. For example, let's say my schema looked like this:
type Course
#model
#auth(rules: [{ allow: owner, ownerField: "contributors", operations: [read, create, update, delete] }])
{
id: ID!
title: String!
contributors: [String!]!
questions: [Question!]! #hasMany
}
type Question
#model
#auth(rules: [{ allow: private, operations: [read, create] }, { allow: owner, operations: [read, create, update, delete] }])
{
id: ID!
title: String!
owner: String!
course: Course! #belongsTo
}
Notice in the above schema, a Course has many Questions, and a Question belongs to a Course. I want to allow the "contributors" of a Course to also have update/delete access on its child Questions, but in the above schema only the creator of the Question (which is any random signed-in user) will have update/delete access.
Is there a way that the Question type could set it's update/delete #auth access to allow not just the owner of the Question, but also of its parent Course "contributors"?

AWS Amplify - Field Level GraphQL Auth on Required Fields

I am trying to set up GraphQL via AWS Amplify so that all users can see part of a Member object (e.g. the name), but only members in certain groups can see other parts (e.g. the e-mail address).
I have set up my schema.graphql as follows (note this is a truncated version):
type Member #model(subscriptions: { level: off }) #auth(rules: [{allow: groups, groups: ["MANAGER"]}, {allow: private, operations: [read]}]) {
membershipNumber: Int! #primaryKey
firstName: String!
lastName: String!
email: String! #auth(rules: [{allow: groups, groups: ["MANAGER"]}, {allow: groups, groups: ["COMMITTEE"], operations: [read]}])
dietaryRequirements: String #auth(rules: [{allow: groups, groups: ["MANAGER"]}, {allow: groups, groups: ["COMMITTEE"], operations: [read]}])
}
As I understand it, all logged in users should be able to read membershipNumber, firstName and lastName. Users in the COMMITTEE group should also be able to read email and dietaryRequirements, and users in the MANAGER group should be able to read/write all fields.
When I try to run a query as a logged in user with no groups though, I get an unauthorized error on dietaryRequirements (which is good) but I am able to read email without an error (which is bad).
The only difference I can see is that email is a required field, whereas dietaryRequirements isn't. What am I doing wrong? Do required fields override the authorization rules?

How can I set one field to be less restricted in an Amplify GraphQL API schema?

I have the following schema for an amplify project using GraphQL API:
type SomeItem
#model
#auth(
rules: [
{ allow: owner, operations: [create, delete, update] }
]
){
id: ID!
owner: String
version: Int!
text: String
read: Boolean #auth(rules: [{ allow: owner, operations: [create, delete] }])
createdAt: AWSDateTime
updatedAt: AWSDateTime
}
What I want to be able to do is for only the Owner to create/update/delete every field.
I want to allow anybody to update the read field only. I have tried the above to make the read field less restrictive but it's not working. How can I make one field in the model less restrictive than the other fields? Do I need to set an #auth for each field individually?

AWS Amplify with GraphQL - Defining authentication rules by different types of users

Using Amplify, GraphQL, AppSync, Cognito, DynamoDB
Having the following model:
type Post
#model
{
id: ID!
content: String!
author: String!
}
I want my rules to enable the following case:
Only Admin users can create, update and delete Post
Some Posts where only premium users allow to read
Some Posts where all logged in users allow to read
Some Posts where all users (also unauthenticated) allow to read
What is the best way to implement it using the mentioned tools?
Thanks
From your question, it is not clear how you define "Some Posts" and how you would differentiate one from another. If I was designing this, I would have at least one more field in my Post type to manage the access level (For example: 3 (Admin) > 2 (Premium) > 1 (Logged-in) > 0 (Unregistered)), like so;
type Post
#model
{
id: ID!
content: String!
author: String!
accessLevel: Int!
}
To manage this on user level, I think your best bet is to manage it using Cognito groups (like mentioned in the official documentation) and assign appropriate permission for each group.
Things you would need in Cognito:
A user pool which will contain all of your registered users.
A user group for premium members.
A user group for your admins.
Things you would need in your AppSync:
For Admin users to create, update and delete Post:
type Mutation {
createPost(id:ID!, content:String!, author:String!):Post!
#aws_auth(cognito_groups: ["Admin"])
updatePost(id:ID!, content:String!, author:String!):Post!
#aws_auth(cognito_groups: ["Admin"])
deletePost(id:ID!, content:String!, author:String!):Post!
#aws_auth(cognito_groups: ["Admin"])
}
For some posts only visible to premium, logged-in or unregistered users to read:
type Query {
getPost(id:ID!):Post!
#aws_api_key #aws_cognito_user_pools
}
Furthermore, you can use the accessLevel in your resolver to filter out the result based on which post you want to be visible to premium, logged-in or unregistered users.
I used #Myz answers.
And https://aws.amazon.com/blogs/mobile/graphql-security-appsync-amplify/ for full solution:
type Post
#model
#auth(
rules: [
{ allow: owner }
{ allow: groups, groups: ["Admin"], operations: [create, update, delete] }
{ allow: groups, groupsField: "group", operations: [read] }
]
) {
id: ID!
content: String!
author: String!
group: [String] # or String for a single group
}

Resources