Skip to content

Comments

In the previous steps, we implemented a fully functional blog application with advanced access controls, relations and a GraphQL API that was generated by Slicknode based on our data model.

As a little recap, we can now use that knowledge to add the comment functionality.

Instructions

Data Model

First, we need to add the data model for our comment type to our blog module. Open the schema.graphql file of the blog module and add the type definition:

modules/blog/schema.graphql:

type Blog_Comment implements Node & TimeStampedInterface {
  id: ID!
  text: String! @input(type: MARKDOWN)
  article: Blog_Article!
  author: User
  createdAt: DateTime!
  lastUpdatedAt: DateTime
}

Deploy the changes to the cloud, fix any errors and create a few comments using the data browser:

slicknode deploy

Relations

We want to be able to load an article with all its comments for an article page. Let's add the back relation on the Blog_Article type, using the @relation directive.

modules/blog/schema.graphql:

type Blog_Article implements Node & TimeStampedInterface {
  # ...
  comments: [Blog_Comment!]! @relation(path: "Blog_Article=article.Blog_Comment")
}

Save the schema file and deploy the changes to the cloud:

slicknode deploy

Test the comments relationship in the playground.

Authorization

The permissions for the Blog_Comment nodes are very similar to the Blog_Article. We want to add the following business logic:

  • Only authorized users are allowed to create comments.
  • Anonymous users can read all comments.
  • A user is not allowed to publish articles in someone else's name.
  • Any authorized user is allowed to publish comments, not just STAFF users.
  • Comments can only be created for articles with the status PUBLISHED.
  • Users can only modify, but not delete their own comments.
  • ADMIN users can perform all operations on all comments.

The permission document should look something like this

modules/blog/permissions/Blog_Comment.graphql:

query Blog_CommentPermission1 {
  scope(role: ANONYMOUS, operations: [READ]) # Anyone can read all comments
}

# Limited access for authenticated users
query Blog_CommentPermission2(
  $user_id: ID!
) {
  scope(role: AUTHENTICATED, operations: [READ, CREATE, UPDATE])
  node(filter: {
    article: {
      status: {eq: PUBLISHED} # Allow only comments for published articles
    }
    author: {
      id: {eq: $user_id} # Access only to own comments
    }
  })
}

# Full access for admin user
query Blog_CommentPermission3 {
  scope(role: ADMIN, operations: [READ, CREATE, UPDATE, DELETE])
}

Save the document and deploy the changes to the Slicknode Cloud:

slicknode deploy