Compare commits
5 commits
feature/#2
...
main
Author | SHA1 | Date | |
---|---|---|---|
0b0e664656 | |||
006574df03 | |||
f7a56a0bed | |||
fafc3722cd | |||
Christoph Lienhard | f66f8adecb |
4
.env
4
.env
|
@ -1,7 +1,7 @@
|
|||
COMPOSE_FILE=docker-compose.dev.yml
|
||||
COMPOSE_PROJECT_NAME=candymat
|
||||
COMPOSE_PROJECT_NAME=kandimat
|
||||
|
||||
# Backend vars
|
||||
POSTGRES_PASSWORD=postgres!dev
|
||||
DATABASE_URL=postgres://candymat_postgraphile:postgres!dev@postgres:5432/candymat_db
|
||||
DATABASE_URL=postgres://kandimat_postgraphile:postgres!dev@postgres:5432/kandimat_db
|
||||
JWT_SECRET=asdfasdfasdf
|
||||
|
|
8
.gitmodules
vendored
8
.gitmodules
vendored
|
@ -1,4 +1,4 @@
|
|||
[submodule "candymat-user-app"]
|
||||
path = candymat-user-app
|
||||
url = git@git.verdigado.com:Netzbegruenung/candymat-user-app.git
|
||||
branch = develop-candymat
|
||||
[submodule "kandimat-user-app"]
|
||||
path = kandimat-user-app
|
||||
url = https://git.verdigado.com/NB-Public/kandimat-user-app.git
|
||||
branch = main
|
||||
|
|
12
README.md
12
README.md
|
@ -1,8 +1,8 @@
|
|||
# Candymat - Wahl-o-Mat fuer Personalwahlen
|
||||
# Kandimat - Wahl-o-Mat fuer Personalwahlen
|
||||
|
||||
## Introduction
|
||||
|
||||
The candymat is a Wahl-o-Mat for elections of candidates.
|
||||
The kandimat is a Wahl-o-Mat for elections of candidates.
|
||||
|
||||
|
||||
## Services
|
||||
|
@ -27,7 +27,7 @@ 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)
|
||||
See also: [Service Readme](https://git.verdigado.com/Netzbegruenung/kandimat-user-app/src/README.md)
|
||||
|
||||
### Postgraphile (Backend)
|
||||
|
||||
|
@ -39,7 +39,7 @@ For more on this (e.g. how to use the graphQl api by yourself) see [backend read
|
|||
|
||||
### Check-out repository
|
||||
* [Install git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
|
||||
* `git clone https://git.verdigado.com/Netzbegruenung/candymat.git`
|
||||
* `git clone https://git.verdigado.com/Netzbegruenung/kandimat.git`
|
||||
* To get the (external) user-app source:
|
||||
```
|
||||
git submodule update --init
|
||||
|
@ -65,8 +65,8 @@ docker-compose up
|
|||
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
|
||||
docker container rm kandimat_postgres_1
|
||||
docker volume rm kandimat_db-data
|
||||
```
|
||||
before starting docker-compose.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Candymat Backend
|
||||
# Kandimat Backend
|
||||
|
||||
The candymat backend consists of a postgres database and a [postgraphile](https://www.graphile.org/postgraphile/introduction/) instance.
|
||||
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
|
||||
|
@ -29,7 +29,7 @@ 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).
|
||||
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
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Postgres database setup
|
||||
POSTGRES_USER=candymat_postgraphile
|
||||
POSTGRES_USER=kandimat_postgraphile
|
||||
# Password is handled by docker-compose
|
||||
POSTGRES_DB=candymat_db
|
||||
POSTGRES_SCHEMA=candymat_data
|
||||
POSTGRES_DB=kandimat_db
|
||||
POSTGRES_SCHEMA=kandimat_data
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#!/bin/bash
|
||||
|
||||
docker-compose stop postgres
|
||||
CONTAINER=$(docker image rm candymat-postgres:11.5 2> >(grep -P '[a-f0-9]{12}' -o) | head -1)
|
||||
CONTAINER=$(docker image rm kandimat-postgres:11.5 2> >(grep -P '[a-f0-9]{12}' -o) | head -1)
|
||||
echo "Going to remove container: $CONTAINER"
|
||||
docker container rm $CONTAINER
|
||||
docker image rm candymat-postgres:11.5
|
||||
docker image rm kandimat-postgres:11.5
|
||||
echo "Deleting db-data docker volumes ..."
|
||||
VOLUMES=$(docker volume ls -q | grep "db-data")
|
||||
for volume in ${VOLUMES[@]}; do
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
\connect candymat_db
|
||||
\connect kandimat_db
|
||||
|
||||
-- Create schema for candymat_data
|
||||
create SCHEMA candymat_data;
|
||||
create SCHEMA candymat_data_privat;
|
||||
-- Create schema for kandimat_data
|
||||
create SCHEMA kandimat_data;
|
||||
create SCHEMA kandimat_data_privat;
|
||||
|
||||
-- create roles
|
||||
create role candymat_person;
|
||||
create role candymat_anonymous;
|
||||
create role candymat_editor;
|
||||
create role candymat_candidate;
|
||||
create role kandimat_person;
|
||||
create role kandimat_anonymous;
|
||||
create role kandimat_editor;
|
||||
create role kandimat_candidate;
|
||||
|
||||
grant candymat_editor to candymat_postgraphile;
|
||||
grant candymat_candidate to candymat_postgraphile;
|
||||
grant candymat_person to candymat_postgraphile, candymat_candidate, candymat_editor;
|
||||
grant candymat_anonymous to candymat_postgraphile;
|
||||
grant kandimat_editor to kandimat_postgraphile;
|
||||
grant kandimat_candidate to kandimat_postgraphile;
|
||||
grant kandimat_person to kandimat_postgraphile, kandimat_candidate, kandimat_editor;
|
||||
grant kandimat_anonymous to kandimat_postgraphile;
|
||||
|
||||
create type candymat_data.role as enum (
|
||||
'candymat_editor',
|
||||
'candymat_candidate',
|
||||
'candymat_person'
|
||||
create type kandimat_data.role as enum (
|
||||
'kandimat_editor',
|
||||
'kandimat_candidate',
|
||||
'kandimat_person'
|
||||
);
|
||||
|
||||
-- set table wide permissions
|
||||
grant usage on schema candymat_data to candymat_anonymous, candymat_person;
|
||||
grant usage on schema kandimat_data to kandimat_anonymous, kandimat_person;
|
||||
|
||||
-- make functions non executeable w/o further checks
|
||||
alter default privileges revoke execute on functions from public;
|
||||
|
|
|
@ -1,43 +1,43 @@
|
|||
-- create table for users
|
||||
create table candymat_data.person
|
||||
create table kandimat_data.person
|
||||
(
|
||||
row_id serial primary key,
|
||||
first_name character varying(200) check (first_name <> ''),
|
||||
last_name character varying(200) check (last_name <> ''),
|
||||
about character varying(2000),
|
||||
created_at timestamp default now(),
|
||||
role candymat_data.role not null default 'candymat_person'
|
||||
role kandimat_data.role not null default 'kandimat_person'
|
||||
);
|
||||
grant select, update, delete on table candymat_data.person to candymat_person;
|
||||
grant select, update, delete on table kandimat_data.person to kandimat_person;
|
||||
-- the following is only necessary as long as anonymous should be able to view candidates and editors
|
||||
grant select on table candymat_data.person to candymat_anonymous;
|
||||
grant select on table kandimat_data.person to kandimat_anonymous;
|
||||
|
||||
-- create table for accounts
|
||||
create table candymat_data_privat.person_account
|
||||
create table kandimat_data_privat.person_account
|
||||
(
|
||||
person_row_id integer primary key references candymat_data.person (row_id) on delete cascade,
|
||||
person_row_id integer primary key references kandimat_data.person (row_id) on delete cascade,
|
||||
email character varying(320) not null unique check (email ~* '^.+@.+\..+$'),
|
||||
password_hash character varying(256) not null
|
||||
);
|
||||
|
||||
alter table candymat_data.person
|
||||
alter table kandimat_data.person
|
||||
enable row level security;
|
||||
create policy update_person on candymat_data.person for update to candymat_person
|
||||
create policy update_person on kandimat_data.person for update to kandimat_person
|
||||
with check (row_id = nullif(current_setting('jwt.claims.person_row_id', true), '')::integer);
|
||||
create policy delete_person on candymat_data.person for delete to candymat_person
|
||||
create policy delete_person on kandimat_data.person for delete to kandimat_person
|
||||
using (row_id = nullif(current_setting('jwt.claims.person_row_id', true), '')::integer);
|
||||
|
||||
-- The following enables viewing candidates and editors information for every person.
|
||||
-- This may be changed to only enable registered (and verified) persons.
|
||||
create policy select_person_public
|
||||
on candymat_data.person
|
||||
on kandimat_data.person
|
||||
for select
|
||||
to candymat_anonymous, candymat_person -- maybe change to candymat_person only in the future
|
||||
using (role in ('candymat_editor', 'candymat_candidate'));
|
||||
to kandimat_anonymous, kandimat_person -- maybe change to kandimat_person only in the future
|
||||
using (role in ('kandimat_editor', 'kandimat_candidate'));
|
||||
|
||||
-- Editors can see all registered persons in order to elevate their privileges
|
||||
create policy select_person_editor
|
||||
on candymat_data.person
|
||||
on kandimat_data.person
|
||||
for select
|
||||
to candymat_editor
|
||||
to kandimat_editor
|
||||
using (true);
|
||||
|
|
|
@ -1,51 +1,51 @@
|
|||
-- create table for categories
|
||||
create table candymat_data.category
|
||||
create table kandimat_data.category
|
||||
(
|
||||
row_id serial primary key,
|
||||
title character varying(300) UNIQUE NOT NULL check ( title <> '' ),
|
||||
description character varying(15000)
|
||||
);
|
||||
grant select on table candymat_data.category to candymat_person;
|
||||
-- the following line is only necessary as long as the candymat should be publicly accessible
|
||||
grant select on table candymat_data.category to candymat_anonymous;
|
||||
grant insert, update, delete on table candymat_data.category to candymat_editor;
|
||||
grant usage on sequence candymat_data.category_row_id_seq to candymat_editor;
|
||||
grant select on table kandimat_data.category to kandimat_person;
|
||||
-- the following line is only necessary as long as the kandimat should be publicly accessible
|
||||
grant select on table kandimat_data.category to kandimat_anonymous;
|
||||
grant insert, update, delete on table kandimat_data.category to kandimat_editor;
|
||||
grant usage on sequence kandimat_data.category_row_id_seq to kandimat_editor;
|
||||
|
||||
-- create table for questions
|
||||
create table candymat_data.question
|
||||
create table kandimat_data.question
|
||||
(
|
||||
row_id serial primary key,
|
||||
category_row_id integer REFERENCES candymat_data.category (row_id) ON UPDATE CASCADE ON DELETE SET NULL,
|
||||
category_row_id integer REFERENCES kandimat_data.category (row_id) ON UPDATE CASCADE ON DELETE SET NULL,
|
||||
title character varying(3000) UNIQUE NOT NULL check ( title <> '' ),
|
||||
description character varying(15000)
|
||||
);
|
||||
grant select on table candymat_data.question to candymat_person;
|
||||
-- the following line is only necessary as long as the candymat should be publicly accessible
|
||||
grant select on table candymat_data.question to candymat_anonymous;
|
||||
grant insert, update, delete on table candymat_data.question to candymat_editor;
|
||||
grant usage on sequence candymat_data.question_row_id_seq to candymat_editor;
|
||||
grant select on table kandimat_data.question to kandimat_person;
|
||||
-- the following line is only necessary as long as the kandimat should be publicly accessible
|
||||
grant select on table kandimat_data.question to kandimat_anonymous;
|
||||
grant insert, update, delete on table kandimat_data.question to kandimat_editor;
|
||||
grant usage on sequence kandimat_data.question_row_id_seq to kandimat_editor;
|
||||
|
||||
-- create table for answers
|
||||
create table candymat_data.answer
|
||||
create table kandimat_data.answer
|
||||
(
|
||||
question_row_id integer REFERENCES candymat_data.question (row_id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
person_row_id integer REFERENCES candymat_data.person (row_id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
question_row_id integer REFERENCES kandimat_data.question (row_id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
person_row_id integer REFERENCES kandimat_data.person (row_id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
position integer NOT NULL check (position between 0 and 3),
|
||||
text character varying(15000),
|
||||
created_at timestamp default now(),
|
||||
primary key (question_row_id, person_row_id)
|
||||
);
|
||||
grant select on table candymat_data.answer to candymat_person;
|
||||
-- the following line is only necessary as long as the candymat should be publicly accessible
|
||||
grant select on table candymat_data.answer to candymat_anonymous;
|
||||
grant insert, update, delete on table candymat_data.answer to candymat_candidate;
|
||||
grant select on table kandimat_data.answer to kandimat_person;
|
||||
-- the following line is only necessary as long as the kandimat should be publicly accessible
|
||||
grant select on table kandimat_data.answer to kandimat_anonymous;
|
||||
grant insert, update, delete on table kandimat_data.answer to kandimat_candidate;
|
||||
|
||||
alter table candymat_data.answer
|
||||
alter table kandimat_data.answer
|
||||
enable row level security;
|
||||
create policy change_answer on candymat_data.answer to candymat_candidate
|
||||
create policy change_answer on kandimat_data.answer to kandimat_candidate
|
||||
using (person_row_id = nullif(current_setting('jwt.claims.person_row_id', true), '')::integer);
|
||||
create policy select_answer
|
||||
on candymat_data.answer
|
||||
on kandimat_data.answer
|
||||
for select
|
||||
to candymat_anonymous, candymat_person -- maybe change to candymat_person only in the future
|
||||
to kandimat_anonymous, kandimat_person -- maybe change to kandimat_person only in the future
|
||||
using (true);
|
||||
|
|
|
@ -2,8 +2,8 @@ create extension if not exists "pgcrypto";
|
|||
|
||||
|
||||
-- Define JWT claim structure
|
||||
drop type if exists candymat_data.jwt_token cascade;
|
||||
create type candymat_data.jwt_token as
|
||||
drop type if exists kandimat_data.jwt_token cascade;
|
||||
create type kandimat_data.jwt_token as
|
||||
(
|
||||
role text,
|
||||
person_row_id integer,
|
||||
|
@ -12,28 +12,28 @@ create type candymat_data.jwt_token as
|
|||
|
||||
|
||||
-- Function to get the currently logged-in person
|
||||
drop function if exists candymat_data.current_person;
|
||||
create function candymat_data.current_person(
|
||||
) returns candymat_data.person as
|
||||
drop function if exists kandimat_data.current_person;
|
||||
create function kandimat_data.current_person(
|
||||
) returns kandimat_data.person as
|
||||
$$
|
||||
select *
|
||||
from candymat_data.person
|
||||
from kandimat_data.person
|
||||
where row_id = nullif(current_setting('jwt.claims.person_row_id', true), '')::integer
|
||||
$$ language sql stable;
|
||||
grant execute on function candymat_data.current_person() to candymat_person;
|
||||
grant execute on function kandimat_data.current_person() to kandimat_person;
|
||||
|
||||
|
||||
-- Function to register a new user
|
||||
drop function if exists candymat_data.register_person;
|
||||
create function candymat_data.register_person(
|
||||
drop function if exists kandimat_data.register_person;
|
||||
create function kandimat_data.register_person(
|
||||
first_name text,
|
||||
last_name text,
|
||||
email text,
|
||||
password text
|
||||
) returns candymat_data.person as
|
||||
) returns kandimat_data.person as
|
||||
$$
|
||||
declare
|
||||
person candymat_data.person;
|
||||
person kandimat_data.person;
|
||||
begin
|
||||
if (trim(register_person.first_name) <> '') is not true then
|
||||
raise 'Invalid first name: ''%''', register_person.first_name;
|
||||
|
@ -44,70 +44,70 @@ begin
|
|||
if (trim(register_person.password) <> '') is not true then
|
||||
raise 'Invalid password.';
|
||||
end if;
|
||||
insert into candymat_data.person (first_name, last_name)
|
||||
insert into kandimat_data.person (first_name, last_name)
|
||||
values ($1, $2)
|
||||
returning * into person;
|
||||
|
||||
insert into candymat_data_privat.person_account (person_row_id, email, password_hash)
|
||||
insert into kandimat_data_privat.person_account (person_row_id, email, password_hash)
|
||||
values (person.row_id, $3, crypt($4, gen_salt('bf')));
|
||||
|
||||
return person;
|
||||
end ;
|
||||
$$ language plpgsql strict
|
||||
security definer;
|
||||
grant execute on function candymat_data.register_person(text, text, text, text) to candymat_anonymous;
|
||||
grant execute on function kandimat_data.register_person(text, text, text, text) to kandimat_anonymous;
|
||||
|
||||
|
||||
-- Authenticate: Login for user
|
||||
drop function if exists candymat_data.authenticate;
|
||||
create function candymat_data.authenticate(
|
||||
drop function if exists kandimat_data.authenticate;
|
||||
create function kandimat_data.authenticate(
|
||||
email text,
|
||||
password text
|
||||
) returns candymat_data.jwt_token as
|
||||
) returns kandimat_data.jwt_token as
|
||||
$$
|
||||
declare
|
||||
account candymat_data_privat.person_account;
|
||||
declare person candymat_data.person;
|
||||
account kandimat_data_privat.person_account;
|
||||
declare person kandimat_data.person;
|
||||
begin
|
||||
select a.*
|
||||
into account
|
||||
from candymat_data_privat.person_account as a
|
||||
from kandimat_data_privat.person_account as a
|
||||
where a.email = $1;
|
||||
|
||||
select p.*
|
||||
into person
|
||||
from candymat_data.person as p
|
||||
from kandimat_data.person as p
|
||||
where p.row_id = account.person_row_id;
|
||||
|
||||
if account.password_hash = crypt(password, account.password_hash) then
|
||||
return (person.role, account.person_row_id,
|
||||
extract(epoch from (now() + interval '2 days')))::candymat_data.jwt_token;
|
||||
extract(epoch from (now() + interval '2 days')))::kandimat_data.jwt_token;
|
||||
else
|
||||
return null;
|
||||
end if;
|
||||
end;
|
||||
$$ language plpgsql strict
|
||||
security definer;
|
||||
grant execute on function candymat_data.authenticate(text, text) to candymat_anonymous, candymat_person;
|
||||
grant execute on function kandimat_data.authenticate(text, text) to kandimat_anonymous, kandimat_person;
|
||||
|
||||
|
||||
-- Change role: Changes role for a given user. Only editors are allowed to use it.
|
||||
drop function if exists candymat_data.change_role;
|
||||
create function candymat_data.change_role(
|
||||
drop function if exists kandimat_data.change_role;
|
||||
create function kandimat_data.change_role(
|
||||
person_row_id integer,
|
||||
new_role candymat_data.role
|
||||
new_role kandimat_data.role
|
||||
)
|
||||
returns candymat_data.person as
|
||||
returns kandimat_data.person as
|
||||
$$
|
||||
declare
|
||||
person candymat_data.person;
|
||||
person kandimat_data.person;
|
||||
begin
|
||||
update candymat_data.person
|
||||
update kandimat_data.person
|
||||
set role = new_role
|
||||
where candymat_data.person.row_id = $1
|
||||
where kandimat_data.person.row_id = $1
|
||||
returning * into person;
|
||||
|
||||
return person;
|
||||
end;
|
||||
$$ language plpgsql strict security definer;
|
||||
grant execute on function candymat_data.change_role(integer, candymat_data.role) to candymat_editor;
|
||||
grant execute on function kandimat_data.change_role(integer, kandimat_data.role) to kandimat_editor;
|
||||
|
|
|
@ -1,40 +1,40 @@
|
|||
select candymat_data.register_person(
|
||||
select kandimat_data.register_person(
|
||||
'Erika',
|
||||
'Mustermann',
|
||||
'erika@mustermann.de',
|
||||
'password'
|
||||
);
|
||||
select candymat_data.change_role(
|
||||
select kandimat_data.change_role(
|
||||
1,
|
||||
'candymat_editor'
|
||||
'kandimat_editor'
|
||||
);
|
||||
select candymat_data.register_person(
|
||||
select kandimat_data.register_person(
|
||||
'Max',
|
||||
'Mustermann',
|
||||
'max@mustermann.de',
|
||||
'password'
|
||||
);
|
||||
select candymat_data.change_role(
|
||||
select kandimat_data.change_role(
|
||||
2,
|
||||
'candymat_candidate'
|
||||
'kandimat_candidate'
|
||||
);
|
||||
select candymat_data.register_person(
|
||||
select kandimat_data.register_person(
|
||||
'Tricia',
|
||||
'McMillan',
|
||||
'trillian@universe.com',
|
||||
'password'
|
||||
);
|
||||
select candymat_data.change_role(
|
||||
select kandimat_data.change_role(
|
||||
3,
|
||||
'candymat_candidate'
|
||||
'kandimat_candidate'
|
||||
);
|
||||
select candymat_data.register_person(
|
||||
select kandimat_data.register_person(
|
||||
'Happy',
|
||||
'User',
|
||||
'happy@user.de',
|
||||
'password'
|
||||
);
|
||||
select candymat_data.change_role(
|
||||
select kandimat_data.change_role(
|
||||
4,
|
||||
'candymat_person'
|
||||
'kandimat_person'
|
||||
);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
insert into candymat_data.category (title, description) values
|
||||
insert into kandimat_data.category (title, description) values
|
||||
('Umwelt', 'Themen rund um Naturschutz usw.');
|
||||
insert into candymat_data.category (title, description) values
|
||||
insert into kandimat_data.category (title, description) values
|
||||
('Sonstiges', '');
|
||||
|
||||
insert into candymat_data.question (category_row_id, title, description) values
|
||||
insert into kandimat_data.question (category_row_id, title, description) values
|
||||
(1, 'Was sagen Sie zur 10H Regel?', 'In Bayern dürfen Windräder nur ...');
|
||||
insert into candymat_data.question (category_row_id, title, description) values
|
||||
insert into kandimat_data.question (category_row_id, title, description) values
|
||||
(2, 'Umgehungsstraße XY?', 'Zur Entlastung der Hauptstraße ...');
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
insert into candymat_data.answer (question_row_id, person_row_id, position, text)
|
||||
insert into kandimat_data.answer (question_row_id, person_row_id, position, text)
|
||||
values (1, 2, 2, 'bin dagegen');
|
||||
insert into candymat_data.answer (question_row_id, person_row_id, position, text)
|
||||
insert into kandimat_data.answer (question_row_id, person_row_id, position, text)
|
||||
values (2, 2, 0, 'bin dafür');
|
||||
|
||||
insert into candymat_data.answer (question_row_id, person_row_id, position, text)
|
||||
insert into kandimat_data.answer (question_row_id, person_row_id, position, text)
|
||||
values (1, 3, 1, 'mir egal');
|
||||
insert into candymat_data.answer (question_row_id, person_row_id, position, text)
|
||||
insert into kandimat_data.answer (question_row_id, person_row_id, position, text)
|
||||
values (2, 3, 3, 'keine lust mehr');
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 4e290449cb4b5821f5542d1ea6a9a629b99e6aa3
|
|
@ -15,7 +15,7 @@ services:
|
|||
|
||||
user-app:
|
||||
build:
|
||||
context: ./candymat-user-app/
|
||||
context: kandimat-user-app/
|
||||
dockerfile: ./dev.Dockerfile
|
||||
depends_on:
|
||||
- graphql
|
||||
|
@ -25,7 +25,7 @@ services:
|
|||
- frontend
|
||||
|
||||
postgres:
|
||||
image: candymat-postgres:11.5
|
||||
image: kandimat-postgres:11.5
|
||||
build:
|
||||
dockerfile: ./Dockerfile
|
||||
context: ./backend/
|
||||
|
@ -53,9 +53,9 @@ services:
|
|||
"--host", "0.0.0.0",
|
||||
"--port", "5000",
|
||||
"--cors",
|
||||
"--schema", "candymat_data",
|
||||
"--default-role", "candymat_anonymous",
|
||||
"--jwt-token-identifier", "candymat_data.jwt_token",
|
||||
"--schema", "kandimat_data",
|
||||
"--default-role", "kandimat_anonymous",
|
||||
"--jwt-token-identifier", "kandimat_data.jwt_token",
|
||||
"--jwt-secret", $JWT_SECRET,
|
||||
"--watch",
|
||||
"--retry-on-init-fail",
|
||||
|
|
1
kandimat-user-app
Submodule
1
kandimat-user-app
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit dc1602b6e87c80d3c37f92bc87f02c98865895d3
|
|
@ -7,7 +7,7 @@
|
|||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="App zum Erstellen von Fragen für den Candymat"
|
||||
content="App zum Erstellen von Fragen für den Kandimat"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
|
@ -24,7 +24,7 @@
|
|||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>Candymat Redaktion</title>
|
||||
<title>Kandimat Redaktion</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"short_name": "Candymat Redaktion",
|
||||
"name": "Candymat Redaktions App",
|
||||
"short_name": "Kandimat Redaktion",
|
||||
"name": "Kandimat Redaktions App",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
|
|
|
@ -12,7 +12,7 @@ export const getPersonsByRoleAllFilledData: GetPersonsSortedByRoleResponse = {
|
|||
rowId: 1,
|
||||
firstName: "Erika",
|
||||
lastName: "Mustermann",
|
||||
role: "CANDYMAT_EDITOR",
|
||||
role: "KANDIMAT_EDITOR",
|
||||
__typename: "Person",
|
||||
},
|
||||
],
|
||||
|
@ -25,7 +25,7 @@ export const getPersonsByRoleAllFilledData: GetPersonsSortedByRoleResponse = {
|
|||
rowId: 2,
|
||||
firstName: "Max",
|
||||
lastName: "Mustermann",
|
||||
role: "CANDYMAT_CANDIDATE",
|
||||
role: "KANDIMAT_CANDIDATE",
|
||||
__typename: "Person",
|
||||
},
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ export const getPersonsByRoleAllFilledData: GetPersonsSortedByRoleResponse = {
|
|||
rowId: 3,
|
||||
firstName: "Tricia",
|
||||
lastName: "McMillan",
|
||||
role: "CANDYMAT_CANDIDATE",
|
||||
role: "KANDIMAT_CANDIDATE",
|
||||
__typename: "Person",
|
||||
},
|
||||
],
|
||||
|
@ -46,7 +46,7 @@ export const getPersonsByRoleAllFilledData: GetPersonsSortedByRoleResponse = {
|
|||
rowId: 4,
|
||||
firstName: "Happy",
|
||||
lastName: "User",
|
||||
role: "CANDYMAT_PERSON",
|
||||
role: "KANDIMAT_PERSON",
|
||||
__typename: "Person",
|
||||
},
|
||||
],
|
||||
|
@ -76,7 +76,7 @@ export const getPersonsByRoleNoCandidatesData: GetPersonsSortedByRoleResponse =
|
|||
rowId: 1,
|
||||
firstName: "Erika",
|
||||
lastName: "Mustermann",
|
||||
role: "CANDYMAT_EDITOR",
|
||||
role: "KANDIMAT_EDITOR",
|
||||
__typename: "Person",
|
||||
},
|
||||
],
|
||||
|
@ -93,7 +93,7 @@ export const getPersonsByRoleNoCandidatesData: GetPersonsSortedByRoleResponse =
|
|||
rowId: 2,
|
||||
firstName: "Max",
|
||||
lastName: "Mustermann",
|
||||
role: "CANDYMAT_PERSON",
|
||||
role: "KANDIMAT_PERSON",
|
||||
__typename: "Person",
|
||||
},
|
||||
{
|
||||
|
@ -101,7 +101,7 @@ export const getPersonsByRoleNoCandidatesData: GetPersonsSortedByRoleResponse =
|
|||
rowId: 3,
|
||||
firstName: "Tricia",
|
||||
lastName: "McMillan",
|
||||
role: "CANDYMAT_PERSON",
|
||||
role: "KANDIMAT_PERSON",
|
||||
__typename: "Person",
|
||||
},
|
||||
{
|
||||
|
@ -109,7 +109,7 @@ export const getPersonsByRoleNoCandidatesData: GetPersonsSortedByRoleResponse =
|
|||
rowId: 4,
|
||||
firstName: "Happy",
|
||||
lastName: "User",
|
||||
role: "CANDYMAT_PERSON",
|
||||
role: "KANDIMAT_PERSON",
|
||||
__typename: "Person",
|
||||
},
|
||||
],
|
||||
|
|
|
@ -22,17 +22,17 @@ export interface BasicPersonResponse {
|
|||
|
||||
export const GET_PERSONS_SORTED_BY_ROLE = gql`
|
||||
query AllPeople {
|
||||
editors: allPeople(condition: { role: CANDYMAT_EDITOR }) {
|
||||
editors: allPeople(condition: { role: KANDIMAT_EDITOR }) {
|
||||
nodes {
|
||||
...BasicPersonFragment
|
||||
}
|
||||
}
|
||||
candidates: allPeople(condition: { role: CANDYMAT_CANDIDATE }) {
|
||||
candidates: allPeople(condition: { role: KANDIMAT_CANDIDATE }) {
|
||||
nodes {
|
||||
...BasicPersonFragment
|
||||
}
|
||||
}
|
||||
users: allPeople(condition: { role: CANDYMAT_PERSON }) {
|
||||
users: allPeople(condition: { role: KANDIMAT_PERSON }) {
|
||||
nodes {
|
||||
...BasicPersonFragment
|
||||
}
|
||||
|
|
|
@ -51,11 +51,11 @@ export default function ChangeRoleMenu(
|
|||
);
|
||||
const displayRole = (role: UppercaseUserRole) => {
|
||||
switch (role) {
|
||||
case "CANDYMAT_CANDIDATE":
|
||||
case "KANDIMAT_CANDIDATE":
|
||||
return "zu Kandidat:in machen";
|
||||
case "CANDYMAT_EDITOR":
|
||||
case "KANDIMAT_EDITOR":
|
||||
return "zu RedakteurIn machen";
|
||||
case "CANDYMAT_PERSON":
|
||||
case "KANDIMAT_PERSON":
|
||||
return "zu Standard User machen";
|
||||
}
|
||||
};
|
||||
|
|
|
@ -63,7 +63,7 @@ function CustomAppBar(): React.ReactElement {
|
|||
<MenuIcon />
|
||||
</IconButton>
|
||||
<Typography variant="h6" className={classes.title}>
|
||||
Candymat
|
||||
Kandimat
|
||||
</Typography>
|
||||
<ProfileMenu />
|
||||
</Toolbar>
|
||||
|
|
|
@ -24,14 +24,14 @@ const baseJwt: JwtPayload = {
|
|||
exp: 0,
|
||||
iat: 0,
|
||||
iss: "postgraphile",
|
||||
role: "candymat_person",
|
||||
role: "kandimat_person",
|
||||
person_row_id: 3,
|
||||
};
|
||||
|
||||
describe("As an editor, the main page", () => {
|
||||
const jwt: JwtPayload = {
|
||||
...baseJwt,
|
||||
role: "candymat_editor",
|
||||
role: "kandimat_editor",
|
||||
person_row_id: 1,
|
||||
};
|
||||
|
||||
|
@ -65,7 +65,7 @@ describe("As a candidate, the main page", () => {
|
|||
test("displays the candidate's home page ", () => {
|
||||
const jwt: JwtPayload = {
|
||||
...baseJwt,
|
||||
role: "candymat_candidate",
|
||||
role: "kandimat_candidate",
|
||||
person_row_id: 2,
|
||||
};
|
||||
renderMainPage(jwt);
|
||||
|
@ -81,7 +81,7 @@ describe("As a simple user, the main page", () => {
|
|||
test("displays the user's home page.", () => {
|
||||
const jwt: JwtPayload = {
|
||||
...baseJwt,
|
||||
role: "candymat_person",
|
||||
role: "kandimat_person",
|
||||
person_row_id: 3,
|
||||
};
|
||||
renderMainPage(jwt);
|
||||
|
|
|
@ -51,24 +51,24 @@ function Main(props: MainProps): ReactElement {
|
|||
|
||||
const getHomePage = (): ReactElement => {
|
||||
switch (props.userRole) {
|
||||
case "candymat_editor":
|
||||
case "kandimat_editor":
|
||||
return <HomePageEditor loggedInUserRowId={props.loggedInUserRowId} />;
|
||||
case "candymat_candidate":
|
||||
case "kandimat_candidate":
|
||||
return (
|
||||
<HomePageCandidate loggedInPersonRowId={props.loggedInUserRowId} />
|
||||
);
|
||||
case "candymat_person":
|
||||
case "kandimat_person":
|
||||
return <HomePageUser />;
|
||||
}
|
||||
};
|
||||
|
||||
const getMenuOptions = (): Array<MenuOption> => {
|
||||
switch (props.userRole) {
|
||||
case "candymat_editor":
|
||||
case "kandimat_editor":
|
||||
return Object.values(editorRoutes);
|
||||
case "candymat_candidate":
|
||||
case "kandimat_candidate":
|
||||
return Object.values(candidateRoutes);
|
||||
case "candymat_person":
|
||||
case "kandimat_person":
|
||||
return Object.values(userRoutes);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { parseJwt } from "./jwt";
|
||||
|
||||
describe("The parseJwt function", () => {
|
||||
test("parses a valid candymat jwt", () => {
|
||||
test("parses a valid kandimat jwt", () => {
|
||||
const validJwt =
|
||||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiY2FuZHltYXRfZWRpdG9yIiwicGVyc29uX3Jvd19pZCI6MSwiZXhwIjoxNjA5NDEyMTY4LCJpYXQiOjE2MDkyMzkzNjgsImF1ZCI6InBvc3RncmFwaGlsZSIsImlzcyI6InBvc3RncmFwaGlsZSJ9.6VLDBS5_HwgWIf_MKkMCuj4EVBZkbSGm87aWt5grP2M";
|
||||
|
||||
|
@ -9,7 +9,7 @@ describe("The parseJwt function", () => {
|
|||
|
||||
expect(jwt).not.toBeNull();
|
||||
expect(jwt?.person_row_id).toBe(1);
|
||||
expect(jwt?.role).toBe("candymat_editor");
|
||||
expect(jwt?.role).toBe("kandimat_editor");
|
||||
});
|
||||
|
||||
test("returns null if role claim is invalid", () => {
|
||||
|
|
|
@ -3,14 +3,14 @@ import { client } from "../backend/helper";
|
|||
type Claim = "role" | "person_row_id" | "exp" | "iat" | "aud" | "iss";
|
||||
|
||||
export type UppercaseUserRole =
|
||||
| "CANDYMAT_PERSON"
|
||||
| "CANDYMAT_EDITOR"
|
||||
| "CANDYMAT_CANDIDATE";
|
||||
| "KANDIMAT_PERSON"
|
||||
| "KANDIMAT_EDITOR"
|
||||
| "KANDIMAT_CANDIDATE";
|
||||
|
||||
export type UserRole =
|
||||
| "candymat_editor"
|
||||
| "candymat_candidate"
|
||||
| "candymat_person";
|
||||
| "kandimat_editor"
|
||||
| "kandimat_candidate"
|
||||
| "kandimat_person";
|
||||
|
||||
export interface JwtPayload {
|
||||
role: UserRole;
|
||||
|
@ -24,15 +24,15 @@ export interface JwtPayload {
|
|||
const CLAIMS: Claim[] = ["role", "person_row_id", "exp", "iat", "aud", "iss"];
|
||||
|
||||
export const UPPERCASE_USER_ROLES: UppercaseUserRole[] = [
|
||||
"CANDYMAT_PERSON",
|
||||
"CANDYMAT_EDITOR",
|
||||
"CANDYMAT_CANDIDATE",
|
||||
"KANDIMAT_PERSON",
|
||||
"KANDIMAT_EDITOR",
|
||||
"KANDIMAT_CANDIDATE",
|
||||
];
|
||||
|
||||
export const USER_ROLES: UserRole[] = [
|
||||
"candymat_editor",
|
||||
"candymat_candidate",
|
||||
"candymat_person",
|
||||
"kandimat_editor",
|
||||
"kandimat_candidate",
|
||||
"kandimat_person",
|
||||
];
|
||||
|
||||
export const getRawJsonWebToken = (): string | null => {
|
||||
|
|
Loading…
Reference in a new issue