Skip to content

Commit

Permalink
Merge pull request #92 from Arquisoft/88-users-enhancenment
Browse files Browse the repository at this point in the history
Finished user managment
  • Loading branch information
uo289267 authored Apr 22, 2024
2 parents fe4f955 + 1b05925 commit 4449563
Show file tree
Hide file tree
Showing 44 changed files with 901 additions and 360 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ jobs:
- uses: actions/checkout@v4
- name: Publish to Registry
uses: elgohr/Publish-Docker-Github-Action@v5
env:
JWT_KEY: ${{secrets.JWT_KEY}}
with:
name: arquisoft/wiq_en1b/authservice
username: ${{ github.actor }}
Expand Down
163 changes: 117 additions & 46 deletions gatewayservice/gateway-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const promBundle = require('express-prom-bundle');
const swaggerUi = require('swagger-ui-express');
const fs = require("fs")
const YAML = require('yaml')

const jwt = require('jsonwebtoken');
const app = express();
const port = 8000;

Expand All @@ -33,7 +33,7 @@ app.post('/login', async (req, res) => {
const authResponse = await axios.post(authServiceUrl+'/login', req.body);
res.json(authResponse.data);
} catch (error) {
res.status(error.response.status).json({ error: error.response.data.error });
manageError(error)
}
});

Expand All @@ -43,103 +43,130 @@ app.post('/adduser', async (req, res) => {
const userResponse = await axios.post(userServiceUrl+'/adduser', req.body);
res.json(userResponse.data);
} catch (error) {
res.status(error.response.status).json({ error: error.response.data.error });
manageError(error);

}
});

app.get('/questions', async (req, res) => {
app.get('/questions', verifyToken, async (req, res) => {
try {

// Forward the question request to the quetion service
const questionResponse = await axios.get(questionServiceUrl+'/questions');
res.json(questionResponse.data);
} catch (error) {
res.status(error.response.status).json({ error: error.response.data.error });
manageError(error)
}
});

app.get('/questions/:lang/:amount/:type', async (req, res) => {
try {
const lang = req.params.lang.toString();
const amount = req.params.amount.toString();
const type = req.params.type.toString();
// Forward the question request to the quetion service
const questionResponse = await axios.get(questionServiceUrl+'/questions/' + lang + '/' + amount + '/' + type);

res.json(questionResponse.data);

app.get('/questions/:lang/:amount/:type', verifyToken, async (req, res) => {
try {
if(!validateLang(req.params.lang.toString()) ||
!validateAmount(req.params.amount.toString()) ||
!validateType(req.params.type.toString()))
res.status(400).json({ error: 'Wrong values given' });
else {
const lang = encodeURIComponent(req.params.lang.toString());
const amount = encodeURIComponent(req.params.amount.toString());
const type = encodeURIComponent(req.params.type.toString());
// Forward the question request to the quetion service
const questionResponse = await axios.get(questionServiceUrl+'/questions/' + lang + '/' + amount + '/' + type);

res.json(questionResponse.data);
}
} catch (error) {

res.status(error.response.status).json({ error: error.response.data.error });
manageError(error)
}
});


app.get('/questions/:lang/:amount', async (req, res) => {
app.get('/questions/:lang/:amount', verifyToken, async (req, res) => {
try {
const lang = req.params.lang.toString();
const amount = req.params.amount.toString();
// Forward the question request to the quetion service
const questionResponse = await axios.get(questionServiceUrl+'/questions/' + lang + '/' + amount);

res.json(questionResponse.data);
if(!validateLang(req.params.lang.toString()) ||
!validateAmount(req.params.amount.toString()))
res.status(400).json({ error: 'Wrong values given' });
else{
const lang = encodeURIComponent(req.params.lang.toString());
const amount = encodeURIComponent(req.params.amount.toString());
// Forward the question request to the quetion service
const questionResponse = await axios.get(questionServiceUrl+'/questions/' + lang + '/' + amount);

res.json(questionResponse.data);
}
} catch (error) {

res.status(error.response.status).json({ error: error.response.data.error });
manageError(error)
}
});

app.get('/questions/:lang', async (req, res) => {
app.get('/questions/:lang', verifyToken, async (req, res) => {
try {
const lang = req.params.lang.toString();
// Forward the question request to the quetion service
const questionResponse = await axios.get(questionServiceUrl+'/questions/' + lang);

res.json(questionResponse.data);
if(!validateLang(req.params.lang.toString()))
res.status(400).json({ error: 'Wrong values given' });
else{
const lang = encodeURIComponent(req.params.lang.toString());
// Forward the question request to the quetion service
const questionResponse = await axios.get(questionServiceUrl+'/questions/' + lang.toString());

res.json(questionResponse.data);
}

} catch (error) {

res.status(error.response.status).json({ error: error.response.data.error });
manageError(error)
}
});

app.post('/record', async(req, res) => {
app.post('/record', verifyToken, async(req, res) => {

try {
// Forward the record request to the record service
const recordResponse = await axios.post(recordServiceUrl+'/record', req.body);
res.json(recordResponse.data);
} catch (error) {
res.send(error);
manageError(error)
}
});

app.get('/record/ranking/top10', async(req, res)=>{
app.get('/record/ranking/top10', verifyToken, async(req, res)=>{
try {
// Forward the record request to the record service
const recordResponse = await axios.get(recordServiceUrl + '/record/ranking/top10');
res.json(recordResponse.data);
} catch (error) {
res.send(error);
manageError(error)
}
});

app.get('/record/ranking/:user', async(req, res)=>{
app.get('/record/ranking/:user', verifyToken, async(req, res)=>{
try {
const user = req.params.user;
// Forward the record request to the record service
const recordResponse = await axios.get(recordServiceUrl + '/record/ranking/' + user);
res.json(recordResponse.data);
if(!validateUser(req.params.user.toString()))
res.status(400).json({ error: 'Wrong values given' });
else{
const user = encodeURIComponent(req.params.user.toString());
// Forward the record request to the record service
const recordResponse = await axios.get(recordServiceUrl + '/record/ranking/' + user);
res.json(recordResponse.data);
}
} catch (error) {
res.send(error);
manageError(error)
}
});

app.get('/record/:user', async(req, res)=>{
app.get('/record/:user', verifyToken, async(req, res)=>{
try {
const user = req.params.user;
// Forward the record request to the record service
const recordResponse = await axios.get(recordServiceUrl + '/record/' + user);
res.json(recordResponse.data);
if(!validateUser(req.params.user.toString()))
res.status(400).json({ error: 'Wrong values given' });
else{
const user = encodeURIComponent(req.params.user.toString());
// Forward the record request to the record service
const recordResponse = await axios.get(recordServiceUrl + '/record/' + user);
res.json(recordResponse.data);
}
} catch (error) {
res.send(error);
manageError(error)
}
});

Expand All @@ -159,4 +186,48 @@ const server = app.listen(port, () => {
console.log(`Gateway Service listening at http://localhost:${port}`);
});

function verifyToken(req, res, next) {
// Get the token from the request headers
const token = req.headers['token'] || req.body.token || req.query.token;

// Verify if the token is valid
jwt.verify(token, (process.env.JWT_KEY??'my-key'), (err, decoded) => {
if (err) {
// Token is not valid
res.status(403).json({authorized: false,
error: 'Invalid token or outdated'});
} else {
// Token is valid
req.decodedToken = decoded;
// Call next() to proceed to the next middleware or route handler
next();
}
});
}

function validateLang(lang){
return ['en', 'es', 'tk'].includes(lang);
}

function validateAmount(amount) {
const parsed = parseInt(amount, 10);
// We only accept integers and positive ones
return !isNaN(parsed) && parsed > 0;
}

function validateType(type){
return ['POPULATION', 'CAPITAL', 'LANGUAGE', 'SIZE'].includes(type);
}

function validateUser(user){
return !(/\s/.test(user)) //True if there are no spaces
}

function manageError(error){
if(error.response) //Some microservice responded with an error
res.status(error.response.status).json({ error: error.response.data.error });
else //Some other error
res.status(500).json({error : "Interanl server error"})
}

module.exports = server
34 changes: 25 additions & 9 deletions gatewayservice/gateway-service.test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
const request = require('supertest');
const axios = require('axios');
const jwt = require('jsonwebtoken');
const app = require('./gateway-service');

afterAll(async () => {
app.close();
});


jest.mock('jsonwebtoken');

jest.mock('axios');

describe('Gateway Service', () => {


describe('Gateway Service with token mock', () => {

// Mock responses from external services
axios.post.mockImplementation((url, data) => {
if (url.endsWith('/login')) {
Expand Down Expand Up @@ -45,6 +52,14 @@ describe('Gateway Service', () => {
}
});



// Mock the `verify` function of JWT
jwt.verify.mockImplementation((token, secretOrPublicKey, callback) => {
// Assume the token is valid and return the payload
callback(null, "decoded");
});

// Test /login endpoint
it('should forward login request to auth service', async () => {
const response = await request(app)
Expand All @@ -69,39 +84,39 @@ describe('Gateway Service', () => {
// Test /questions endpoint
it('should forward questions request to question service', async () => {
const response = await request(app)
.get('/questions');
.get('/questions').set('token', 'valorDelToken');

checkQuestion(response);
});

// Test /questions/:lang endpoint
it('should forward questions request to question service', async () => {
const response = await request(app)
.get('/questions/es');
.get('/questions/es').set('token', 'valorDelToken');

checkQuestion(response);
});

// Test /questions/:lang/:amount endpoint
it('should forward questions request to question service', async () => {
const response = await request(app)
.get('/questions/es/1');
.get('/questions/es/1').set('token', 'valorDelToken');

checkQuestion(response);
});

// Test /questions/:lang/:amount/:type endpoint
it('should forward questions request to question service', async () => {
const response = await request(app)
.get('/questions/es/1/CAPITAL');
.get('/questions/es/1/CAPITAL').set('token', 'valorDelToken');

checkQuestion(response);
});

// Test /record endpoint
it('should forward record request to record service', async () => {
const response = await request(app)
.post('/record');
.post('/record').set('token', 'valorDelToken');

expect(response.statusCode).toBe(200);
expect(response.body.user).toBe('testuser');
Expand All @@ -110,26 +125,27 @@ describe('Gateway Service', () => {
// Test /record/:user endpoint
it('should forward record request to record service', async () => {
const response = await request(app)
.get('/record/testuser');
.get('/record/testuser').set('token', 'valorDelToken');

checkRecord(response);
});

// Test /record/ranking/:user endpoint
it('should forward record request to record service', async () => {
const response = await request(app)
.get('/record/ranking/testuser');
.get('/record/ranking/testuser').set('token', 'valorDelToken');

checkRecord(response);
});

// Test /record/ranking/top10 endpoint
it('should forward record request to record service', async () => {
const response = await request(app)
.get('/record/ranking/top10');
.get('/record/ranking/top10').set('token', 'valorDelToken');
checkRecord(response);

});

});

function checkRecord(response){
Expand Down
Loading

0 comments on commit 4449563

Please sign in to comment.