Rename candymat -> kandimat everywhere

Furthermore, submodule link to new public repo
This commit is contained in:
Christoph Lienhard 2022-02-02 13:13:34 +01:00
parent fafc3722cd
commit f7a56a0bed
26 changed files with 174 additions and 174 deletions

4
.env
View File

@ -1,7 +1,7 @@
COMPOSE_FILE=docker-compose.dev.yml COMPOSE_FILE=docker-compose.dev.yml
COMPOSE_PROJECT_NAME=candymat COMPOSE_PROJECT_NAME=kandimat
# Backend vars # Backend vars
POSTGRES_PASSWORD=postgres!dev 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 JWT_SECRET=asdfasdfasdf

6
.gitmodules vendored
View File

@ -1,4 +1,4 @@
[submodule "candymat-user-app"] [submodule "candymat-user-app"]
path = candymat-user-app path = kandimat-user-app
url = git@git.verdigado.com:Netzbegruenung/candymat-user-app.git url = git@git.verdigado.com:NB-Public/kandimat-user-app.git
branch = develop-candymat branch = main

View File

@ -1,8 +1,8 @@
# Candymat - Wahl-o-Mat fuer Personalwahlen # Kandimat - Wahl-o-Mat fuer Personalwahlen
## Introduction ## Introduction
The candymat is a Wahl-o-Mat for elections of candidates. The kandimat is a Wahl-o-Mat for elections of candidates.
## Services ## 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. 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) ### 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 ### Check-out repository
* [Install git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) * [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: * To get the (external) user-app source:
``` ```
git submodule update --init 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 To start with a clean database, either delete the volume from the postgres configuration in the compose file
or run or run
``` ```
docker container rm candymat_postgres_1 docker container rm kandimat_postgres_1
docker volume rm candymat_db-data docker volume rm kandimat_db-data
``` ```
before starting docker-compose. before starting docker-compose.

View File

@ -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. Postgraphile generates a Graphql backend based on the underlying postgres schema.
## Introduction ## Introduction
@ -29,7 +29,7 @@ in setups where there is no public access to the data.
#### Authentication #### Authentication
Authentication is handled via jwt. 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 ## Manually test the backend

View File

@ -1,5 +1,5 @@
# Postgres database setup # Postgres database setup
POSTGRES_USER=candymat_postgraphile POSTGRES_USER=kandimat_postgraphile
# Password is handled by docker-compose # Password is handled by docker-compose
POSTGRES_DB=candymat_db POSTGRES_DB=kandimat_db
POSTGRES_SCHEMA=candymat_data POSTGRES_SCHEMA=kandimat_data

View File

@ -1,10 +1,10 @@
#!/bin/bash #!/bin/bash
docker-compose stop postgres 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" echo "Going to remove container: $CONTAINER"
docker container rm $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 ..." echo "Deleting db-data docker volumes ..."
VOLUMES=$(docker volume ls -q | grep "db-data") VOLUMES=$(docker volume ls -q | grep "db-data")
for volume in ${VOLUMES[@]}; do for volume in ${VOLUMES[@]}; do

View File

@ -1,28 +1,28 @@
\connect candymat_db \connect kandimat_db
-- Create schema for candymat_data -- Create schema for kandimat_data
create SCHEMA candymat_data; create SCHEMA kandimat_data;
create SCHEMA candymat_data_privat; create SCHEMA kandimat_data_privat;
-- create roles -- create roles
create role candymat_person; create role kandimat_person;
create role candymat_anonymous; create role kandimat_anonymous;
create role candymat_editor; create role kandimat_editor;
create role candymat_candidate; create role kandimat_candidate;
grant candymat_editor to candymat_postgraphile; grant kandimat_editor to kandimat_postgraphile;
grant candymat_candidate to candymat_postgraphile; grant kandimat_candidate to kandimat_postgraphile;
grant candymat_person to candymat_postgraphile, candymat_candidate, candymat_editor; grant kandimat_person to kandimat_postgraphile, kandimat_candidate, kandimat_editor;
grant candymat_anonymous to candymat_postgraphile; grant kandimat_anonymous to kandimat_postgraphile;
create type candymat_data.role as enum ( create type kandimat_data.role as enum (
'candymat_editor', 'kandimat_editor',
'candymat_candidate', 'kandimat_candidate',
'candymat_person' 'kandimat_person'
); );
-- set table wide permissions -- 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 -- make functions non executeable w/o further checks
alter default privileges revoke execute on functions from public; alter default privileges revoke execute on functions from public;

View File

@ -1,43 +1,43 @@
-- create table for users -- create table for users
create table candymat_data.person create table kandimat_data.person
( (
row_id serial primary key, row_id serial primary key,
first_name character varying(200) check (first_name <> ''), first_name character varying(200) check (first_name <> ''),
last_name character varying(200) check (last_name <> ''), last_name character varying(200) check (last_name <> ''),
about character varying(2000), about character varying(2000),
created_at timestamp default now(), 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 -- 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 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 ~* '^.+@.+\..+$'), email character varying(320) not null unique check (email ~* '^.+@.+\..+$'),
password_hash character varying(256) not null password_hash character varying(256) not null
); );
alter table candymat_data.person alter table kandimat_data.person
enable row level security; 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); 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); using (row_id = nullif(current_setting('jwt.claims.person_row_id', true), '')::integer);
-- The following enables viewing candidates and editors information for every person. -- The following enables viewing candidates and editors information for every person.
-- This may be changed to only enable registered (and verified) persons. -- This may be changed to only enable registered (and verified) persons.
create policy select_person_public create policy select_person_public
on candymat_data.person on kandimat_data.person
for select 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 (role in ('candymat_editor', 'candymat_candidate')); using (role in ('kandimat_editor', 'kandimat_candidate'));
-- Editors can see all registered persons in order to elevate their privileges -- Editors can see all registered persons in order to elevate their privileges
create policy select_person_editor create policy select_person_editor
on candymat_data.person on kandimat_data.person
for select for select
to candymat_editor to kandimat_editor
using (true); using (true);

View File

@ -1,51 +1,51 @@
-- create table for categories -- create table for categories
create table candymat_data.category create table kandimat_data.category
( (
row_id serial primary key, row_id serial primary key,
title character varying(300) UNIQUE NOT NULL check ( title <> '' ), title character varying(300) UNIQUE NOT NULL check ( title <> '' ),
description character varying(15000) description character varying(15000)
); );
grant select on table candymat_data.category to candymat_person; grant select on table kandimat_data.category to kandimat_person;
-- the following line is only necessary as long as the candymat should be publicly accessible -- the following line is only necessary as long as the kandimat should be publicly accessible
grant select on table candymat_data.category to candymat_anonymous; grant select on table kandimat_data.category to kandimat_anonymous;
grant insert, update, delete on table candymat_data.category to candymat_editor; grant insert, update, delete on table kandimat_data.category to kandimat_editor;
grant usage on sequence candymat_data.category_row_id_seq to candymat_editor; grant usage on sequence kandimat_data.category_row_id_seq to kandimat_editor;
-- create table for questions -- create table for questions
create table candymat_data.question create table kandimat_data.question
( (
row_id serial primary key, 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 <> '' ), title character varying(3000) UNIQUE NOT NULL check ( title <> '' ),
description character varying(15000) description character varying(15000)
); );
grant select on table candymat_data.question to candymat_person; grant select on table kandimat_data.question to kandimat_person;
-- the following line is only necessary as long as the candymat should be publicly accessible -- the following line is only necessary as long as the kandimat should be publicly accessible
grant select on table candymat_data.question to candymat_anonymous; grant select on table kandimat_data.question to kandimat_anonymous;
grant insert, update, delete on table candymat_data.question to candymat_editor; grant insert, update, delete on table kandimat_data.question to kandimat_editor;
grant usage on sequence candymat_data.question_row_id_seq to candymat_editor; grant usage on sequence kandimat_data.question_row_id_seq to kandimat_editor;
-- create table for answers -- 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, question_row_id integer REFERENCES kandimat_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, 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), position integer NOT NULL check (position between 0 and 3),
text character varying(15000), text character varying(15000),
created_at timestamp default now(), created_at timestamp default now(),
primary key (question_row_id, person_row_id) primary key (question_row_id, person_row_id)
); );
grant select on table candymat_data.answer to candymat_person; grant select on table kandimat_data.answer to kandimat_person;
-- the following line is only necessary as long as the candymat should be publicly accessible -- the following line is only necessary as long as the kandimat should be publicly accessible
grant select on table candymat_data.answer to candymat_anonymous; grant select on table kandimat_data.answer to kandimat_anonymous;
grant insert, update, delete on table candymat_data.answer to candymat_candidate; 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; 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); using (person_row_id = nullif(current_setting('jwt.claims.person_row_id', true), '')::integer);
create policy select_answer create policy select_answer
on candymat_data.answer on kandimat_data.answer
for select 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); using (true);

View File

@ -2,8 +2,8 @@ create extension if not exists "pgcrypto";
-- Define JWT claim structure -- Define JWT claim structure
drop type if exists candymat_data.jwt_token cascade; drop type if exists kandimat_data.jwt_token cascade;
create type candymat_data.jwt_token as create type kandimat_data.jwt_token as
( (
role text, role text,
person_row_id integer, person_row_id integer,
@ -12,28 +12,28 @@ create type candymat_data.jwt_token as
-- Function to get the currently logged-in person -- Function to get the currently logged-in person
drop function if exists candymat_data.current_person; drop function if exists kandimat_data.current_person;
create function candymat_data.current_person( create function kandimat_data.current_person(
) returns candymat_data.person as ) returns kandimat_data.person as
$$ $$
select * select *
from candymat_data.person from kandimat_data.person
where row_id = nullif(current_setting('jwt.claims.person_row_id', true), '')::integer where row_id = nullif(current_setting('jwt.claims.person_row_id', true), '')::integer
$$ language sql stable; $$ 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 -- Function to register a new user
drop function if exists candymat_data.register_person; drop function if exists kandimat_data.register_person;
create function candymat_data.register_person( create function kandimat_data.register_person(
first_name text, first_name text,
last_name text, last_name text,
email text, email text,
password text password text
) returns candymat_data.person as ) returns kandimat_data.person as
$$ $$
declare declare
person candymat_data.person; person kandimat_data.person;
begin begin
if (trim(register_person.first_name) <> '') is not true then if (trim(register_person.first_name) <> '') is not true then
raise 'Invalid first name: ''%''', register_person.first_name; raise 'Invalid first name: ''%''', register_person.first_name;
@ -44,70 +44,70 @@ begin
if (trim(register_person.password) <> '') is not true then if (trim(register_person.password) <> '') is not true then
raise 'Invalid password.'; raise 'Invalid password.';
end if; end if;
insert into candymat_data.person (first_name, last_name) insert into kandimat_data.person (first_name, last_name)
values ($1, $2) values ($1, $2)
returning * into person; 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'))); values (person.row_id, $3, crypt($4, gen_salt('bf')));
return person; return person;
end ; end ;
$$ language plpgsql strict $$ language plpgsql strict
security definer; 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 -- Authenticate: Login for user
drop function if exists candymat_data.authenticate; drop function if exists kandimat_data.authenticate;
create function candymat_data.authenticate( create function kandimat_data.authenticate(
email text, email text,
password text password text
) returns candymat_data.jwt_token as ) returns kandimat_data.jwt_token as
$$ $$
declare declare
account candymat_data_privat.person_account; account kandimat_data_privat.person_account;
declare person candymat_data.person; declare person kandimat_data.person;
begin begin
select a.* select a.*
into account into account
from candymat_data_privat.person_account as a from kandimat_data_privat.person_account as a
where a.email = $1; where a.email = $1;
select p.* select p.*
into person into person
from candymat_data.person as p from kandimat_data.person as p
where p.row_id = account.person_row_id; where p.row_id = account.person_row_id;
if account.password_hash = crypt(password, account.password_hash) then if account.password_hash = crypt(password, account.password_hash) then
return (person.role, account.person_row_id, 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 else
return null; return null;
end if; end if;
end; end;
$$ language plpgsql strict $$ language plpgsql strict
security definer; 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. -- Change role: Changes role for a given user. Only editors are allowed to use it.
drop function if exists candymat_data.change_role; drop function if exists kandimat_data.change_role;
create function candymat_data.change_role( create function kandimat_data.change_role(
person_row_id integer, 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 declare
person candymat_data.person; person kandimat_data.person;
begin begin
update candymat_data.person update kandimat_data.person
set role = new_role set role = new_role
where candymat_data.person.row_id = $1 where kandimat_data.person.row_id = $1
returning * into person; returning * into person;
return person; return person;
end; end;
$$ language plpgsql strict security definer; $$ 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;

View File

@ -1,40 +1,40 @@
select candymat_data.register_person( select kandimat_data.register_person(
'Erika', 'Erika',
'Mustermann', 'Mustermann',
'erika@mustermann.de', 'erika@mustermann.de',
'password' 'password'
); );
select candymat_data.change_role( select kandimat_data.change_role(
1, 1,
'candymat_editor' 'kandimat_editor'
); );
select candymat_data.register_person( select kandimat_data.register_person(
'Max', 'Max',
'Mustermann', 'Mustermann',
'max@mustermann.de', 'max@mustermann.de',
'password' 'password'
); );
select candymat_data.change_role( select kandimat_data.change_role(
2, 2,
'candymat_candidate' 'kandimat_candidate'
); );
select candymat_data.register_person( select kandimat_data.register_person(
'Tricia', 'Tricia',
'McMillan', 'McMillan',
'trillian@universe.com', 'trillian@universe.com',
'password' 'password'
); );
select candymat_data.change_role( select kandimat_data.change_role(
3, 3,
'candymat_candidate' 'kandimat_candidate'
); );
select candymat_data.register_person( select kandimat_data.register_person(
'Happy', 'Happy',
'User', 'User',
'happy@user.de', 'happy@user.de',
'password' 'password'
); );
select candymat_data.change_role( select kandimat_data.change_role(
4, 4,
'candymat_person' 'kandimat_person'
); );

View File

@ -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.'); ('Umwelt', 'Themen rund um Naturschutz usw.');
insert into candymat_data.category (title, description) values insert into kandimat_data.category (title, description) values
('Sonstiges', ''); ('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 ...'); (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 ...'); (2, 'Umgehungsstraße XY?', 'Zur Entlastung der Hauptstraße ...');

View File

@ -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'); 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'); 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'); 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'); values (2, 3, 3, 'keine lust mehr');

@ -1 +0,0 @@
Subproject commit d7f669bc9978b0f0284bfc6d17552a75fbc13a7c

View File

@ -15,7 +15,7 @@ services:
user-app: user-app:
build: build:
context: ./candymat-user-app/ context: kandimat-user-app/
dockerfile: ./dev.Dockerfile dockerfile: ./dev.Dockerfile
depends_on: depends_on:
- graphql - graphql
@ -25,7 +25,7 @@ services:
- frontend - frontend
postgres: postgres:
image: candymat-postgres:11.5 image: kandimat-postgres:11.5
build: build:
dockerfile: ./Dockerfile dockerfile: ./Dockerfile
context: ./backend/ context: ./backend/
@ -53,9 +53,9 @@ services:
"--host", "0.0.0.0", "--host", "0.0.0.0",
"--port", "5000", "--port", "5000",
"--cors", "--cors",
"--schema", "candymat_data", "--schema", "kandimat_data",
"--default-role", "candymat_anonymous", "--default-role", "kandimat_anonymous",
"--jwt-token-identifier", "candymat_data.jwt_token", "--jwt-token-identifier", "kandimat_data.jwt_token",
"--jwt-secret", $JWT_SECRET, "--jwt-secret", $JWT_SECRET,
"--watch", "--watch",
"--retry-on-init-fail", "--retry-on-init-fail",

1
kandimat-user-app Submodule

@ -0,0 +1 @@
Subproject commit dc1602b6e87c80d3c37f92bc87f02c98865895d3

View File

@ -7,7 +7,7 @@
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="#000000" />
<meta <meta
name="description" 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" /> <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. 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`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title>Candymat Redaktion</title> <title>Kandimat Redaktion</title>
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>

View File

@ -1,6 +1,6 @@
{ {
"short_name": "Candymat Redaktion", "short_name": "Kandimat Redaktion",
"name": "Candymat Redaktions App", "name": "Kandimat Redaktions App",
"icons": [ "icons": [
{ {
"src": "favicon.ico", "src": "favicon.ico",

View File

@ -12,7 +12,7 @@ export const getPersonsByRoleAllFilledData: GetPersonsSortedByRoleResponse = {
rowId: 1, rowId: 1,
firstName: "Erika", firstName: "Erika",
lastName: "Mustermann", lastName: "Mustermann",
role: "CANDYMAT_EDITOR", role: "KANDIMAT_EDITOR",
__typename: "Person", __typename: "Person",
}, },
], ],
@ -25,7 +25,7 @@ export const getPersonsByRoleAllFilledData: GetPersonsSortedByRoleResponse = {
rowId: 2, rowId: 2,
firstName: "Max", firstName: "Max",
lastName: "Mustermann", lastName: "Mustermann",
role: "CANDYMAT_CANDIDATE", role: "KANDIMAT_CANDIDATE",
__typename: "Person", __typename: "Person",
}, },
{ {
@ -33,7 +33,7 @@ export const getPersonsByRoleAllFilledData: GetPersonsSortedByRoleResponse = {
rowId: 3, rowId: 3,
firstName: "Tricia", firstName: "Tricia",
lastName: "McMillan", lastName: "McMillan",
role: "CANDYMAT_CANDIDATE", role: "KANDIMAT_CANDIDATE",
__typename: "Person", __typename: "Person",
}, },
], ],
@ -46,7 +46,7 @@ export const getPersonsByRoleAllFilledData: GetPersonsSortedByRoleResponse = {
rowId: 4, rowId: 4,
firstName: "Happy", firstName: "Happy",
lastName: "User", lastName: "User",
role: "CANDYMAT_PERSON", role: "KANDIMAT_PERSON",
__typename: "Person", __typename: "Person",
}, },
], ],
@ -76,7 +76,7 @@ export const getPersonsByRoleNoCandidatesData: GetPersonsSortedByRoleResponse =
rowId: 1, rowId: 1,
firstName: "Erika", firstName: "Erika",
lastName: "Mustermann", lastName: "Mustermann",
role: "CANDYMAT_EDITOR", role: "KANDIMAT_EDITOR",
__typename: "Person", __typename: "Person",
}, },
], ],
@ -93,7 +93,7 @@ export const getPersonsByRoleNoCandidatesData: GetPersonsSortedByRoleResponse =
rowId: 2, rowId: 2,
firstName: "Max", firstName: "Max",
lastName: "Mustermann", lastName: "Mustermann",
role: "CANDYMAT_PERSON", role: "KANDIMAT_PERSON",
__typename: "Person", __typename: "Person",
}, },
{ {
@ -101,7 +101,7 @@ export const getPersonsByRoleNoCandidatesData: GetPersonsSortedByRoleResponse =
rowId: 3, rowId: 3,
firstName: "Tricia", firstName: "Tricia",
lastName: "McMillan", lastName: "McMillan",
role: "CANDYMAT_PERSON", role: "KANDIMAT_PERSON",
__typename: "Person", __typename: "Person",
}, },
{ {
@ -109,7 +109,7 @@ export const getPersonsByRoleNoCandidatesData: GetPersonsSortedByRoleResponse =
rowId: 4, rowId: 4,
firstName: "Happy", firstName: "Happy",
lastName: "User", lastName: "User",
role: "CANDYMAT_PERSON", role: "KANDIMAT_PERSON",
__typename: "Person", __typename: "Person",
}, },
], ],

View File

@ -22,17 +22,17 @@ export interface BasicPersonResponse {
export const GET_PERSONS_SORTED_BY_ROLE = gql` export const GET_PERSONS_SORTED_BY_ROLE = gql`
query AllPeople { query AllPeople {
editors: allPeople(condition: { role: CANDYMAT_EDITOR }) { editors: allPeople(condition: { role: KANDIMAT_EDITOR }) {
nodes { nodes {
...BasicPersonFragment ...BasicPersonFragment
} }
} }
candidates: allPeople(condition: { role: CANDYMAT_CANDIDATE }) { candidates: allPeople(condition: { role: KANDIMAT_CANDIDATE }) {
nodes { nodes {
...BasicPersonFragment ...BasicPersonFragment
} }
} }
users: allPeople(condition: { role: CANDYMAT_PERSON }) { users: allPeople(condition: { role: KANDIMAT_PERSON }) {
nodes { nodes {
...BasicPersonFragment ...BasicPersonFragment
} }

View File

@ -51,11 +51,11 @@ export default function ChangeRoleMenu(
); );
const displayRole = (role: UppercaseUserRole) => { const displayRole = (role: UppercaseUserRole) => {
switch (role) { switch (role) {
case "CANDYMAT_CANDIDATE": case "KANDIMAT_CANDIDATE":
return "zu Kandidat:in machen"; return "zu Kandidat:in machen";
case "CANDYMAT_EDITOR": case "KANDIMAT_EDITOR":
return "zu RedakteurIn machen"; return "zu RedakteurIn machen";
case "CANDYMAT_PERSON": case "KANDIMAT_PERSON":
return "zu Standard User machen"; return "zu Standard User machen";
} }
}; };

View File

@ -63,7 +63,7 @@ function CustomAppBar(): React.ReactElement {
<MenuIcon /> <MenuIcon />
</IconButton> </IconButton>
<Typography variant="h6" className={classes.title}> <Typography variant="h6" className={classes.title}>
Candymat Kandimat
</Typography> </Typography>
<ProfileMenu /> <ProfileMenu />
</Toolbar> </Toolbar>

View File

@ -24,14 +24,14 @@ const baseJwt: JwtPayload = {
exp: 0, exp: 0,
iat: 0, iat: 0,
iss: "postgraphile", iss: "postgraphile",
role: "candymat_person", role: "kandimat_person",
person_row_id: 3, person_row_id: 3,
}; };
describe("As an editor, the main page", () => { describe("As an editor, the main page", () => {
const jwt: JwtPayload = { const jwt: JwtPayload = {
...baseJwt, ...baseJwt,
role: "candymat_editor", role: "kandimat_editor",
person_row_id: 1, person_row_id: 1,
}; };
@ -65,7 +65,7 @@ describe("As a candidate, the main page", () => {
test("displays the candidate's home page ", () => { test("displays the candidate's home page ", () => {
const jwt: JwtPayload = { const jwt: JwtPayload = {
...baseJwt, ...baseJwt,
role: "candymat_candidate", role: "kandimat_candidate",
person_row_id: 2, person_row_id: 2,
}; };
renderMainPage(jwt); renderMainPage(jwt);
@ -81,7 +81,7 @@ describe("As a simple user, the main page", () => {
test("displays the user's home page.", () => { test("displays the user's home page.", () => {
const jwt: JwtPayload = { const jwt: JwtPayload = {
...baseJwt, ...baseJwt,
role: "candymat_person", role: "kandimat_person",
person_row_id: 3, person_row_id: 3,
}; };
renderMainPage(jwt); renderMainPage(jwt);

View File

@ -51,24 +51,24 @@ function Main(props: MainProps): ReactElement {
const getHomePage = (): ReactElement => { const getHomePage = (): ReactElement => {
switch (props.userRole) { switch (props.userRole) {
case "candymat_editor": case "kandimat_editor":
return <HomePageEditor loggedInUserRowId={props.loggedInUserRowId} />; return <HomePageEditor loggedInUserRowId={props.loggedInUserRowId} />;
case "candymat_candidate": case "kandimat_candidate":
return ( return (
<HomePageCandidate loggedInPersonRowId={props.loggedInUserRowId} /> <HomePageCandidate loggedInPersonRowId={props.loggedInUserRowId} />
); );
case "candymat_person": case "kandimat_person":
return <HomePageUser />; return <HomePageUser />;
} }
}; };
const getMenuOptions = (): Array<MenuOption> => { const getMenuOptions = (): Array<MenuOption> => {
switch (props.userRole) { switch (props.userRole) {
case "candymat_editor": case "kandimat_editor":
return Object.values(editorRoutes); return Object.values(editorRoutes);
case "candymat_candidate": case "kandimat_candidate":
return Object.values(candidateRoutes); return Object.values(candidateRoutes);
case "candymat_person": case "kandimat_person":
return Object.values(userRoutes); return Object.values(userRoutes);
} }
}; };

View File

@ -1,7 +1,7 @@
import { parseJwt } from "./jwt"; import { parseJwt } from "./jwt";
describe("The parseJwt function", () => { describe("The parseJwt function", () => {
test("parses a valid candymat jwt", () => { test("parses a valid kandimat jwt", () => {
const validJwt = const validJwt =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiY2FuZHltYXRfZWRpdG9yIiwicGVyc29uX3Jvd19pZCI6MSwiZXhwIjoxNjA5NDEyMTY4LCJpYXQiOjE2MDkyMzkzNjgsImF1ZCI6InBvc3RncmFwaGlsZSIsImlzcyI6InBvc3RncmFwaGlsZSJ9.6VLDBS5_HwgWIf_MKkMCuj4EVBZkbSGm87aWt5grP2M"; "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiY2FuZHltYXRfZWRpdG9yIiwicGVyc29uX3Jvd19pZCI6MSwiZXhwIjoxNjA5NDEyMTY4LCJpYXQiOjE2MDkyMzkzNjgsImF1ZCI6InBvc3RncmFwaGlsZSIsImlzcyI6InBvc3RncmFwaGlsZSJ9.6VLDBS5_HwgWIf_MKkMCuj4EVBZkbSGm87aWt5grP2M";
@ -9,7 +9,7 @@ describe("The parseJwt function", () => {
expect(jwt).not.toBeNull(); expect(jwt).not.toBeNull();
expect(jwt?.person_row_id).toBe(1); 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", () => { test("returns null if role claim is invalid", () => {

View File

@ -3,14 +3,14 @@ import { client } from "../backend/helper";
type Claim = "role" | "person_row_id" | "exp" | "iat" | "aud" | "iss"; type Claim = "role" | "person_row_id" | "exp" | "iat" | "aud" | "iss";
export type UppercaseUserRole = export type UppercaseUserRole =
| "CANDYMAT_PERSON" | "KANDIMAT_PERSON"
| "CANDYMAT_EDITOR" | "KANDIMAT_EDITOR"
| "CANDYMAT_CANDIDATE"; | "KANDIMAT_CANDIDATE";
export type UserRole = export type UserRole =
| "candymat_editor" | "kandimat_editor"
| "candymat_candidate" | "kandimat_candidate"
| "candymat_person"; | "kandimat_person";
export interface JwtPayload { export interface JwtPayload {
role: UserRole; role: UserRole;
@ -24,15 +24,15 @@ export interface JwtPayload {
const CLAIMS: Claim[] = ["role", "person_row_id", "exp", "iat", "aud", "iss"]; const CLAIMS: Claim[] = ["role", "person_row_id", "exp", "iat", "aud", "iss"];
export const UPPERCASE_USER_ROLES: UppercaseUserRole[] = [ export const UPPERCASE_USER_ROLES: UppercaseUserRole[] = [
"CANDYMAT_PERSON", "KANDIMAT_PERSON",
"CANDYMAT_EDITOR", "KANDIMAT_EDITOR",
"CANDYMAT_CANDIDATE", "KANDIMAT_CANDIDATE",
]; ];
export const USER_ROLES: UserRole[] = [ export const USER_ROLES: UserRole[] = [
"candymat_editor", "kandimat_editor",
"candymat_candidate", "kandimat_candidate",
"candymat_person", "kandimat_person",
]; ];
export const getRawJsonWebToken = (): string | null => { export const getRawJsonWebToken = (): string | null => {