Massively extend documentation

This commit is contained in:
Christoph Lienhard 2020-05-31 13:46:48 +02:00
parent 02845e65db
commit 2068dfd1af
2 changed files with 241 additions and 14 deletions

View file

@ -1,5 +1,40 @@
# Candymat - Wahl-o-Mat fuer Personalwahlen
## Introduction
The candymat is a Wahl-o-Mat for elections of candidates.
## Services
The project consists of three services:
* GraphQL backend (+ postgres)
* Redaktions-App
* User-App
### Redaktions-App
The Redaktions-App is used for editors and candidates to provide questions and answers.
The app is written with react and appollo-react to access the backend.
See also: [Service Readme](redaktions-app/README.md)
### User-App
The User-App is based on the [EuroMat](https://www.euromat.info/en) (Source: https://github.com/morkro/euromat)
and is used to find the perfect candidate for everyone who is allowed to vote.
It is written in vue.js.
See also: [Service Readme](https://git.verdigado.com/Netzbegruenung/candymat-user-app/src/README.md)
### Postgraphile (Backend)
A package which creates an GraphQL api based on an underlying postgres schema.
For more on this (e.g. how to use the graphQl api by yourself) see [backend readme](backend/README.md)
## Development Setup
### Check-out repository
@ -12,16 +47,22 @@
### Start the services
```docker-compose up -d``` for dev setup.
The database will use a volume to persist changes in-between runs.
To start with a clean database, either delete the volume from the postgres configuration in the compose file
or run ```docker volume rm candymat_db-data``` before starting the containers.
### Where to access the services
For dev setup:
```
docker-compose up
```
* GraphQL IDE/GUI: http://localhost:5433/graphiql
* GraphQL Endpoint: http://localhost:5433/graphql
* UserApp: http://localhost:8080
* RedaktionsApp: http://localhost:8081
* Postgres database: http://localhost:5432
**Note:** The database will use a volume to persist changes in-between runs.
To start with a clean database, either delete the volume from the postgres configuration in the compose file
or run
```
docker container rm candymat_postgres_1
docker volume rm candymat_db-data
```
before starting docker-compose.

View file

@ -1,11 +1,197 @@
# Candymat Backend
## Setup dev environment
The candymat 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.
### Postgres via Docker
missing
## Introduction
### Postgres on your machine
* Install postgres and start it
* Create a new database
* Execute the scripts in the `./sql` folder in chronological order
### 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 candymat 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.