Skip to content

Commit

Permalink
1601-submitting-hoax
Browse files Browse the repository at this point in the history
  • Loading branch information
basarbk committed Aug 7, 2020
1 parent 7a1b155 commit 873f85b
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 22 deletions.
22 changes: 12 additions & 10 deletions __tests__/Auth.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ beforeEach(async () => {

const activeUser = { username: 'user1', email: '[email protected]', password: 'P4ssword', inactive: false };

const credentials = { email: '[email protected]', password: 'P4ssword' };

const addUser = async (user = { ...activeUser }) => {
const hash = await bcrypt.hash(user.password, 10);
user.password = hash;
Expand All @@ -44,24 +46,24 @@ const postLogout = (options = {}) => {
describe('Authentication', () => {
it('returns 200 when credentials are correct', async () => {
await addUser();
const response = await postAuthentication({ email: '[email protected]', password: 'P4ssword' });
const response = await postAuthentication(credentials);
expect(response.status).toBe(200);
});

it('returns user id, username, image and token when login success', async () => {
const user = await addUser();
const response = await postAuthentication({ email: '[email protected]', password: 'P4ssword' });
const response = await postAuthentication(credentials);
expect(response.body.id).toBe(user.id);
expect(response.body.username).toBe(user.username);
expect(Object.keys(response.body)).toEqual(['id', 'username', 'image', 'token']);
});
it('returns 401 when user does not exist', async () => {
const response = await postAuthentication({ email: '[email protected]', password: 'P4ssword' });
const response = await postAuthentication(credentials);
expect(response.status).toBe(401);
});
it('returns proper error body when authentication fails', async () => {
const nowInMillis = new Date().getTime();
const response = await postAuthentication({ email: '[email protected]', password: 'P4ssword' });
const response = await postAuthentication(credentials);
const error = response.body;
expect(error.path).toBe('/api/1.0/auth');
expect(error.timestamp).toBeGreaterThan(nowInMillis);
Expand All @@ -73,7 +75,7 @@ describe('Authentication', () => {
${'tr'} | ${tr.authentication_failure}
${'en'} | ${en.authentication_failure}
`('returns $message when authentication fails and language is set as $language', async ({ language, message }) => {
const response = await postAuthentication({ email: '[email protected]', password: 'P4ssword' }, { language });
const response = await postAuthentication(credentials, { language });
expect(response.body.message).toBe(message);
});

Expand All @@ -85,13 +87,13 @@ describe('Authentication', () => {

it('returns 403 when logging in with an inactive account', async () => {
await addUser({ ...activeUser, inactive: true });
const response = await postAuthentication({ email: '[email protected]', password: 'P4ssword' });
const response = await postAuthentication(credentials);
expect(response.status).toBe(403);
});
it('returns proper error body when inactive authentication fails', async () => {
await addUser({ ...activeUser, inactive: true });
const nowInMillis = new Date().getTime();
const response = await postAuthentication({ email: '[email protected]', password: 'P4ssword' });
const response = await postAuthentication(credentials);
const error = response.body;
expect(error.path).toBe('/api/1.0/auth');
expect(error.timestamp).toBeGreaterThan(nowInMillis);
Expand All @@ -105,7 +107,7 @@ describe('Authentication', () => {
'returns $message when authentication fails for inactive account and language is set as $language',
async ({ language, message }) => {
await addUser({ ...activeUser, inactive: true });
const response = await postAuthentication({ email: '[email protected]', password: 'P4ssword' }, { language });
const response = await postAuthentication(credentials, { language });
expect(response.body.message).toBe(message);
}
);
Expand All @@ -119,7 +121,7 @@ describe('Authentication', () => {
});
it('returns token in response body when credentials are correct', async () => {
await addUser();
const response = await postAuthentication({ email: '[email protected]', password: 'P4ssword' });
const response = await postAuthentication(credentials);
expect(response.body.token).not.toBeUndefined();
});
});
Expand All @@ -131,7 +133,7 @@ describe('Logout', () => {
});
it('removes the token from database', async () => {
await addUser();
const response = await postAuthentication({ email: '[email protected]', password: 'P4ssword' });
const response = await postAuthentication(credentials);
const token = response.body.token;
await postLogout({ token: token });
const storedToken = await Token.findOne({ where: { token: token } });
Expand Down
74 changes: 74 additions & 0 deletions __tests__/HoaxSubmit.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const request = require('supertest');
const app = require('../src/app');
const en = require('../locales/en/translation.json');
const tr = require('../locales/tr/translation.json');
const User = require('../src/user/User');
const sequelize = require('../src/config/database');
const bcrypt = require('bcrypt');

beforeAll(async () => {
if (process.env.NODE_ENV === 'test') {
await sequelize.sync();
}
});

beforeEach(async () => {
await User.destroy({ truncate: { cascade: true } });
});

const activeUser = { username: 'user1', email: '[email protected]', password: 'P4ssword', inactive: false };

const credentials = { email: '[email protected]', password: 'P4ssword' };

const addUser = async (user = { ...activeUser }) => {
const hash = await bcrypt.hash(user.password, 10);
user.password = hash;
return await User.create(user);
};

const postHoax = async (body = null, options = {}) => {
let agent = request(app);
let token;
if (options.auth) {
const response = await agent.post('/api/1.0/auth').send(options.auth);
token = response.body.token;
}
agent = request(app).post('/api/1.0/hoaxes');
if (options.language) {
agent.set('Accept-Language', options.language);
}
if (token) {
agent.set('Authorization', `Bearer ${token}`);
}
if (options.token) {
agent.set('Authorization', `Bearer ${options.token}`);
}
return agent.send(body);
};

describe('Post Hoax', () => {
it('returns 401 when hoax post request has no authentication', async () => {
const response = await postHoax();
expect(response.status).toBe(401);
});
it.each`
language | message
${'tr'} | ${tr.unauthorized_hoax_submit}
${'en'} | ${en.unauthorized_hoax_submit}
`(
'returns error body with $message when unauthorized request sent with language $language',
async ({ language, message }) => {
const nowInMillis = Date.now();
const response = await postHoax(null, { language });
const error = response.body;
expect(error.path).toBe('/api/1.0/hoaxes');
expect(error.message).toBe(message);
expect(error.timestamp).toBeGreaterThan(nowInMillis);
}
);
it('returns 200 when valid hoax submitted with authorized user', async () => {
await addUser();
const response = await postHoax({ content: 'Hoax content' }, { auth: credentials });
expect(response.status).toBe(200);
});
});
14 changes: 8 additions & 6 deletions __tests__/UserDelete.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ beforeEach(async () => {

const activeUser = { username: 'user1', email: '[email protected]', password: 'P4ssword', inactive: false };

const credentials = { email: '[email protected]', password: 'P4ssword' };

const addUser = async (user = { ...activeUser }) => {
const hash = await bcrypt.hash(user.password, 10);
user.password = hash;
Expand Down Expand Up @@ -68,7 +70,7 @@ describe('User Delete', () => {
it('returns forbidden when delete request is sent with correct credentials but for different user', async () => {
await addUser();
const userToBeDelete = await addUser({ ...activeUser, username: 'user2', email: '[email protected]' });
const token = await auth({ auth: { email: '[email protected]', password: 'P4ssword' } });
const token = await auth({ auth: credentials });
const response = await deleteUser(userToBeDelete.id, { token: token });
expect(response.status).toBe(403);
});
Expand All @@ -78,30 +80,30 @@ describe('User Delete', () => {
});
it('returns 200 ok when delete request sent from authorized user', async () => {
const savedUser = await addUser();
const token = await auth({ auth: { email: '[email protected]', password: 'P4ssword' } });
const token = await auth({ auth: credentials });
const response = await deleteUser(savedUser.id, { token: token });
expect(response.status).toBe(200);
});
it('deletes user from database when request sent from authorized user', async () => {
const savedUser = await addUser();
const token = await auth({ auth: { email: '[email protected]', password: 'P4ssword' } });
const token = await auth({ auth: credentials });
await deleteUser(savedUser.id, { token: token });

const inDBUser = await User.findOne({ where: { id: savedUser.id } });
expect(inDBUser).toBeNull();
});
it('deletes token from database when delete user request sent from authorized user', async () => {
const savedUser = await addUser();
const token = await auth({ auth: { email: '[email protected]', password: 'P4ssword' } });
const token = await auth({ auth: credentials });
await deleteUser(savedUser.id, { token: token });

const tokenInDB = await Token.findOne({ where: { token: token } });
expect(tokenInDB).toBeNull();
});
it('deletes all tokens from database when delete user request sent from authorized user', async () => {
const savedUser = await addUser();
const token1 = await auth({ auth: { email: '[email protected]', password: 'P4ssword' } });
const token2 = await auth({ auth: { email: '[email protected]', password: 'P4ssword' } });
const token1 = await auth({ auth: credentials });
const token2 = await auth({ auth: credentials });
await deleteUser(savedUser.id, { token: token1 });

const tokenInDB = await Token.findOne({ where: { token: token2 } });
Expand Down
5 changes: 3 additions & 2 deletions __tests__/UserUpdate.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ beforeEach(async () => {
});

const activeUser = { username: 'user1', email: '[email protected]', password: 'P4ssword', inactive: false };
const credentials = { email: '[email protected]', password: 'P4ssword' };

const addUser = async (user = { ...activeUser }) => {
const hash = await bcrypt.hash(user.password, 10);
Expand Down Expand Up @@ -89,14 +90,14 @@ describe('User Update', () => {
await addUser();
const userToBeUpdated = await addUser({ ...activeUser, username: 'user2', email: '[email protected]' });
const response = await putUser(userToBeUpdated.id, null, {
auth: { email: '[email protected]', password: 'P4ssword' },
auth: credentials,
});
expect(response.status).toBe(403);
});
it('returns forbidden when update request is sent by inactive user with correct credentials for its own user', async () => {
const inactiveUser = await addUser({ ...activeUser, inactive: true });
const response = await putUser(inactiveUser.id, null, {
auth: { email: '[email protected]', password: 'P4ssword' },
auth: credentials,
});
expect(response.status).toBe(403);
});
Expand Down
3 changes: 2 additions & 1 deletion locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
"password_reset_request_success": "Check your e-mail for resetting your password",
"unauthroized_password_reset": "You are not authorized to update your password. Please follow the password reset steps again.",
"profile_image_size": "Your profile image cannot be bigger than 2MB",
"unsupported_image_file": "Only JPEG or PNG files are allowed"
"unsupported_image_file": "Only JPEG or PNG files are allowed",
"unauthorized_hoax_submit": "You are not authorized to post hoax"
}
3 changes: 2 additions & 1 deletion locales/tr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
"password_reset_request_success": "Şifrenizi yenilemek için e-postanızı kontrol edin",
"unauthroized_password_reset": "Şifrenizi yenileme yetkiniz bulunmuyor. Lütfen şifre yenileme adımlarını tekrarlayınız.",
"profile_image_size": "Kullandığınız resim 2MB'dan büyük olamaz",
"unsupported_image_file": "Sadece JPEG ya da PNG dosyalarını kullanabilirsiniz"
"unsupported_image_file": "Sadece JPEG ya da PNG dosyalarını kullanabilirsiniz",
"unauthorized_hoax_submit": "Efsane göndermeye yetkiniz bulunmamaktadır"
}
2 changes: 2 additions & 0 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const tokenAuthentication = require('./middleware/tokenAuthentication');
const FileService = require('./file/FileService');
const config = require('config');
const path = require('path');
const HoaxRouter = require('./hoax/HoaxRouter');

const { uploadDir, profileDir } = config;
const profileFolder = path.join('.', uploadDir, profileDir);
Expand Down Expand Up @@ -45,6 +46,7 @@ app.use(tokenAuthentication);

app.use(UserRouter);
app.use(AuthenticationRouter);
app.use(HoaxRouter);

app.use(errorHandler);

Expand Down
4 changes: 2 additions & 2 deletions src/auth/AuthenticationException.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = function AuthenticationException() {
module.exports = function AuthenticationException(message) {
this.status = 401;
this.message = 'authentication_failure';
this.message = message || 'authentication_failure';
};
12 changes: 12 additions & 0 deletions src/hoax/HoaxRouter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const express = require('express');
const router = express.Router();
const AuthenticationException = require('../auth/AuthenticationException');

router.post('/api/1.0/hoaxes', (req, res) => {
if (req.authenticatedUser) {
return res.send();
}
throw new AuthenticationException('unauthorized_hoax_submit');
});

module.exports = router;

0 comments on commit 873f85b

Please sign in to comment.