diff --git a/gameservice/game-service.js b/gameservice/game-service.js index 3f69e773..3baa359e 100644 --- a/gameservice/game-service.js +++ b/gameservice/game-service.js @@ -24,7 +24,7 @@ const validateRequiredFields = (req, fields) => { }; // Ruta para agregar un nuevo juego -app.post('/addgame', async (req, res) => { +app.post('/games', async (req, res) => { try { validateRequiredFields(req, ['userId', 'pAcertadas', 'pFalladas', 'totalTime', 'gameMode']); @@ -80,7 +80,7 @@ app.get('/api/info/users', async (req, res) => { let usersData=[]; if(username!=undefined){ try{ - const user = await axios.get(`${USER_SERVICE_URL}/getUserInfo/${username}`) + const user = await axios.get(`${USER_SERVICE_URL}/users/${username}`) if (!user.data) { res.status(400).json({ error: 'User not found' }); return; @@ -94,7 +94,7 @@ app.get('/api/info/users', async (req, res) => { } }else{ try { - const users = await axios.get(`${USER_SERVICE_URL}/getAllUsers`); + const users = await axios.get(`${USER_SERVICE_URL}/users`); if(users.data) users.data.forEach(user => {usersData.push(user)}); } catch (error) { @@ -132,7 +132,7 @@ app.get('/api/info/users', async (req, res) => { }); // Ruta para obtener datos de participación del usuario -app.get('/getParticipation/:userId', async (req, res) => { +app.get('/games/:userId', async (req, res) => { try { const userId = req.params.userId; @@ -199,7 +199,7 @@ app.get('/api/ranking', async (req, res) => { const rankedPlayers = []; for (const entry of ranking) { try { - const user = await axios.get(`${USER_SERVICE_URL}/getUserInfo/${entry._id}`); + const user = await axios.get(`${USER_SERVICE_URL}/users/${entry._id}`); rankedPlayers.push({ user: user.data.username, // Puedes usar el campo apropiado según tu esquema de usuario totalGames: entry.totalGames diff --git a/gameservice/game-service.test.js b/gameservice/game-service.test.js index bf84fed2..53a2943d 100644 --- a/gameservice/game-service.test.js +++ b/gameservice/game-service.test.js @@ -48,7 +48,7 @@ afterEach(async () => { describe('Game Service', () => { // Test para agregar un nuevo juego con éxito - it('should add a new game on POST /addgame', async () => { + it('should add a new game on POST /games', async () => { const newGame = { userId: userId, pAcertadas: 5, @@ -57,7 +57,7 @@ describe('Game Service', () => { gameMode: 'classic' }; - const response = await request(app).post('/addgame').send(newGame); + const response = await request(app).post('/games').send(newGame); expect(response.status).toBe(200); const data = response.body; expect(data).toHaveProperty("user"); @@ -88,7 +88,7 @@ describe('Game Service', () => { - const response = await request(app).get(`/getParticipation/${userId}`); + const response = await request(app).get(`/games/${userId}`); expect(response.status).toBe(200); expect(response.body).toEqual(mockParticipationData); @@ -97,7 +97,7 @@ describe('Game Service', () => { // Test para manejar el caso de usuario no encontrado al obtener los datos de participación it('should return 404 when getting participation data for invalid user', async () => { const nonExistentUserId = ''; - const response = await request(app).get(`/getParticipation/${nonExistentUserId}`); + const response = await request(app).get(`/games/${nonExistentUserId}`); expect(response.status).toBe(404); }); @@ -109,7 +109,7 @@ describe('Game Service', () => { }); const userNGId = userNoGames._id; - const response = await request(app).get(`/getParticipation/${userNGId}`); + const response = await request(app).get(`/games/${userNGId}`); expect(response.status).toBe(204); }); diff --git a/gameservice/openapi.yml b/gameservice/openapi.yml index 309fc9f1..d298614a 100644 --- a/gameservice/openapi.yml +++ b/gameservice/openapi.yml @@ -6,7 +6,7 @@ servers: - url: 'http://localhost:8005' - url: http://gameservice:8005 paths: - /getParticipation/{userId}: + /games/{userId}: get: summary: Get user participation data parameters: @@ -31,7 +31,7 @@ paths: description: No participation data found for the user '500': description: Error occurred while retrieving participation data - /addgame: + /games: post: summary: Add a new game requestBody: diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index e6ecfb31..baca9851 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -63,7 +63,7 @@ app.get('/metrics', (req, res) => { res.end(promClient.register.metrics()); }); -app.delete('/deletefriend/:username/:friend', async (req, res, next) => { +app.delete('/friends/:friend_username', async (req, res, next) => { if (req.headers.authorization) { try{ const response = await axios.get(`${authServiceUrl}/verify`, { @@ -83,7 +83,7 @@ app.delete('/deletefriend/:username/:friend', async (req, res, next) => { } }); // Security middleware -app.post(['/addgame','/addfriend'], async (req, res, next) => { +app.post(['/games','/friends'], async (req, res, next) => { if (req.headers.authorization) { try{ const response = await axios.get(`${authServiceUrl}/verify`, { @@ -144,11 +144,11 @@ app.get('/verify', async (req, res) => { }); -app.post('/adduser', async (req, res) => { +app.post('/users', async (req, res) => { try { // Forward the add user request to the user service try{ - const userResponse = await axios.post(userServiceUrl+'/adduser', req.body); + const userResponse = await axios.post(userServiceUrl+'/users', req.body); res.json(userResponse.data); } catch (error) { res.status(error.response.status).json(error.response.data); @@ -232,11 +232,11 @@ app.get('/api/info/games', async (req, res) => { }); // Ruta para agregar una nuevo amigo -app.post('/addgame', async (req, res) => { +app.post('/games', async (req, res) => { try { try{ // Forward the add game request to the games service - const gameResponse = await axios.post(gameServiceUrl + '/addgame', req.body); + const gameResponse = await axios.post(gameServiceUrl + '/games', req.body); res.json(gameResponse.data); }catch(error){ res.status(error.response.status).json(error.response.data); @@ -247,11 +247,11 @@ app.post('/addgame', async (req, res) => { }); // Ruta para agregar una nuevo game -app.post('/addfriend', async (req, res) => { +app.post('/friends', async (req, res) => { try { try{ // Forward the add game request to the games service - const friendsResponse = await axios.post(friendServiceUrl + '/addfriend', req.body); + const friendsResponse = await axios.post(friendServiceUrl + '/friends', req.body); res.json(friendsResponse.data); }catch(error){ res.status(error.response.status).json(error.response.data); @@ -260,13 +260,10 @@ app.post('/addfriend', async (req, res) => { res.status(500).json({ error: "Service down" }); } }); -app.delete('/deletefriend/:username/:friend', async (req, res) => { +app.delete('/friends/:friend_username', async (req, res) => { try { try{ - if(req.body.user!==req.params.username){ - throw new Error('Unauthorized'); - } - const friendsResponse = await axios.delete(friendServiceUrl + '/deletefriend/'+req.body.user+'/'+req.params.friend); + const friendsResponse = await axios.delete(friendServiceUrl + '/friends/'+req.body.user.toString()+'/'+req.params.friend_username.toString()); res.json(friendsResponse.data); }catch(error){ res.status(error.response.status).json(error.response.data); @@ -275,10 +272,10 @@ app.delete('/deletefriend/:username/:friend', async (req, res) => { res.status(500).json({ error: "Service down" }); } }); -app.get('/getFriends/:username', async (req, res) => { +app.get('/friends/:username', async (req, res) => { try { try{ - const friendsResponse = await axios.get(friendServiceUrl + '/getFriends/'+req.params.username); + const friendsResponse = await axios.get(friendServiceUrl + '/friends/'+req.params.username.toString()); res.json(friendsResponse.data); }catch(error){ res.status(error.response.status).json(error.response.data); @@ -289,10 +286,10 @@ app.get('/getFriends/:username', async (req, res) => { }); /// Ruta para obtener la participación del usuario -app.get('/getParticipation/:userId', async (req, res) => { +app.get('/games/:userId', async (req, res) => { try { const userId = req.params.userId; - const apiUrl = `${gameServiceUrl}/getParticipation/${userId}`; + const apiUrl = `${gameServiceUrl}/games/${userId}`; try{ const gameResponse = await axios.get(apiUrl); res.json(gameResponse.data); diff --git a/gatewayservice/gateway-service.test.js b/gatewayservice/gateway-service.test.js index 5f0ffe61..15c9296c 100644 --- a/gatewayservice/gateway-service.test.js +++ b/gatewayservice/gateway-service.test.js @@ -14,9 +14,9 @@ jest.mock('axios'); describe('Gateway Service', () => { // Mock responses from external services axios.post.mockImplementation((url, data) => { - if (url.endsWith('/adduser')) { + if (url.endsWith('/users')) { return Promise.resolve({ data: { userId: 'mockedUserId' } }); - }else if (url.endsWith('/addquestion')) { + }else if (url.endsWith('/questions')) { return Promise.resolve({ data: { question: 'Mocked Question', @@ -132,7 +132,7 @@ describe('Gateway Service', () => { // Test /adduser endpoint it('should forward add user request to user service', async () => { const response = await request(app) - .post('/adduser') + .post('/users') .send({ username: 'newuser', password: 'newpassword' }); expect(response.statusCode).toBe(200); @@ -141,7 +141,7 @@ describe('Gateway Service', () => { it('should return an error when the user service is down', async () => { axios.post.mockRejectedValueOnce({ response: { status: 500, data: { error: 'Service down' } } }); const response = await request(app) - .post('/adduser') + .post('/users') .send({ username: 'testuser', password: 'testpassword' }); expect(response.statusCode).toBe(500); expect(response.body).toEqual({ error: 'Service down' }); @@ -221,14 +221,14 @@ describe('Gateway Service', () => { }); -describe('GET /getParticipation/:userId', () => { +describe('GET /games/:userId', () => { it('should return the participation of the user', async () => { const mockedUserId = 'mockedUserId'; const mockedGameResponse = { participation: 10 }; axios.get.mockResolvedValueOnce({ data: mockedGameResponse }); - const response = await request(app).get(`/getParticipation/${mockedUserId}`); + const response = await request(app).get(`/games/${mockedUserId}`); expect(response.statusCode).toBe(200); expect(response.body).toEqual(mockedGameResponse); @@ -240,7 +240,7 @@ describe('GET /getParticipation/:userId', () => { axios.get.mockRejectedValueOnce({ response: { status: 500, data: mockedError } }); - const response = await request(app).get(`/getParticipation/${mockedUserId}`); + const response = await request(app).get(`/games/${mockedUserId}`); expect(response.statusCode).toBe(500); expect(response.body).toEqual(mockedError); @@ -278,6 +278,15 @@ describe('GET /api/info/users', () => { }); }); describe('GET /api/info/games', () => { + const runGameInfoTest = async (mockedUsername, mockedInfoResponse) => { + axios.get.mockResolvedValueOnce({ data: mockedInfoResponse }); + + const response = await request(app).get(`/api/info/games?user=${mockedUsername}`); + + expect(response.statusCode).toBe(200); + expect(response.body).toEqual(mockedInfoResponse); + }; + it('should return game information', async () => { const mockedUsername = 'mockedUser'; const mockedInfoResponse = { @@ -286,29 +295,29 @@ describe('GET /api/info/games', () => { answers: ['User 1', 'User 2'], questions: ['Question 1', 'Question 2'] }; - axios.get.mockResolvedValueOnce({ data: mockedInfoResponse }); - const response = await request(app).get(`/api/info/games?user=${mockedUsername}`); - - expect(response.statusCode).toBe(200); - expect(response.body).toEqual(mockedInfoResponse); + await runGameInfoTest(mockedUsername, mockedInfoResponse); }); - it('should return an error when the game service is down', async () => { - const mockedUsername = 'mockedUser'; - const mockedError = { error: 'Service down' }; - + const runErrorTest = async (endpoint, mockedUsername, mockedError) => { axios.get.mockRejectedValueOnce({ response: { status: 500, data: mockedError } }); - const response = await request(app).get(`/api/info/games?user=${mockedUsername}`); + const response = await request(app).get(`${endpoint}?user=${mockedUsername}`); expect(response.statusCode).toBe(500); expect(response.body).toEqual(mockedError); + }; + + it('should return an error when the game service is down', async () => { + const mockedUsername = 'mockedUser'; + const mockedError = { error: 'Service down' }; + + await runErrorTest('/api/info/games', mockedUsername, mockedError); }); }); describe('addGame', () =>{ it('should return 401 Unauthorized if authorization token is missing', async () => { - const response = await request(app).post('/addgame'); + const response = await request(app).post('/games'); expect(response.statusCode).toBe(401); expect(response.body).toEqual({ error: 'Unauthorized' }); }); @@ -317,15 +326,27 @@ describe('addGame', () =>{ const mockedToken = 'invalidToken'; axios.get.mockRejectedValueOnce({ response: { status: 401 } }); const response = await request(app) - .post('/addgame') + .post('/games') .set('Authorization', `Bearer ${mockedToken}`); expect(response.statusCode).toBe(401); expect(response.body).toEqual({ error: 'Unauthorized' }); }); -}); -describe('POST /addfriend', () => { +describe('Add a friend', () => { + const runMiddlewareTest = async (endpoint, mockedToken, mockedResponse) => { + axios.post.mockResolvedValueOnce(mockedResponse); + axios.get.mockResolvedValueOnce(mockedResponse); + const nextMiddleware = jest.fn(); + + await request(app) + .post(endpoint) + .send({ username: 'mockedUser', friend: 'mockedFriend'}) + .set('Authorization', `Bearer ${mockedToken}`); + nextMiddleware(); + expect(nextMiddleware).toHaveBeenCalled(); + }; + it('should skip the middleware and return 401 Unauthorized if authorization token is missing', async () => { - const response = await request(app).post('/addfriend'); + const response = await request(app).post('/friends'); expect(response.statusCode).toBe(401); expect(response.body).toEqual({ error: 'Unauthorized' }); }); @@ -334,7 +355,7 @@ describe('POST /addfriend', () => { const mockedToken = 'invalidToken'; axios.get.mockRejectedValueOnce({ response: { status: 401 } }); const response = await request(app) - .post('/addfriend') + .post('/friends') .set('Authorization', `Bearer ${mockedToken}`); expect(response.statusCode).toBe(401); expect(response.body).toEqual({ error: 'Unauthorized' }); @@ -343,63 +364,63 @@ describe('POST /addfriend', () => { it('should skip the middleware and call the next middleware if authorization token is valid', async () => { const mockedToken = 'validToken'; const mockedResponse = { status: 200, data: { username: 'mockedUser' } }; - axios.post.mockResolvedValueOnce(mockedResponse); - axios.get.mockResolvedValueOnce(mockedResponse); - const nextMiddleware = jest.fn(); - - await request(app) - .post('/addfriend') - .send({ username: 'mockedUser', friend: 'mockedFriend'}) - .set('Authorization', `Bearer ${mockedToken}`); - nextMiddleware(); - expect(nextMiddleware).toHaveBeenCalled(); + await runMiddlewareTest('/friends', mockedToken, mockedResponse); }); }); -describe('Friend Service', () => { - - // Test middleware for deletefriend endpoint - it('should call the next middleware if authorization token is valid', async () => { - const mockedToken = 'validToken'; - const mockedResponse = { status: 200, data: { username: 'mockedUser' } }; +describe('Friend Service', () => { + const runMiddlewareTest = async (endpoint, mockedToken, mockedResponse) => { axios.delete.mockResolvedValueOnce(mockedResponse); axios.get.mockResolvedValueOnce(mockedResponse); await request(app) - .delete('/deletefriend/testuser/friend') + .delete(endpoint) .set('Authorization', `Bearer ${mockedToken}`); + }; + + it('should call the next middleware if authorization token is valid', async () => { + const mockedToken = 'validToken'; + const mockedResponse = { status: 200, data: { username: 'mockedUser' } }; + await runMiddlewareTest('/friends/mockedUser', mockedToken, mockedResponse); }); + it('should return 401 Unauthorized if authorization token is missing', async () => { - const response = await request(app).delete('/deletefriend/testuser/friend'); + const response = await request(app).delete('/friends/friend'); expect(response.statusCode).toBe(401); expect(response.body).toEqual({ error: 'Unauthorized' }); }); + it('should return 401 Unauthorized if authorization token is invalid', async () => { const mockedToken = 'invalidToken'; axios.get.mockRejectedValueOnce({ response: { status: 401 } }); const response = await request(app) - .delete('/deletefriend/testuser/friend') + .delete('/friends/friend1') .set('Authorization', `Bearer ${mockedToken}`); expect(response.statusCode).toBe(401); expect(response.body).toEqual({ error: 'Unauthorized' }); }); - // Test /getFriends endpoint it('should forward get friends request to friend service', async () => { const mockedUsername = 'testuser'; const mockedFriends = ['friend1', 'friend2']; axios.get.mockResolvedValueOnce({ data: mockedFriends , status: 200}); const response = await request(app) - .get(`/getFriends/${mockedUsername}`); + .get(`/friends/${mockedUsername}`); expect(response.statusCode).toBe(200); expect(response.body).toEqual(mockedFriends); }); - it('should return an error when the friend service is down', async () => { - const mockedUsername = 'testuser'; - const mockedError = { error: 'Service down' }; - jest.spyOn(axios, 'get').mockImplementation({ response: { status: 500, data: { error: 'Service down' } } }); + + const testFriendServiceError = async (mockedUsername, mockedError) => { + jest.spyOn(axios, 'get').mockRejectedValueOnce({ response: { status: 500, data: mockedError } }); const response = await request(app) - .get(`/getFriends/${mockedUsername}`); + .get(`/friends/${mockedUsername}`); expect(response.statusCode).toBe(500); expect(response.body).toEqual(mockedError); + }; + + it('should return an error when the friend service is down', async () => { + const mockedUsername = 'testuser'; + const mockedError = { error: 'Service down' }; + await testFriendServiceError(mockedUsername, mockedError); }); +}); }); \ No newline at end of file diff --git a/gatewayservice/openapi.yml b/gatewayservice/openapi.yml index 07dfd881..8b976257 100644 --- a/gatewayservice/openapi.yml +++ b/gatewayservice/openapi.yml @@ -24,7 +24,7 @@ paths: description: Error occurred while forwarding the login request '500': description: Service down - /adduser: + /users: post: summary: Forward the add user request to the user service requestBody: @@ -40,7 +40,7 @@ paths: description: Error occurred while forwarding the add user request '500': description: Service down - /addquestion: + /questions: post: summary: Add a new question requestBody: @@ -56,7 +56,7 @@ paths: description: Error occurred while adding question '500': description: Service down - /addgame: + /games: post: summary: Add a new game requestBody: @@ -76,7 +76,7 @@ paths: description: Service down security: - bearerAuth: [] - /addfriend: + /friends: post: summary: Add a new friend requestBody: @@ -99,18 +99,12 @@ paths: description: Service down security: - bearerAuth: [] - /deletefriend/{username}/{friend}: + /friends//{friend_username}: delete: summary: Delete a friend parameters: - in: path - name: username - schema: - type: string - required: true - description: The username of the user - - in: path - name: friend + name: friend_username schema: type: string required: true @@ -332,7 +326,7 @@ paths: description: User not found '500': description: Error occurred while retrieving information about games - /getParticipation/{userId}: + /games/{userId}: get: summary: Get participation of a user parameters: @@ -357,7 +351,7 @@ paths: description: No participation data found for the user. '500': description: Service down - /getFriends/{username}: + /friends/{username}: get: summary: Get friends of a user parameters: diff --git a/question_generator/locales/es.json b/question_generator/locales/es.json index b6da2926..74e13158 100644 --- a/question_generator/locales/es.json +++ b/question_generator/locales/es.json @@ -37,7 +37,7 @@ "Which f1 driver was born in?": "¿Qué piloto de F1 nació en %s?", "Which f1 driver has more podiums?": "¿Qué piloto de F1 tiene más podiums?", - "Which f1 driver has more wins?": "¿Qué pilto de F1 tiene más victorias?", + "Which f1 driver has more wins?": "¿Qué piloto de F1 tiene más victorias?", "Which f1 driver has wins?": "¿Qué piloto de F1 tiene %s victorias?", "Which song is song by?": "¿Qué canción canta %s?", diff --git a/question_generator/questionGenerationService.js b/question_generator/questionGenerationService.js index b1720f82..4dbb8cc8 100644 --- a/question_generator/questionGenerationService.js +++ b/question_generator/questionGenerationService.js @@ -78,7 +78,7 @@ app.get('/api/questions/create', async (req, res) => { } randomQuestion.question = i18n.__(randomQuestion.question, randomQuestion.question_param); const saveQuestion = async (question) => { - const url = `${questionServiceUrl}/addquestion`; + const url = `${questionServiceUrl}/questions`; try { await axios.post(url, question); } catch (error) { diff --git a/questionservice/openapi.yml b/questionservice/openapi.yml index 5b175781..3d5227fd 100644 --- a/questionservice/openapi.yml +++ b/questionservice/openapi.yml @@ -6,7 +6,7 @@ servers: - url: 'http://localhost:8004' - url: http://questionservice:8004 paths: - /addQuestion: + /questions: post: summary: Add a new question requestBody: diff --git a/questionservice/question-service.js b/questionservice/question-service.js index d675eefe..052b4c29 100644 --- a/questionservice/question-service.js +++ b/questionservice/question-service.js @@ -45,7 +45,7 @@ const addQuestion = async (req, res) => { } }; // Ruta para agregar una nueva pregunta -app.post('/addquestion', addQuestion); +app.post('/questions', addQuestion); app.get('/api/info/questions', async (req, res) => { diff --git a/questionservice/question-service.test.js b/questionservice/question-service.test.js index 47a40e17..8395a863 100644 --- a/questionservice/question-service.test.js +++ b/questionservice/question-service.test.js @@ -17,7 +17,7 @@ afterAll(async () => { }); describe('Question Service', () => { - it('should add a new question on POST /addquestion', async () => { + it('should add a new question on POST /questions', async () => { const newQuestion = { question: 'Mocked Question', correct: 'Mocked Correct Answer', @@ -26,7 +26,7 @@ describe('Question Service', () => { category: 'Mocked Category' }; - const response = await request(app).post('/addquestion').send(newQuestion); + const response = await request(app).post('/questions').send(newQuestion); expect(response.status).toBe(200); expect(response.body).toHaveProperty('question', 'Mocked Question'); }); diff --git a/users/friendsservice/friends-service.js b/users/friendsservice/friends-service.js index 4766aea3..53579215 100644 --- a/users/friendsservice/friends-service.js +++ b/users/friendsservice/friends-service.js @@ -15,14 +15,14 @@ const Friends = require('./friends-model')(connection) const userServiceUrl = process.env.USER_SERVICE_URL || 'http://localhost:8001'; -app.get('/getFriends/:username', async (req, res) => { +app.get('/friends/:username', async (req, res) => { try{ const username = req.params.username.toString(); if (!username) { throw new Error('Username is required'); } try{ - const response = await axios.get(`${userServiceUrl}/getUserInfo/${username}`); + const response = await axios.get(`${userServiceUrl}/users/${username}`); if (!response || response.status !== 200) { throw new Error('User not found'); } @@ -37,7 +37,7 @@ app.get('/getFriends/:username', async (req, res) => { res.status(400).json({error: error.message||"Error getting friends"}); } }); -app.post('/addfriend', async (req, res) => { +app.post('/friends', async (req, res) => { try { const username=req.body.user; const friend=req.body.friend; @@ -48,7 +48,7 @@ app.post('/addfriend', async (req, res) => { throw new Error('User and friend cannot be the same'); } try{ - const response = await axios.get(`${userServiceUrl}/getUserInfo/${friend}`); + const response = await axios.get(`${userServiceUrl}/users/${friend}`); if (!response || response.status !== 200) { throw new Error('User not found'); } @@ -76,10 +76,10 @@ app.post('/addfriend', async (req, res) => { } }); -app.delete('/deletefriend/:username/:friend', async (req, res) => { +app.delete('/friends/:username/:friend_username', async (req, res) => { try { const username = req.params.username; - const friend = req.params.friend; + const friend = req.params.friend_username; if (!username || !friend) { throw new Error('User and friend are required'); } diff --git a/users/friendsservice/friends-service.test.js b/users/friendsservice/friends-service.test.js index ee00a4c8..aad09ef5 100644 --- a/users/friendsservice/friends-service.test.js +++ b/users/friendsservice/friends-service.test.js @@ -63,16 +63,16 @@ afterEach(async () => { jest.mock('axios'); -describe('GET /getFriends/:username', () => { +describe('GET /friends/:username', () => { it('should return the friends of the specified user', async () => { jest.mock('axios'); axios.get.mockImplementationOnce(() => Promise.resolve({ status: 200 })); - const response = await request(app).get('/getFriends/user1'); + const response = await request(app).get('/friends/user1'); expect(response.body).toEqual({ username: 'user1', friends: ['user2', 'user3'] }); }); it('should return an error if the username does not exist', async () => { - const response = await request(app).get('/getFriends/invalid-username'); + const response = await request(app).get('/friends/invalid-username'); expect(response.status).toBe(400); expect(response.body).toEqual({error: 'User not found'}); @@ -81,7 +81,7 @@ describe('GET /getFriends/:username', () => { // Add more test cases for different scenarios }); -describe('POST /addfriend', () => { +describe('POST /friends', () => { it('should add a friend to the user', async () => { jest.mock('axios'); axios.get.mockImplementationOnce(() => Promise.resolve({ status: 200, data: 'mocked data' })); @@ -89,7 +89,7 @@ describe('POST /addfriend', () => { const mockUser = { username: 'user2', friends: ['user1'] }; const response = await request(app) - .post('/addfriend') + .post('/friends') .send({ user: 'user2', friend: 'user1' }); expect(response.status).toBe(200); expect(response.body).toEqual(mockUser); @@ -99,7 +99,7 @@ describe('POST /addfriend', () => { axios.get.mockImplementationOnce(() => Promise.resolve({ status: 200, data: 'mocked data' })); const response = await request(app) - .post('/addfriend') + .post('/friends') .send({ user: 'user1', friend: 'user2' }); expect(response.status).toBe(400); expect(response.body).toEqual({ error: "Friend already exists" }); @@ -109,25 +109,25 @@ describe('POST /addfriend', () => { axios.get.mockImplementationOnce(() => Promise.resolve({ status: 200, data: 'mocked data' })); const mockUser = { username: 'user1', friends: ['user2','user3','user4'] }; const response = await request(app) - .post('/addfriend') + .post('/friends') .send({ user: 'user1', friend: 'user4' }); expect(response.status).toBe(200); expect(response.body).toEqual(mockUser); }); it('should return an error if the user and friend are the same', async () => { - const response = await request(app).post('/addfriend').send({user: 'user1', friend: 'user1'}); + const response = await request(app).post('/friends').send({user: 'user1', friend: 'user1'}); expect(response.status).toBe(400); expect(response.body).toEqual({ error: 'User and friend cannot be the same' }); }); it('should return an error if the user is not provided', async () => { - const response = await request(app).post('/addfriend/').send({friend: 'friend2'}); + const response = await request(app).post('/friends/').send({friend: 'friend2'}); expect(response.status).toBe(400); expect(response.body).toEqual({ error: 'User and friend are required' }); }); it('should return an error if the user does not exists', async () => { - const response = await request(app).post('/addfriend/').send({user: 'invalid-username', friend: 'invalid-friend'}); + const response = await request(app).post('/friends/').send({user: 'invalid-username', friend: 'invalid-friend'}); expect(response.status).toBe(400); expect(response.body).toEqual({ error: 'User not found' }); @@ -136,18 +136,18 @@ describe('POST /addfriend', () => { // Add more test cases for different scenarios -describe('DELETE /deletefriend/:username/:friend', () => { +describe('DELETE /friends/:username/:friend', () => { it('should delete a friend from the user', async () => { const mockUser = { username: 'user1', friends: ['user2'] }; - const response = await request(app).delete('/deletefriend/user1/user3'); + const response = await request(app).delete('/friends/user1/user3'); expect(response.status).toBe(200); expect(response.body).toEqual(mockUser); }); it('should return an error if the user or friend is not provided', async () => { - const response = await request(app).delete('/deletefriend/user1/invalid-friend'); + const response = await request(app).delete('/friends/user1/invalid-friend'); expect(response.status).toBe(400); expect(response.body).toEqual({ error: 'Friend not found'}); diff --git a/users/friendsservice/openapi.yml b/users/friendsservice/openapi.yml index 2a809c0b..c5ec9ad5 100644 --- a/users/friendsservice/openapi.yml +++ b/users/friendsservice/openapi.yml @@ -6,7 +6,7 @@ servers: - url: http://localhost:8006 - url: http://friendsservice:8006 paths: - /getFriends/{username}: + /friends/{username}: get: summary: Get friends of a user parameters: @@ -36,7 +36,7 @@ paths: properties: error: type: string - /addfriend: + /friends: post: summary: Add a friend to a user requestBody: @@ -73,7 +73,7 @@ paths: properties: error: type: string - /deletefriend/{username}/{friend}: + /friends/{username}/{friend_username}: delete: summary: Delete a friend from a user parameters: @@ -82,7 +82,7 @@ paths: required: true schema: type: string - - name: friend + - name: friend_username in: path required: true schema: diff --git a/users/userservice/openapi.yml b/users/userservice/openapi.yml index 7e95e59a..8c7f3a8a 100644 --- a/users/userservice/openapi.yml +++ b/users/userservice/openapi.yml @@ -6,7 +6,27 @@ servers: - url: http://localhost:8001 - url: http://userservice:8001 paths: - /adduser: + /users: + get: + summary: Get all users + responses: + '200': + description: Users retrieved successfully + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + '400': + description: Bad request + content: + application/json: + schema: + type: object + properties: + error: + type: string post: summary: Add a new user requestBody: @@ -31,7 +51,7 @@ paths: properties: error: type: string - /getUserInfo/{username}: + /users/{username}: get: summary: Get user information parameters: @@ -56,27 +76,7 @@ paths: properties: error: type: string - /getAllUsers: - get: - summary: Get all users - responses: - '200': - description: Users retrieved successfully - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/User' - '400': - description: Bad request - content: - application/json: - schema: - type: object - properties: - error: - type: string + components: schemas: User: diff --git a/users/userservice/user-service.js b/users/userservice/user-service.js index 6fc5fa35..6cc8b6c1 100644 --- a/users/userservice/user-service.js +++ b/users/userservice/user-service.js @@ -27,21 +27,30 @@ function validateRequiredFields(req, requiredFields) { } } -app.post('/adduser', async (req, res) => { +app.post('/users', async (req, res) => { try { // Check if required fields are present in the request body validateRequiredFields(req, ['username', 'password', 'profileImage']); + // Check if the password has at least 4 characters + if (req.body.password.length < 4) { + res.status(400).json({ error: "Password must be at least 4 characters long" }); + return; + } + if (req.body.username.length === 0) { + res.status(400).json({ error: "Username can't be empty" }); + return; + } + if (req.body.username.length > 20) { + res.status(400).json({ error: "Username can't have more than 20 characters" }); + return; + } // Check if the user already exists const existingUser = await User.findOne({ username: req.body.username.toString() }); if (existingUser) { res.status(400).json({ error: "User already exist" }); return; } - // Check if the password has at least 4 characters - if (req.body.password.length < 4) { - res.status(400).json({ error: "Password must be at least 4 characters long" }); - return; - } + // Encrypt the password before saving it const hashedPassword = await bcrypt.hash(req.body.password, 10); @@ -57,7 +66,7 @@ app.post('/adduser', async (req, res) => { res.status(400).json({ error: error.message }); } }); - app.get('/getUserInfo/:username', async (req, res) => { + app.get('/users/:username', async (req, res) => { try { const username = req.params.username; try{ @@ -74,7 +83,7 @@ app.post('/adduser', async (req, res) => { res.status(400).json({ error: error.message }); } }); - app.get('/getAllUsers', async (req, res) => { + app.get('/users', async (req, res) => { try { const users = await User.find({}, { _id: 1, username: 1, createdAt: 1 }); res.json(users); diff --git a/users/userservice/user-service.test.js b/users/userservice/user-service.test.js index 4dd8edc2..c09ccba9 100644 --- a/users/userservice/user-service.test.js +++ b/users/userservice/user-service.test.js @@ -40,44 +40,62 @@ afterEach(async () => { }); describe('User Service', () => { - it('should add a new user on POST /adduser', async () => { + it('should add a new user on POST /users', async () => { const newUser = { username: 'testuser', password: 'testpassword', profileImage: 'perfil2.jpg', }; - const response = await request(app).post('/adduser').send(newUser); + const response = await request(app).post('/users').send(newUser); expect(response.status).toBe(200); expect(response.body).toHaveProperty('username', 'testuser'); }); - it('should return an error when adding a user that already exists on POST /adduser', async () => { + it('should return an error when adding a user that already exists on POST /users', async () => { const existingUser = { username: 'defaultuser', password: 'testpassword', profileImage: 'perfil2.jpg', }; - const response = await request(app).post('/adduser').send(existingUser); + const response = await request(app).post('/users').send(existingUser); expect(response.status).toBe(400); }); - it('should get user info on GET /getUserInfo/:username', async () => { + it('should return an error when adding a user with an empty username on POST /users', async () => { + const user = { + username: '', + password: 'testpassword', + profileImage: 'perfil2.jpg', + }; + const response = await request(app).post('/users').send(user); + expect(response.status).toBe(400); + }); + it('should return an error when adding a user with an username too long on POST /users', async () => { + const user = { + username: 'qwertyuiopasdfghjklñzxcvbnmqwertyuiopasdfghjklñ', + password: 'testpassword', + profileImage: 'perfil2.jpg', + }; + const response = await request(app).post('/users').send(user); + expect(response.status).toBe(400); + }); + it('should get user info on GET /users/:username', async () => { const username = 'defaultuser'; - const response = await request(app).get(`/getUserInfo/${username}`); + const response = await request(app).get(`/users/${username}`); expect(response.status).toBe(200); expect(response.body).toHaveProperty('username', username); expect(response.body).toHaveProperty('_id'); expect(response.body).toHaveProperty('createdAt'); expect(Object.keys(response.body)).toHaveLength(3); }); - it('should return an error when getting info of a non-existent user on GET /getUserInfo/:username', async () => { + it('should return an error when getting info of a non-existent user on GET /users/:username', async () => { const nonExistentUsername = 'nonexistentuser'; - const response = await request(app).get(`/getUserInfo/${nonExistentUsername}`); + const response = await request(app).get(`/users/${nonExistentUsername}`); expect(response.status).toBe(400); expect(response.body).toHaveProperty('error', 'User not found'); }); - it('should get all users on GET /getAllUsers', async () => { - const response = await request(app).get('/getAllUsers'); + it('should get all users on GET /users', async () => { + const response = await request(app).get('/users'); expect(response.status).toBe(200); expect(response.body).toHaveLength(2); expect(response.body[0]).toHaveProperty('_id'); diff --git a/webapp/src/components/AddUser.js b/webapp/src/components/AddUser.js index 448f6eef..31b1fd1e 100644 --- a/webapp/src/components/AddUser.js +++ b/webapp/src/components/AddUser.js @@ -16,7 +16,7 @@ import LanguageSelect from './LanguageSelect'; import Link from '@mui/material/Link'; -const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; +const gatewayUrl = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; const AddUser = ({goTo, changeLanguage, locale, handleToggleView}) => { @@ -48,10 +48,10 @@ const AddUser = ({goTo, changeLanguage, locale, handleToggleView}) => { setError('Passwords do not match'); return; } - await axios.post(`${apiEndpoint}/adduser`, { username, password, profileImage }); + await axios.post(`${gatewayUrl}/users`, { username, password, profileImage }); setOpenSnackbar(true); try{ - const response = await axios.post(`${apiEndpoint}/login`, { username, password }); + const response = await axios.post(`${gatewayUrl}/login`, { username, password }); const { createdAt: userCreatedAt, username: loggedInUsername, token, profileImage, userId: id } = response.data; setLoginSuccess(true); saveSessionData({ username: loggedInUsername, createdAt: userCreatedAt, token, profileImage, userId: id }); diff --git a/webapp/src/components/Friends.jsx b/webapp/src/components/Friends.jsx index f5d3f3eb..36933da6 100644 --- a/webapp/src/components/Friends.jsx +++ b/webapp/src/components/Friends.jsx @@ -14,7 +14,7 @@ const Friends = ({goTo}) => { const [snackbarMessage, setSnackbarMessage] = useState(''); const fetchData = async () => { try { - const response = await axios.get(`${gatewayUrl}/getFriends/${sessionData.username}`, { + const response = await axios.get(`${gatewayUrl}/friends/${sessionData.username}`, { headers: { Authorization: `Bearer ${sessionData.token}` } @@ -45,7 +45,7 @@ const Friends = ({goTo}) => { const addFriend = async () => { try { const body= {user: sessionData.username, friend: searchQuery}; - const response = await axios.post(`${gatewayUrl}/addfriend`, body + const response = await axios.post(`${gatewayUrl}/friends`, body , { headers: { Authorization: `Bearer ${sessionData.token}` @@ -73,7 +73,7 @@ const Friends = ({goTo}) => { const handleDeleteFriend = (friend) => { const deletefriend = async (friend) => { try { - const response = await axios.delete(`${gatewayUrl}/deletefriend/${sessionData.username}/${friend}`, { + const response = await axios.delete(`${gatewayUrl}/friends/${friend}`, { headers: { Authorization: `Bearer ${sessionData.token}` } diff --git a/webapp/src/components/Participation.jsx b/webapp/src/components/Participation.jsx index 4d40194c..eeba5171 100644 --- a/webapp/src/components/Participation.jsx +++ b/webapp/src/components/Participation.jsx @@ -23,7 +23,7 @@ export const Participation = ({ goTo }) => { // Realizar la solicitud al servidor para obtener los datos de participación const fetchData = async () => { try { - const response = await axios.get(`${gatewayUrl}/getParticipation/${sessionData.userId}`); + const response = await axios.get(`${gatewayUrl}/games/${sessionData.userId}`); if (response.status === 204) { setLoading(false); } else { diff --git a/webapp/src/components/PostGame.jsx b/webapp/src/components/PostGame.jsx index e43f9eb8..5f6df098 100644 --- a/webapp/src/components/PostGame.jsx +++ b/webapp/src/components/PostGame.jsx @@ -22,7 +22,7 @@ export const PostGame = ({ gameMode }) => { const saveGame = async () => { try { // Guardar el juego en la base de datos - const response = await axios.post(`${gatewayUrl}/addgame`, { + const response = await axios.post(`${gatewayUrl}/games`, { user: sessionData.userId, pAcertadas: localStorage.getItem("pAcertadas"), pFalladas: localStorage.getItem("pFalladas"), diff --git a/webapp/src/messages/messages_en.json b/webapp/src/messages/messages_en.json index 2a8e3241..f57c8a54 100644 --- a/webapp/src/messages/messages_en.json +++ b/webapp/src/messages/messages_en.json @@ -17,6 +17,8 @@ "Passwords do not match": "Passwords do not match", "Password must be at least 4 characters long": "Password must be at least 4 characters long", "User already exist": "User already exist", + "Username can't be empty": "Username can't be empty", + "Username can't have more than 20 characters": "Username can't have more than 20 characters", "menu": "Menu", "langen": "English", diff --git a/webapp/src/messages/messages_es.json b/webapp/src/messages/messages_es.json index 267e8b24..bd9d525d 100644 --- a/webapp/src/messages/messages_es.json +++ b/webapp/src/messages/messages_es.json @@ -17,6 +17,8 @@ "Passwords do not match": "Las contraseñas no coinciden", "Password must be at least 4 characters long": "La contraseña debe tener al menos 4 caracteres", "User already exist": "El usuario ya existe", + "Username can't be empty": "El nombre de usuario no puede estar vacío", + "Username can't have more than 20 characters": "El nombre de usuario no puede tener más de 20 caracteres", "menu": "Menú", "langen": "Inglés", diff --git a/webapp/src/messages/messages_fr.json b/webapp/src/messages/messages_fr.json index 8f168812..09bdc04a 100644 --- a/webapp/src/messages/messages_fr.json +++ b/webapp/src/messages/messages_fr.json @@ -17,6 +17,8 @@ "Passwords do not match": "Les mots de passe ne correspondent pas", "Password must be at least 4 characters long": "Le mot de passe doit comporter au moins 4 caractères", "User already exist": "L'utilisateur existe déjà", + "Username can't be empty": "Le nom d'utilisateur ne peut pas être vide", + "Username can't have more than 20 characters": "Le nom d'utilisateur ne peut pas comporter plus de 20 caractères", "menu": "Menu", "langen": "Anglais", diff --git a/webapp/src/messages/messages_it.json b/webapp/src/messages/messages_it.json index 345f7658..21931f18 100644 --- a/webapp/src/messages/messages_it.json +++ b/webapp/src/messages/messages_it.json @@ -18,6 +18,8 @@ "Passwords do not match": "Le password non corrispondono", "Password must be at least 4 characters long": "La password deve essere lunga almeno 4 caratteri", "User already exist": "L'utente esiste già", + "Username can't be empty": "Il nome utente non può essere vuoto", + "Username can't have more than 20 characters": "Il nome utente non può avere più di 20 caratteri", "menu": "Menu", "langen": "Inglese", diff --git a/webapp/src/test/AddUser.test.js b/webapp/src/test/AddUser.test.js index 7cb03a96..3303fdab 100644 --- a/webapp/src/test/AddUser.test.js +++ b/webapp/src/test/AddUser.test.js @@ -29,7 +29,7 @@ describe('AddUser component', () => { const addUserButton = screen.getByRole('button', { name: /SIGN UP/i }); // Mock the axios.post request to simulate a successful response - mockAxios.onPost('http://localhost:8000/adduser').reply(200); + mockAxios.onPost('http://localhost:8000/users').reply(200); // Simulate user input fireEvent.change(usernameInput, { target: { value: 'testUser' } }); fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); @@ -69,7 +69,7 @@ describe('AddUser component', () => { const addUserButton = screen.getByRole('button', { name: /SIGN UP/i }); // Mock the axios.post request to simulate a successful response - mockAxios.onPost('http://localhost:8000/adduser').reply(200); + mockAxios.onPost('http://localhost:8000/users').reply(200); mockAxios.onPost('http://localhost:8000/login').reply(200); // Simulate user input @@ -101,7 +101,7 @@ describe('AddUser component', () => { const addUserButton = screen.getByRole('button', { name: /SIGN UP/i }); // Mock the axios.post request to simulate an error response - mockAxios.onPost('http://localhost:8000/adduser').reply(500, { error: 'Internal Server Error' }); + mockAxios.onPost('http://localhost:8000/users').reply(500, { error: 'Internal Server Error' }); mockAxios.onPost('http://localhost:8000/login').reply(500, { error: 'Internal Server Error' }); // Simulate user input @@ -139,7 +139,7 @@ describe('AddUser component', () => { }); it('should handle successful user registration and login', async () => { // Mock the response for successful user registration - mockAxios.onPost('http://localhost:8000/adduser').reply(200); + mockAxios.onPost('http://localhost:8000/users').reply(200); // Mock the response for successful user login mockAxios.onPost('http://localhost:8000/login').reply(200, { diff --git a/webapp/src/test/Friends.test.js b/webapp/src/test/Friends.test.js index 896e352e..519caa2b 100644 --- a/webapp/src/test/Friends.test.js +++ b/webapp/src/test/Friends.test.js @@ -16,7 +16,7 @@ describe('Friends', () => { }); test('renders the friend list', async () => { - mockAxios.onGet('http://localhost:8000/getFriends/testUser').reply(200, + mockAxios.onGet('http://localhost:8000/friends/testUser').reply(200, { friends: ['friend1', 'friend2', 'friend3', 'friend4'] } ); render( @@ -49,7 +49,7 @@ describe('Friends', () => { ); - mockAxios.onPost('http://localhost:8000/addfriend').reply(200, + mockAxios.onPost('http://localhost:8000/friends').reply(200, { friends: ['friend1', 'friend2', 'friend3', 'friend4', 'newFriend'] } ); @@ -74,7 +74,7 @@ describe('Friends', () => { ); - mockAxios.onPost('http://localhost:8000/addfriend').reply(200, + mockAxios.onPost('http://localhost:8000/friends').reply(200, { friends: ['friend1'] } ); const addButton = screen.getByText('Add friend'); @@ -85,7 +85,7 @@ describe('Friends', () => { // Wait for the friends to be fetched await screen.findByText('friend1'); await mockAxios.reset(); - mockAxios.onDelete('http://localhost:8000/deletefriend/testUser/friend1').reply(200, + mockAxios.onDelete('http://localhost:8000/friends/friend1').reply(200, { friends: [] } ); diff --git a/webapp/src/test/PostGame.test.js b/webapp/src/test/PostGame.test.js index eda6b6bc..a086b5cc 100644 --- a/webapp/src/test/PostGame.test.js +++ b/webapp/src/test/PostGame.test.js @@ -72,7 +72,7 @@ describe('PostGame component', () => { // Check if saveGame function is called correctly expect(axios.post).toHaveBeenCalledWith( - 'http://localhost:8000/addgame', + 'http://localhost:8000/games', { user: mockSessionData.userId, pAcertadas: localStorage.getItem('pAcertadas'), @@ -136,7 +136,7 @@ describe('PostGame component', () => { ); // Check if saveGame function is called correctly expect(axios.post).toHaveBeenCalledWith( - 'http://localhost:8000/addgame', + 'http://localhost:8000/games', { user: sessionData.userId, pAcertadas: localStorage.getItem('pAcertadas'),