From 982ef13ec86e85336c41427f36391cc5c2ce955f Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 12 Mar 2022 02:00:45 +0100 Subject: [PATCH 01/34] require 53% coverage on backend --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c9fda7b2a..4f4db310e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -531,7 +531,7 @@ jobs: report_name: Coverage Backend type: lcov result_path: ./backend/coverage/lcov.info - min_coverage: 48 + min_coverage: 53 token: ${{ github.token }} ########################################################################## From afb54b885bf1947caec2e01f234877710e50e682 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 12 Mar 2022 02:10:04 +0100 Subject: [PATCH 02/34] only rotate logfiles --- deployment/bare_metal/logrotate/gradido.conf.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/bare_metal/logrotate/gradido.conf.template b/deployment/bare_metal/logrotate/gradido.conf.template index c038f8e75..c543b54c2 100644 --- a/deployment/bare_metal/logrotate/gradido.conf.template +++ b/deployment/bare_metal/logrotate/gradido.conf.template @@ -1,4 +1,4 @@ -$GRADIDO_LOG_PATH/* { +$GRADIDO_LOG_PATH/*.log { weekly rotate 26 size 10M From 61e5ed287878d742f3960228507535ac4362f2ee Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 12 Mar 2022 02:47:45 +0100 Subject: [PATCH 03/34] date for log files save update log --- deployment/bare_metal/start.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh index 616e4b8ab..e82516dcc 100755 --- a/deployment/bare_metal/start.sh +++ b/deployment/bare_metal/start.sh @@ -42,9 +42,16 @@ if [ -f $LOCK_FILE ] ; then fi touch $LOCK_FILE +# find today string +TODAY=$(date +"%Y-%m-%d") + # Create a new updating.html from the template \cp $SCRIPT_DIR/nginx/update-page/updating.html.template $UPDATE_HTML +# redirect all output of the script to the UPDATE_HTML and also have things on console +# TODO: this might pose a security risk +exec 3>&1 1>>$UPDATE_HTML 2>&1 + # configure nginx for the update-page echo 'Configuring nginx to serve the update-page
' >> $UPDATE_HTML rm /etc/nginx/sites-enabled/gradido.conf @@ -113,7 +120,7 @@ yarn build # TODO maybe handle this differently? export NODE_ENV=production pm2 delete gradido-backend -pm2 start --name gradido-backend "yarn --cwd $PROJECT_ROOT/backend start" -l $GRADIDO_LOG_PATH/pm2.backend.log --log-date-format 'DD-MM HH:mm:ss.SSS' +pm2 start --name gradido-backend "yarn --cwd $PROJECT_ROOT/backend start" -l $GRADIDO_LOG_PATH/pm2.backend.$TODAY.log --log-date-format 'DD-MM HH:mm:ss.SSS' pm2 save # Install & build frontend @@ -126,7 +133,7 @@ yarn build # TODO maybe handle this differently? export NODE_ENV=production pm2 delete gradido-frontend -pm2 start --name gradido-frontend "yarn --cwd $PROJECT_ROOT/frontend start" -l $GRADIDO_LOG_PATH/pm2.frontend.log --log-date-format 'DD-MM HH:mm:ss.SSS' +pm2 start --name gradido-frontend "yarn --cwd $PROJECT_ROOT/frontend start" -l $GRADIDO_LOG_PATH/pm2.frontend.$TODAY.log --log-date-format 'DD-MM HH:mm:ss.SSS' pm2 save # Install & build admin @@ -139,7 +146,7 @@ yarn build # TODO maybe handle this differently? export NODE_ENV=production pm2 delete gradido-admin -pm2 start --name gradido-admin "yarn --cwd $PROJECT_ROOT/admin start" -l $GRADIDO_LOG_PATH/pm2.admin.log --log-date-format 'DD-MM HH:mm:ss.SSS' +pm2 start --name gradido-admin "yarn --cwd $PROJECT_ROOT/admin start" -l $GRADIDO_LOG_PATH/pm2.admin.$TODAY.log --log-date-format 'DD-MM HH:mm:ss.SSS' pm2 save # let nginx showing gradido @@ -148,5 +155,8 @@ ln -s /etc/nginx/sites-available/gradido.conf /etc/nginx/sites-enabled/ rm /etc/nginx/sites-enabled/update-page.conf sudo /etc/init.d/nginx restart +# keep the update log +cat $UPDATE_HTML >> $GRADIDO_LOG_PATH/update.$TODAY.log + # release lock rm $LOCK_FILE \ No newline at end of file From cf36ab72ee930e1d8998dfb20028a662f272b699 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 12 Mar 2022 02:55:27 +0100 Subject: [PATCH 04/34] fetch all for tag compatibility --- deployment/bare_metal/start.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh index e82516dcc..9863bbc2a 100755 --- a/deployment/bare_metal/start.sh +++ b/deployment/bare_metal/start.sh @@ -66,7 +66,8 @@ pm2 stop all BRANCH=${1:-master} echo "Starting with git pull - branch:$BRANCH
" >> $UPDATE_HTML cd $PROJECT_ROOT -git fetch origin $BRANCH +# TODO: this overfetches alot, but ensures we can use start.sh with tags +git fetch origin --all git checkout $BRANCH git pull export BUILD_COMMIT="$(git rev-parse HEAD)" From b5ddd0359b9bcdfe1062683aec11f16787faa788 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 12 Mar 2022 03:03:16 +0100 Subject: [PATCH 05/34] use
 tag

---
 .../nginx/update-page/updating.html.template  |  6 +++---
 deployment/bare_metal/start.sh                | 20 +++++++++----------
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/deployment/bare_metal/nginx/update-page/updating.html.template b/deployment/bare_metal/nginx/update-page/updating.html.template
index a88a40b0f..356a9f139 100644
--- a/deployment/bare_metal/nginx/update-page/updating.html.template
+++ b/deployment/bare_metal/nginx/update-page/updating.html.template
@@ -1,3 +1,3 @@
-Gradido is currently updating...
-please stand by and try again in some minutes
-
\ No newline at end of file +
+Gradido is currently updating...
+please stand by and try again in some minutes
diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh
index 9863bbc2a..ede5cab5d 100755
--- a/deployment/bare_metal/start.sh
+++ b/deployment/bare_metal/start.sh
@@ -53,18 +53,18 @@ TODAY=$(date +"%Y-%m-%d")
 exec 3>&1 1>>$UPDATE_HTML 2>&1
 
 # configure nginx for the update-page
-echo 'Configuring nginx to serve the update-page
' >> $UPDATE_HTML +echo 'Configuring nginx to serve the update-page' >> $UPDATE_HTML rm /etc/nginx/sites-enabled/gradido.conf ln -s /etc/nginx/sites-available/update-page.conf /etc/nginx/sites-enabled/ sudo /etc/init.d/nginx restart # stop all services -echo 'Stopping all Gradido services
' >> $UPDATE_HTML +echo 'Stopping all Gradido services' >> $UPDATE_HTML pm2 stop all # git BRANCH=${1:-master} -echo "Starting with git pull - branch:$BRANCH
" >> $UPDATE_HTML +echo "Starting with git pull - branch:$BRANCH" >> $UPDATE_HTML cd $PROJECT_ROOT # TODO: this overfetches alot, but ensures we can use start.sh with tags git fetch origin --all @@ -73,7 +73,7 @@ git pull export BUILD_COMMIT="$(git rev-parse HEAD)" # Generate gradido.conf from template -echo 'Generate new gradido nginx config
' >> $UPDATE_HTML +echo 'Generate new gradido nginx config' >> $UPDATE_HTML case "$NGINX_SSL" in true) TEMPLATE_FILE="gradido.conf.ssl.template" ;; *) TEMPLATE_FILE="gradido.conf.template" ;; @@ -81,7 +81,7 @@ esac envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $NGINX_CONFIG_DIR/$TEMPLATE_FILE > $NGINX_CONFIG_DIR/gradido.conf # Generate update-page.conf from template -echo 'Generate new update-page nginx config
' >> $UPDATE_HTML +echo 'Generate new update-page nginx config' >> $UPDATE_HTML case "$NGINX_SSL" in true) TEMPLATE_FILE="update-page.conf.ssl.template" ;; *) TEMPLATE_FILE="update-page.conf.template" ;; @@ -99,7 +99,7 @@ envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/frontend/.env envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/admin/.env.template > $PROJECT_ROOT/admin/.env # Install & build database -echo 'Updating database
' >> $UPDATE_HTML +echo 'Updating database' >> $UPDATE_HTML cd $PROJECT_ROOT/database yarn install yarn build @@ -112,7 +112,7 @@ else fi # Install & build backend -echo 'Updating backend
' >> $UPDATE_HTML +echo 'Updating backend' >> $UPDATE_HTML cd $PROJECT_ROOT/backend # TODO maybe handle this differently? unset NODE_ENV @@ -125,7 +125,7 @@ pm2 start --name gradido-backend "yarn --cwd $PROJECT_ROOT/backend start" -l $GR pm2 save # Install & build frontend -echo 'Updating frontend
' >> $UPDATE_HTML +echo 'Updating frontend' >> $UPDATE_HTML cd $PROJECT_ROOT/frontend # TODO maybe handle this differently? unset NODE_ENV @@ -138,7 +138,7 @@ pm2 start --name gradido-frontend "yarn --cwd $PROJECT_ROOT/frontend start" -l $ pm2 save # Install & build admin -echo 'Updating admin
' >> $UPDATE_HTML +echo 'Updating admin' >> $UPDATE_HTML cd $PROJECT_ROOT/admin # TODO maybe handle this differently? unset NODE_ENV @@ -151,7 +151,7 @@ pm2 start --name gradido-admin "yarn --cwd $PROJECT_ROOT/admin start" -l $GRADID pm2 save # let nginx showing gradido -echo 'Configuring nginx to serve gradido again
' >> $UPDATE_HTML +echo 'Configuring nginx to serve gradido again' >> $UPDATE_HTML ln -s /etc/nginx/sites-available/gradido.conf /etc/nginx/sites-enabled/ rm /etc/nginx/sites-enabled/update-page.conf sudo /etc/init.d/nginx restart From 6b2664e6ef4d234d2d1249498b9378f0379de5d9 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 12 Mar 2022 03:05:36 +0100 Subject: [PATCH 06/34] add another newline --- deployment/bare_metal/nginx/update-page/updating.html.template | 1 + 1 file changed, 1 insertion(+) diff --git a/deployment/bare_metal/nginx/update-page/updating.html.template b/deployment/bare_metal/nginx/update-page/updating.html.template index 356a9f139..cc6d7debb 100644 --- a/deployment/bare_metal/nginx/update-page/updating.html.template +++ b/deployment/bare_metal/nginx/update-page/updating.html.template @@ -1,3 +1,4 @@
 Gradido is currently updating...
 please stand by and try again in some minutes
+

From 15219001b1130a53d82edc213600964ffaeeff5e Mon Sep 17 00:00:00 2001
From: Ulf Gebhardt 
Date: Sat, 12 Mar 2022 03:08:45 +0100
Subject: [PATCH 07/34] try ussing tee for proper logoutput in console and file

---
 deployment/bare_metal/start.sh | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh
index ede5cab5d..c6aadeb27 100755
--- a/deployment/bare_metal/start.sh
+++ b/deployment/bare_metal/start.sh
@@ -50,7 +50,8 @@ TODAY=$(date +"%Y-%m-%d")
 
 # redirect all output of the script to the UPDATE_HTML and also have things on console
 # TODO: this might pose a security risk
-exec 3>&1 1>>$UPDATE_HTML 2>&1
+# exec 3>&1 1>>$UPDATE_HTML 2>&1 
+exec > >(tee $UPDATE_HTML) 2>&1
 
 # configure nginx for the update-page
 echo 'Configuring nginx to serve the update-page' >> $UPDATE_HTML

From 0885938bdadf2db01519d9335f14cb51a768941b Mon Sep 17 00:00:00 2001
From: Ulf Gebhardt 
Date: Sat, 12 Mar 2022 03:12:22 +0100
Subject: [PATCH 08/34] removed comment

---
 deployment/bare_metal/start.sh | 1 -
 1 file changed, 1 deletion(-)

diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh
index c6aadeb27..34e63a605 100755
--- a/deployment/bare_metal/start.sh
+++ b/deployment/bare_metal/start.sh
@@ -50,7 +50,6 @@ TODAY=$(date +"%Y-%m-%d")
 
 # redirect all output of the script to the UPDATE_HTML and also have things on console
 # TODO: this might pose a security risk
-# exec 3>&1 1>>$UPDATE_HTML 2>&1 
 exec > >(tee $UPDATE_HTML) 2>&1
 
 # configure nginx for the update-page

From 2975efe58f12de39e624958228ff0d6a8956d127 Mon Sep 17 00:00:00 2001
From: Ulf Gebhardt 
Date: Sat, 12 Mar 2022 03:14:35 +0100
Subject: [PATCH 09/34] try appending to logfile with new method

---
 deployment/bare_metal/start.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh
index 34e63a605..99b2c2947 100755
--- a/deployment/bare_metal/start.sh
+++ b/deployment/bare_metal/start.sh
@@ -50,7 +50,7 @@ TODAY=$(date +"%Y-%m-%d")
 
 # redirect all output of the script to the UPDATE_HTML and also have things on console
 # TODO: this might pose a security risk
-exec > >(tee $UPDATE_HTML) 2>&1
+exec > >>(tee $UPDATE_HTML) 2>&1
 
 # configure nginx for the update-page
 echo 'Configuring nginx to serve the update-page' >> $UPDATE_HTML

From 45068d512ceabfaa7d05576c9cadee71b8c617a2 Mon Sep 17 00:00:00 2001
From: Ulf Gebhardt 
Date: Sat, 12 Mar 2022 03:17:46 +0100
Subject: [PATCH 10/34] tee append

---
 deployment/bare_metal/start.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh
index 99b2c2947..6030899f0 100755
--- a/deployment/bare_metal/start.sh
+++ b/deployment/bare_metal/start.sh
@@ -50,7 +50,7 @@ TODAY=$(date +"%Y-%m-%d")
 
 # redirect all output of the script to the UPDATE_HTML and also have things on console
 # TODO: this might pose a security risk
-exec > >>(tee $UPDATE_HTML) 2>&1
+exec > >(tee -a $UPDATE_HTML) 2>&1
 
 # configure nginx for the update-page
 echo 'Configuring nginx to serve the update-page' >> $UPDATE_HTML

From 549f2182310eb1a2c704c3ff1a6ed4030df4143f Mon Sep 17 00:00:00 2001
From: Ulf Gebhardt 
Date: Sat, 12 Mar 2022 03:52:01 +0100
Subject: [PATCH 11/34] module-aliases in order to have things working with
 `NODE_ENV=production`

---
 backend/src/index.ts | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/backend/src/index.ts b/backend/src/index.ts
index 4c08b422d..7c6219c07 100644
--- a/backend/src/index.ts
+++ b/backend/src/index.ts
@@ -1,5 +1,8 @@
 /* eslint-disable @typescript-eslint/no-explicit-any */
 
+// resolve @-import-aliases
+import 'module-alias/register'
+
 import createServer from './server/createServer'
 
 // config

From 21848c2b1c1fbc4c6674891c8db8084679209458 Mon Sep 17 00:00:00 2001
From: Ulf Gebhardt 
Date: Sat, 12 Mar 2022 04:06:03 +0100
Subject: [PATCH 12/34] reference build folders in moduleAliases

---
 backend/package.json | 10 +++++-----
 backend/src/index.ts |  3 ---
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/backend/package.json b/backend/package.json
index 710d73a8c..79e5fd130 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -60,12 +60,12 @@
     "typescript": "^4.3.4"
   },
   "_moduleAliases": {
-    "@": "./src",
-    "@arg": "./src/graphql/arg",
+    "@": "./build/src",
+    "@arg": "./build/src/graphql/arg",
     "@dbTools": "../database/build/src",
     "@entity": "../database/build/entity",
-    "@enum": "./src/graphql/enum",
-    "@model": "./src/graphql/model",
-    "@repository": "./src/typeorm/repository"
+    "@enum": "./build/src/graphql/enum",
+    "@model": "./build/src/graphql/model",
+    "@repository": "./build/src/typeorm/repository"
   }
 }
diff --git a/backend/src/index.ts b/backend/src/index.ts
index 7c6219c07..4c08b422d 100644
--- a/backend/src/index.ts
+++ b/backend/src/index.ts
@@ -1,8 +1,5 @@
 /* eslint-disable @typescript-eslint/no-explicit-any */
 
-// resolve @-import-aliases
-import 'module-alias/register'
-
 import createServer from './server/createServer'
 
 // config

From 85ca10f000dc85da45fa97f7823e439cfbf1828e Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 10:10:57 +0100
Subject: [PATCH 13/34] refactor: No Reset DB in Backend Unit Tests

---
 .../src/graphql/resolver/UserResolver.test.ts | 34 ++++++-------------
 backend/test/helpers.ts                       | 28 +++++++++++----
 2 files changed, 32 insertions(+), 30 deletions(-)

diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts
index 05ff2b302..ae4f39446 100644
--- a/backend/src/graphql/resolver/UserResolver.test.ts
+++ b/backend/src/graphql/resolver/UserResolver.test.ts
@@ -1,11 +1,10 @@
 /* eslint-disable @typescript-eslint/no-explicit-any */
 /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 
-import { testEnvironment, resetEntities, createUser } from '@test/helpers'
+import { testEnvironment, createUser, headerPushMock, cleanDB } from '@test/helpers'
 import { createUserMutation, setPasswordMutation } from '@test/graphql'
 import gql from 'graphql-tag'
 import { GraphQLError } from 'graphql'
-import { resetDB } from '@dbTools/helpers'
 import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
 import { User } from '@entity/User'
 import CONFIG from '@/config'
@@ -30,30 +29,19 @@ jest.mock('@/apis/KlicktippController', () => {
 })
 */
 
-let token: string
-
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-const headerPushMock = jest.fn((t) => (token = t.value))
-
-const context = {
-  setHeaders: {
-    push: headerPushMock,
-    forEach: jest.fn(),
-  },
-}
-
 let mutate: any, query: any, con: any
 
 beforeAll(async () => {
-  const testEnv = await testEnvironment(context)
+  const testEnv = await testEnvironment()
   mutate = testEnv.mutate
   query = testEnv.query
   con = testEnv.con
+  await cleanDB()
 })
 
 afterAll(async () => {
-  await resetDB(true)
-  await con.close()
+  await cleanDB()
+  con.close()
 })
 
 describe('UserResolver', () => {
@@ -75,7 +63,7 @@ describe('UserResolver', () => {
     })
 
     afterAll(async () => {
-      await resetEntities([User, LoginEmailOptIn])
+      await cleanDB()
     })
 
     it('returns success', () => {
@@ -213,7 +201,7 @@ describe('UserResolver', () => {
       })
 
       afterAll(async () => {
-        await resetEntities([User, LoginEmailOptIn])
+        await cleanDB()
       })
 
       it('sets email checked to true', () => {
@@ -256,7 +244,7 @@ describe('UserResolver', () => {
       })
 
       afterAll(async () => {
-        await resetEntities([User, LoginEmailOptIn])
+        await cleanDB()
       })
 
       it('throws an error', () => {
@@ -282,7 +270,7 @@ describe('UserResolver', () => {
       })
 
       afterAll(async () => {
-        await resetEntities([User, LoginEmailOptIn])
+        await cleanDB()
       })
 
       it('throws an error', () => {
@@ -323,7 +311,7 @@ describe('UserResolver', () => {
     let result: User
 
     afterAll(async () => {
-      await resetEntities([User, LoginEmailOptIn])
+      await cleanDB()
     })
 
     describe('no users in database', () => {
@@ -353,7 +341,7 @@ describe('UserResolver', () => {
       })
 
       afterAll(async () => {
-        await resetEntities([User, LoginEmailOptIn])
+        await cleanDB()
       })
 
       it('returns the user object', () => {
diff --git a/backend/test/helpers.ts b/backend/test/helpers.ts
index f3588cd43..1048b16b7 100644
--- a/backend/test/helpers.ts
+++ b/backend/test/helpers.ts
@@ -7,8 +7,28 @@ import { resetDB, initialize } from '@dbTools/helpers'
 import { createUserMutation, setPasswordMutation } from './graphql'
 import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
 import { User } from '@entity/User'
+import { entities } from '@entity/index'
 
-export const testEnvironment = async (context: any) => {
+let token = ''
+
+export const headerPushMock = jest.fn((t) => (token = t.value))
+
+const context = {
+  token,
+  setHeaders: {
+    push: headerPushMock,
+    forEach: jest.fn(),
+  },
+}
+
+export const cleanDB = async () => {
+  // this only works as lond we do not have foreign key constraints
+  for (let i = 0; i < entities.length; i++) {
+    await resetEntity(entities[i])
+  }
+}
+
+export const testEnvironment = async () => {
   const server = await createServer(context)
   const con = server.con
   const testClient = createTestClient(server.apollo)
@@ -27,12 +47,6 @@ export const resetEntity = async (entity: any) => {
   }
 }
 
-export const resetEntities = async (entities: any[]) => {
-  for (let i = 0; i < entities.length; i++) {
-    await resetEntity(entities[i])
-  }
-}
-
 export const createUser = async (mutate: any, user: any) => {
   await mutate({ mutation: createUserMutation, variables: user })
   const dbUser = await User.findOne({ where: { email: user.email } })

From dedf174f4faa5080690531867ff9d615b14cf53a Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 10:12:56 +0100
Subject: [PATCH 14/34] add dependency database_up to backend unit tests

---
 .github/workflows/test.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index c9fda7b2a..5a5b90979 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -489,7 +489,7 @@ jobs:
   unit_test_backend:
     name: Unit tests - Backend
     runs-on: ubuntu-latest
-    needs: [build_test_mariadb]
+    needs: [build_test_mariadb, build_test_database_up]
     steps:
       ##########################################################################
       # CHECKOUT CODE ##########################################################

From ec1322c5ed12ec1d0177538bd277bf7ce38f505c Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 10:15:01 +0100
Subject: [PATCH 15/34] try backend unit tests in CI without sleeps

---
 .github/workflows/test.yml | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 5a5b90979..ecfb10fda 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -511,14 +511,6 @@ jobs:
       ##########################################################################
       - name: backend | docker-compose
         run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb
-      - name: Sleep for 30 seconds
-        run: sleep 30s
-        shell: bash
-      - name: backend | docker-compose database
-        run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps database
-      - name: Sleep for 30 seconds
-        run: sleep 30s
-        shell: bash
       - name: backend Unit tests | test
         run: cd database && yarn && yarn build && cd ../backend && yarn && yarn test
         # run: docker-compose -f docker-compose.yml -f docker-compose.test.yml exec -T backend yarn test

From 4db0235738137a09d1248263f04ef8f07307e286 Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 10:19:19 +0100
Subject: [PATCH 16/34] await for the connection to close

---
 backend/src/graphql/resolver/UserResolver.test.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts
index ae4f39446..fd0936b9a 100644
--- a/backend/src/graphql/resolver/UserResolver.test.ts
+++ b/backend/src/graphql/resolver/UserResolver.test.ts
@@ -41,7 +41,7 @@ beforeAll(async () => {
 
 afterAll(async () => {
   await cleanDB()
-  con.close()
+  await con.close()
 })
 
 describe('UserResolver', () => {

From a503815829fe1cd30330891e7fcb1c8e1ec3e513 Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 10:19:36 +0100
Subject: [PATCH 17/34] wait again

---
 .github/workflows/test.yml | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index ecfb10fda..5a5b90979 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -511,6 +511,14 @@ jobs:
       ##########################################################################
       - name: backend | docker-compose
         run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb
+      - name: Sleep for 30 seconds
+        run: sleep 30s
+        shell: bash
+      - name: backend | docker-compose database
+        run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps database
+      - name: Sleep for 30 seconds
+        run: sleep 30s
+        shell: bash
       - name: backend Unit tests | test
         run: cd database && yarn && yarn build && cd ../backend && yarn && yarn test
         # run: docker-compose -f docker-compose.yml -f docker-compose.test.yml exec -T backend yarn test

From d0df7002f903792ca581746ffcd135d1443cd278 Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 10:25:12 +0100
Subject: [PATCH 18/34] add dependency database_migration_test to backend unit
 tests, do not wait anymore

---
 .github/workflows/test.yml | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 5a5b90979..02e0bd2c7 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -489,7 +489,7 @@ jobs:
   unit_test_backend:
     name: Unit tests - Backend
     runs-on: ubuntu-latest
-    needs: [build_test_mariadb, build_test_database_up]
+    needs: [build_test_mariadb, database_migration_test, build_test_database_up]
     steps:
       ##########################################################################
       # CHECKOUT CODE ##########################################################
@@ -510,15 +510,7 @@ jobs:
       # UNIT TESTS BACKEND #####################################################
       ##########################################################################
       - name: backend | docker-compose
-        run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb
-      - name: Sleep for 30 seconds
-        run: sleep 30s
-        shell: bash
-      - name: backend | docker-compose database
-        run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps database
-      - name: Sleep for 30 seconds
-        run: sleep 30s
-        shell: bash
+        run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb database
       - name: backend Unit tests | test
         run: cd database && yarn && yarn build && cd ../backend && yarn && yarn test
         # run: docker-compose -f docker-compose.yml -f docker-compose.test.yml exec -T backend yarn test

From 3e25268c328bfac41fc1bd24378e2d5c9ec7b806 Mon Sep 17 00:00:00 2001
From: Ulf Gebhardt 
Date: Mon, 14 Mar 2022 12:41:13 +0100
Subject: [PATCH 19/34] Update deployment/bare_metal/start.sh

Co-authored-by: Moriz Wahl 
---
 deployment/bare_metal/start.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh
index 6030899f0..26e3f7e51 100755
--- a/deployment/bare_metal/start.sh
+++ b/deployment/bare_metal/start.sh
@@ -121,7 +121,7 @@ yarn build
 # TODO maybe handle this differently?
 export NODE_ENV=production
 pm2 delete gradido-backend
-pm2 start --name gradido-backend "yarn --cwd $PROJECT_ROOT/backend start" -l $GRADIDO_LOG_PATH/pm2.backend.$TODAY.log --log-date-format 'DD-MM HH:mm:ss.SSS'
+pm2 start --name gradido-backend "yarn --cwd $PROJECT_ROOT/backend start" -l $GRADIDO_LOG_PATH/pm2.backend.$TODAY.log --log-date-format 'YYYY-MM-DD:mm:ss.SSS'
 pm2 save
 
 # Install & build frontend

From 3a52a3892a1f5c00441ebc86a0604bede101ce4a Mon Sep 17 00:00:00 2001
From: Ulf Gebhardt 
Date: Mon, 14 Mar 2022 12:41:19 +0100
Subject: [PATCH 20/34] Update deployment/bare_metal/start.sh

Co-authored-by: Moriz Wahl 
---
 deployment/bare_metal/start.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh
index 26e3f7e51..3a8927fd2 100755
--- a/deployment/bare_metal/start.sh
+++ b/deployment/bare_metal/start.sh
@@ -147,7 +147,7 @@ yarn build
 # TODO maybe handle this differently?
 export NODE_ENV=production
 pm2 delete gradido-admin
-pm2 start --name gradido-admin "yarn --cwd $PROJECT_ROOT/admin start" -l $GRADIDO_LOG_PATH/pm2.admin.$TODAY.log --log-date-format 'DD-MM HH:mm:ss.SSS'
+pm2 start --name gradido-admin "yarn --cwd $PROJECT_ROOT/admin start" -l $GRADIDO_LOG_PATH/pm2.admin.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
 pm2 save
 
 # let nginx showing gradido

From e97bcd4d2036e31840b371150e0c62d3ea06ac3d Mon Sep 17 00:00:00 2001
From: Ulf Gebhardt 
Date: Mon, 14 Mar 2022 12:41:25 +0100
Subject: [PATCH 21/34] Update deployment/bare_metal/start.sh

Co-authored-by: Moriz Wahl 
---
 deployment/bare_metal/start.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh
index 3a8927fd2..6d979a79e 100755
--- a/deployment/bare_metal/start.sh
+++ b/deployment/bare_metal/start.sh
@@ -134,7 +134,7 @@ yarn build
 # TODO maybe handle this differently?
 export NODE_ENV=production
 pm2 delete gradido-frontend
-pm2 start --name gradido-frontend "yarn --cwd $PROJECT_ROOT/frontend start" -l $GRADIDO_LOG_PATH/pm2.frontend.$TODAY.log --log-date-format 'DD-MM HH:mm:ss.SSS'
+pm2 start --name gradido-frontend "yarn --cwd $PROJECT_ROOT/frontend start" -l $GRADIDO_LOG_PATH/pm2.frontend.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
 pm2 save
 
 # Install & build admin

From 60e83b56d1c4b656d5025a80a904bed3a778a681 Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 12:56:58 +0100
Subject: [PATCH 22/34] feat: Test Logout

---
 .../src/graphql/resolver/UserResolver.test.ts | 117 +++++++++++++++---
 backend/src/graphql/resolver/UserResolver.ts  |  12 ++
 backend/test/helpers.ts                       |  10 +-
 3 files changed, 116 insertions(+), 23 deletions(-)

diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts
index fd0936b9a..570f09823 100644
--- a/backend/src/graphql/resolver/UserResolver.test.ts
+++ b/backend/src/graphql/resolver/UserResolver.test.ts
@@ -1,7 +1,7 @@
 /* eslint-disable @typescript-eslint/no-explicit-any */
 /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 
-import { testEnvironment, createUser, headerPushMock, cleanDB } from '@test/helpers'
+import { testEnvironment, createUser, headerPushMock, cleanDB, resetToken } from '@test/helpers'
 import { createUserMutation, setPasswordMutation } from '@test/graphql'
 import gql from 'graphql-tag'
 import { GraphQLError } from 'graphql'
@@ -31,6 +31,24 @@ jest.mock('@/apis/KlicktippController', () => {
 
 let mutate: any, query: any, con: any
 
+const loginQuery = gql`
+  query ($email: String!, $password: String!, $publisherId: Int) {
+    login(email: $email, password: $password, publisherId: $publisherId) {
+      email
+      firstName
+      lastName
+      language
+      coinanimation
+      klickTipp {
+        newsletterState
+      }
+      hasElopage
+      publisherId
+      isAdmin
+    }
+  }
+`
+
 beforeAll(async () => {
   const testEnv = await testEnvironment()
   mutate = testEnv.mutate
@@ -284,24 +302,6 @@ describe('UserResolver', () => {
   })
 
   describe('login', () => {
-    const loginQuery = gql`
-      query ($email: String!, $password: String!, $publisherId: Int) {
-        login(email: $email, password: $password, publisherId: $publisherId) {
-          email
-          firstName
-          lastName
-          language
-          coinanimation
-          klickTipp {
-            newsletterState
-          }
-          hasElopage
-          publisherId
-          isAdmin
-        }
-      }
-    `
-
     const variables = {
       email: 'peter@lustig.de',
       password: 'Aa12345_',
@@ -328,7 +328,7 @@ describe('UserResolver', () => {
       })
     })
 
-    describe('user is in database', () => {
+    describe('user is in database and correct login data', () => {
       beforeAll(async () => {
         await createUser(mutate, {
           email: 'peter@lustig.de',
@@ -370,5 +370,82 @@ describe('UserResolver', () => {
         expect(headerPushMock).toBeCalledWith({ key: 'token', value: expect.any(String) })
       })
     })
+
+    describe('user is in database and wrong password', () => {
+      beforeAll(async () => {
+        resetToken()
+        await createUser(mutate, {
+          email: 'peter@lustig.de',
+          firstName: 'Peter',
+          lastName: 'Lustig',
+          language: 'de',
+          publisherId: 1234,
+        })
+      })
+
+      afterAll(async () => {
+        await cleanDB()
+      })
+
+      it('returns an error', () => {
+        expect(
+          query({ query: loginQuery, variables: { ...variables, password: 'wrong' } }),
+        ).resolves.toEqual(
+          expect.objectContaining({
+            errors: [new GraphQLError('No user with this credentials')],
+          }),
+        )
+      })
+    })
+  })
+
+  describe('logout', () => {
+    const logoutQuery = gql`
+      query {
+        logout
+      }
+    `
+
+    describe('unauthenticated', () => {
+      it('throws an error', async () => {
+        await expect(query({ query: logoutQuery })).resolves.toEqual(
+          expect.objectContaining({
+            errors: [new GraphQLError('401 Unauthorized')],
+          }),
+        )
+      })
+    })
+
+    describe('authenticated', () => {
+      const variables = {
+        email: 'peter@lustig.de',
+        password: 'Aa12345_',
+      }
+
+      beforeAll(async () => {
+        resetToken()
+        await createUser(mutate, {
+          email: 'peter@lustig.de',
+          firstName: 'Peter',
+          lastName: 'Lustig',
+          language: 'de',
+          publisherId: 1234,
+        })
+        await query({ query: loginQuery, variables })
+      })
+
+      afterAll(async () => {
+        await cleanDB()
+      })
+
+      it('returns true', async () => {
+        await expect(query({ query: logoutQuery })).resolves.toEqual(
+          expect.objectContaining({
+            data: { logout: 'true' },
+            errors: undefined,
+          }),
+        )
+      })
+    })
   })
 })
diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts
index 4d1454e86..9896ddc97 100644
--- a/backend/src/graphql/resolver/UserResolver.ts
+++ b/backend/src/graphql/resolver/UserResolver.ts
@@ -373,6 +373,8 @@ export class UserResolver {
         /{code}/g,
         emailOptIn.verificationCode.toString(),
       )
+
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
       const emailSent = await sendAccountActivationEmail({
         link: activationLink,
         firstName,
@@ -380,11 +382,13 @@ export class UserResolver {
         email,
       })
 
+      /* uncomment this, when you need the activation link on the console
       // In case EMails are disabled log the activation link for the user
       if (!emailSent) {
         // eslint-disable-next-line no-console
         console.log(`Account confirmation link: ${activationLink}`)
       }
+      */
       await queryRunner.commitTransaction()
     } catch (e) {
       await queryRunner.rollbackTransaction()
@@ -414,6 +418,7 @@ export class UserResolver {
         emailOptIn.verificationCode.toString(),
       )
 
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
       const emailSent = await sendAccountActivationEmail({
         link: activationLink,
         firstName: user.firstName,
@@ -421,11 +426,13 @@ export class UserResolver {
         email,
       })
 
+      /*  uncomment this, when you need the activation link on the console
       // In case EMails are disabled log the activation link for the user
       if (!emailSent) {
         // eslint-disable-next-line no-console
         console.log(`Account confirmation link: ${activationLink}`)
       }
+      */
       await queryRunner.commitTransaction()
     } catch (e) {
       await queryRunner.rollbackTransaction()
@@ -450,6 +457,7 @@ export class UserResolver {
       optInCode.verificationCode.toString(),
     )
 
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
     const emailSent = await sendResetPasswordEmail({
       link,
       firstName: user.firstName,
@@ -457,11 +465,13 @@ export class UserResolver {
       email,
     })
 
+    /*  uncomment this, when you need the activation link on the console
     // In case EMails are disabled log the activation link for the user
     if (!emailSent) {
       // eslint-disable-next-line no-console
       console.log(`Reset password link: ${link}`)
     }
+    */
 
     return true
   }
@@ -551,7 +561,9 @@ export class UserResolver {
       } catch {
         // TODO is this a problem?
         // eslint-disable-next-line no-console
+        /*  uncomment this, when you need the activation link on the console
         console.log('Could not subscribe to klicktipp')
+        */
       }
     }
 
diff --git a/backend/test/helpers.ts b/backend/test/helpers.ts
index 1048b16b7..0154f268a 100644
--- a/backend/test/helpers.ts
+++ b/backend/test/helpers.ts
@@ -9,12 +9,16 @@ import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
 import { User } from '@entity/User'
 import { entities } from '@entity/index'
 
-let token = ''
+export const headerPushMock = jest.fn((t) => {
+  context.token = t.value
+})
 
-export const headerPushMock = jest.fn((t) => (token = t.value))
+export const resetToken = () => {
+  context.token = ''
+}
 
 const context = {
-  token,
+  token: '',
   setHeaders: {
     push: headerPushMock,
     forEach: jest.fn(),

From 1dd9f522599a5d957374f9450869c861b9790eae Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 13:50:30 +0100
Subject: [PATCH 23/34] try to fix the token reset

---
 backend/src/graphql/directive/isAuthorized.ts     | 8 ++++++++
 backend/src/graphql/resolver/UserResolver.test.ts | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/backend/src/graphql/directive/isAuthorized.ts b/backend/src/graphql/directive/isAuthorized.ts
index aa407c95f..4a31dfede 100644
--- a/backend/src/graphql/directive/isAuthorized.ts
+++ b/backend/src/graphql/directive/isAuthorized.ts
@@ -13,6 +13,8 @@ import { ServerUser } from '@entity/ServerUser'
 const isAuthorized: AuthChecker = async ({ context }, rights) => {
   context.role = ROLE_UNAUTHORIZED // unauthorized user
 
+  // moriz: I think it is better to check the INALIENABLE_RIGHTS here
+
   // Do we have a token?
   if (context.token) {
     // Decode the token
@@ -33,6 +35,12 @@ const isAuthorized: AuthChecker = async ({ context }, rights) => {
     }
     // Set context pubKey
     context.pubKey = Buffer.from(decoded.pubKey).toString('hex')
+
+    // Problem found by unit testing:
+    // I have a valid token in the context, but the database is cleaned,
+    // so the user object cannot be found here
+    // this should be working for inalienable rights
+
     // set new header token
     // TODO - load from database dynamically & admin - maybe encode this in the token to prevent many database requests
     // TODO this implementation is bullshit - two database queries cause our user identifiers are not aligned and vary between email, id and pubKey
diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts
index 570f09823..9b2db42e8 100644
--- a/backend/src/graphql/resolver/UserResolver.test.ts
+++ b/backend/src/graphql/resolver/UserResolver.test.ts
@@ -373,7 +373,7 @@ describe('UserResolver', () => {
 
     describe('user is in database and wrong password', () => {
       beforeAll(async () => {
-        resetToken()
+        // resetToken()
         await createUser(mutate, {
           email: 'peter@lustig.de',
           firstName: 'Peter',

From 0aa9e290d96313a630bc6e4e4ce3990e1f831d59 Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 13:52:52 +0100
Subject: [PATCH 24/34] wait for mariadb to start

---
 .github/workflows/test.yml | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 402b1a6ef..3778dae93 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -509,8 +509,13 @@ jobs:
       ##########################################################################
       # UNIT TESTS BACKEND #####################################################
       ##########################################################################
-      - name: backend | docker-compose
-        run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb database
+      - name: backend | docker-compose mariadb
+        run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb
+      - name: Sleep for 30 seconds
+        run: sleep 30s
+        shell: bash
+      - name: backend | docker-compose database
+        run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps database
       - name: backend Unit tests | test
         run: cd database && yarn && yarn build && cd ../backend && yarn && yarn test
         # run: docker-compose -f docker-compose.yml -f docker-compose.test.yml exec -T backend yarn test

From 35cc38ba7c2aa2f03682d7f5893042faaaf67385 Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 14:15:24 +0100
Subject: [PATCH 25/34] introduce reset token, comment isAuthorized

---
 backend/src/graphql/directive/isAuthorized.ts     | 6 ++++++
 backend/src/graphql/resolver/UserResolver.test.ts | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/backend/src/graphql/directive/isAuthorized.ts b/backend/src/graphql/directive/isAuthorized.ts
index 4a31dfede..c72a52ac4 100644
--- a/backend/src/graphql/directive/isAuthorized.ts
+++ b/backend/src/graphql/directive/isAuthorized.ts
@@ -14,6 +14,12 @@ const isAuthorized: AuthChecker = async ({ context }, rights) => {
   context.role = ROLE_UNAUTHORIZED // unauthorized user
 
   // moriz: I think it is better to check the INALIENABLE_RIGHTS here
+  /* 
+  if ((rights).reduce(
+    (acc, right) => acc && INALIENABLE_RIGHTS.includes(right),
+    true,
+  )) return true
+  */
 
   // Do we have a token?
   if (context.token) {
diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts
index 9b2db42e8..570f09823 100644
--- a/backend/src/graphql/resolver/UserResolver.test.ts
+++ b/backend/src/graphql/resolver/UserResolver.test.ts
@@ -373,7 +373,7 @@ describe('UserResolver', () => {
 
     describe('user is in database and wrong password', () => {
       beforeAll(async () => {
-        // resetToken()
+        resetToken()
         await createUser(mutate, {
           email: 'peter@lustig.de',
           firstName: 'Peter',

From 109853d257d0d6f9a9a177f0bc5c647e60311194 Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 14:21:40 +0100
Subject: [PATCH 26/34] reset token not exported

---
 backend/src/graphql/resolver/UserResolver.test.ts | 4 +---
 backend/test/helpers.ts                           | 9 +++++----
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts
index 570f09823..4b20f035d 100644
--- a/backend/src/graphql/resolver/UserResolver.test.ts
+++ b/backend/src/graphql/resolver/UserResolver.test.ts
@@ -1,7 +1,7 @@
 /* eslint-disable @typescript-eslint/no-explicit-any */
 /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 
-import { testEnvironment, createUser, headerPushMock, cleanDB, resetToken } from '@test/helpers'
+import { testEnvironment, createUser, headerPushMock, cleanDB } from '@test/helpers'
 import { createUserMutation, setPasswordMutation } from '@test/graphql'
 import gql from 'graphql-tag'
 import { GraphQLError } from 'graphql'
@@ -373,7 +373,6 @@ describe('UserResolver', () => {
 
     describe('user is in database and wrong password', () => {
       beforeAll(async () => {
-        resetToken()
         await createUser(mutate, {
           email: 'peter@lustig.de',
           firstName: 'Peter',
@@ -423,7 +422,6 @@ describe('UserResolver', () => {
       }
 
       beforeAll(async () => {
-        resetToken()
         await createUser(mutate, {
           email: 'peter@lustig.de',
           firstName: 'Peter',
diff --git a/backend/test/helpers.ts b/backend/test/helpers.ts
index 0154f268a..aa11d54e9 100644
--- a/backend/test/helpers.ts
+++ b/backend/test/helpers.ts
@@ -13,10 +13,6 @@ export const headerPushMock = jest.fn((t) => {
   context.token = t.value
 })
 
-export const resetToken = () => {
-  context.token = ''
-}
-
 const context = {
   token: '',
   setHeaders: {
@@ -52,6 +48,7 @@ export const resetEntity = async (entity: any) => {
 }
 
 export const createUser = async (mutate: any, user: any) => {
+  resetToken()
   await mutate({ mutation: createUserMutation, variables: user })
   const dbUser = await User.findOne({ where: { email: user.email } })
   if (!dbUser) throw new Error('Ups, no user found')
@@ -62,3 +59,7 @@ export const createUser = async (mutate: any, user: any) => {
     variables: { password: 'Aa12345_', code: optin.verificationCode },
   })
 }
+
+const resetToken = () => {
+  context.token = ''
+}

From 87bd89ec74d0c80b3d2dc2369472e38b1f4d54a6 Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 14:58:37 +0100
Subject: [PATCH 27/34] Update .github/workflows/test.yml

Co-authored-by: Ulf Gebhardt 
---
 .github/workflows/test.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 3778dae93..0739729b5 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -489,7 +489,7 @@ jobs:
   unit_test_backend:
     name: Unit tests - Backend
     runs-on: ubuntu-latest
-    needs: [build_test_mariadb, database_migration_test, build_test_database_up]
+    needs: [build_test_mariadb]
     steps:
       ##########################################################################
       # CHECKOUT CODE ##########################################################

From 1b1510a70f8f01f8bf979588b1f73971b1808f82 Mon Sep 17 00:00:00 2001
From: Ulf Gebhardt 
Date: Mon, 14 Mar 2022 15:00:37 +0100
Subject: [PATCH 28/34] Update deployment/bare_metal/start.sh

Co-authored-by: Moriz Wahl 
---
 deployment/bare_metal/start.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh
index 6d979a79e..250971419 100755
--- a/deployment/bare_metal/start.sh
+++ b/deployment/bare_metal/start.sh
@@ -121,7 +121,7 @@ yarn build
 # TODO maybe handle this differently?
 export NODE_ENV=production
 pm2 delete gradido-backend
-pm2 start --name gradido-backend "yarn --cwd $PROJECT_ROOT/backend start" -l $GRADIDO_LOG_PATH/pm2.backend.$TODAY.log --log-date-format 'YYYY-MM-DD:mm:ss.SSS'
+pm2 start --name gradido-backend "yarn --cwd $PROJECT_ROOT/backend start" -l $GRADIDO_LOG_PATH/pm2.backend.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
 pm2 save
 
 # Install & build frontend

From e5215b56aa3f8f1f6796f7be5c1f365bc00cc836 Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 15:18:45 +0100
Subject: [PATCH 29/34] do not reset db on start of database in backend unit
 tests

---
 backend/test/helpers.ts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/backend/test/helpers.ts b/backend/test/helpers.ts
index aa11d54e9..74addae3d 100644
--- a/backend/test/helpers.ts
+++ b/backend/test/helpers.ts
@@ -35,7 +35,6 @@ export const testEnvironment = async () => {
   const mutate = testClient.mutate
   const query = testClient.query
   await initialize()
-  await resetDB()
   return { mutate, query, con }
 }
 

From ed84a1dd56bed2dcd0d5afdfac6d32e7b2599ed4 Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 15:35:39 +0100
Subject: [PATCH 30/34] no resetDB and test for inalienable rights first

---
 backend/src/graphql/directive/isAuthorized.ts | 23 ++++---------------
 backend/test/helpers.ts                       |  2 +-
 2 files changed, 5 insertions(+), 20 deletions(-)

diff --git a/backend/src/graphql/directive/isAuthorized.ts b/backend/src/graphql/directive/isAuthorized.ts
index c72a52ac4..f2d646cad 100644
--- a/backend/src/graphql/directive/isAuthorized.ts
+++ b/backend/src/graphql/directive/isAuthorized.ts
@@ -13,31 +13,16 @@ import { ServerUser } from '@entity/ServerUser'
 const isAuthorized: AuthChecker = async ({ context }, rights) => {
   context.role = ROLE_UNAUTHORIZED // unauthorized user
 
-  // moriz: I think it is better to check the INALIENABLE_RIGHTS here
-  /* 
-  if ((rights).reduce(
-    (acc, right) => acc && INALIENABLE_RIGHTS.includes(right),
-    true,
-  )) return true
-  */
+  // is rights an inalienable right?
+  if ((rights).reduce((acc, right) => acc && INALIENABLE_RIGHTS.includes(right), true))
+    return true
 
   // Do we have a token?
   if (context.token) {
     // Decode the token
     const decoded = decode(context.token)
     if (!decoded) {
-      // Are all rights requested public?
-      const isInalienable = (rights).reduce(
-        (acc, right) => acc && INALIENABLE_RIGHTS.includes(right),
-        true,
-      )
-      if (isInalienable) {
-        // If public dont throw and permit access
-        return true
-      } else {
-        // Throw on a protected route
-        throw new Error('403.13 - Client certificate revoked')
-      }
+      throw new Error('403.13 - Client certificate revoked')
     }
     // Set context pubKey
     context.pubKey = Buffer.from(decoded.pubKey).toString('hex')
diff --git a/backend/test/helpers.ts b/backend/test/helpers.ts
index 74addae3d..f5a6c902c 100644
--- a/backend/test/helpers.ts
+++ b/backend/test/helpers.ts
@@ -3,7 +3,7 @@
 
 import { createTestClient } from 'apollo-server-testing'
 import createServer from '../src/server/createServer'
-import { resetDB, initialize } from '@dbTools/helpers'
+import { initialize } from '@dbTools/helpers'
 import { createUserMutation, setPasswordMutation } from './graphql'
 import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
 import { User } from '@entity/User'

From bc29e3d6a622ad2fc72cb22b74d38152d79ece01 Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 16:17:11 +0100
Subject: [PATCH 31/34] fix wrong db query in create user helper, improve
 isAuthorized, delete token to simulate unauthenticated

---
 backend/src/graphql/directive/isAuthorized.ts     | 12 ++++++++----
 backend/src/graphql/resolver/UserResolver.test.ts |  3 ++-
 backend/test/helpers.ts                           |  8 ++++----
 3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/backend/src/graphql/directive/isAuthorized.ts b/backend/src/graphql/directive/isAuthorized.ts
index f2d646cad..2c003d818 100644
--- a/backend/src/graphql/directive/isAuthorized.ts
+++ b/backend/src/graphql/directive/isAuthorized.ts
@@ -36,11 +36,15 @@ const isAuthorized: AuthChecker = async ({ context }, rights) => {
     // TODO - load from database dynamically & admin - maybe encode this in the token to prevent many database requests
     // TODO this implementation is bullshit - two database queries cause our user identifiers are not aligned and vary between email, id and pubKey
     const userRepository = await getCustomRepository(UserRepository)
-    const user = await userRepository.findByPubkeyHex(context.pubKey)
-    const countServerUsers = await ServerUser.count({ email: user.email })
-    context.role = countServerUsers > 0 ? ROLE_ADMIN : ROLE_USER
+    try {
+      const user = await userRepository.findByPubkeyHex(context.pubKey)
+      const countServerUsers = await ServerUser.count({ email: user.email })
+      context.role = countServerUsers > 0 ? ROLE_ADMIN : ROLE_USER
 
-    context.setHeaders.push({ key: 'token', value: encode(decoded.pubKey) })
+      context.setHeaders.push({ key: 'token', value: encode(decoded.pubKey) })
+    } catch {
+      throw new Error('401 Unauthorized')
+    }
   }
 
   // check for correct rights
diff --git a/backend/src/graphql/resolver/UserResolver.test.ts b/backend/src/graphql/resolver/UserResolver.test.ts
index 4b20f035d..947636aa4 100644
--- a/backend/src/graphql/resolver/UserResolver.test.ts
+++ b/backend/src/graphql/resolver/UserResolver.test.ts
@@ -1,7 +1,7 @@
 /* eslint-disable @typescript-eslint/no-explicit-any */
 /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 
-import { testEnvironment, createUser, headerPushMock, cleanDB } from '@test/helpers'
+import { testEnvironment, createUser, headerPushMock, cleanDB, resetToken } from '@test/helpers'
 import { createUserMutation, setPasswordMutation } from '@test/graphql'
 import gql from 'graphql-tag'
 import { GraphQLError } from 'graphql'
@@ -407,6 +407,7 @@ describe('UserResolver', () => {
 
     describe('unauthenticated', () => {
       it('throws an error', async () => {
+        resetToken()
         await expect(query({ query: logoutQuery })).resolves.toEqual(
           expect.objectContaining({
             errors: [new GraphQLError('401 Unauthorized')],
diff --git a/backend/test/helpers.ts b/backend/test/helpers.ts
index f5a6c902c..edb4eb3e4 100644
--- a/backend/test/helpers.ts
+++ b/backend/test/helpers.ts
@@ -39,7 +39,7 @@ export const testEnvironment = async () => {
 }
 
 export const resetEntity = async (entity: any) => {
-  const items = await entity.find()
+  const items = await entity.find({ withDeleted: true })
   if (items.length > 0) {
     const ids = items.map((i: any) => i.id)
     await entity.delete(ids)
@@ -47,11 +47,11 @@ export const resetEntity = async (entity: any) => {
 }
 
 export const createUser = async (mutate: any, user: any) => {
-  resetToken()
+  // resetToken()
   await mutate({ mutation: createUserMutation, variables: user })
   const dbUser = await User.findOne({ where: { email: user.email } })
   if (!dbUser) throw new Error('Ups, no user found')
-  const optin = await LoginEmailOptIn.findOne(dbUser.id)
+  const optin = await LoginEmailOptIn.findOne({ where: { userId: dbUser.id } })
   if (!optin) throw new Error('Ups, no optin found')
   await mutate({
     mutation: setPasswordMutation,
@@ -59,6 +59,6 @@ export const createUser = async (mutate: any, user: any) => {
   })
 }
 
-const resetToken = () => {
+export const resetToken = () => {
   context.token = ''
 }

From fe38cec4acb2e437e44fdc96fc9a3ef92fe368be Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 16:22:57 +0100
Subject: [PATCH 32/34] further improvement of isAuthorized

---
 backend/src/graphql/directive/isAuthorized.ts | 46 +++++++++----------
 1 file changed, 21 insertions(+), 25 deletions(-)

diff --git a/backend/src/graphql/directive/isAuthorized.ts b/backend/src/graphql/directive/isAuthorized.ts
index 2c003d818..9a60fb10d 100644
--- a/backend/src/graphql/directive/isAuthorized.ts
+++ b/backend/src/graphql/directive/isAuthorized.ts
@@ -18,33 +18,27 @@ const isAuthorized: AuthChecker = async ({ context }, rights) => {
     return true
 
   // Do we have a token?
-  if (context.token) {
-    // Decode the token
-    const decoded = decode(context.token)
-    if (!decoded) {
-      throw new Error('403.13 - Client certificate revoked')
-    }
-    // Set context pubKey
-    context.pubKey = Buffer.from(decoded.pubKey).toString('hex')
+  if (!context.token) {
+    throw new Error('401 Unauthorized')
+  }
 
-    // Problem found by unit testing:
-    // I have a valid token in the context, but the database is cleaned,
-    // so the user object cannot be found here
-    // this should be working for inalienable rights
+  // Decode the token
+  const decoded = decode(context.token)
+  if (!decoded) {
+    throw new Error('403.13 - Client certificate revoked')
+  }
+  // Set context pubKey
+  context.pubKey = Buffer.from(decoded.pubKey).toString('hex')
 
-    // set new header token
-    // TODO - load from database dynamically & admin - maybe encode this in the token to prevent many database requests
-    // TODO this implementation is bullshit - two database queries cause our user identifiers are not aligned and vary between email, id and pubKey
-    const userRepository = await getCustomRepository(UserRepository)
-    try {
-      const user = await userRepository.findByPubkeyHex(context.pubKey)
-      const countServerUsers = await ServerUser.count({ email: user.email })
-      context.role = countServerUsers > 0 ? ROLE_ADMIN : ROLE_USER
-
-      context.setHeaders.push({ key: 'token', value: encode(decoded.pubKey) })
-    } catch {
-      throw new Error('401 Unauthorized')
-    }
+  // TODO - load from database dynamically & admin - maybe encode this in the token to prevent many database requests
+  // TODO this implementation is bullshit - two database queries cause our user identifiers are not aligned and vary between email, id and pubKey
+  const userRepository = await getCustomRepository(UserRepository)
+  try {
+    const user = await userRepository.findByPubkeyHex(context.pubKey)
+    const countServerUsers = await ServerUser.count({ email: user.email })
+    context.role = countServerUsers > 0 ? ROLE_ADMIN : ROLE_USER
+  } catch {
+    throw new Error('401 Unauthorized')
   }
 
   // check for correct rights
@@ -53,6 +47,8 @@ const isAuthorized: AuthChecker = async ({ context }, rights) => {
     throw new Error('401 Unauthorized')
   }
 
+  // set new header token
+  context.setHeaders.push({ key: 'token', value: encode(decoded.pubKey) })
   return true
 }
 

From e7b104c3b5a1ca561967f6c28acbe0fb6fc1fa6c Mon Sep 17 00:00:00 2001
From: Moriz Wahl 
Date: Mon, 14 Mar 2022 16:27:36 +0100
Subject: [PATCH 33/34] Update backend/src/graphql/directive/isAuthorized.ts

Co-authored-by: Ulf Gebhardt 
---
 backend/src/graphql/directive/isAuthorized.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/backend/src/graphql/directive/isAuthorized.ts b/backend/src/graphql/directive/isAuthorized.ts
index 9a60fb10d..159a1614c 100644
--- a/backend/src/graphql/directive/isAuthorized.ts
+++ b/backend/src/graphql/directive/isAuthorized.ts
@@ -38,6 +38,7 @@ const isAuthorized: AuthChecker = async ({ context }, rights) => {
     const countServerUsers = await ServerUser.count({ email: user.email })
     context.role = countServerUsers > 0 ? ROLE_ADMIN : ROLE_USER
   } catch {
+    // in case the database query fails (user deleted)
     throw new Error('401 Unauthorized')
   }
 

From e706d994426d694865b22877a4c45a135d31f58e Mon Sep 17 00:00:00 2001
From: Ulf Gebhardt 
Date: Mon, 14 Mar 2022 17:48:00 +0100
Subject: [PATCH 34/34] 54% backend coverage

---
 .github/workflows/test.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 0739729b5..e9762b4bb 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -528,7 +528,7 @@ jobs:
           report_name: Coverage Backend
           type: lcov
           result_path: ./backend/coverage/lcov.info
-          min_coverage: 53
+          min_coverage: 54
           token: ${{ github.token }}
 
   ##########################################################################