diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index c8de682a..29dbe2a9 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -2,7 +2,9 @@ const express = require("express"); const axios = require("axios"); const cors = require("cors"); const promBundle = require("express-prom-bundle"); - +const YAML = require('yaml'); +const fs = require("fs"); +const swaggerUi = require('swagger-ui-express'); const app = express(); const port = 8000; @@ -155,6 +157,21 @@ app.get("/ranking", async (req, res) => { } }); +openapiPath='./openapi.yaml' +if (fs.existsSync(openapiPath)) { + const file = fs.readFileSync(openapiPath, 'utf8'); + + // Parse the YAML content into a JavaScript object representing the Swagger document + const swaggerDocument = YAML.parse(file); + + // Serve the Swagger UI documentation at the '/api-doc' endpoint + // This middleware serves the Swagger UI files and sets up the Swagger UI page + // It takes the parsed Swagger document as input + app.use('/api-doc', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); +} else { + console.log("Not configuring OpenAPI. Configuration file not present.") +} + // Start the gateway service const server = app.listen(port, () => { console.log(`Gateway Service listening at http://localhost:${port}`); diff --git a/gatewayservice/openapi.yaml b/gatewayservice/openapi.yaml new file mode 100644 index 00000000..f997dde0 --- /dev/null +++ b/gatewayservice/openapi.yaml @@ -0,0 +1,367 @@ +openapi: 3.0.0 +info: + title: Gateway Service API + version: 1.0.0 + description: API gateway for managing authentication, user information, game statistics, and questions. + +servers: + - url: http://localhost:8000 + description: Local development server + +paths: + /health: + get: + summary: Health Check + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: OK + + /login: + post: + summary: Authenticate User + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/LoginRequest' + responses: + '200': + description: Successful authentication + content: + application/json: + schema: + $ref: '#/components/schemas/AuthResponse' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /adduser: + post: + summary: Add User + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/User' + responses: + '200': + description: User added successfully + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /userInfo: + get: + summary: Get User Information + parameters: + - in: query + name: userId + schema: + type: string + description: ID of the user to retrieve information for + responses: + '200': + description: User information retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/UserInfo' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /saveGameList: + post: + summary: Save Game List + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GameList' + responses: + '200': + description: Game list saved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessMessage' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /questions: + get: + summary: Get Questions + parameters: + - in: query + name: category + schema: + type: string + description: Category of questions to retrieve + responses: + '200': + description: Questions retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/QuestionList' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + post: + summary: Add Question + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Question' + responses: + '200': + description: Question added successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessMessage' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /stats: + get: + summary: Get Statistics + parameters: + - in: query + name: userId + schema: + type: string + description: ID of the user to retrieve statistics for + responses: + '200': + description: Statistics retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Stats' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /saveGame: + post: + summary: Save Game + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Game' + responses: + '200': + description: Game saved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessMessage' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /ranking: + get: + summary: Get Ranking + parameters: + - in: query + name: category + schema: + type: string + description: Category to filter the ranking + responses: + '200': + description: Ranking retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/RankingList' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + +components: + schemas: + LoginRequest: + type: object + properties: + username: + type: string + password: + type: string + + AuthResponse: + type: object + properties: + token: + type: string + + User: + type: object + properties: + username: + type: string + password: + type: string + createdAt: + type: string + format: date-time + games: + $ref: '#/components/schemas/GameList' + + UserInfo: + type: object + properties: + username: + type: string + createdAt: + type: string + format: date-time + games: + $ref: '#/components/schemas/GameList' + + GameList: + type: object + properties: + games: + type: array + items: + type: object + + QuestionList: + type: array + items: + type: object + + Question: + type: object + properties: + + Stats: + type: object + properties: + + Game: + type: object + properties: + + SuccessMessage: + type: object + properties: + message: + type: string + + RankingList: + type: array + items: + type: object + + Error: + type: object + properties: + error: + type: string diff --git a/gatewayservice/package-lock.json b/gatewayservice/package-lock.json index fc5f2d60..17be91a7 100644 --- a/gatewayservice/package-lock.json +++ b/gatewayservice/package-lock.json @@ -12,7 +12,9 @@ "axios": "^1.6.5", "cors": "^2.8.5", "express": "^4.18.2", - "express-prom-bundle": "^7.0.0" + "express-prom-bundle": "^7.0.0", + "swagger-ui-express": "^5.0.0", + "yaml": "^2.4.1" }, "devDependencies": { "jest": "^29.7.0", @@ -4389,6 +4391,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swagger-ui-dist": { + "version": "5.12.3", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.12.3.tgz", + "integrity": "sha512-UAFxQSzxVkY/yfmipeMLj4LwH6I/ZGcfezwSquPm2U9CqOiHp8L6fD7TcyPDYfCZuHFaPw5y4io+fny37Ov9NQ==" + }, + "node_modules/swagger-ui-express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", + "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, "node_modules/tdigest": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", @@ -4636,6 +4657,17 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "node_modules/yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/gatewayservice/package.json b/gatewayservice/package.json index cb57ef13..46723ad7 100644 --- a/gatewayservice/package.json +++ b/gatewayservice/package.json @@ -21,7 +21,9 @@ "axios": "^1.6.5", "cors": "^2.8.5", "express": "^4.18.2", - "express-prom-bundle": "^7.0.0" + "express-prom-bundle": "^7.0.0", + "swagger-ui-express": "^5.0.0", + "yaml": "^2.4.1" }, "devDependencies": { "jest": "^29.7.0", diff --git a/webapp/src/components/Nav/Nav.js b/webapp/src/components/Nav/Nav.js index 8c62a3a7..ab1083ed 100644 --- a/webapp/src/components/Nav/Nav.js +++ b/webapp/src/components/Nav/Nav.js @@ -22,7 +22,7 @@ const Nav = () => { }; return ( - + WIQ @@ -50,6 +50,7 @@ const Nav = () => { + diff --git a/webapp/src/pages/Perfil/Perfil.js b/webapp/src/pages/Perfil/Perfil.js index 3c5f4219..4578fccd 100644 --- a/webapp/src/pages/Perfil/Perfil.js +++ b/webapp/src/pages/Perfil/Perfil.js @@ -8,7 +8,7 @@ const Perfil = () => { const gatewayUrl = process.env.GATEWAY_SERVICE_URL || "http://localhost:8000"; const [userData, setUserData] = useState(null); const [loading, setLoading] = useState(true); - const [username,setUsername]=useState(localStorage.username); + const [username,setUsername]=useState(localStorage.username || 'error'); const [error, setError] = useState(null); useEffect(() => { @@ -27,61 +27,69 @@ const Perfil = () => { return ( <> -