Example project for Play Framework that wires up couple of components:
- Scala 2.13
- Play framework 2.8
- Sangria 2.0
- Slick 3
- Silhouette 7
- H2 in memory DB
- GraphiQL graphical interface
- Flyway migrations
Its aim is to showcase how these compenents can be wired together to provide secure graphql endpoints with authorization. Authentication is built upon JWT tokens.
sbt run
App runs on http 9000 by default.
Make sure you invoke db migrations.
After opening localhost:9000
you should see:
Make sure you apply migration.
Static graphiql UI is available at localhost:9000/graphiql
There are two users shipped with application:
username | password | role |
---|---|---|
testuser | test | user |
testadmin | test | admin |
Admin is able to add records to database via graphql query, user can only read from it.
curl -X POST http://localhost:9000/auth/signin
-H 'Content-Type: application/json'
-d '{"identifier": "testuser", "password": "test"}'
< HTTP/1.1 200 OK
{
"token":"eyJ0eXAiOiJKV......this is long....XhGJk6f7yxgjA"
}
Despite having users shipped you may want to create new one:
curl -X POST http://localhost:9000/auth/signup \
-H 'Content-Type: application/json' \
-d '{
"identifier": "newadminuser",
"password": "newpassword",
"email": "newadmin@test.com",
"firstName": "newname",
"lastName": "newsurname",
"isAdmin": true
}'
< HTTP/1.1 200 OK
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGci..."
}
After acquiring JWT token (either by signin or signup methods) you may execute graphQL queries:
This also showcases Sangria's deferred fetchers capability which allows to reference records between tables (sort of DB join but not quite).
curl -X POST http://localhost:9000/graphql\
-H 'Content-Type: application/json' \
-H "X-Auth-Token: eyJ0eXAiOiJKV1Q....." \
-d '{"query" : "{product(id: 1){ id name opinions {text}}}"}'
< HTTP/1.1 200 OK
{
"data":{
"product":{
"id":1,
"name":"First product",
"opinions":[
{
"text":"good"
},
{
"text":"very good"
}
]
}
}
}
This requires admin account
curl -X POST http://localhost:9000/graphql\
-H 'Content-Type: application/json' \
-H "X-Auth-Token: eyJ0eXAiOi..." \
-d '{"query" : "mutation { insertProduct(name: \"new product name\"){ id name}}"}'
< HTTP/1.1 200 OK
{
"data": {
"insertProduct": {
"id": 5,
"name": "new product name"
}
}
}
In case executed with plain user privileges will get followig error:
< HTTP/1.1 200 OK
{
"data": null,
"errors": [{
"message": "You do not have permission to do this operation",
"path": ["insertProduct"],
"locations": [{
"line": 1,
"column": 12
}]
}]
}
or in case of DB intergrity constarint validation:
{
"data": null,
"errors": [{
"message": "product with given name already exists",
"path": ["insertProduct"],
"locations": [{
"line": 1,
"column": 12
}]
}]
}
#test