Skip to content

Commit

Permalink
Merge pull request #166 from Arquisoft/Develop
Browse files Browse the repository at this point in the history
Autologin, changes on displayed information and api-doc updated
  • Loading branch information
uo276976 authored Apr 7, 2024
2 parents 1fb2bed + d21efa0 commit 82c1d44
Show file tree
Hide file tree
Showing 21 changed files with 4,936 additions and 222 deletions.
19 changes: 18 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,21 @@ jobs:
uses: sonarsource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
e2e-tests:
needs: [unit-tests]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm --prefix users/authservice install
- run: npm --prefix users/userservice install
- run: npm --prefix question_generator install
- run: npm --prefix questionservice install
- run: npm --prefix gameservice install
- run: npm --prefix gatewayservice install
- run: npm --prefix webapp install
- run: npm --prefix webapp run build
- run: npm --prefix webapp run test:e2e
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,4 @@ jobs:
wget https://raw.githubusercontent.com/arquisoft/wiq_es3b/master/docker-compose.yml -O docker-compose.yml
wget https://raw.githubusercontent.com/arquisoft/wiq_es3b/master/.env -O .env
docker compose --profile prod down
docker-compose --profile prod up -d --pull always
docker compose --profile prod up -d --pull always
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
106 changes: 77 additions & 29 deletions gatewayservice/gateway-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,49 @@ app.get('/health', (_req, res) => {
app.post('/login', async (req, res) => {
try {
// Forward the login request to the authentication service
const authResponse = await axios.post(authServiceUrl+'/login', req.body);
res.json(authResponse.data);
try{
const authResponse = await axios.post(authServiceUrl+'/login', req.body);
res.json(authResponse.data);
} catch (error) {
res.status(error.response.status).json(error.response.data);
}
} catch (error) {
res.status(500).json({ error: 'Service down' });
}
});
app.get('/verify', async (req, res) => {
try {
if (req.headers.authorization) {
try{
const authResponse = await axios.get(authServiceUrl+'/verify', {
headers: {
Authorization: req.headers.authorization
}
});
res.json(authResponse.data);
} catch (error) {
res.status(error.response.status).json(error.response.data);
}
} else {
res.status(401).json({ error: 'Unauthorized' });
}
} catch (error) {
res.status(500).json({ error: error.message||'Service down' });
res.status(500).json({ error: 'Service down' });
}
});


app.post('/adduser', async (req, res) => {
try {
// Forward the add user request to the user service
const userResponse = await axios.post(userServiceUrl+'/adduser', req.body);
res.json(userResponse.data);
try{
const userResponse = await axios.post(userServiceUrl+'/adduser', req.body);
res.json(userResponse.data);
} catch (error) {
res.status(error.response.status).json(error.response.data);
}
} catch (error) {
res.status(500).json({ error: error.message||'Service down' });
res.status(500).json({ error: 'Service down' });
}
});

Expand All @@ -73,13 +102,17 @@ app.get('/api/questions/create', async (req, res) => {
const apiUrl = new URL('/api/questions/create', questionGenerationServiceUrl);
apiUrl.search = queryParams.toString();

// Forward the add user request to the user service
const userResponse = await axios.get(apiUrl.toString(), {
headers: {
Authorization: req.headers.authorization
}
});
res.json(userResponse.data);
try{
// Forward the add user request to the user service
const userResponse = await axios.get(apiUrl.toString(), {
headers: {
Authorization: req.headers.authorization
}
});
res.json(userResponse.data);
}catch(error){
res.status(error.response.status).json(error.response.data);
}
} catch (error) {
res.status(500).json({ error: "Service down" });
}
Expand All @@ -91,8 +124,12 @@ app.get('/api/info/questions', async function (req, res) {
if(Object.keys(req.query).length > 0) {
url += '?' + new URLSearchParams(req.query).toString();
}
const infoResponse = await axios.get(url);
res.json(infoResponse.data);
try{
const infoResponse = await axios.get(url);
res.json(infoResponse.data);
}catch(error){
res.status(error.response.status).json(error.response.data);
}
} catch (error) {
res.status(500).json({ error: "Service down" });
}
Expand All @@ -104,8 +141,12 @@ app.get('/api/info/users', async (req, res) => {
if(username){
url += '?user=' + username;
}
const infoResponse = await axios.get(url);
res.json(infoResponse.data);
try{
const infoResponse = await axios.get(url);
res.json(infoResponse.data);
}catch(error){
res.status(error.response.status).json(error.response.data);
}
} catch (error) {
res.status(500).json({ error: "Service down" });
}
Expand All @@ -117,8 +158,12 @@ app.get('/api/info/games', async (req, res) => {
if(username){
url += '?user=' + username;
}
const infoResponse = await axios.get(url);
res.json(infoResponse.data);
try{
const infoResponse = await axios.get(url);
res.json(infoResponse.data);
}catch(error){
res.status(error.response.status).json(error.response.data);
}
} catch (error) {
res.status(500).json({ error: "Service down" });
}
Expand All @@ -127,9 +172,13 @@ app.get('/api/info/games', async (req, res) => {
// Ruta para agregar una nuevo game
app.post('/addgame', async (req, res) => {
try {
// Forward the add game request to the games service
const gameResponse = await axios.post(gameServiceUrl + '/addgame', req.body);
res.json(gameResponse.data);
try{
// Forward the add game request to the games service
const gameResponse = await axios.post(gameServiceUrl + '/addgame', req.body);
res.json(gameResponse.data);
}catch(error){
res.status(error.response.status).json(error.response.data);
}
} catch (error) {
res.status(500).json({ error: "Service down" });
}
Expand All @@ -139,14 +188,13 @@ app.post('/addgame', async (req, res) => {
app.get('/getParticipation/:userId', async (req, res) => {
try {
const userId = req.params.userId;
if (!userId) {
res.status(404).json({ error: 'User ID not provided' });
return;
}
const apiUrl = `${gameServiceUrl}/getParticipation/${userId}`;
const gameResponse = await axios.get(apiUrl);

res.json(gameResponse.data);
try{
const gameResponse = await axios.get(apiUrl);
res.json(gameResponse.data);
}catch(error){
res.status(error.response.status).json(error.response.data);
}
} catch (error) {
res.status(500).json({ error: "Service down" });
}
Expand Down
118 changes: 102 additions & 16 deletions gatewayservice/gateway-service.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ let app;
beforeAll(async () => {
app = require('./gateway-service');
});

afterAll(async () => {
app.close();
});
Expand All @@ -13,9 +14,7 @@ jest.mock('axios');
describe('Gateway Service', () => {
// Mock responses from external services
axios.post.mockImplementation((url, data) => {
if (url.endsWith('/login')) {
return Promise.resolve({ data: { token: 'mockedToken' } });
} else if (url.endsWith('/adduser')) {
if (url.endsWith('/adduser')) {
return Promise.resolve({ data: { userId: 'mockedUserId' } });
}else if (url.endsWith('/addquestion')) {
return Promise.resolve({
Expand All @@ -28,15 +27,7 @@ describe('Gateway Service', () => {
}
});
axios.get.mockImplementation((url) => {
if (url.endsWith('/api/questions/create')) {
return Promise.resolve({
data: {
question: 'Mocked Question',
correct: 'Mocked Correct Answer',
incorrects: ['Mocked Option 1', 'Mocked Option 2']
}
});
}else if(url.endsWith('/api/questions/create?lang=es&category=sports')){
if(url.endsWith('/api/questions/create?lang=es&category=sports')){
return Promise.resolve({
data: {
question: 'Mocked Question',
Expand Down Expand Up @@ -65,27 +56,79 @@ describe('Gateway Service', () => {
}
]
});
}else if(url.endsWith('/verify')){
return Promise.resolve({ data: { username: 'testuser' } });
}
});

// Test /health endpoint
it('should give information of the status', async () => {
const response = await request(app)
.get('/health');

expect(response.statusCode).toBe(200);
expect(response.body.status).toBe('OK');
});

// Test /login endpoint
it('should forward login request to auth service', async () => {
axios.post.mockResolvedValueOnce({ data: { token: 'mockedToken' } });
const response = await request(app)
.post('/login')
.send({ username: 'testuser', password: 'testpassword' });

expect(response.statusCode).toBe(200);
expect(response.body.token).toBe('mockedToken');
});

it('should return an error when the user service is down', async () => {
jest.spyOn(axios, 'post').mockRejectedValueOnce({ response: { status: 500, data: { error: 'Service down' } } });
const response = await request(app)
.post('/login')
.send({ username: 'testuser', password: 'testpassword' });
expect(response.status).toBe(500);
expect(response.body).toEqual({ error: 'Service down' });
});
// Test /verify endpoint
it('should verify authorization token with auth service', async () => {
const mockedToken = 'mockedToken';
const authResponse = { username: 'testuser' };
axios.get.mockResolvedValueOnce({ data: authResponse });
const response = await request(app)
.get('/verify')
.set('Authorization', `Bearer ${mockedToken}`);
expect(response.statusCode).toBe(200);
expect(response.body).toEqual(authResponse);
});
it("should return 401 Unauthorized for unauthorized request", async () => {
const response = await request(app).get("/verify");
expect(response.statusCode).toBe(401);
expect(response.body).toEqual({ error: "Unauthorized" });
});
// Test /verify endpoint when auth service is down
it('should return an error when the auth service is down', async () => {
const mockedToken = 'mockedToken';
axios.get.mockImplementation({ response: { status: 500, data: { error: 'Service down' } } });
const response = await request(app)
.get('/verify')
.set('Authorization', `Bearer ${mockedToken}`);
expect(response.statusCode).toBe(500);
expect(response.body).toEqual({ error: 'Service down' });
});

// Test /verify endpoint when auth service returns an error
it('should return an error when the auth service returns an error', async () => {
const mockedToken = 'mockedToken';
const mockedError = { error: 'Unauthorized' };
axios.get.mockRejectedValueOnce({ response: { status: 401, data: mockedError } });
const response = await request(app)
.get('/verify')
.set('Authorization', `Bearer ${mockedToken}`);
expect(response.statusCode).toBe(401);
expect(response.body).toEqual(mockedError);
});




// Test /adduser endpoint
it('should forward add user request to user service', async () => {
const response = await request(app)
Expand All @@ -95,15 +138,24 @@ describe('Gateway Service', () => {
expect(response.statusCode).toBe(200);
expect(response.body.userId).toBe('mockedUserId');
});
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')
.send({ username: 'testuser', password: 'testpassword' });
expect(response.statusCode).toBe(500);
expect(response.body).toEqual({ error: 'Service down' });
});

// Test /api/info/questions endpoint
it('should forward info request with id to question service', async () => {
axios.get.mockResolvedValueOnce({ data: { question: 'Mocked Question', correct: 'Mocked Correct Answer', incorrects: ['Mocked Option 1', 'Mocked Option 2'] } });
const response = await request(app)
.get('/api/info/questions');
expect(response.statusCode).toBe(200);
expect(response.headers['content-type']).toContain('application/json');
expect(response.body).toEqual(expect.any(Array));
});
expect(response.body).toEqual({ question: 'Mocked Question', correct: 'Mocked Correct Answer', incorrects: ['Mocked Option 1', 'Mocked Option 2'] });
});

// Test /api/info/questions endpoint when service is down
it('should return an error when the question service is down', async () => {
Expand All @@ -120,13 +172,29 @@ describe('Gateway Service', () => {

// Test /api/questions/create endpoint
it('should forward create question request to question generation service', async () => {
axios.get.mockImplementation(() => {
return Promise.resolve({
data: {
question: 'Mocked Question',
correct: 'Mocked Correct Answer',
incorrects: ['Mocked Option 1', 'Mocked Option 2']
}
});
});
const response = await request(app)
.get('/api/questions/create');
expect(response.statusCode).toBe(200);
expect(response.body).toHaveProperty('question');
expect(response.body).toHaveProperty('correct');
expect(response.body).toHaveProperty('incorrects');
},10000);
it('should return an error when the user service is down', async () => {
axios.get.mockRejectedValueOnce({ response: { status: 500, data: { error: 'Service down' } } });
const response = await request(app)
.get('/api/questions/create')
expect(response.statusCode).toBe(500);
expect(response.body).toEqual({ error: 'Service down' });
});

it('should forward create question request to question generation service', async () => {
const response = await request(app)
Expand Down Expand Up @@ -238,4 +306,22 @@ describe('GET /api/info/games', () => {
expect(response.body).toEqual(mockedError);
});
});
describe('addGame', () =>{
it('should return 401 Unauthorized if authorization token is missing', async () => {
const response = await request(app).post('/addgame');
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)
.post('/addgame')
.set('Authorization', `Bearer ${mockedToken}`);
expect(response.statusCode).toBe(401);
expect(response.body).toEqual({ error: 'Unauthorized' });
});


});
Loading

0 comments on commit 82c1d44

Please sign in to comment.