kandimat/backend/README.md

198 lines
4.3 KiB
Markdown

# Kandimat Backend
The kandimat backend consists of a postgres database and a [postgraphile](https://www.graphile.org/postgraphile/introduction/) instance.
Postgraphile generates a Graphql backend based on the underlying postgres schema.
## Introduction
### Basic structure
There are three "data" tables:
* category
* question
* answer
Questions can belong to categories.
Answers belong to questions and candidates.
### User management
There are four types of roles:
* editor
* candidate
* user
* anonymous
Editors handle questions and categories, candidates handle their specific answers and users are only important
in setups where there is no public access to the data.
#### Authentication
Authentication is handled via jwt.
The kandimat setup roughly follows the instructions in the [postgraphile docu](https://www.graphile.org/postgraphile/postgresql-schema-design/#authentication-and-authorization).
## Manually test the backend
To test the backend manually an (enhanced) graphiql instance is started in dev mode.
To access it navigate to http://localhost:5433/graphiql.
#### Authenticate (or how to pose as a member of one of the roles)
To pose as one of the three roles authenticate as
* `erika@musterman.de` (editor)
* `max@mustermann.de` (candidate)
* `happy@user.de` (normal user)
The password is always "password".
Use following graphQL mutation to get the jwtToken of an editor:
```
mutation Authenticate {
__typename
authenticate(input: {email: "erika@mustermann.de", password: "password"}) {
jwtToken
}
}
```
The jwtToken in the response has to be added to the headers in the following way:
```
{
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiY2FuZHltYXRfY2FuZGlkYXRlIiwicGVyc29uX2lkIjoyLCJleHAiOjE1OTEwNDgzMzgsImlhdCI6MTU5MDg3NTUzNywiYXVkIjoicG9zdGdyYXBoaWxlIiwiaXNzIjoicG9zdGdyYXBoaWxlIn0.21Lu51_suJ5O2RU-UKN2Y6fvKw4SYe-oqx_QqlU0-GE"
}
```
#### Query the data tables
This is possible as member of any role, including no role (anonymous).
You can use the schema to get familiar with possible queries.
As an example, here is a query which retrieves all questions including the category they belong to:
```graphql
{
allQuestions {
nodes {
categoryByCategoryId {
title
description
}
text
description
}
}
}
```
Example response:
```json
{
"data": {
"allQuestions": {
"nodes": [
{
"categoryByCategoryId": {
"title": "Umwelt",
"description": "Themen rund um Naturschutz usw."
},
"text": "Was sagen Sie zur 10H Regel?",
"description": "In Bayern dürfen Windräder nur ..."
}
]
}
}
}
```
#### Creating new users
aka "register"
Only possible if no bearer token is set in the headers.
```graphql
mutation Register {
registerPerson(input: {firstName: "Ford", lastName: "Prefect", email: "ford@prefect.com", password: "password"}) {
person {
id
}
}
}
```
#### Creating questions
This is only possible as "editor". Use the following mutation:
```
mutation CreateQuestion($text: String!) {
createQuestion(input: {question: {text: $text}}) {
question {
text
id
}
}
}
```
with the variables
```
{
"text": "Die Antwort auf die Frage nach dem Leben, dem Universum und dem ganzen Rest?"
}
```
#### Creating categories
This is only possible as "editor".
Mutation:
```
mutation CreateCategory($title: String!) {
createCategory(input: {category: {title: $title}}) {
category {
title
id
}
}
}
```
Variables
```
{
"title": "Verkehr"
}
```
##### Creating answers
This is only possible as "candidate".
Also the `personId` needs to be `2` (the id of Max Mustermann).
It is impossible for a candidate to pose as a different candidate when answering a question.
Mutation:
```
mutation CreateAnswer($position: Int!, $questionId: Int!, $personId: Int!) {
createAnswer(input: {answer: {position: $position, questionId: $questionId, personId: $personId}}) {
answer {
position
}
}
}
}
```
Variables
```
{
"questionId": 1,
"personId": 2,
"position": 2
}
```
Also change the `personId` to see that the candidate can only answer for themself.
##### Updating, Deleting
Works the same as creating and has the same restrictions for the specific roles.
The exact mutations can be inferred looking at the schema definitions.