3
votes

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:

  1. Only Admin users can create, update and delete Post
  2. Some Posts where only premium users allow to read
  3. Some Posts where all logged in users allow to read
  4. Some Posts where all users (also unauthenticated) allow to read

What is the best way to implement it using the mentioned tools?

Thanks

2
Can you add what datastore you are using? Are you using DynamoDB? Also what is behind you AppSync/GraphQL - Lambda? One way to accomplish what you are trying to do: create Cognito Roles and only give permission to that role for the Lambda execution for different users.Maksood
Thank you. I will edit my question. I'm using DynamoDB and didn't any Lambda function yet but planning to add.bhizmi

2 Answers

2
votes

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:

  1. A user pool which will contain all of your registered users.

  2. A user group for premium members.

  3. A user group for your admins.

Things you would need in your AppSync:

  1. 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"])
    }
    
  2. 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.

2
votes

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
}