Skip to content

Commit

Permalink
Added validations to solve sonarcloud security ranking
Browse files Browse the repository at this point in the history
  • Loading branch information
Mister-Mario committed Apr 22, 2024
1 parent 19a68d3 commit e27f842
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 102 deletions.
148 changes: 70 additions & 78 deletions gatewayservice/gateway-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,81 +58,68 @@ app.get('/questions', verifyToken, async (req, res) => {
}
});

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);
} catch (error) {

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


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);
} catch (error) {

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

app.get('/questions/:lang/:amount/:type', verifyToken, 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);
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 });
}
});


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 });
}
});

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.toString());

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 });
}
});

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

try {
// Forward the record request to the record service
const recordResponse = await axios.post(recordServiceUrl+'/record', req.body);
Expand All @@ -154,42 +141,29 @@ app.get('/record/ranking/top10', verifyToken, 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);
} catch (error) {
res.send(error);
}
});

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);
}
});

app.get('/record/ranking/:user', 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);
}
});

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);
}
Expand Down Expand Up @@ -230,4 +204,22 @@ function verifyToken(req, res, 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
}

module.exports = server
21 changes: 5 additions & 16 deletions gatewayservice/gateway-service.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,15 @@ describe('Gateway Service with token mock', () => {
// 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);
});
Expand All @@ -126,37 +126,26 @@ describe('Gateway Service with token mock', () => {
it('should forward record request to record service', async () => {
const response = await request(app)
.get('/record/testuser').set('token', 'valorDelToken');
expect(response.statusCode).toBe(200);
expect(response.body).toHaveProperty('record', "undefined");
});


});

describe('Gateway Service without token mock', () => {
// Test /record/:user endpoint
it('should not verify the token', async () => {
const response = await request(app)
.get('/record/testuser');

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
41 changes: 40 additions & 1 deletion users/userservice/user-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/userdb';
mongoose.connect(mongoUri);


const validateEmail = (email) => {
return String(email)
.toLowerCase()
.match(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);
};

// Function to validate required fields in the request body
function validateRequiredFields(req, requiredFields) {
Expand All @@ -25,13 +30,47 @@ function validateRequiredFields(req, requiredFields) {
throw new Error(`Missing required field: ${field}`);
}
}

let email = req.body.email.toString();
let username = req.body.username.toString();
let password = req.body.password.toString();
let repeatPassword = req.body.repeatPassword.toString();

if(!validateEmail(email)){
//User put a wrong format email
throw new Error("Wrong email format ([email protected])")
}

if(password !== repeatPassword){
//User put the same password
throw new Error("Passwords dont match");
}
if(/\s/.test(password)){
//User put spaces in password
throw new Error("Password cannot have spaces");
}
if(password.length < 8){
//Password too short
throw new Error("Password must be at least 8 characters long");
}

if(password.length > 64){
//Password too long
throw new Error("Password must less than 64 characters long");
}

if(/\s/.test(username)){
//Spaces in username
throw new Error("Username cannot have spaces");
}

}

app.post('/adduser', async (req, res) => {
try {
// Check if required fields are present in the request body
try{
validateRequiredFields(req, ['email', 'username', 'password']);
validateRequiredFields(req, ['email', 'username', 'password', 'repeatPassword']);
}
catch(error){
res.status(400).json({ error : error.message });
Expand Down
Loading

0 comments on commit e27f842

Please sign in to comment.