From b1186fd396f762244406158e6b97f60ba657adf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Cadenas?= <77900120+andrrsin@users.noreply.github.com> Date: Mon, 26 Feb 2024 19:45:37 +0100 Subject: [PATCH 01/34] build try one --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c926570..d7c6d2e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,7 +7,7 @@ on: types: [opened, synchronize, reopened] jobs: unit-tests: - runs-on: ubuntu-latest + runs-on: arm64 steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0c8a950..64a3d7d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ on: jobs: unit-tests: - runs-on: ubuntu-latest + runs-on: arm64 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -27,7 +27,7 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} e2e-tests: needs: [unit-tests] - runs-on: ubuntu-latest + runs-on: arm64 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -41,7 +41,7 @@ jobs: - run: npm --prefix webapp run test:e2e docker-push-webapp: name: Push webapp Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: arm64 permissions: contents: read packages: write @@ -61,7 +61,7 @@ jobs: buildargs: API_URI docker-push-authservice: name: Push auth service Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: arm64 permissions: contents: read packages: write @@ -78,7 +78,7 @@ jobs: workdir: users/authservice docker-push-userservice: name: Push user service Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: arm64 permissions: contents: read packages: write @@ -95,7 +95,7 @@ jobs: workdir: users/userservice docker-push-gatewayservice: name: Push gateway service Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: arm64 permissions: contents: read packages: write @@ -112,7 +112,7 @@ jobs: workdir: gatewayservice deploy: name: Deploy over SSH - runs-on: ubuntu-latest + runs-on: arm64 needs: [docker-push-userservice,docker-push-authservice,docker-push-gatewayservice,docker-push-webapp] steps: - name: Deploy over SSH From f98a1de3e0bb30f2c65e3387bc61bb6702276866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Cadenas?= <77900120+andrrsin@users.noreply.github.com> Date: Mon, 26 Feb 2024 20:13:11 +0100 Subject: [PATCH 02/34] fixed hosting --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d7c6d2e..c926570 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,7 +7,7 @@ on: types: [opened, synchronize, reopened] jobs: unit-tests: - runs-on: arm64 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 64a3d7d..d3abd5f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ on: jobs: unit-tests: - runs-on: arm64 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -27,7 +27,7 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} e2e-tests: needs: [unit-tests] - runs-on: arm64 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -41,7 +41,7 @@ jobs: - run: npm --prefix webapp run test:e2e docker-push-webapp: name: Push webapp Docker Image to GitHub Packages - runs-on: arm64 + runs-on: ubuntu-latest permissions: contents: read packages: write @@ -61,7 +61,7 @@ jobs: buildargs: API_URI docker-push-authservice: name: Push auth service Docker Image to GitHub Packages - runs-on: arm64 + runs-on: ubuntu-latest permissions: contents: read packages: write @@ -78,7 +78,7 @@ jobs: workdir: users/authservice docker-push-userservice: name: Push user service Docker Image to GitHub Packages - runs-on: arm64 + runs-on: ubuntu-latest permissions: contents: read packages: write @@ -95,7 +95,7 @@ jobs: workdir: users/userservice docker-push-gatewayservice: name: Push gateway service Docker Image to GitHub Packages - runs-on: arm64 + runs-on: ubuntu-latest permissions: contents: read packages: write @@ -112,7 +112,7 @@ jobs: workdir: gatewayservice deploy: name: Deploy over SSH - runs-on: arm64 + runs-on: self-hosted needs: [docker-push-userservice,docker-push-authservice,docker-push-gatewayservice,docker-push-webapp] steps: - name: Deploy over SSH From 1a3be5eb4c9d6de1859757b8878b18534730de13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Cadenas?= <77900120+andrrsin@users.noreply.github.com> Date: Mon, 26 Feb 2024 20:54:01 +0100 Subject: [PATCH 03/34] Self host changes --- .github/workflows/release.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d3abd5f..6f2a300 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ on: jobs: unit-tests: - runs-on: ubuntu-latest + runs-on: self-hosted steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -27,7 +27,7 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} e2e-tests: needs: [unit-tests] - runs-on: ubuntu-latest + runs-on: self-hosted steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -41,7 +41,7 @@ jobs: - run: npm --prefix webapp run test:e2e docker-push-webapp: name: Push webapp Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: self-hosted permissions: contents: read packages: write @@ -61,7 +61,7 @@ jobs: buildargs: API_URI docker-push-authservice: name: Push auth service Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: self-hosted permissions: contents: read packages: write @@ -78,7 +78,7 @@ jobs: workdir: users/authservice docker-push-userservice: name: Push user service Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: self-hosted permissions: contents: read packages: write @@ -95,7 +95,7 @@ jobs: workdir: users/userservice docker-push-gatewayservice: name: Push gateway service Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: self-hosted permissions: contents: read packages: write From 6913dbde8987bc3a99da05f5de798a0ba29a40fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Cadenas?= <77900120+andrrsin@users.noreply.github.com> Date: Mon, 26 Feb 2024 20:56:56 +0100 Subject: [PATCH 04/34] ARM64 added --- .github/workflows/release.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6f2a300..157920e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ on: jobs: unit-tests: - runs-on: self-hosted + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -27,7 +27,7 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} e2e-tests: needs: [unit-tests] - runs-on: self-hosted + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -41,7 +41,7 @@ jobs: - run: npm --prefix webapp run test:e2e docker-push-webapp: name: Push webapp Docker Image to GitHub Packages - runs-on: self-hosted + runs-on: ubuntu-latest permissions: contents: read packages: write @@ -61,7 +61,7 @@ jobs: buildargs: API_URI docker-push-authservice: name: Push auth service Docker Image to GitHub Packages - runs-on: self-hosted + runs-on: ubuntu-latest permissions: contents: read packages: write @@ -78,7 +78,7 @@ jobs: workdir: users/authservice docker-push-userservice: name: Push user service Docker Image to GitHub Packages - runs-on: self-hosted + runs-on: ubuntu-latest permissions: contents: read packages: write @@ -95,7 +95,7 @@ jobs: workdir: users/userservice docker-push-gatewayservice: name: Push gateway service Docker Image to GitHub Packages - runs-on: self-hosted + runs-on: ubuntu-latest permissions: contents: read packages: write @@ -112,7 +112,7 @@ jobs: workdir: gatewayservice deploy: name: Deploy over SSH - runs-on: self-hosted + runs-on: ARM64 needs: [docker-push-userservice,docker-push-authservice,docker-push-gatewayservice,docker-push-webapp] steps: - name: Deploy over SSH From 5b718a370a6ece3fe9978611d2f92275ae379947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Cadenas?= <77900120+andrrsin@users.noreply.github.com> Date: Wed, 28 Feb 2024 00:03:47 +0100 Subject: [PATCH 05/34] platforms added to Docker Image --- .github/workflows/release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 157920e..02a96c5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,6 +59,7 @@ jobs: registry: ghcr.io workdir: webapp buildargs: API_URI + platforms: linux/amd64,linux/arm64 docker-push-authservice: name: Push auth service Docker Image to GitHub Packages runs-on: ubuntu-latest @@ -76,6 +77,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} registry: ghcr.io workdir: users/authservice + platforms: linux/amd64,linux/arm64 docker-push-userservice: name: Push user service Docker Image to GitHub Packages runs-on: ubuntu-latest @@ -93,6 +95,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} registry: ghcr.io workdir: users/userservice + platforms: linux/amd64,linux/arm64 docker-push-gatewayservice: name: Push gateway service Docker Image to GitHub Packages runs-on: ubuntu-latest From 28312679f7bf49d006515eeab31f22446a3faf2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Cadenas?= <77900120+andrrsin@users.noreply.github.com> Date: Wed, 28 Feb 2024 00:22:52 +0100 Subject: [PATCH 06/34] Platform added --- .github/workflows/release.yml | 3 --- docker-compose.yml | 8 ++++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 02a96c5..157920e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,7 +59,6 @@ jobs: registry: ghcr.io workdir: webapp buildargs: API_URI - platforms: linux/amd64,linux/arm64 docker-push-authservice: name: Push auth service Docker Image to GitHub Packages runs-on: ubuntu-latest @@ -77,7 +76,6 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} registry: ghcr.io workdir: users/authservice - platforms: linux/amd64,linux/arm64 docker-push-userservice: name: Push user service Docker Image to GitHub Packages runs-on: ubuntu-latest @@ -95,7 +93,6 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} registry: ghcr.io workdir: users/userservice - platforms: linux/amd64,linux/arm64 docker-push-gatewayservice: name: Push gateway service Docker Image to GitHub Packages runs-on: ubuntu-latest diff --git a/docker-compose.yml b/docker-compose.yml index 4a074de..e5b61dd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,7 @@ services: - "27017:27017" networks: - mynetwork + platform: linux/arm64 authservice: container_name: authservice-${teamname:-defaultASW} @@ -24,6 +25,7 @@ services: - mynetwork environment: MONGODB_URI: mongodb://mongodb:27017/userdb + platform: linux/arm64 userservice: container_name: userservice-${teamname:-defaultASW} @@ -38,6 +40,7 @@ services: - mynetwork environment: MONGODB_URI: mongodb://mongodb:27017/userdb + platform: linux/arm64 gatewayservice: container_name: gatewayservice-${teamname:-defaultASW} @@ -55,6 +58,7 @@ services: environment: AUTH_SERVICE_URL: http://authservice:8002 USER_SERVICE_URL: http://userservice:8001 + platform: linux/arm64 webapp: container_name: webapp-${teamname:-defaultASW} @@ -65,6 +69,8 @@ services: - gatewayservice ports: - "3000:3000" + platform: linux/arm64 + prometheus: image: prom/prometheus @@ -79,6 +85,7 @@ services: - "9090:9090" depends_on: - gatewayservice + grafana: image: grafana/grafana @@ -100,6 +107,7 @@ services: - prometheus + volumes: mongodb_data: prometheus_data: From 0bd0e4f05d40227ffd4ddb9e8e64c67650ce4975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fern=C3=A1ndez=20Noriega?= Date: Sat, 2 Mar 2024 20:39:27 +0100 Subject: [PATCH 07/34] Documentation parts 3 and 5 corrected and updated --- docs/src/03_system_scope_and_context.adoc | 2 +- docs/src/05_building_block_view.adoc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/03_system_scope_and_context.adoc b/docs/src/03_system_scope_and_context.adoc index 9c79942..818439d 100644 --- a/docs/src/03_system_scope_and_context.adoc +++ b/docs/src/03_system_scope_and_context.adoc @@ -48,7 +48,7 @@ The title of the table is the name of your system, the three columns contain the **** -[plantuml,"Context diagram",png] +[plantuml,"Context Diagram",png] ---- actor Player actor Client diff --git a/docs/src/05_building_block_view.adoc b/docs/src/05_building_block_view.adoc index 036ba49..048b720 100644 --- a/docs/src/05_building_block_view.adoc +++ b/docs/src/05_building_block_view.adoc @@ -63,7 +63,7 @@ In the best case you will get away with examples or simple signatures. **** -[plantuml,"White box overall system",png] +[plantuml,"Whitebox overall system",png] ---- actor Player actor Client @@ -165,7 +165,7 @@ Leave out normal, simple, boring or standardized parts of your system ...describes the internal structure of _building block 1_. **** -[plantuml,"Generated Questions API (White Box)",png] +[plantuml,"Generated Questions API (WhiteBox)",png] ---- [Wikidata] [wikidatanpm] <> From 43102e2424d3030f32daee943261601697cce74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fern=C3=A1ndez=20Noriega?= Date: Sun, 3 Mar 2024 20:22:30 +0100 Subject: [PATCH 08/34] Doc 3 and 5 updated (Second try) --- docs/src/03_system_scope_and_context.adoc | 13 +++----- docs/src/05_building_block_view.adoc | 36 +++++------------------ 2 files changed, 11 insertions(+), 38 deletions(-) diff --git a/docs/src/03_system_scope_and_context.adoc b/docs/src/03_system_scope_and_context.adoc index 818439d..3f24776 100644 --- a/docs/src/03_system_scope_and_context.adoc +++ b/docs/src/03_system_scope_and_context.adoc @@ -51,14 +51,12 @@ The title of the table is the name of your system, the three columns contain the [plantuml,"Context Diagram",png] ---- actor Player -actor Client [Wikidata] <> [WIQ Game] <> [UsersAPI] <> [GeneratedQuestionsAPI] <> Player ..> (WIQ Game) : register/login -Client ..> (WIQ Game) : view data [GeneratedQuestionsAPI] ..> Wikidata [WIQ Game] ..> UsersAPI [WIQ Game] ..> GeneratedQuestionsAPI @@ -71,21 +69,18 @@ Client ..> (WIQ Game) : view data |Player |Plays the game and can consult past scores -|Client -|Can access the data about players and generated questions - |WIQ Game |Main system in which generated questions are shown and can be answered by players |Wikidata -|External data repository from which questions are generated using the WikidataAPI +|External data repository from which questions are generated |MongoDB -|Database for storing generated questions, players' info and scores +|Database for storing players' info and scores |Users Info API -|Allows clients to see the info about players stored in the database +|Manages data of users, both registration/login data and their past scores |Generated Questions API -|Allows clients to see the info about generated questions stored in the database +|Manages generation of questions from Wikidata |=== \ No newline at end of file diff --git a/docs/src/05_building_block_view.adoc b/docs/src/05_building_block_view.adoc index 048b720..006ba7a 100644 --- a/docs/src/05_building_block_view.adoc +++ b/docs/src/05_building_block_view.adoc @@ -66,21 +66,16 @@ In the best case you will get away with examples or simple signatures. [plantuml,"Whitebox overall system",png] ---- actor Player -actor Client [Wikidata] rectangle "WIQ Game (Level 1)"{ [WIQ Game GUI] -[Data View] [UsersAPI] [GeneratedQuestionsAPI] #BurlyWood Player ..> (WIQ Game GUI) -Client ..> (Data View) [GeneratedQuestionsAPI] ..> Wikidata [WIQ Game GUI] ..> UsersAPI [WIQ Game GUI] ..> GeneratedQuestionsAPI -[Data View] ..> UsersAPI -[Data View] ..> GeneratedQuestionsAPI } ---- @@ -97,11 +92,8 @@ Contained Black boxes:: |WIQ Game GUI |Main window in which questions are shown and can be answered by the player. The latter can also see past scores. -|Data View -|Access to data about users and generated questions for the client. - |Generated Questions API -|In charge of generating the questions and storing their data +|In charge of generating the questions |UsersAPI |In charge of keeping track of the data of the users (registration and scores) @@ -168,18 +160,15 @@ Leave out normal, simple, boring or standardized parts of your system [plantuml,"Generated Questions API (WhiteBox)",png] ---- [Wikidata] -[wikidatanpm] <> +[wikibase-sdk] <> [WIQ Game GUI] -[Data View] database MongoDB rectangle "GenedQuestsAPI (Level 2)"{ - -[GenQuestsService] ..> wikidatanpm +[GenQuestsService] ..> wikibase-sdk [GenQuestsService] ..> Wikidata [GenQuestsService] <--> MongoDB [WIQ Game GUI] ..> GenQuestsService : new Question -[Data View] ..> GenQuestsService : get Questions } ---- @@ -194,23 +183,12 @@ Contained Black boxes:: |Name |Responsibility |GenQuestsService -|Receives different petitions regarding the generation of questions or their retrieval and responds accordingly. +|Receives different petitions regarding the generation of questions and responds accordingly. -|wikidatanpm +|wikibase-sdk |External library that facilitates and simplifies the use of wikidata for the generation of questions. |MongoDB -|The data of the generated questions is stored here for showing it later to the client. - -|=== - -Additional explanation of relationships:: - -The service is requested either the generation of a question or the retrieval of a subset (from WIQ Game GUI or -Data View respectively). - -For the first case, it makes use of the library to generate the question, retrieves it -for the interface to use and stores the pertinent data in the DB. +|Data about users and their scores is stored here -In the other case, it just makes the query according to the client choosings and retrieves the data of the -questions for the Data View to show. \ No newline at end of file +|=== \ No newline at end of file From e33e27a348e6985394ed2793b174b792d5a2c1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Cadenas?= <77900120+andrrsin@users.noreply.github.com> Date: Sun, 3 Mar 2024 23:58:32 +0100 Subject: [PATCH 09/34] ARM64 added --- .github/workflows/release.yml | 6 +++--- docker-compose.yml | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 157920e..3fa0fbd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,7 +41,7 @@ jobs: - run: npm --prefix webapp run test:e2e docker-push-webapp: name: Push webapp Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: ARM64 permissions: contents: read packages: write @@ -61,7 +61,7 @@ jobs: buildargs: API_URI docker-push-authservice: name: Push auth service Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: ARM64 permissions: contents: read packages: write @@ -78,7 +78,7 @@ jobs: workdir: users/authservice docker-push-userservice: name: Push user service Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: ARM64 permissions: contents: read packages: write diff --git a/docker-compose.yml b/docker-compose.yml index e5b61dd..ae4a9d8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ services: - "27017:27017" networks: - mynetwork - platform: linux/arm64 + # platform: linux/arm64 authservice: container_name: authservice-${teamname:-defaultASW} @@ -25,7 +25,7 @@ services: - mynetwork environment: MONGODB_URI: mongodb://mongodb:27017/userdb - platform: linux/arm64 + # platform: linux/arm64 userservice: container_name: userservice-${teamname:-defaultASW} @@ -40,7 +40,7 @@ services: - mynetwork environment: MONGODB_URI: mongodb://mongodb:27017/userdb - platform: linux/arm64 + # platform: linux/arm64 gatewayservice: container_name: gatewayservice-${teamname:-defaultASW} @@ -58,7 +58,7 @@ services: environment: AUTH_SERVICE_URL: http://authservice:8002 USER_SERVICE_URL: http://userservice:8001 - platform: linux/arm64 + # platform: linux/arm64 webapp: container_name: webapp-${teamname:-defaultASW} @@ -69,7 +69,7 @@ services: - gatewayservice ports: - "3000:3000" - platform: linux/arm64 + # platform: linux/arm64 prometheus: From 475bc2c54d2f69cf3dada9cd5f1af181592f4e11 Mon Sep 17 00:00:00 2001 From: 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 Date: Mon, 4 Mar 2024 12:11:16 +0100 Subject: [PATCH 10/34] Readme updated --- README.md | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f05f003..4f956f6 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,28 @@ -# wiq_en1a +# WIQ [![Deploy on release](https://github.com/Arquisoft/wiq_en1a/actions/workflows/release.yml/badge.svg)](https://github.com/Arquisoft/wiq_en1a/actions/workflows/release.yml) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Arquisoft_wiq_en1a&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Arquisoft_wiq_en1a) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=Arquisoft_wiq_en1a&metric=coverage)](https://sonarcloud.io/summary/new_code?id=Arquisoft_wiq_en1a) -### Members + +Welcome to WIQ, your gateway to a world of knowledge exploration! 🚀 + +WIQ is a dynamic web application that harnesses the power of Wikidata to create an engaging and educational experience. Dive into the vast ocean of information, challenge yourself with thought-provoking questions across various topics, and elevate your learning journey. + +Happy exploring! 🌐✨ +### Getting Started: +A quick start is using docker compose, so all containers will be created automatically. The web application is hosted on the port 3000 whereas the gateway service is in 8000. + +```bash +git clone https://github.com/Arquisoft/wiq_en1a.git +docker compose --profile dev up --build +``` + +## Meet our Team +We are students of Software Architecture in the University of Oviedo. This web application is the laboratory project of the subject. We hope you like our webapp and we are welcomed to proposals of new content by our Issues. + +You can check our Documentation [here](https://arquisoft.github.io/wiq_en1a/) where all the tecnical details are explained + +### Developers + | Name | Email | |-----------------------------|--------------------| | Andrés Cadenas Blanco | UO282276@uniovi.es | From 73c20b6627b3a37c8df22a7249226e57a6b27019 Mon Sep 17 00:00:00 2001 From: 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 Date: Mon, 4 Mar 2024 12:15:56 +0100 Subject: [PATCH 11/34] hotfix of deployment --- .github/workflows/release.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0c8a950..485cabf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,7 +41,7 @@ jobs: - run: npm --prefix webapp run test:e2e docker-push-webapp: name: Push webapp Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: ARM64 permissions: contents: read packages: write @@ -61,7 +61,7 @@ jobs: buildargs: API_URI docker-push-authservice: name: Push auth service Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: ARM64 permissions: contents: read packages: write @@ -78,7 +78,7 @@ jobs: workdir: users/authservice docker-push-userservice: name: Push user service Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: ARM64 permissions: contents: read packages: write @@ -95,7 +95,7 @@ jobs: workdir: users/userservice docker-push-gatewayservice: name: Push gateway service Docker Image to GitHub Packages - runs-on: ubuntu-latest + runs-on: ARM64 permissions: contents: read packages: write @@ -112,7 +112,7 @@ jobs: workdir: gatewayservice deploy: name: Deploy over SSH - runs-on: ubuntu-latest + runs-on: ARM64 needs: [docker-push-userservice,docker-push-authservice,docker-push-gatewayservice,docker-push-webapp] steps: - name: Deploy over SSH From 0461995bdc56671dbb5dab689d657a1d01bff682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fern=C3=A1ndez=20Noriega?= Date: Tue, 5 Mar 2024 16:15:28 +0100 Subject: [PATCH 12/34] Slight mistake in documentation point 5 corrected --- docs/src/05_building_block_view.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/05_building_block_view.adoc b/docs/src/05_building_block_view.adoc index 006ba7a..4f0573c 100644 --- a/docs/src/05_building_block_view.adoc +++ b/docs/src/05_building_block_view.adoc @@ -165,10 +165,10 @@ Leave out normal, simple, boring or standardized parts of your system database MongoDB rectangle "GenedQuestsAPI (Level 2)"{ -[GenQuestsService] ..> wikibase-sdk -[GenQuestsService] ..> Wikidata +[GenQuestsService] ..> [wikibase-sdk] +[GenQuestsService] ..> [Wikidata] [GenQuestsService] <--> MongoDB -[WIQ Game GUI] ..> GenQuestsService : new Question +[WIQ Game GUI] ..> [GenQuestsService] : new Question } ---- From 20874f0fb2c7e75f7a9c2d45d7995570fcb7f67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fern=C3=A1ndez=20Noriega?= Date: Wed, 6 Mar 2024 17:46:10 +0100 Subject: [PATCH 13/34] Added question service and linked it with the gateway service --- gatewayservice/gateway-service.js | 21 +++++ questionservice/package-lock.json | 20 +++++ questionservice/package.json | 5 ++ questionservice/question-service.js | 126 ++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+) create mode 100644 questionservice/package-lock.json create mode 100644 questionservice/package.json create mode 100644 questionservice/question-service.js diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 88b84c8..7dd7eca 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -8,6 +8,7 @@ const port = 8000; const authServiceUrl = process.env.AUTH_SERVICE_URL || 'http://localhost:8002'; const userServiceUrl = process.env.USER_SERVICE_URL || 'http://localhost:8001'; +const questionServiceUrl = process.env.QUESTION_SERVICE_URL || 'http://localhost:8010'; app.use(cors()); app.use(express.json()); @@ -41,6 +42,26 @@ app.post('/adduser', async (req, res) => { } }); +app.get('/flags/question', async (req, res) => { + try { + // Forward the request to the question service + const questionResponse = await axios.get(questionServiceUrl+'/flags/question', req.body); + res.json(questionResponse.data); + } catch (error) { + res.status(error.response.status).json({ error: error.response.data.error }); + } +}); + +app.get('/flags/answer', async (req, res) => { + try { + // Forward the request to the question service + const questionResponse = await axios.get(questionServiceUrl+'/flags/answer', req.body); + res.json(questionResponse.data); + } catch (error) { + res.status(error.response.status).json({ error: error.response.data.error }); + } +}); + // Start the gateway service const server = app.listen(port, () => { console.log(`Gateway Service listening at http://localhost:${port}`); diff --git a/questionservice/package-lock.json b/questionservice/package-lock.json new file mode 100644 index 0000000..9a22c15 --- /dev/null +++ b/questionservice/package-lock.json @@ -0,0 +1,20 @@ +{ + "name": "questionservice", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "wikibase-sdk": "^8.1.1" + } + }, + "node_modules/wikibase-sdk": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/wikibase-sdk/-/wikibase-sdk-8.1.1.tgz", + "integrity": "sha512-1NjMnfNQ4OaLh0dFAeTMvV3vGAq6HXsNKGfYUJYOVyBPGBDMunlY3QZ8+72hLV5FiKmc6Bzg1xbI0jCHfHmIew==", + "engines": { + "node": ">= 10.0.0" + } + } + } +} diff --git a/questionservice/package.json b/questionservice/package.json new file mode 100644 index 0000000..bbadfd7 --- /dev/null +++ b/questionservice/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "wikibase-sdk": "^8.1.1" + } +} diff --git a/questionservice/question-service.js b/questionservice/question-service.js new file mode 100644 index 0000000..350aa64 --- /dev/null +++ b/questionservice/question-service.js @@ -0,0 +1,126 @@ +const WBK = require('wikibase-sdk') +const wbk = WBK({ + instance: 'https://www.wikidata.org', + sparqlEndpoint: 'https://query.wikidata.org/sparql' // Required to use `sparqlQuery` and `getReverseClaims` functions, optional otherwise +}) +const express = require('express'); +const app = express(); +const port = 8010; + +app.use(express.static('public')); + +app.use(express.text()); + +//Correct image +var correctAnswerFlag +//Associates flags with their countries +var flagToCountryMap = new Map() + +class WIQ_API{ + /** + * + * @returns JSON with the question and the flags + */ + async getQuestionAndCountryFlags() { + //Reset the map for the new question + flagToCountryMap = new Map() + + //Num of fetched countries + const countriesNum = 100 + + //Required by wikidata to accept the request + const headers = new Headers(); + headers.append('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)' + +' AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36'); + + const sparql = `SELECT ?país ?paísLabel ?imagen_de_la_bandera WHERE { + SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". } + ?país wdt:P31 wd:Q6256. + OPTIONAL { ?país wdt:P41 ?imagen_de_la_bandera. } + } + LIMIT ${countriesNum}` + + //Constructing the url for the wikidata request + var url = wbk.sparqlQuery(sparql); + + const response = await fetch(url, { headers }); + const data = await response.json() + + var chosenNums = []; + const numOfChosen = 4 + // Generate n random numbers + for (let i = 0; i < numOfChosen; i++) { + this.#getRandomNumNotInSetAndUpdate(countriesNum, chosenNums) + } + + const countries = [] + const imgs = [] + for(var i=0;i { + const question = await wiq.getQuestionAndCountryFlags() + res.json(question); +}); + +/** + * Gets a response indicating if the chosen flag img was correct or not + * @param {string} req - Flag img url selected by the player + * @param {Object} res - JSON containing whether the answer was correct "true" + * or not "false". In case it was incorrect, the chosen + * country will be returned as well +*/ +app.get('flags/answer', (req, res) => { + const answeredFlag = req.body + if(correctAnswerFlag==answeredFlag){ + res.json({ + correct: "true" + }) + } else { + res.json({ + correct: "false", + country: `${flagToCountryMap.get(answeredFlag)}` + }) + } +}); + +app.listen(port, () => { + console.log(`Questions service listening on http://localhost:${port}`); +}); \ No newline at end of file From 11ebe9654d726a28b73c4f7a9e17e66267e9618a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?adri=C3=A1n?= Date: Fri, 8 Mar 2024 10:43:44 +0100 Subject: [PATCH 14/34] Backend for rankings --- gatewayservice/gateway-service.js | 20 ++++++++++++++++++++ gatewayservice/package-lock.json | 21 +++++++++++++++++++++ gatewayservice/package.json | 1 + users/authservice/auth-service.js | 8 ++++++-- users/authservice/package-lock.json | 21 +++++++++++++++++++++ users/authservice/package.json | 1 + users/userservice/user-model.js | 7 +++++++ users/userservice/user-service.js | 29 +++++++++++++++++++++++++++++ 8 files changed, 106 insertions(+), 2 deletions(-) diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 88b84c8..b9e6e40 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -2,6 +2,7 @@ const express = require('express'); const axios = require('axios'); const cors = require('cors'); const promBundle = require('express-prom-bundle'); +const cookieParser = require('cookie-parser'); const app = express(); const port = 8000; @@ -9,8 +10,24 @@ const port = 8000; const authServiceUrl = process.env.AUTH_SERVICE_URL || 'http://localhost:8002'; const userServiceUrl = process.env.USER_SERVICE_URL || 'http://localhost:8001'; +function parseCookies(response) { + const cookies = {}; + const cookieHeader = response.headers['set-cookie'] + + if (cookieHeader) { + const cookieStrings = Array.isArray(cookieHeader) ? cookieHeader : [cookieHeader]; + for (const cookieString of cookieStrings) { + const [name, value] = cookieString.split(';')[0].split('='); + cookies[name.trim()] = value.trim(); + } + } + + return cookies; +} + app.use(cors()); app.use(express.json()); +app.use(cookieParser()); //Prometheus configuration const metricsMiddleware = promBundle({includeMethod: true}); @@ -25,6 +42,9 @@ app.post('/login', async (req, res) => { try { // Forward the login request to the authentication service const authResponse = await axios.post(authServiceUrl+'/login', req.body); + const cookies = parseCookies(authResponse) + const token = cookies.token + res.cookie('token', token) res.json(authResponse.data); } catch (error) { res.status(error.response.status).json({ error: error.response.data.error }); diff --git a/gatewayservice/package-lock.json b/gatewayservice/package-lock.json index fc5f2d6..5ef04ef 100644 --- a/gatewayservice/package-lock.json +++ b/gatewayservice/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "axios": "^1.6.5", + "cookie-parser": "^1.4.6", "cors": "^2.8.5", "express": "^4.18.2", "express-prom-bundle": "^7.0.0" @@ -1787,6 +1788,26 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", diff --git a/gatewayservice/package.json b/gatewayservice/package.json index f712722..313b29f 100644 --- a/gatewayservice/package.json +++ b/gatewayservice/package.json @@ -19,6 +19,7 @@ "homepage": "https://github.com/arquisoft/wiq_en1a#readme", "dependencies": { "axios": "^1.6.5", + "cookie-parser": "^1.4.6", "cors": "^2.8.5", "express": "^4.18.2", "express-prom-bundle": "^7.0.0" diff --git a/users/authservice/auth-service.js b/users/authservice/auth-service.js index 9764f08..6641650 100644 --- a/users/authservice/auth-service.js +++ b/users/authservice/auth-service.js @@ -2,13 +2,16 @@ const express = require('express'); const mongoose = require('mongoose'); const bcrypt = require('bcrypt'); const jwt = require('jsonwebtoken'); -const User = require('./auth-model') +const User = require('./auth-model'); +const cookieParser = require('cookie-parser') const app = express(); const port = 8002; // Middleware to parse JSON in request body app.use(express.json()); +// Middleware to do anything related with cookies +app.use(cookieParser()) // Connect to MongoDB const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/userdb'; @@ -36,8 +39,9 @@ app.post('/login', async (req, res) => { // Check if the user exists and verify the password if (user && await bcrypt.compare(password, user.password)) { - // Generate a JWT token + // Generate a JWT token and save it in a cookie const token = jwt.sign({ userId: user._id }, 'your-secret-key', { expiresIn: '1h' }); + res.cookie('token', token); // Respond with the token and user information res.json({ token: token, username: username, createdAt: user.createdAt }); } else { diff --git a/users/authservice/package-lock.json b/users/authservice/package-lock.json index e0ceb0b..978a817 100644 --- a/users/authservice/package-lock.json +++ b/users/authservice/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "bcrypt": "^5.1.1", "body-parser": "^1.20.2", + "cookie-parser": "^1.4.6", "express": "^4.18.2", "jsonwebtoken": "^9.0.2", "mongoose": "^8.0.4" @@ -1898,6 +1899,26 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", diff --git a/users/authservice/package.json b/users/authservice/package.json index 23f1c02..e9d7694 100644 --- a/users/authservice/package.json +++ b/users/authservice/package.json @@ -20,6 +20,7 @@ "dependencies": { "bcrypt": "^5.1.1", "body-parser": "^1.20.2", + "cookie-parser": "^1.4.6", "express": "^4.18.2", "jsonwebtoken": "^9.0.2", "mongoose": "^8.0.4" diff --git a/users/userservice/user-model.js b/users/userservice/user-model.js index 71d81b5..328601b 100644 --- a/users/userservice/user-model.js +++ b/users/userservice/user-model.js @@ -13,6 +13,13 @@ const userSchema = new mongoose.Schema({ type: Date, default: Date.now, }, + points: { + type: Number, + default: function() { + // Generate a random integer between 0 and 100 + return Math.floor(Math.random() * 101); + } + } }); const User = mongoose.model('User', userSchema); diff --git a/users/userservice/user-service.js b/users/userservice/user-service.js index be95842..bfb581f 100644 --- a/users/userservice/user-service.js +++ b/users/userservice/user-service.js @@ -26,6 +26,35 @@ function validateRequiredFields(req, requiredFields) { } } +// Function to get the user's ranking data +async function getRankingFor(loggedUser) { + const users = await User.find().sort({points: -1}) + const ranking = users.indexOf( (user) => user._id == loggedUser._id) + + return { ranking: ranking, points: loggedUser.points, user: loggedUser.username } +} + +app.get('/rankings', async (req, res) => { + try { + const { token } = req.cookies + const decoded = jwt.verify(token, 'your-secret-key') + const userId = decoded.userId + const loggedUser = await User.findById(userId) + const userRanking = getRankingFor(loggedUser) + const usersRanking = (await User.find().sort({points: -1})).map( (user, index) => { + return { + ranking: index+1, + points: user.points, + user: user.username } + }) + + res.json(userRanking, usersRanking) + + } catch (error) { + res.status(400).json({ error: error.message }); + } +}) + app.post('/adduser', async (req, res) => { try { // Check if required fields are present in the request body From bec70f1d4a8f82f39759086fc5a3a037586e1bed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?adri=C3=A1n?= Date: Fri, 8 Mar 2024 11:09:21 +0100 Subject: [PATCH 15/34] Removed token cookie --- gatewayservice/gateway-service.js | 20 -------------------- users/authservice/auth-service.js | 6 +----- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 5d1f47d..7dd7eca 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -2,7 +2,6 @@ const express = require('express'); const axios = require('axios'); const cors = require('cors'); const promBundle = require('express-prom-bundle'); -const cookieParser = require('cookie-parser'); const app = express(); const port = 8000; @@ -11,24 +10,8 @@ const authServiceUrl = process.env.AUTH_SERVICE_URL || 'http://localhost:8002'; const userServiceUrl = process.env.USER_SERVICE_URL || 'http://localhost:8001'; const questionServiceUrl = process.env.QUESTION_SERVICE_URL || 'http://localhost:8010'; -function parseCookies(response) { - const cookies = {}; - const cookieHeader = response.headers['set-cookie'] - - if (cookieHeader) { - const cookieStrings = Array.isArray(cookieHeader) ? cookieHeader : [cookieHeader]; - for (const cookieString of cookieStrings) { - const [name, value] = cookieString.split(';')[0].split('='); - cookies[name.trim()] = value.trim(); - } - } - - return cookies; -} - app.use(cors()); app.use(express.json()); -app.use(cookieParser()); //Prometheus configuration const metricsMiddleware = promBundle({includeMethod: true}); @@ -43,9 +26,6 @@ app.post('/login', async (req, res) => { try { // Forward the login request to the authentication service const authResponse = await axios.post(authServiceUrl+'/login', req.body); - const cookies = parseCookies(authResponse) - const token = cookies.token - res.cookie('token', token) res.json(authResponse.data); } catch (error) { res.status(error.response.status).json({ error: error.response.data.error }); diff --git a/users/authservice/auth-service.js b/users/authservice/auth-service.js index 6641650..a05dd51 100644 --- a/users/authservice/auth-service.js +++ b/users/authservice/auth-service.js @@ -3,15 +3,12 @@ const mongoose = require('mongoose'); const bcrypt = require('bcrypt'); const jwt = require('jsonwebtoken'); const User = require('./auth-model'); -const cookieParser = require('cookie-parser') const app = express(); const port = 8002; // Middleware to parse JSON in request body app.use(express.json()); -// Middleware to do anything related with cookies -app.use(cookieParser()) // Connect to MongoDB const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/userdb'; @@ -39,9 +36,8 @@ app.post('/login', async (req, res) => { // Check if the user exists and verify the password if (user && await bcrypt.compare(password, user.password)) { - // Generate a JWT token and save it in a cookie + // Generate a JWT token const token = jwt.sign({ userId: user._id }, 'your-secret-key', { expiresIn: '1h' }); - res.cookie('token', token); // Respond with the token and user information res.json({ token: token, username: username, createdAt: user.createdAt }); } else { From 50fe55a6e4b1a101df37fcbfe14cede367921026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?adri=C3=A1n?= Date: Sat, 9 Mar 2024 16:41:51 +0100 Subject: [PATCH 16/34] Added Rankings component --- gatewayservice/gateway-service.js | 10 + questionservice/package-lock.json | 679 +++++++++++++++++++++++++++++ questionservice/package.json | 5 + users/userservice/user-service.js | 8 +- webapp/package-lock.json | 43 +- webapp/package.json | 3 + webapp/src/components/Rankings.jsx | 42 ++ webapp/src/index.css | 4 + webapp/tailwind.config.js | 10 + 9 files changed, 780 insertions(+), 24 deletions(-) create mode 100644 webapp/src/components/Rankings.jsx create mode 100644 webapp/tailwind.config.js diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 7dd7eca..90fe0ac 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -62,6 +62,16 @@ app.get('/flags/answer', async (req, res) => { } }); +app.get('/rankings', async (req, res) => { + try { + // Forward the request to the user service + const userResponse = await axios.get(userServiceUrl+'/rankings', req.body); + res.json(userResponse.data); + } catch (error) { + res.status(error.response.status).json({ error: error.response.data.error }); + } +}); + // Start the gateway service const server = app.listen(port, () => { console.log(`Gateway Service listening at http://localhost:${port}`); diff --git a/questionservice/package-lock.json b/questionservice/package-lock.json index 9a22c15..6ea2cf7 100644 --- a/questionservice/package-lock.json +++ b/questionservice/package-lock.json @@ -5,9 +5,688 @@ "packages": { "": { "dependencies": { + "express": "^4.18.3", "wikibase-sdk": "^8.1.1" } }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz", + "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "dependencies": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/wikibase-sdk": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/wikibase-sdk/-/wikibase-sdk-8.1.1.tgz", diff --git a/questionservice/package.json b/questionservice/package.json index bbadfd7..b6071ef 100644 --- a/questionservice/package.json +++ b/questionservice/package.json @@ -1,5 +1,10 @@ { + "scripts": { + "start": "node question-service.js", + "test": "jest" + }, "dependencies": { + "express": "^4.18.3", "wikibase-sdk": "^8.1.1" } } diff --git a/users/userservice/user-service.js b/users/userservice/user-service.js index bfb581f..170a7c1 100644 --- a/users/userservice/user-service.js +++ b/users/userservice/user-service.js @@ -36,11 +36,11 @@ async function getRankingFor(loggedUser) { app.get('/rankings', async (req, res) => { try { - const { token } = req.cookies + /* const { token } = req.cookies const decoded = jwt.verify(token, 'your-secret-key') const userId = decoded.userId const loggedUser = await User.findById(userId) - const userRanking = getRankingFor(loggedUser) + const userRanking = getRankingFor(loggedUser) */ const usersRanking = (await User.find().sort({points: -1})).map( (user, index) => { return { ranking: index+1, @@ -48,8 +48,8 @@ app.get('/rankings', async (req, res) => { user: user.username } }) - res.json(userRanking, usersRanking) - + //res.json(userRanking, usersRanking) + res.json(usersRanking) } catch (error) { res.status(400).json({ error: error.message }); } diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 27466ae..bccaf13 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -14,10 +14,13 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^14.1.2", "@testing-library/user-event": "^14.5.2", + "autoprefixer": "^10.4.18", "axios": "^1.6.5", + "postcss": "^8.4.35", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", + "tailwindcss": "^3.4.1", "web-vitals": "^3.5.1" }, "devDependencies": { @@ -6931,9 +6934,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.16", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", - "integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==", + "version": "10.4.18", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.18.tgz", + "integrity": "sha512-1DKbDfsr6KUElM6wg+0zRNkB/Q7WcKYAaK+pzXn+Xqmszm/5Xa9coeNdtP88Vi+dPzZnMjhge8GIV49ZQkDa+g==", "funding": [ { "type": "opencollective", @@ -6949,9 +6952,9 @@ } ], "dependencies": { - "browserslist": "^4.21.10", - "caniuse-lite": "^1.0.30001538", - "fraction.js": "^4.3.6", + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001591", + "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", "postcss-value-parser": "^4.2.0" @@ -7633,9 +7636,9 @@ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" }, "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "funding": [ { "type": "opencollective", @@ -7651,8 +7654,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -7818,9 +7821,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001576", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz", - "integrity": "sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==", + "version": "1.0.30001596", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001596.tgz", + "integrity": "sha512-zpkZ+kEr6We7w63ORkoJ2pOfBwBkY/bJrG/UZ90qNb45Isblu8wzDgevEOrRL1r9dWayHjYiiyCMEXPn4DweGQ==", "funding": [ { "type": "opencollective", @@ -9544,9 +9547,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.623", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.623.tgz", - "integrity": "sha512-lKoz10iCYlP1WtRYdh5MvocQPWVRoI7ysp6qf18bmeBgR8abE6+I2CsfyNKztRDZvhdWc+krKT6wS7Neg8sw3A==" + "version": "1.4.699", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.699.tgz", + "integrity": "sha512-I7q3BbQi6e4tJJN5CRcyvxhK0iJb34TV8eJQcgh+fR2fQ8miMgZcEInckCo1U9exDHbfz7DLDnFn8oqH/VcRKw==" }, "node_modules/emittery": { "version": "0.13.1", @@ -20153,9 +20156,9 @@ } }, "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "funding": [ { "type": "opencollective", diff --git a/webapp/package.json b/webapp/package.json index 74e31be..15bc2b2 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -9,10 +9,13 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^14.1.2", "@testing-library/user-event": "^14.5.2", + "autoprefixer": "^10.4.18", "axios": "^1.6.5", + "postcss": "^8.4.35", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", + "tailwindcss": "^3.4.1", "web-vitals": "^3.5.1" }, "scripts": { diff --git a/webapp/src/components/Rankings.jsx b/webapp/src/components/Rankings.jsx new file mode 100644 index 0000000..4e3ee4c --- /dev/null +++ b/webapp/src/components/Rankings.jsx @@ -0,0 +1,42 @@ +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; + +const apiEndpoint = 'http://localhost:8000'; + +const Rankings = () => { + const [users, setUsers] = useState([]); + + useEffect(() => { + const fetchData = async () => { + try { + const response = await axios.get(`${apiEndpoint}/rankings`); + setUsers(response.data); + } catch (error) { + console.error('Error fetching data:', error); + } + }; + + fetchData(); + }, []); + + return ( +
+
+

Rankings

+
    + {users.map(user => ( +
  • +
    + {user.ranking} + {user.user} +
    + {user.points} points +
  • + ))} +
+
+
+ ) +} + +export default Rankings \ No newline at end of file diff --git a/webapp/src/index.css b/webapp/src/index.css index ec2585e..17df0e7 100644 --- a/webapp/src/index.css +++ b/webapp/src/index.css @@ -1,3 +1,7 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', diff --git a/webapp/tailwind.config.js b/webapp/tailwind.config.js new file mode 100644 index 0000000..4049afe --- /dev/null +++ b/webapp/tailwind.config.js @@ -0,0 +1,10 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./index.html", + "./src/**/*.{js,ts,jsx,tsx}"], + theme: { + extend: {}, + }, + plugins: [], +} + From f0044ec860300d3f979e52e9e99a8a40b156b07b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?adri=C3=A1n?= Date: Sat, 9 Mar 2024 17:52:20 +0100 Subject: [PATCH 17/34] Added navbar --- webapp/package-lock.json | 39 ++++++++++++++++++++++++++++++++ webapp/package.json | 1 + webapp/src/App.js | 23 ++++++++++++++++--- webapp/src/components/Navbar.jsx | 21 +++++++++++++++++ 4 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 webapp/src/components/Navbar.jsx diff --git a/webapp/package-lock.json b/webapp/package-lock.json index bccaf13..380820a 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -19,6 +19,7 @@ "postcss": "^8.4.35", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-router-dom": "^6.22.3", "react-scripts": "5.0.1", "tailwindcss": "^3.4.1", "web-vitals": "^3.5.1" @@ -5008,6 +5009,14 @@ "node": ">=12" } }, + "node_modules/@remix-run/router": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz", + "integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -22012,6 +22021,36 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.22.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz", + "integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==", + "dependencies": { + "@remix-run/router": "1.15.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.22.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz", + "integrity": "sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==", + "dependencies": { + "@remix-run/router": "1.15.3", + "react-router": "6.22.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", diff --git a/webapp/package.json b/webapp/package.json index 15bc2b2..ca6979f 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -14,6 +14,7 @@ "postcss": "^8.4.35", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-router-dom": "^6.22.3", "react-scripts": "5.0.1", "tailwindcss": "^3.4.1", "web-vitals": "^3.5.1" diff --git a/webapp/src/App.js b/webapp/src/App.js index d932005..fba5876 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -1,6 +1,9 @@ import React, { useState } from 'react'; +import {BrowserRouter, Routes, Route} from 'react-router-dom' import AddUser from './components/AddUser'; +import Navbar from './components/Navbar'; import Login from './components/Login'; +import Rankings from './components/Rankings'; import CssBaseline from '@mui/material/CssBaseline'; import Container from '@mui/material/Container'; import Typography from '@mui/material/Typography'; @@ -14,7 +17,21 @@ function App() { }; return ( - + + + + Home page}/> + } /> + } /> + } /> + Play page} /> + + + + + + + /* Welcome to the 2024 edition of the Software Architecture course @@ -31,8 +48,8 @@ function App() { )} - - ); + */ + ) } export default App; diff --git a/webapp/src/components/Navbar.jsx b/webapp/src/components/Navbar.jsx new file mode 100644 index 0000000..19e0a91 --- /dev/null +++ b/webapp/src/components/Navbar.jsx @@ -0,0 +1,21 @@ +function Navbar() { + + return ( +
+
+ WIQ +
+ +
+ ) +} + +export default Navbar \ No newline at end of file From 9f07aa77ec5cdc4dd1b6139d66aca8d8c4443d79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fern=C3=A1ndez=20Noriega?= Date: Sat, 9 Mar 2024 18:28:00 +0100 Subject: [PATCH 18/34] Documentation points 8, 11 and 12 advanced --- docs/src/08_concepts.adoc | 23 +++++++++++++++-------- docs/src/11_technical_risks.adoc | 11 +++++++++++ docs/src/12_glossary.adoc | 8 ++++---- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/docs/src/08_concepts.adoc b/docs/src/08_concepts.adoc index 591ccf1..5ea68b2 100644 --- a/docs/src/08_concepts.adoc +++ b/docs/src/08_concepts.adoc @@ -55,19 +55,26 @@ image::08-Crosscutting-Concepts-Structure-EN.png["Possible topics for crosscutti See https://docs.arc42.org/section-8/[Concepts] in the arc42 documentation. **** +=== _Domain model and terminology_ -=== __ -__ +=== _Microservice based system_ -=== __ +Different business functionallities will be developed in different independent services. +This will ensure that if one of them fails, the rest are still working (For example, +if the rankings go down that will not affect the main game) as they have their own deployment +as well. +Other benefits are increased maintainability due to separation in small, more readable modules +and the possibillity of using different languages or technologies for each module if needed/prefered +without colliding with the rest. -__ -... +=== _Gateway service routing_ -=== __ - -__ +We will use a speciallized service that will route the requests to the corresponding service, acting as +a single entry point for the application. Requests to the services are much simpler as only the api base +endpoint and the action needs to be known and the gateway can also act as a filter to manage requests +conditionally if needed. This approach also favors security as we can control which requests are actually +sent based on its content or the context of the app. \ No newline at end of file diff --git a/docs/src/11_technical_risks.adoc b/docs/src/11_technical_risks.adoc index dc5575f..35ecca7 100644 --- a/docs/src/11_technical_risks.adoc +++ b/docs/src/11_technical_risks.adoc @@ -23,3 +23,14 @@ List of risks and/or technical debts, probably including suggested measures to m See https://docs.arc42.org/section-11/[Risks and Technical Debt] in the arc42 documentation. **** + +[cols="e,4e" options="header"] +|=== +|Risk |Why it exists |Severity - Explanation |Possible solutions + +|Use of wikibase-sdk version 8 (not final) +|It is the last version that supports 'require', which is needed to use express in the same module +|Low - The difference is, a priori, merely functional, but retains the needed characteristics +|Upgrade only if a newer version supports 'require' + +|=== \ No newline at end of file diff --git a/docs/src/12_glossary.adoc b/docs/src/12_glossary.adoc index 192b235..9b0adb5 100644 --- a/docs/src/12_glossary.adoc +++ b/docs/src/12_glossary.adoc @@ -34,9 +34,9 @@ See https://docs.arc42.org/section-12/[Glossary] in the arc42 documentation. |=== |Term |Definition -| -| +|Microservice +|Small and independent component that performs a specific business function -| -| +|API +|Set of endpoints exposed by the backend server whose purpose is interacting with the client-side |=== From 1a4c473bf8fbc6273efa3af315abf6a6e4a3f8bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fern=C3=A1ndez=20Noriega?= Date: Sat, 9 Mar 2024 18:59:18 +0100 Subject: [PATCH 19/34] Corrected small format mistake in point 11 table --- docs/src/11_technical_risks.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/11_technical_risks.adoc b/docs/src/11_technical_risks.adoc index 35ecca7..6297197 100644 --- a/docs/src/11_technical_risks.adoc +++ b/docs/src/11_technical_risks.adoc @@ -24,7 +24,7 @@ See https://docs.arc42.org/section-11/[Risks and Technical Debt] in the arc42 do **** -[cols="e,4e" options="header"] +[options="header", cols="1,1,1,1"] |=== |Risk |Why it exists |Severity - Explanation |Possible solutions From 5f46c24b0cc3569cf6c25936a008394fbefc43fa Mon Sep 17 00:00:00 2001 From: ChristianFN2 <157963970+ChristianFN2@users.noreply.github.com> Date: Sat, 9 Mar 2024 18:59:56 +0100 Subject: [PATCH 20/34] Documentation points 8, 11 and 12 advanced (#43) --- docs/src/08_concepts.adoc | 23 +++++++++++++++-------- docs/src/11_technical_risks.adoc | 11 +++++++++++ docs/src/12_glossary.adoc | 8 ++++---- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/docs/src/08_concepts.adoc b/docs/src/08_concepts.adoc index 591ccf1..5ea68b2 100644 --- a/docs/src/08_concepts.adoc +++ b/docs/src/08_concepts.adoc @@ -55,19 +55,26 @@ image::08-Crosscutting-Concepts-Structure-EN.png["Possible topics for crosscutti See https://docs.arc42.org/section-8/[Concepts] in the arc42 documentation. **** +=== _Domain model and terminology_ -=== __ -__ +=== _Microservice based system_ -=== __ +Different business functionallities will be developed in different independent services. +This will ensure that if one of them fails, the rest are still working (For example, +if the rankings go down that will not affect the main game) as they have their own deployment +as well. +Other benefits are increased maintainability due to separation in small, more readable modules +and the possibillity of using different languages or technologies for each module if needed/prefered +without colliding with the rest. -__ -... +=== _Gateway service routing_ -=== __ - -__ +We will use a speciallized service that will route the requests to the corresponding service, acting as +a single entry point for the application. Requests to the services are much simpler as only the api base +endpoint and the action needs to be known and the gateway can also act as a filter to manage requests +conditionally if needed. This approach also favors security as we can control which requests are actually +sent based on its content or the context of the app. \ No newline at end of file diff --git a/docs/src/11_technical_risks.adoc b/docs/src/11_technical_risks.adoc index dc5575f..35ecca7 100644 --- a/docs/src/11_technical_risks.adoc +++ b/docs/src/11_technical_risks.adoc @@ -23,3 +23,14 @@ List of risks and/or technical debts, probably including suggested measures to m See https://docs.arc42.org/section-11/[Risks and Technical Debt] in the arc42 documentation. **** + +[cols="e,4e" options="header"] +|=== +|Risk |Why it exists |Severity - Explanation |Possible solutions + +|Use of wikibase-sdk version 8 (not final) +|It is the last version that supports 'require', which is needed to use express in the same module +|Low - The difference is, a priori, merely functional, but retains the needed characteristics +|Upgrade only if a newer version supports 'require' + +|=== \ No newline at end of file diff --git a/docs/src/12_glossary.adoc b/docs/src/12_glossary.adoc index 192b235..9b0adb5 100644 --- a/docs/src/12_glossary.adoc +++ b/docs/src/12_glossary.adoc @@ -34,9 +34,9 @@ See https://docs.arc42.org/section-12/[Glossary] in the arc42 documentation. |=== |Term |Definition -| -| +|Microservice +|Small and independent component that performs a specific business function -| -| +|API +|Set of endpoints exposed by the backend server whose purpose is interacting with the client-side |=== From 2a14b1820f3fae8049e2d1ccf3c21f22a161d6fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fern=C3=A1ndez=20Noriega?= Date: Sat, 9 Mar 2024 19:13:25 +0100 Subject: [PATCH 21/34] Another small mistake done during conflict solving corrected --- docs/src/11_technical_risks.adoc | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/src/11_technical_risks.adoc b/docs/src/11_technical_risks.adoc index 34e8992..6297197 100644 --- a/docs/src/11_technical_risks.adoc +++ b/docs/src/11_technical_risks.adoc @@ -25,7 +25,6 @@ See https://docs.arc42.org/section-11/[Risks and Technical Debt] in the arc42 do **** [options="header", cols="1,1,1,1"] -======= |=== |Risk |Why it exists |Severity - Explanation |Possible solutions From a2d8be8baf8ea8852b3bbf749e0ed1ee6e5d45eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fern=C3=A1ndez=20Noriega?= Date: Sat, 9 Mar 2024 19:22:23 +0100 Subject: [PATCH 22/34] Minor correction in the endpoints of the question service: they were missing a slash at the start --- questionservice/question-service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/questionservice/question-service.js b/questionservice/question-service.js index 350aa64..9c7d276 100644 --- a/questionservice/question-service.js +++ b/questionservice/question-service.js @@ -95,7 +95,7 @@ const wiq = new WIQ_API() * @param {} req - Not used * @param {Object} res - Contains the question (question) and the images of the flags (flags) */ -app.get('flags/question', async (req, res) => { +app.get('/flags/question', async (req, res) => { const question = await wiq.getQuestionAndCountryFlags() res.json(question); }); @@ -107,7 +107,7 @@ app.get('flags/question', async (req, res) => { * or not "false". In case it was incorrect, the chosen * country will be returned as well */ -app.get('flags/answer', (req, res) => { +app.get('/flags/answer', (req, res) => { const answeredFlag = req.body if(correctAnswerFlag==answeredFlag){ res.json({ From 6f434781c74ea1ab06054fb1b7343c14f77fe4cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Cadenas?= <77900120+andrrsin@users.noreply.github.com> Date: Sat, 9 Mar 2024 19:47:43 +0100 Subject: [PATCH 23/34] Login Local Storage and backend (#48) * Added Login to local storage * checkUsert Logged in --- gatewayservice/gateway-service.js | 17 +++++++++++++++++ users/authservice/auth-service.js | 26 +++++++++++++++++++++++++- users/userservice/user-service.js | 3 +++ webapp/src/App.js | 21 +++++++++++++++++---- webapp/src/components/Login.js | 15 ++++++--------- webapp/src/index.js | 2 ++ 6 files changed, 70 insertions(+), 14 deletions(-) diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 90fe0ac..62fe881 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -32,6 +32,7 @@ app.post('/login', async (req, res) => { } }); + app.post('/adduser', async (req, res) => { try { // Forward the add user request to the user service @@ -62,6 +63,22 @@ app.get('/flags/answer', async (req, res) => { } }); + +app.get('/self', async (req, res) => { + try { + // Forward the self request to the user service + + const userResponse = await axios.get(authServiceUrl+'/self', { + headers: { + Authorization: req.headers.authorization, + }, + }); + + res.status(200).json(userResponse.data); + } catch (error) { +res.status(error.response.status).json({ error: error.response.data.error }); + } +}); app.get('/rankings', async (req, res) => { try { // Forward the request to the user service diff --git a/users/authservice/auth-service.js b/users/authservice/auth-service.js index a05dd51..05673de 100644 --- a/users/authservice/auth-service.js +++ b/users/authservice/auth-service.js @@ -39,7 +39,7 @@ app.post('/login', async (req, res) => { // Generate a JWT token const token = jwt.sign({ userId: user._id }, 'your-secret-key', { expiresIn: '1h' }); // Respond with the token and user information - res.json({ token: token, username: username, createdAt: user.createdAt }); + res.status(200).json({ token: token }); } else { res.status(401).json({ error: 'Invalid credentials' }); } @@ -53,6 +53,30 @@ const server = app.listen(port, () => { console.log(`Auth Service listening at http://localhost:${port}`); }); +app.get('/self', async (req, res) => { + try { + + const token = req.headers.authorization; + let id = {}; + if (!token) { + return res.status(403).json({ error: 'No token provided' }); + } + jwt.verify(token, 'your-secret-key', (err, decoded) => { + if (err) { + return res.status(500).json({ error: 'Failed to authenticate token' }); + } + + // If everything is good, save the user id to request for use in other routes + id = decoded.userId; + + }); + const user = await User.findById(id); + res.status(200).json(user); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + server.on('close', () => { // Close the Mongoose connection mongoose.connection.close(); diff --git a/users/userservice/user-service.js b/users/userservice/user-service.js index 170a7c1..c169099 100644 --- a/users/userservice/user-service.js +++ b/users/userservice/user-service.js @@ -3,6 +3,7 @@ const express = require('express'); const mongoose = require('mongoose'); const bcrypt = require('bcrypt'); const bodyParser = require('body-parser'); + const User = require('./user-model') const app = express(); @@ -78,6 +79,8 @@ const server = app.listen(port, () => { console.log(`User Service listening at http://localhost:${port}`); }); + + // Listen for the 'close' event on the Express.js server server.on('close', () => { // Close the Mongoose connection diff --git a/webapp/src/App.js b/webapp/src/App.js index fba5876..7f6e8bf 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -8,14 +8,27 @@ import CssBaseline from '@mui/material/CssBaseline'; import Container from '@mui/material/Container'; import Typography from '@mui/material/Typography'; import Link from '@mui/material/Link'; - +import { useEffect } from 'react'; +import axios from 'axios'; function App() { const [showLogin, setShowLogin] = useState(true); - + const [user, setUser] = useState({}); + const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; const handleToggleView = () => { setShowLogin(!showLogin); }; - + const checkUser = () => { + const token = localStorage.getItem('uToken'); + if (token) { + axios.get(`${apiEndpoint}/self`, { + headers: { + Authorization: token, + }, + }).then((response) => { + setUser(response.data); + }); + } + }; return ( @@ -34,7 +47,7 @@ function App() { /* - Welcome to the 2024 edition of the Software Architecture course + Welcome to the 2024 edition of the Software Architecture course hola {showLogin ? : } diff --git a/webapp/src/components/Login.js b/webapp/src/components/Login.js index 0ad6268..80ff0cd 100644 --- a/webapp/src/components/Login.js +++ b/webapp/src/components/Login.js @@ -3,12 +3,13 @@ import React, { useState } from 'react'; import axios from 'axios'; import { Container, Typography, TextField, Button, Snackbar } from '@mui/material'; + const Login = () => { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(''); const [loginSuccess, setLoginSuccess] = useState(false); - const [createdAt, setCreatedAt] = useState(''); + const [openSnackbar, setOpenSnackbar] = useState(false); const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; @@ -18,11 +19,9 @@ const Login = () => { const response = await axios.post(`${apiEndpoint}/login`, { username, password }); // Extract data from the response - const { createdAt: userCreatedAt } = response.data; - - setCreatedAt(userCreatedAt); + + localStorage.setItem('uToken', response.data.token); setLoginSuccess(true); - setOpenSnackbar(true); } catch (error) { setError(error.response.data.error); @@ -38,11 +37,9 @@ const Login = () => { {loginSuccess ? (
- Hello {username}! - - - Your account was created on {new Date(createdAt).toLocaleDateString()}. + {localStorage.getItem('user')} +
) : (
diff --git a/webapp/src/index.js b/webapp/src/index.js index d563c0f..ec6a487 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -5,6 +5,8 @@ import App from './App'; import reportWebVitals from './reportWebVitals'; const root = ReactDOM.createRoot(document.getElementById('root')); + + root.render( From 58f4621e67b744be7bacd39b5e672ca3640af7af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Cadenas?= <77900120+andrrsin@users.noreply.github.com> Date: Sat, 9 Mar 2024 23:27:29 +0100 Subject: [PATCH 24/34] docker and login --- .github/workflows/release.yml | 25 +++++-- docker-compose.yml | 17 +++++ gatewayservice/gateway-service.js | 6 +- questionservice/.dockerignore | 2 + questionservice/Dockerfile | 20 ++++++ users/authservice/auth-model.js | 1 + users/authservice/auth-service.js | 6 +- users/userservice/user-model.js | 4 ++ users/userservice/user-service.js | 3 +- webapp/src/App.js | 80 ++++++++++++---------- webapp/src/components/AddUser.js | 94 +++++++++++++++----------- webapp/src/components/Game.jsx | 27 ++++++++ webapp/src/components/Login.js | 105 +++++++++++++++-------------- webapp/src/components/MainPage.jsx | 9 +++ webapp/src/components/Navbar.jsx | 17 ++++- webapp/src/components/Rankings.jsx | 14 +++- 16 files changed, 293 insertions(+), 137 deletions(-) create mode 100644 questionservice/.dockerignore create mode 100644 questionservice/Dockerfile create mode 100644 webapp/src/components/Game.jsx create mode 100644 webapp/src/components/MainPage.jsx diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 485cabf..54031bf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,7 +45,7 @@ jobs: permissions: contents: read packages: write - needs: [e2e-tests] + # needs: [e2e-tests] steps: - uses: actions/checkout@v4 - name: Publish to Registry @@ -82,7 +82,7 @@ jobs: permissions: contents: read packages: write - needs: [e2e-tests] + # needs: [e2e-tests] steps: - uses: actions/checkout@v4 - name: Publish to Registry @@ -93,13 +93,30 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} registry: ghcr.io workdir: users/userservice + docker-push-questionservice: + name: Push question service Docker Image to GitHub Packages + runs-on: ARM64 + permissions: + contents: read + packages: write + # needs: [e2e-tests] + steps: + - uses: actions/checkout@v4 + - name: Publish to Registry + uses: elgohr/Publish-Docker-Github-Action@v5 + with: + name: arquisoft/wiq_en1a/usequestionservicerservice + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + registry: ghcr.io + workdir: questionservice docker-push-gatewayservice: name: Push gateway service Docker Image to GitHub Packages runs-on: ARM64 permissions: contents: read packages: write - needs: [e2e-tests] + # needs: [e2e-tests] steps: - uses: actions/checkout@v4 - name: Publish to Registry @@ -113,7 +130,7 @@ jobs: deploy: name: Deploy over SSH runs-on: ARM64 - needs: [docker-push-userservice,docker-push-authservice,docker-push-gatewayservice,docker-push-webapp] + needs: [docker-push-userservice,docker-push-authservice,docker-push-gatewayservice,docker-push-webapp,docker-push-questionservice] steps: - name: Deploy over SSH uses: fifsky/ssh-action@master diff --git a/docker-compose.yml b/docker-compose.yml index ae4a9d8..1397812 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -42,6 +42,21 @@ services: MONGODB_URI: mongodb://mongodb:27017/userdb # platform: linux/arm64 + questionservice: + container_name: questionservice-${teamname:-defaultASW} + image: ghcr.io/arquisoft/wiq_en1a/questionservice:latest + profiles: ["dev", "prod"] + build: ./questionservice + depends_on: + - mongodb + ports: + - "8010:8010" + networks: + - mynetwork + environment: + MONGODB_URI: mongodb://mongodb:27017/userdb + # platform: linux/arm64 + gatewayservice: container_name: gatewayservice-${teamname:-defaultASW} image: ghcr.io/arquisoft/wiq_en1a/gatewayservice:latest @@ -51,6 +66,7 @@ services: - mongodb - userservice - authservice + - questionservice ports: - "8000:8000" networks: @@ -58,6 +74,7 @@ services: environment: AUTH_SERVICE_URL: http://authservice:8002 USER_SERVICE_URL: http://userservice:8001 + QUESTION_SERVICE_URL: http://questionservice:8010 # platform: linux/arm64 webapp: diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 62fe881..6358fd0 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -25,8 +25,10 @@ app.get('/health', (_req, res) => { app.post('/login', async (req, res) => { try { // Forward the login request to the authentication service + const authResponse = await axios.post(authServiceUrl+'/login', req.body); - res.json(authResponse.data); + + res.status(200).json(authResponse.data); } catch (error) { res.status(error.response.status).json({ error: error.response.data.error }); } @@ -37,7 +39,7 @@ app.post('/adduser', async (req, res) => { try { // Forward the add user request to the user service const userResponse = await axios.post(userServiceUrl+'/adduser', req.body); - res.json(userResponse.data); + res.status(200).json(userResponse.data); } catch (error) { res.status(error.response.status).json({ error: error.response.data.error }); } diff --git a/questionservice/.dockerignore b/questionservice/.dockerignore new file mode 100644 index 0000000..3091757 --- /dev/null +++ b/questionservice/.dockerignore @@ -0,0 +1,2 @@ +node_modules +coverage \ No newline at end of file diff --git a/questionservice/Dockerfile b/questionservice/Dockerfile new file mode 100644 index 0000000..b13a1ff --- /dev/null +++ b/questionservice/Dockerfile @@ -0,0 +1,20 @@ +# Use an official Node.js runtime as a parent image +FROM node:20 + +# Set the working directory in the container +WORKDIR /usr/src/questionservice + +# Copy package.json and package-lock.json to the working directory +COPY package*.json ./ + +# Install app dependencies +RUN npm install + +# Copy the app source code to the working directory +COPY . . + +# Expose the port the app runs on +EXPOSE 8002 + +# Define the command to run your app +CMD ["node", "auth-service.js"] diff --git a/users/authservice/auth-model.js b/users/authservice/auth-model.js index 7763b51..d86c36c 100644 --- a/users/authservice/auth-model.js +++ b/users/authservice/auth-model.js @@ -2,6 +2,7 @@ const mongoose = require('mongoose'); const userSchema = new mongoose.Schema({ username: String, + email: String, password: String, createdAt: Date, }); diff --git a/users/authservice/auth-service.js b/users/authservice/auth-service.js index 05673de..3206de0 100644 --- a/users/authservice/auth-service.js +++ b/users/authservice/auth-service.js @@ -27,12 +27,12 @@ function validateRequiredFields(req, requiredFields) { app.post('/login', async (req, res) => { try { // Check if required fields are present in the request body - validateRequiredFields(req, ['username', 'password']); + validateRequiredFields(req, ['email', 'password']); - const { username, password } = req.body; + const { email, password } = req.body; // Find the user by username in the database - const user = await User.findOne({ username }); + const user = await User.findOne({ email: email }); // Check if the user exists and verify the password if (user && await bcrypt.compare(password, user.password)) { diff --git a/users/userservice/user-model.js b/users/userservice/user-model.js index 328601b..24dc435 100644 --- a/users/userservice/user-model.js +++ b/users/userservice/user-model.js @@ -9,6 +9,10 @@ const userSchema = new mongoose.Schema({ type: String, required: true, }, + email: { + type: String, + required: true, + }, createdAt: { type: Date, default: Date.now, diff --git a/users/userservice/user-service.js b/users/userservice/user-service.js index c169099..5690e2d 100644 --- a/users/userservice/user-service.js +++ b/users/userservice/user-service.js @@ -59,12 +59,13 @@ app.get('/rankings', async (req, res) => { app.post('/adduser', async (req, res) => { try { // Check if required fields are present in the request body - validateRequiredFields(req, ['username', 'password']); + validateRequiredFields(req, ['username', 'email', 'password']); // Encrypt the password before saving it const hashedPassword = await bcrypt.hash(req.body.password, 10); const newUser = new User({ + email: req.body.email, username: req.body.username, password: hashedPassword, }); diff --git a/webapp/src/App.js b/webapp/src/App.js index 7f6e8bf..cde23d3 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -1,67 +1,75 @@ import React, { useState } from 'react'; -import {BrowserRouter, Routes, Route} from 'react-router-dom' +import { BrowserRouter, Routes, Route } from 'react-router-dom' import AddUser from './components/AddUser'; import Navbar from './components/Navbar'; import Login from './components/Login'; import Rankings from './components/Rankings'; -import CssBaseline from '@mui/material/CssBaseline'; -import Container from '@mui/material/Container'; -import Typography from '@mui/material/Typography'; -import Link from '@mui/material/Link'; +import MainPage from './components/MainPage'; +import Game from './components/Game'; import { useEffect } from 'react'; import axios from 'axios'; +import { createContext } from 'react'; + + +export const UserContext = createContext(); + function App() { - const [showLogin, setShowLogin] = useState(true); + const [user, setUser] = useState({}); + const [loggedIn, setLoggedIn] = useState(false); const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; - const handleToggleView = () => { - setShowLogin(!showLogin); - }; - const checkUser = () => { + + + const checkUser = async () => { + try{ + + const token = localStorage.getItem('uToken'); if (token) { - axios.get(`${apiEndpoint}/self`, { + await axios.get(`${apiEndpoint}/self`, { headers: { Authorization: token, }, }).then((response) => { + console.log(response.data); setUser(response.data); + setLoggedIn(true); + return true; }); + }else{ + setUser(undefined); + setLoggedIn(false); + return false; } + + + }catch (error) { + // localStorage.setItem('uToken', ''); + // setUser({}); + // window.location.href = '/'; + setUser(undefined); + console.log("hola"); + setLoggedIn(false); + return false; + } }; + useEffect(() => { + checkUser(); + }, []); + return ( + - + - Home page}/> + } /> } /> } /> } /> - Play page} /> + } /> - - - - - /* - - - Welcome to the 2024 edition of the Software Architecture course hola - - {showLogin ? : } - - {showLogin ? ( - - Don't have an account? Register here. - - ) : ( - - Already have an account? Login here. - - )} - - */ + ) } diff --git a/webapp/src/components/AddUser.js b/webapp/src/components/AddUser.js index 00d522a..9bfb1cf 100644 --- a/webapp/src/components/AddUser.js +++ b/webapp/src/components/AddUser.js @@ -1,60 +1,76 @@ // src/components/AddUser.js import React, { useState } from 'react'; import axios from 'axios'; -import { Container, Typography, TextField, Button, Snackbar } from '@mui/material'; - -const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; +import { Link, useNavigate } from 'react-router-dom'; +import { Snackbar } from '@mui/material'; const AddUser = () => { + const [email, setEmail] = useState(''); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); + const [cpassword, setCpassword] = useState(''); + const navigate = useNavigate(); const [error, setError] = useState(''); - const [openSnackbar, setOpenSnackbar] = useState(false); + const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; - const addUser = async () => { + const register = async () => { try { - await axios.post(`${apiEndpoint}/adduser`, { username, password }); - setOpenSnackbar(true); + console.log(password, cpassword); + if(password !== cpassword){ + throw new Error('Passwords do not match'); + } + await axios.post(`${apiEndpoint}/adduser`, { email, username, password }); + localStorage.removeItem('uToken'); + window.location.href = '/login'; } catch (error) { - setError(error.response.data.error); + setError(true); } }; - const handleCloseSnackbar = () => { - setOpenSnackbar(false); - }; return ( - - - Add User - - setUsername(e.target.value)} - /> - setPassword(e.target.value)} - /> - - +
+
+
+

Sign up

+

Sign up below to access WIQ

+
+
+
+
+ setEmail(e.target.value)}/> + +
+
+ setUsername(e.target.value)}/> + +
+
+ setPassword(e.target.value)}/> + +
+
+ setCpassword(e.target.value)}/> + +
+
+ +
+

Already have an account? + Sign in + . +

+
+
+
{error && ( - setError('')} message={`Error: ${error}`} /> + setError(false)} message={`Something is wrong...`} /> )} - +
+ ); }; -export default AddUser; +export default AddUser; \ No newline at end of file diff --git a/webapp/src/components/Game.jsx b/webapp/src/components/Game.jsx new file mode 100644 index 0000000..aa35368 --- /dev/null +++ b/webapp/src/components/Game.jsx @@ -0,0 +1,27 @@ +import React, { useEffect } from 'react'; +import { useContext } from 'react'; +import { UserContext } from '../App'; +import { useNavigate } from 'react-router-dom'; + +export default function MainPage() { + const { user, setUser, checkUser } = useContext(UserContext); + const navigate = useNavigate(); + useEffect(() => { + + const checkLog = async () => { + const res = await checkUser(); + console.log(res); + if(res === false) + navigate('/'); + } + checkLog(); + + }, []); + + return ( +
+

Game Page

+ {user.username} +
+ ) +} \ No newline at end of file diff --git a/webapp/src/components/Login.js b/webapp/src/components/Login.js index 80ff0cd..0b490c6 100644 --- a/webapp/src/components/Login.js +++ b/webapp/src/components/Login.js @@ -1,76 +1,81 @@ // src/components/Login.js import React, { useState } from 'react'; import axios from 'axios'; -import { Container, Typography, TextField, Button, Snackbar } from '@mui/material'; +import { Link, useNavigate } from 'react-router-dom'; +import { Snackbar } from '@mui/material'; +import { UserContext } from '../App'; +import { useContext } from 'react'; const Login = () => { - const [username, setUsername] = useState(''); + const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); + const navigate = useNavigate(); const [error, setError] = useState(''); - const [loginSuccess, setLoginSuccess] = useState(false); - - const [openSnackbar, setOpenSnackbar] = useState(false); - + const { user, setUser, checkUser } = useContext(UserContext); const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; const loginUser = async () => { try { - const response = await axios.post(`${apiEndpoint}/login`, { username, password }); - // Extract data from the response - + console.log(email, password); + const response = await axios.post(`${apiEndpoint}/login`, { email, password }); + console.log(response.data); + + setUser({}); + + localStorage.removeItem('uToken'); localStorage.setItem('uToken', response.data.token); - setLoginSuccess(true); - setOpenSnackbar(true); + await axios.get(`${apiEndpoint}/self`, { + headers: { + Authorization: response.data.token, + }, + }).then((response) => { + console.log(response.data); + setUser(response.data); + }); + window.location.href = '/'; } catch (error) { - setError(error.response.data.error); + setError(true); } }; - const handleCloseSnackbar = () => { - setOpenSnackbar(false); - }; return ( - - {loginSuccess ? ( -
- - {localStorage.getItem('user')} - - +
+
+
+

Sign in

+

Sign in below to access WIQ

- ) : ( -
- - Login - - setUsername(e.target.value)} - /> - setPassword(e.target.value)} - /> - - - {error && ( - setError('')} message={`Error: ${error}`} /> - )} +
+
+
+ setEmail(e.target.value)}/> + +
+
+ setPassword(e.target.value)}/> + +
+
+ +
+

Don't have an account yet? + Sign + up + . +

+
+
+ {error && ( + setError('')} message={`Email or password incorrect`} /> )} - +
+ ); }; diff --git a/webapp/src/components/MainPage.jsx b/webapp/src/components/MainPage.jsx new file mode 100644 index 0000000..63ebcfb --- /dev/null +++ b/webapp/src/components/MainPage.jsx @@ -0,0 +1,9 @@ +import React from 'react'; + +export default function MainPage() { + return ( +
+

Main page

+
+ ) +} \ No newline at end of file diff --git a/webapp/src/components/Navbar.jsx b/webapp/src/components/Navbar.jsx index 19e0a91..45ce6d0 100644 --- a/webapp/src/components/Navbar.jsx +++ b/webapp/src/components/Navbar.jsx @@ -1,16 +1,31 @@ +import React, { useEffect } from "react"; +import { useContext } from "react"; +import { UserContext } from "../App"; + function Navbar() { + const { user, setUser, loggedIn } = useContext(UserContext); + + const Logout = () => { + setUser(undefined); + localStorage.setItem('uToken', ''); + window.location.href = '/'; + } + return (
WIQ +
+
{loggedIn} +
diff --git a/webapp/src/components/Rankings.jsx b/webapp/src/components/Rankings.jsx index 4e3ee4c..d4f7145 100644 --- a/webapp/src/components/Rankings.jsx +++ b/webapp/src/components/Rankings.jsx @@ -1,11 +1,15 @@ import React, { useState, useEffect } from 'react'; import axios from 'axios'; +import { useNavigate } from 'react-router-dom'; +import { useContext } from 'react'; +import { UserContext } from '../App'; const apiEndpoint = 'http://localhost:8000'; const Rankings = () => { const [users, setUsers] = useState([]); - + const auth = useContext(UserContext); + const navigate = useNavigate(); useEffect(() => { const fetchData = async () => { try { @@ -17,6 +21,14 @@ const Rankings = () => { }; fetchData(); + + const checkLog = async () => { + const res = await auth.checkUser(); + console.log(res); + if(res === false) + navigate('/'); + } + checkLog(); }, []); return ( From 15c4490c6383ef9c768270775b74fdc008861828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?adri=C3=A1n?= Date: Sun, 10 Mar 2024 00:12:58 +0100 Subject: [PATCH 25/34] Revert "docker and login" This reverts commit 58f4621e67b744be7bacd39b5e672ca3640af7af. --- .github/workflows/release.yml | 25 ++----- docker-compose.yml | 17 ----- gatewayservice/gateway-service.js | 6 +- questionservice/.dockerignore | 2 - questionservice/Dockerfile | 20 ------ users/authservice/auth-model.js | 1 - users/authservice/auth-service.js | 6 +- users/userservice/user-model.js | 4 -- users/userservice/user-service.js | 3 +- webapp/src/App.js | 80 ++++++++++------------ webapp/src/components/AddUser.js | 94 +++++++++++--------------- webapp/src/components/Game.jsx | 27 -------- webapp/src/components/Login.js | 105 ++++++++++++++--------------- webapp/src/components/MainPage.jsx | 9 --- webapp/src/components/Navbar.jsx | 17 +---- webapp/src/components/Rankings.jsx | 14 +--- 16 files changed, 137 insertions(+), 293 deletions(-) delete mode 100644 questionservice/.dockerignore delete mode 100644 questionservice/Dockerfile delete mode 100644 webapp/src/components/Game.jsx delete mode 100644 webapp/src/components/MainPage.jsx diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 54031bf..485cabf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,7 +45,7 @@ jobs: permissions: contents: read packages: write - # needs: [e2e-tests] + needs: [e2e-tests] steps: - uses: actions/checkout@v4 - name: Publish to Registry @@ -82,7 +82,7 @@ jobs: permissions: contents: read packages: write - # needs: [e2e-tests] + needs: [e2e-tests] steps: - uses: actions/checkout@v4 - name: Publish to Registry @@ -93,30 +93,13 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} registry: ghcr.io workdir: users/userservice - docker-push-questionservice: - name: Push question service Docker Image to GitHub Packages - runs-on: ARM64 - permissions: - contents: read - packages: write - # needs: [e2e-tests] - steps: - - uses: actions/checkout@v4 - - name: Publish to Registry - uses: elgohr/Publish-Docker-Github-Action@v5 - with: - name: arquisoft/wiq_en1a/usequestionservicerservice - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - registry: ghcr.io - workdir: questionservice docker-push-gatewayservice: name: Push gateway service Docker Image to GitHub Packages runs-on: ARM64 permissions: contents: read packages: write - # needs: [e2e-tests] + needs: [e2e-tests] steps: - uses: actions/checkout@v4 - name: Publish to Registry @@ -130,7 +113,7 @@ jobs: deploy: name: Deploy over SSH runs-on: ARM64 - needs: [docker-push-userservice,docker-push-authservice,docker-push-gatewayservice,docker-push-webapp,docker-push-questionservice] + needs: [docker-push-userservice,docker-push-authservice,docker-push-gatewayservice,docker-push-webapp] steps: - name: Deploy over SSH uses: fifsky/ssh-action@master diff --git a/docker-compose.yml b/docker-compose.yml index 1397812..ae4a9d8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -42,21 +42,6 @@ services: MONGODB_URI: mongodb://mongodb:27017/userdb # platform: linux/arm64 - questionservice: - container_name: questionservice-${teamname:-defaultASW} - image: ghcr.io/arquisoft/wiq_en1a/questionservice:latest - profiles: ["dev", "prod"] - build: ./questionservice - depends_on: - - mongodb - ports: - - "8010:8010" - networks: - - mynetwork - environment: - MONGODB_URI: mongodb://mongodb:27017/userdb - # platform: linux/arm64 - gatewayservice: container_name: gatewayservice-${teamname:-defaultASW} image: ghcr.io/arquisoft/wiq_en1a/gatewayservice:latest @@ -66,7 +51,6 @@ services: - mongodb - userservice - authservice - - questionservice ports: - "8000:8000" networks: @@ -74,7 +58,6 @@ services: environment: AUTH_SERVICE_URL: http://authservice:8002 USER_SERVICE_URL: http://userservice:8001 - QUESTION_SERVICE_URL: http://questionservice:8010 # platform: linux/arm64 webapp: diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 6358fd0..62fe881 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -25,10 +25,8 @@ app.get('/health', (_req, res) => { app.post('/login', async (req, res) => { try { // Forward the login request to the authentication service - const authResponse = await axios.post(authServiceUrl+'/login', req.body); - - res.status(200).json(authResponse.data); + res.json(authResponse.data); } catch (error) { res.status(error.response.status).json({ error: error.response.data.error }); } @@ -39,7 +37,7 @@ app.post('/adduser', async (req, res) => { try { // Forward the add user request to the user service const userResponse = await axios.post(userServiceUrl+'/adduser', req.body); - res.status(200).json(userResponse.data); + res.json(userResponse.data); } catch (error) { res.status(error.response.status).json({ error: error.response.data.error }); } diff --git a/questionservice/.dockerignore b/questionservice/.dockerignore deleted file mode 100644 index 3091757..0000000 --- a/questionservice/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -coverage \ No newline at end of file diff --git a/questionservice/Dockerfile b/questionservice/Dockerfile deleted file mode 100644 index b13a1ff..0000000 --- a/questionservice/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -# Use an official Node.js runtime as a parent image -FROM node:20 - -# Set the working directory in the container -WORKDIR /usr/src/questionservice - -# Copy package.json and package-lock.json to the working directory -COPY package*.json ./ - -# Install app dependencies -RUN npm install - -# Copy the app source code to the working directory -COPY . . - -# Expose the port the app runs on -EXPOSE 8002 - -# Define the command to run your app -CMD ["node", "auth-service.js"] diff --git a/users/authservice/auth-model.js b/users/authservice/auth-model.js index d86c36c..7763b51 100644 --- a/users/authservice/auth-model.js +++ b/users/authservice/auth-model.js @@ -2,7 +2,6 @@ const mongoose = require('mongoose'); const userSchema = new mongoose.Schema({ username: String, - email: String, password: String, createdAt: Date, }); diff --git a/users/authservice/auth-service.js b/users/authservice/auth-service.js index 3206de0..05673de 100644 --- a/users/authservice/auth-service.js +++ b/users/authservice/auth-service.js @@ -27,12 +27,12 @@ function validateRequiredFields(req, requiredFields) { app.post('/login', async (req, res) => { try { // Check if required fields are present in the request body - validateRequiredFields(req, ['email', 'password']); + validateRequiredFields(req, ['username', 'password']); - const { email, password } = req.body; + const { username, password } = req.body; // Find the user by username in the database - const user = await User.findOne({ email: email }); + const user = await User.findOne({ username }); // Check if the user exists and verify the password if (user && await bcrypt.compare(password, user.password)) { diff --git a/users/userservice/user-model.js b/users/userservice/user-model.js index 24dc435..328601b 100644 --- a/users/userservice/user-model.js +++ b/users/userservice/user-model.js @@ -9,10 +9,6 @@ const userSchema = new mongoose.Schema({ type: String, required: true, }, - email: { - type: String, - required: true, - }, createdAt: { type: Date, default: Date.now, diff --git a/users/userservice/user-service.js b/users/userservice/user-service.js index 5690e2d..c169099 100644 --- a/users/userservice/user-service.js +++ b/users/userservice/user-service.js @@ -59,13 +59,12 @@ app.get('/rankings', async (req, res) => { app.post('/adduser', async (req, res) => { try { // Check if required fields are present in the request body - validateRequiredFields(req, ['username', 'email', 'password']); + validateRequiredFields(req, ['username', 'password']); // Encrypt the password before saving it const hashedPassword = await bcrypt.hash(req.body.password, 10); const newUser = new User({ - email: req.body.email, username: req.body.username, password: hashedPassword, }); diff --git a/webapp/src/App.js b/webapp/src/App.js index cde23d3..7f6e8bf 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -1,75 +1,67 @@ import React, { useState } from 'react'; -import { BrowserRouter, Routes, Route } from 'react-router-dom' +import {BrowserRouter, Routes, Route} from 'react-router-dom' import AddUser from './components/AddUser'; import Navbar from './components/Navbar'; import Login from './components/Login'; import Rankings from './components/Rankings'; -import MainPage from './components/MainPage'; -import Game from './components/Game'; +import CssBaseline from '@mui/material/CssBaseline'; +import Container from '@mui/material/Container'; +import Typography from '@mui/material/Typography'; +import Link from '@mui/material/Link'; import { useEffect } from 'react'; import axios from 'axios'; -import { createContext } from 'react'; - - -export const UserContext = createContext(); - function App() { - + const [showLogin, setShowLogin] = useState(true); const [user, setUser] = useState({}); - const [loggedIn, setLoggedIn] = useState(false); const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; - - - const checkUser = async () => { - try{ - - + const handleToggleView = () => { + setShowLogin(!showLogin); + }; + const checkUser = () => { const token = localStorage.getItem('uToken'); if (token) { - await axios.get(`${apiEndpoint}/self`, { + axios.get(`${apiEndpoint}/self`, { headers: { Authorization: token, }, }).then((response) => { - console.log(response.data); setUser(response.data); - setLoggedIn(true); - return true; }); - }else{ - setUser(undefined); - setLoggedIn(false); - return false; } - - - }catch (error) { - // localStorage.setItem('uToken', ''); - // setUser({}); - // window.location.href = '/'; - setUser(undefined); - console.log("hola"); - setLoggedIn(false); - return false; - } }; - useEffect(() => { - checkUser(); - }, []); - return ( - - + - } /> + Home page}/> } /> } /> } /> - } /> + Play page} /> - + + + + + /* + + + Welcome to the 2024 edition of the Software Architecture course hola + + {showLogin ? : } + + {showLogin ? ( + + Don't have an account? Register here. + + ) : ( + + Already have an account? Login here. + + )} + + */ ) } diff --git a/webapp/src/components/AddUser.js b/webapp/src/components/AddUser.js index 9bfb1cf..00d522a 100644 --- a/webapp/src/components/AddUser.js +++ b/webapp/src/components/AddUser.js @@ -1,76 +1,60 @@ // src/components/AddUser.js import React, { useState } from 'react'; import axios from 'axios'; -import { Link, useNavigate } from 'react-router-dom'; -import { Snackbar } from '@mui/material'; +import { Container, Typography, TextField, Button, Snackbar } from '@mui/material'; + +const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; const AddUser = () => { - const [email, setEmail] = useState(''); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); - const [cpassword, setCpassword] = useState(''); - const navigate = useNavigate(); const [error, setError] = useState(''); - const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; + const [openSnackbar, setOpenSnackbar] = useState(false); - const register = async () => { + const addUser = async () => { try { - console.log(password, cpassword); - if(password !== cpassword){ - throw new Error('Passwords do not match'); - } - await axios.post(`${apiEndpoint}/adduser`, { email, username, password }); - localStorage.removeItem('uToken'); - window.location.href = '/login'; + await axios.post(`${apiEndpoint}/adduser`, { username, password }); + setOpenSnackbar(true); } catch (error) { - setError(true); + setError(error.response.data.error); } }; + const handleCloseSnackbar = () => { + setOpenSnackbar(false); + }; return ( -
-
-
-

Sign up

-

Sign up below to access WIQ

-
-
-
-
- setEmail(e.target.value)}/> - -
-
- setUsername(e.target.value)}/> - -
-
- setPassword(e.target.value)}/> - -
-
- setCpassword(e.target.value)}/> - -
-
- -
-

Already have an account? - Sign in - . -

-
-
-
+ + + Add User + + setUsername(e.target.value)} + /> + setPassword(e.target.value)} + /> + + {error && ( - setError(false)} message={`Something is wrong...`} /> + setError('')} message={`Error: ${error}`} /> )} -
- + ); }; -export default AddUser; \ No newline at end of file +export default AddUser; diff --git a/webapp/src/components/Game.jsx b/webapp/src/components/Game.jsx deleted file mode 100644 index aa35368..0000000 --- a/webapp/src/components/Game.jsx +++ /dev/null @@ -1,27 +0,0 @@ -import React, { useEffect } from 'react'; -import { useContext } from 'react'; -import { UserContext } from '../App'; -import { useNavigate } from 'react-router-dom'; - -export default function MainPage() { - const { user, setUser, checkUser } = useContext(UserContext); - const navigate = useNavigate(); - useEffect(() => { - - const checkLog = async () => { - const res = await checkUser(); - console.log(res); - if(res === false) - navigate('/'); - } - checkLog(); - - }, []); - - return ( -
-

Game Page

- {user.username} -
- ) -} \ No newline at end of file diff --git a/webapp/src/components/Login.js b/webapp/src/components/Login.js index 0b490c6..80ff0cd 100644 --- a/webapp/src/components/Login.js +++ b/webapp/src/components/Login.js @@ -1,81 +1,76 @@ // src/components/Login.js import React, { useState } from 'react'; import axios from 'axios'; -import { Link, useNavigate } from 'react-router-dom'; -import { Snackbar } from '@mui/material'; -import { UserContext } from '../App'; -import { useContext } from 'react'; +import { Container, Typography, TextField, Button, Snackbar } from '@mui/material'; const Login = () => { - const [email, setEmail] = useState(''); + const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); - const navigate = useNavigate(); const [error, setError] = useState(''); - const { user, setUser, checkUser } = useContext(UserContext); + const [loginSuccess, setLoginSuccess] = useState(false); + + const [openSnackbar, setOpenSnackbar] = useState(false); + const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; const loginUser = async () => { try { + const response = await axios.post(`${apiEndpoint}/login`, { username, password }); - console.log(email, password); - const response = await axios.post(`${apiEndpoint}/login`, { email, password }); - console.log(response.data); - - setUser({}); - - localStorage.removeItem('uToken'); + // Extract data from the response + localStorage.setItem('uToken', response.data.token); - await axios.get(`${apiEndpoint}/self`, { - headers: { - Authorization: response.data.token, - }, - }).then((response) => { - console.log(response.data); - setUser(response.data); - }); - window.location.href = '/'; + setLoginSuccess(true); + setOpenSnackbar(true); } catch (error) { - setError(true); + setError(error.response.data.error); } }; + const handleCloseSnackbar = () => { + setOpenSnackbar(false); + }; return ( -
-
-
-

Sign in

-

Sign in below to access WIQ

+ + {loginSuccess ? ( +
+ + {localStorage.getItem('user')} + +
-
-
-
- setEmail(e.target.value)}/> - -
-
- setPassword(e.target.value)}/> - -
-
- -
-

Don't have an account yet? - Sign - up - . -

-
+ ) : ( +
+ + Login + + setUsername(e.target.value)} + /> + setPassword(e.target.value)} + /> + + + {error && ( + setError('')} message={`Error: ${error}`} /> + )}
-
- {error && ( - setError('')} message={`Email or password incorrect`} /> )} -
- + ); }; diff --git a/webapp/src/components/MainPage.jsx b/webapp/src/components/MainPage.jsx deleted file mode 100644 index 63ebcfb..0000000 --- a/webapp/src/components/MainPage.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; - -export default function MainPage() { - return ( -
-

Main page

-
- ) -} \ No newline at end of file diff --git a/webapp/src/components/Navbar.jsx b/webapp/src/components/Navbar.jsx index 45ce6d0..19e0a91 100644 --- a/webapp/src/components/Navbar.jsx +++ b/webapp/src/components/Navbar.jsx @@ -1,31 +1,16 @@ -import React, { useEffect } from "react"; -import { useContext } from "react"; -import { UserContext } from "../App"; - function Navbar() { - const { user, setUser, loggedIn } = useContext(UserContext); - - const Logout = () => { - setUser(undefined); - localStorage.setItem('uToken', ''); - window.location.href = '/'; - } - return (
WIQ -
-
{loggedIn} -
diff --git a/webapp/src/components/Rankings.jsx b/webapp/src/components/Rankings.jsx index d4f7145..4e3ee4c 100644 --- a/webapp/src/components/Rankings.jsx +++ b/webapp/src/components/Rankings.jsx @@ -1,15 +1,11 @@ import React, { useState, useEffect } from 'react'; import axios from 'axios'; -import { useNavigate } from 'react-router-dom'; -import { useContext } from 'react'; -import { UserContext } from '../App'; const apiEndpoint = 'http://localhost:8000'; const Rankings = () => { const [users, setUsers] = useState([]); - const auth = useContext(UserContext); - const navigate = useNavigate(); + useEffect(() => { const fetchData = async () => { try { @@ -21,14 +17,6 @@ const Rankings = () => { }; fetchData(); - - const checkLog = async () => { - const res = await auth.checkUser(); - console.log(res); - if(res === false) - navigate('/'); - } - checkLog(); }, []); return ( From 9dff314baee206c88b966cbb6cf61fd5adb2a2f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?adri=C3=A1n?= Date: Sun, 10 Mar 2024 12:49:48 +0100 Subject: [PATCH 26/34] Game and styling --- questionservice/question-service.js | 4 +- webapp/src/{App.js => App.jsx} | 5 ++- webapp/src/components/Game.jsx | 29 ++++++++++++++ webapp/src/components/Login.js | 2 +- webapp/src/components/Navbar.jsx | 16 ++++---- webapp/src/components/Question.jsx | 60 +++++++++++++++++++++++++++++ webapp/src/components/Rankings.jsx | 14 +++---- 7 files changed, 111 insertions(+), 19 deletions(-) rename webapp/src/{App.js => App.jsx} (92%) create mode 100644 webapp/src/components/Game.jsx create mode 100644 webapp/src/components/Question.jsx diff --git a/questionservice/question-service.js b/questionservice/question-service.js index 9c7d276..aec6f7d 100644 --- a/questionservice/question-service.js +++ b/questionservice/question-service.js @@ -96,7 +96,7 @@ const wiq = new WIQ_API() * @param {Object} res - Contains the question (question) and the images of the flags (flags) */ app.get('/flags/question', async (req, res) => { - const question = await wiq.getQuestionAndCountryFlags() + const question = JSON.parse(await wiq.getQuestionAndCountryFlags()); res.json(question); }); @@ -109,6 +109,8 @@ app.get('/flags/question', async (req, res) => { */ app.get('/flags/answer', (req, res) => { const answeredFlag = req.body + console.log(answeredFlag); + console.log(correctAnswerFlag); if(correctAnswerFlag==answeredFlag){ res.json({ correct: "true" diff --git a/webapp/src/App.js b/webapp/src/App.jsx similarity index 92% rename from webapp/src/App.js rename to webapp/src/App.jsx index 7f6e8bf..6a69627 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.jsx @@ -10,6 +10,7 @@ import Typography from '@mui/material/Typography'; import Link from '@mui/material/Link'; import { useEffect } from 'react'; import axios from 'axios'; +import Game from './components/Game'; function App() { const [showLogin, setShowLogin] = useState(true); const [user, setUser] = useState({}); @@ -33,11 +34,11 @@ function App() { - Home page}/> + Home page}/> } /> } /> } /> - Play page} /> + } /> diff --git a/webapp/src/components/Game.jsx b/webapp/src/components/Game.jsx new file mode 100644 index 0000000..30c497a --- /dev/null +++ b/webapp/src/components/Game.jsx @@ -0,0 +1,29 @@ +import React, { useState } from "react"; +import axios from "axios"; +import Question from "./Question"; + +const Game = () => { + const [gameStarted, setGameStarted] = useState(false); + + const startGame = () => { + setGameStarted(!gameStarted); + }; + + return ( +
+ {gameStarted ? ( + + ) : ( +
+

Welcome to WIQ!

+ +
+ )} +
+ ) +}; + +export default Game; \ No newline at end of file diff --git a/webapp/src/components/Login.js b/webapp/src/components/Login.js index 80ff0cd..69f5cc2 100644 --- a/webapp/src/components/Login.js +++ b/webapp/src/components/Login.js @@ -37,7 +37,7 @@ const Login = () => { {loginSuccess ? (
- {localStorage.getItem('user')} + {localStorage.getItem('uToken')}
diff --git a/webapp/src/components/Navbar.jsx b/webapp/src/components/Navbar.jsx index 19e0a91..fbbdd64 100644 --- a/webapp/src/components/Navbar.jsx +++ b/webapp/src/components/Navbar.jsx @@ -1,16 +1,16 @@ function Navbar() { return ( -
-
- WIQ +
+
+ WIQ
-