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 1/9] 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 2/9] 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 3/9] 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 4/9] 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 5/9] 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 6/9] 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 7/9] 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 8/9] 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 9/9] 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({