Skip to content

Instantly share code, notes, and snippets.

@Deyems
Created June 8, 2023 18:02
Show Gist options
  • Save Deyems/7a87df42957e8b62684acef261992e13 to your computer and use it in GitHub Desktop.
Save Deyems/7a87df42957e8b62684acef261992e13 to your computer and use it in GitHub Desktop.
User Controller file - Handles Post, Get Requests
const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const compress = require('compression');
const methodOverride = require('method-override');
const cors = require('cors');
const helmet = require('helmet');
const passport = require('passport');
const routes = require('../api/routes/v1');
const { logs } = require('./vars');
const strategies = require('./passport');
const error = require('../api/middlewares/error');
/**
* Express instance
* @public
*/
const app = express();
// request logging. dev: console | production: file
app.use(morgan(logs));
// parse body params and attache them to req.body
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// gzip compression
app.use(compress());
// lets you use HTTP verbs such as PUT or DELETE
// in places where the client doesn't support it
app.use(methodOverride());
// secure apps by setting various HTTP headers
app.use(helmet());
// enable CORS - Cross Origin Resource Sharing
app.use(cors());
// enable authentication
app.use(passport.initialize());
passport.use('jwt', strategies.jwt);
passport.use('facebook', strategies.facebook);
passport.use('google', strategies.google);
// mount api v1 routes
app.use('/v1', routes);
// if error is not an instanceOf APIError, convert it.
app.use(error.converter);
// catch 404 and forward to error handler
app.use(error.notFound);
// error handler, send stacktrace only during development
app.use(error.handler);
module.exports = app;
const express = require('express');
const userRoutes = require('./user.route');
const authRoutes = require('./auth.route');
const router = express.Router();
/**
* GET v1/status
*/
router.get('/status', (req, res) => res.send('OK'));
/**
* GET v1/docs
*/
router.use('/docs', express.static('docs'));
router.use('/users', userRoutes);
router.use('/auth', authRoutes);
module.exports = router;
const mongoose = require('mongoose');
const logger = require('./logger');
const { mongo, env } = require('./vars');
// set mongoose Promise to Bluebird
mongoose.Promise = Promise;
// Exit application on error
mongoose.connection.on('error', (err) => {
logger.error(`MongoDB connection error: ${err}`);
process.exit(-1);
});
// print mongoose logs in dev env
if (env === 'development') {
mongoose.set('debug', true);
}
/**
* Connect to mongo db
*
* @returns {object} Mongoose connection
* @public
*/
exports.connect = () => {
mongoose
.connect(mongo.uri, {
useCreateIndex: true,
keepAlive: 1,
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
})
.then(() => console.log('mongoDB connected...'));
return mongoose.connection;
};
const httpStatus = require('http-status');
const { omit } = require('lodash');
const User = require('../models/user.model');
/**
* Load user and append to req.
* @public
*/
exports.load = async (req, res, next, id) => {
try {
const user = await User.get(id);
req.locals = { user };
return next();
} catch (error) {
return next(error);
}
};
/**
* Get user
* @public
*/
exports.get = (req, res) => res.json(req.locals.user.transform());
/**
* Get logged in user info
* @public
*/
exports.loggedIn = (req, res) => res.json(req.user.transform());
/**
* Create new user
* @public
*/
exports.create = async (req, res, next) => {
try {
const user = new User(req.body);
const savedUser = await user.save();
res.status(httpStatus.CREATED);
res.json(savedUser.transform());
} catch (error) {
next(User.checkDuplicateEmail(error));
}
};
/**
* Replace existing user
* @public
*/
exports.replace = async (req, res, next) => {
try {
const { user } = req.locals;
const newUser = new User(req.body);
const ommitRole = user.role !== 'admin' ? 'role' : '';
const newUserObject = omit(newUser.toObject(), '_id', ommitRole);
await user.updateOne(newUserObject, { override: true, upsert: true });
const savedUser = await User.findById(user._id);
res.json(savedUser.transform());
} catch (error) {
next(User.checkDuplicateEmail(error));
}
};
/**
* Update existing user
* @public
*/
exports.update = (req, res, next) => {
const ommitRole = req.locals.user.role !== 'admin' ? 'role' : '';
const updatedUser = omit(req.body, ommitRole);
const user = Object.assign(req.locals.user, updatedUser);
user.save()
.then((savedUser) => res.json(savedUser.transform()))
.catch((e) => next(User.checkDuplicateEmail(e)));
};
/**
* Get user list
* @public
*/
exports.list = async (req, res, next) => {
try {
const users = await User.list(req.query);
const transformedUsers = users.map((user) => user.transform());
res.json(transformedUsers);
} catch (error) {
next(error);
}
};
/**
* Delete user
* @public
*/
exports.remove = (req, res, next) => {
const { user } = req.locals;
user.remove()
.then(() => res.status(httpStatus.NO_CONTENT).end())
.catch((e) => next(e));
};
const express = require('express');
const validate = require('express-validation');
const controller = require('../../controllers/user.controller');
const { authorize, ADMIN, LOGGED_USER } = require('../../middlewares/auth');
const {
listUsers,
createUser,
replaceUser,
updateUser,
} = require('../../validations/user.validation');
const router = express.Router();
/**
* Load user when API with userId route parameter is hit
*/
router.param('userId', controller.load);
router
.route('/')
/**
* @api {get} v1/users List Users
* @apiDescription Get a list of users
* @apiVersion 1.0.0
* @apiName ListUsers
* @apiGroup User
* @apiPermission admin
*
* @apiHeader {String} Authorization User's access token
*
* @apiParam {Number{1-}} [page=1] List page
* @apiParam {Number{1-100}} [perPage=1] Users per page
* @apiParam {String} [name] User's name
* @apiParam {String} [email] User's email
* @apiParam {String=user,admin} [role] User's role
*
* @apiSuccess {Object[]} users List of users.
*
* @apiError (Unauthorized 401) Unauthorized Only authenticated users can access the data
* @apiError (Forbidden 403) Forbidden Only admins can access the data
*/
.get(authorize(ADMIN), validate(listUsers), controller.list)
/**
* @api {post} v1/users Create User
* @apiDescription Create a new user
* @apiVersion 1.0.0
* @apiName CreateUser
* @apiGroup User
* @apiPermission admin
*
* @apiHeader {String} Authorization User's access token
*
* @apiParam {String} email User's email
* @apiParam {String{6..128}} password User's password
* @apiParam {String{..128}} [name] User's name
* @apiParam {String=user,admin} [role] User's role
*
* @apiSuccess (Created 201) {String} id User's id
* @apiSuccess (Created 201) {String} name User's name
* @apiSuccess (Created 201) {String} email User's email
* @apiSuccess (Created 201) {String} role User's role
* @apiSuccess (Created 201) {Date} createdAt Timestamp
*
* @apiError (Bad Request 400) ValidationError Some parameters may contain invalid values
* @apiError (Unauthorized 401) Unauthorized Only authenticated users can create the data
* @apiError (Forbidden 403) Forbidden Only admins can create the data
*/
.post(authorize(ADMIN), validate(createUser), controller.create);
router
.route('/profile')
/**
* @api {get} v1/users/profile User Profile
* @apiDescription Get logged in user profile information
* @apiVersion 1.0.0
* @apiName UserProfile
* @apiGroup User
* @apiPermission user
*
* @apiHeader {String} Authorization User's access token
*
* @apiSuccess {String} id User's id
* @apiSuccess {String} name User's name
* @apiSuccess {String} email User's email
* @apiSuccess {String} role User's role
* @apiSuccess {Date} createdAt Timestamp
*
* @apiError (Unauthorized 401) Unauthorized Only authenticated Users can access the data
*/
.get(authorize(), controller.loggedIn);
router
.route('/:userId')
/**
* @api {get} v1/users/:id Get User
* @apiDescription Get user information
* @apiVersion 1.0.0
* @apiName GetUser
* @apiGroup User
* @apiPermission user
*
* @apiHeader {String} Authorization User's access token
*
* @apiSuccess {String} id User's id
* @apiSuccess {String} name User's name
* @apiSuccess {String} email User's email
* @apiSuccess {String} role User's role
* @apiSuccess {Date} createdAt Timestamp
*
* @apiError (Unauthorized 401) Unauthorized Only authenticated users can access the data
* @apiError (Forbidden 403) Forbidden Only user with same id or admins can access the data
* @apiError (Not Found 404) NotFound User does not exist
*/
.get(authorize(LOGGED_USER), controller.get)
/**
* @api {put} v1/users/:id Replace User
* @apiDescription Replace the whole user document with a new one
* @apiVersion 1.0.0
* @apiName ReplaceUser
* @apiGroup User
* @apiPermission user
*
* @apiHeader {String} Authorization User's access token
*
* @apiParam {String} email User's email
* @apiParam {String{6..128}} password User's password
* @apiParam {String{..128}} [name] User's name
* @apiParam {String=user,admin} [role] User's role
* (You must be an admin to change the user's role)
*
* @apiSuccess {String} id User's id
* @apiSuccess {String} name User's name
* @apiSuccess {String} email User's email
* @apiSuccess {String} role User's role
* @apiSuccess {Date} createdAt Timestamp
*
* @apiError (Bad Request 400) ValidationError Some parameters may contain invalid values
* @apiError (Unauthorized 401) Unauthorized Only authenticated users can modify the data
* @apiError (Forbidden 403) Forbidden Only user with same id or admins can modify the data
* @apiError (Not Found 404) NotFound User does not exist
*/
.put(authorize(LOGGED_USER), validate(replaceUser), controller.replace)
/**
* @api {patch} v1/users/:id Update User
* @apiDescription Update some fields of a user document
* @apiVersion 1.0.0
* @apiName UpdateUser
* @apiGroup User
* @apiPermission user
*
* @apiHeader {String} Authorization User's access token
*
* @apiParam {String} email User's email
* @apiParam {String{6..128}} password User's password
* @apiParam {String{..128}} [name] User's name
* @apiParam {String=user,admin} [role] User's role
* (You must be an admin to change the user's role)
*
* @apiSuccess {String} id User's id
* @apiSuccess {String} name User's name
* @apiSuccess {String} email User's email
* @apiSuccess {String} role User's role
* @apiSuccess {Date} createdAt Timestamp
*
* @apiError (Bad Request 400) ValidationError Some parameters may contain invalid values
* @apiError (Unauthorized 401) Unauthorized Only authenticated users can modify the data
* @apiError (Forbidden 403) Forbidden Only user with same id or admins can modify the data
* @apiError (Not Found 404) NotFound User does not exist
*/
.patch(authorize(LOGGED_USER), validate(updateUser), controller.update)
/**
* @api {patch} v1/users/:id Delete User
* @apiDescription Delete a user
* @apiVersion 1.0.0
* @apiName DeleteUser
* @apiGroup User
* @apiPermission user
*
* @apiHeader {String} Authorization User's access token
*
* @apiSuccess (No Content 204) Successfully deleted
*
* @apiError (Unauthorized 401) Unauthorized Only authenticated users can delete the data
* @apiError (Forbidden 403) Forbidden Only user with same id or admins can delete the data
* @apiError (Not Found 404) NotFound User does not exist
*/
.delete(authorize(LOGGED_USER), controller.remove);
module.exports = router;
/* eslint-disable arrow-body-style */
/* eslint-disable no-unused-expressions */
const request = require('supertest');
const httpStatus = require('http-status');
const { expect } = require('chai');
const sinon = require('sinon');
const bcrypt = require('bcryptjs');
const { some, omitBy, isNil } = require('lodash');
const app = require('../../../index');
const User = require('../../models/user.model');
const JWT_EXPIRATION = require('../../../config/vars').jwtExpirationInterval;
/**
* root level hooks
*/
async function format(user) {
const formated = user;
// delete password
delete formated.password;
// get users from database
const dbUser = (await User.findOne({ email: user.email })).transform();
// remove null and undefined properties
return omitBy(dbUser, isNil);
}
describe('Users API', async () => {
let adminAccessToken;
let userAccessToken;
let dbUsers;
let user;
let admin;
const password = '123456';
const passwordHashed = await bcrypt.hash(password, 1);
beforeEach(async () => {
dbUsers = {
branStark: {
email: 'branstark@gmail.com',
password: passwordHashed,
name: 'Bran Stark',
role: 'admin',
},
jonSnow: {
email: 'jonsnow@gmail.com',
password: passwordHashed,
name: 'Jon Snow',
},
};
user = {
email: 'sousa.dfs@gmail.com',
password,
name: 'Daniel Sousa',
};
admin = {
email: 'sousa.dfs@gmail.com',
password,
name: 'Daniel Sousa',
role: 'admin',
};
await User.deleteMany({});
await User.insertMany([dbUsers.branStark, dbUsers.jonSnow]);
dbUsers.branStark.password = password;
dbUsers.jonSnow.password = password;
adminAccessToken = (await User.findAndGenerateToken(dbUsers.branStark)).accessToken;
userAccessToken = (await User.findAndGenerateToken(dbUsers.jonSnow)).accessToken;
});
describe('POST /v1/users', () => {
it('should create a new user when request is ok', () => {
return request(app)
.post('/v1/users')
.set('Authorization', `Bearer ${adminAccessToken}`)
.send(admin)
.expect(httpStatus.CREATED)
.then((res) => {
delete admin.password;
expect(res.body).to.include(admin);
});
});
it('should create a new user and set default role to "user"', () => {
return request(app)
.post('/v1/users')
.set('Authorization', `Bearer ${adminAccessToken}`)
.send(user)
.expect(httpStatus.CREATED)
.then((res) => {
expect(res.body.role).to.be.equal('user');
});
});
it('should report error when email already exists', () => {
user.email = dbUsers.branStark.email;
return request(app)
.post('/v1/users')
.set('Authorization', `Bearer ${adminAccessToken}`)
.send(user)
.expect(httpStatus.CONFLICT)
.then((res) => {
const { field } = res.body.errors[0];
const { location } = res.body.errors[0];
const { messages } = res.body.errors[0];
expect(field).to.be.equal('email');
expect(location).to.be.equal('body');
expect(messages).to.include('"email" already exists');
});
});
it('should report error when email is not provided', () => {
delete user.email;
return request(app)
.post('/v1/users')
.set('Authorization', `Bearer ${adminAccessToken}`)
.send(user)
.expect(httpStatus.BAD_REQUEST)
.then((res) => {
const { field } = res.body.errors[0];
const { location } = res.body.errors[0];
const { messages } = res.body.errors[0];
expect(field).to.be.equal('email');
expect(location).to.be.equal('body');
expect(messages).to.include('"email" is required');
});
});
it('should report error when password length is less than 6', () => {
user.password = '12345';
return request(app)
.post('/v1/users')
.set('Authorization', `Bearer ${adminAccessToken}`)
.send(user)
.expect(httpStatus.BAD_REQUEST)
.then((res) => {
const { field } = res.body.errors[0];
const { location } = res.body.errors[0];
const { messages } = res.body.errors[0];
expect(field).to.be.equal('password');
expect(location).to.be.equal('body');
expect(messages).to.include('"password" length must be at least 6 characters long');
});
});
it('should report error when logged user is not an admin', () => {
return request(app)
.post('/v1/users')
.set('Authorization', `Bearer ${userAccessToken}`)
.send(user)
.expect(httpStatus.FORBIDDEN)
.then((res) => {
expect(res.body.code).to.be.equal(httpStatus.FORBIDDEN);
expect(res.body.message).to.be.equal('Forbidden');
});
});
});
describe('GET /v1/users', () => {
it('should get all users', () => {
return request(app)
.get('/v1/users')
.set('Authorization', `Bearer ${adminAccessToken}`)
.expect(httpStatus.OK)
.then(async (res) => {
const bran = await format(dbUsers.branStark);
const john = await format(dbUsers.jonSnow);
// before comparing it is necessary to convert String to Date
res.body[0].createdAt = new Date(res.body[0].createdAt);
res.body[1].createdAt = new Date(res.body[1].createdAt);
const includesBranStark = some(res.body, bran);
const includesjonSnow = some(res.body, john);
expect(res.body).to.be.an('array');
expect(res.body).to.have.lengthOf(2);
expect(includesBranStark).to.be.true;
expect(includesjonSnow).to.be.true;
});
});
it('should get all users with pagination', () => {
return request(app)
.get('/v1/users')
.set('Authorization', `Bearer ${adminAccessToken}`)
.query({ page: 2, perPage: 1 })
.expect(httpStatus.OK)
.then(async (res) => {
delete dbUsers.jonSnow.password;
expect(res.body).to.be.an('array');
expect(res.body[0]).to.be.an('object');
expect(res.body).to.have.lengthOf(1);
expect(res.body[0].name).to.be.equal('Jon Snow');
});
});
it('should filter users', () => {
return request(app)
.get('/v1/users')
.set('Authorization', `Bearer ${adminAccessToken}`)
.query({ email: dbUsers.jonSnow.email })
.expect(httpStatus.OK)
.then(async (res) => {
delete dbUsers.jonSnow.password;
const john = await format(dbUsers.jonSnow);
// before comparing it is necessary to convert String to Date
res.body[0].createdAt = new Date(res.body[0].createdAt);
const includesjonSnow = some(res.body, john);
expect(res.body).to.be.an('array');
expect(res.body).to.have.lengthOf(1);
expect(includesjonSnow).to.be.true;
});
});
it('should report error when pagination\'s parameters are not a number', () => {
return request(app)
.get('/v1/users')
.set('Authorization', `Bearer ${adminAccessToken}`)
.query({ page: '?', perPage: 'whaat' })
.expect(httpStatus.BAD_REQUEST)
.then((res) => {
const { field } = res.body.errors[0];
const { location } = res.body.errors[0];
const { messages } = res.body.errors[0];
expect(field).to.be.equal('page');
expect(location).to.be.equal('query');
expect(messages).to.include('"page" must be a number');
return Promise.resolve(res);
})
.then((res) => {
const { field } = res.body.errors[1];
const { location } = res.body.errors[1];
const { messages } = res.body.errors[1];
expect(field).to.be.equal('perPage');
expect(location).to.be.equal('query');
expect(messages).to.include('"perPage" must be a number');
});
});
it('should report error if logged user is not an admin', () => {
return request(app)
.get('/v1/users')
.set('Authorization', `Bearer ${userAccessToken}`)
.expect(httpStatus.FORBIDDEN)
.then((res) => {
expect(res.body.code).to.be.equal(httpStatus.FORBIDDEN);
expect(res.body.message).to.be.equal('Forbidden');
});
});
});
describe('GET /v1/users/:userId', () => {
it('should get user', async () => {
const id = (await User.findOne({}))._id;
delete dbUsers.branStark.password;
return request(app)
.get(`/v1/users/${id}`)
.set('Authorization', `Bearer ${adminAccessToken}`)
.expect(httpStatus.OK)
.then((res) => {
expect(res.body).to.include(dbUsers.branStark);
});
});
it('should report error "User does not exist" when user does not exists', () => {
return request(app)
.get('/v1/users/56c787ccc67fc16ccc1a5e92')
.set('Authorization', `Bearer ${adminAccessToken}`)
.expect(httpStatus.NOT_FOUND)
.then((res) => {
expect(res.body.code).to.be.equal(404);
expect(res.body.message).to.be.equal('User does not exist');
});
});
it('should report error "User does not exist" when id is not a valid ObjectID', () => {
return request(app)
.get('/v1/users/palmeiras1914')
.set('Authorization', `Bearer ${adminAccessToken}`)
.expect(httpStatus.NOT_FOUND)
.then((res) => {
expect(res.body.code).to.be.equal(404);
expect(res.body.message).to.equal('User does not exist');
});
});
it('should report error when logged user is not the same as the requested one', async () => {
const id = (await User.findOne({ email: dbUsers.branStark.email }))._id;
return request(app)
.get(`/v1/users/${id}`)
.set('Authorization', `Bearer ${userAccessToken}`)
.expect(httpStatus.FORBIDDEN)
.then((res) => {
expect(res.body.code).to.be.equal(httpStatus.FORBIDDEN);
expect(res.body.message).to.be.equal('Forbidden');
});
});
});
describe('PUT /v1/users/:userId', () => {
it('should replace user', async () => {
delete dbUsers.branStark.password;
const id = (await User.findOne(dbUsers.branStark))._id;
return request(app)
.put(`/v1/users/${id}`)
.set('Authorization', `Bearer ${adminAccessToken}`)
.send(user)
.expect(httpStatus.OK)
.then((res) => {
delete user.password;
expect(res.body).to.include(user);
expect(res.body.role).to.be.equal('user');
});
});
it('should report error when email is not provided', async () => {
const id = (await User.findOne({}))._id;
delete user.email;
return request(app)
.put(`/v1/users/${id}`)
.set('Authorization', `Bearer ${adminAccessToken}`)
.send(user)
.expect(httpStatus.BAD_REQUEST)
.then((res) => {
const { field } = res.body.errors[0];
const { location } = res.body.errors[0];
const { messages } = res.body.errors[0];
expect(field).to.be.equal('email');
expect(location).to.be.equal('body');
expect(messages).to.include('"email" is required');
});
});
it('should report error user when password length is less than 6', async () => {
const id = (await User.findOne({}))._id;
user.password = '12345';
return request(app)
.put(`/v1/users/${id}`)
.set('Authorization', `Bearer ${adminAccessToken}`)
.send(user)
.expect(httpStatus.BAD_REQUEST)
.then((res) => {
const { field } = res.body.errors[0];
const { location } = res.body.errors[0];
const { messages } = res.body.errors[0];
expect(field).to.be.equal('password');
expect(location).to.be.equal('body');
expect(messages).to.include('"password" length must be at least 6 characters long');
});
});
it('should report error "User does not exist" when user does not exists', () => {
return request(app)
.put('/v1/users/palmeiras1914')
.set('Authorization', `Bearer ${adminAccessToken}`)
.expect(httpStatus.NOT_FOUND)
.then((res) => {
expect(res.body.code).to.be.equal(404);
expect(res.body.message).to.be.equal('User does not exist');
});
});
it('should report error when logged user is not the same as the requested one', async () => {
const id = (await User.findOne({ email: dbUsers.branStark.email }))._id;
return request(app)
.put(`/v1/users/${id}`)
.set('Authorization', `Bearer ${userAccessToken}`)
.expect(httpStatus.FORBIDDEN)
.then((res) => {
expect(res.body.code).to.be.equal(httpStatus.FORBIDDEN);
expect(res.body.message).to.be.equal('Forbidden');
});
});
it('should not replace the role of the user (not admin)', async () => {
const id = (await User.findOne({ email: dbUsers.jonSnow.email }))._id;
const role = 'admin';
return request(app)
.put(`/v1/users/${id}`)
.set('Authorization', `Bearer ${userAccessToken}`)
.send(admin)
.expect(httpStatus.OK)
.then((res) => {
expect(res.body.role).to.not.be.equal(role);
});
});
});
describe('PATCH /v1/users/:userId', () => {
it('should update user', async () => {
delete dbUsers.branStark.password;
const id = (await User.findOne(dbUsers.branStark))._id;
const { name } = user;
return request(app)
.patch(`/v1/users/${id}`)
.set('Authorization', `Bearer ${adminAccessToken}`)
.send({ name })
.expect(httpStatus.OK)
.then((res) => {
expect(res.body.name).to.be.equal(name);
expect(res.body.email).to.be.equal(dbUsers.branStark.email);
});
});
it('should not update user when no parameters were given', async () => {
delete dbUsers.branStark.password;
const id = (await User.findOne(dbUsers.branStark))._id;
return request(app)
.patch(`/v1/users/${id}`)
.set('Authorization', `Bearer ${adminAccessToken}`)
.send()
.expect(httpStatus.OK)
.then((res) => {
expect(res.body).to.include(dbUsers.branStark);
});
});
it('should report error "User does not exist" when user does not exists', () => {
return request(app)
.patch('/v1/users/palmeiras1914')
.set('Authorization', `Bearer ${adminAccessToken}`)
.expect(httpStatus.NOT_FOUND)
.then((res) => {
expect(res.body.code).to.be.equal(404);
expect(res.body.message).to.be.equal('User does not exist');
});
});
it('should report error when logged user is not the same as the requested one', async () => {
const id = (await User.findOne({ email: dbUsers.branStark.email }))._id;
return request(app)
.patch(`/v1/users/${id}`)
.set('Authorization', `Bearer ${userAccessToken}`)
.expect(httpStatus.FORBIDDEN)
.then((res) => {
expect(res.body.code).to.be.equal(httpStatus.FORBIDDEN);
expect(res.body.message).to.be.equal('Forbidden');
});
});
it('should not update the role of the user (not admin)', async () => {
const id = (await User.findOne({ email: dbUsers.jonSnow.email }))._id;
const role = 'admin';
return request(app)
.patch(`/v1/users/${id}`)
.set('Authorization', `Bearer ${userAccessToken}`)
.send({ role })
.expect(httpStatus.OK)
.then((res) => {
expect(res.body.role).to.not.be.equal(role);
});
});
});
describe('DELETE /v1/users', () => {
it('should delete user', async () => {
const id = (await User.findOne({}))._id;
return request(app)
.delete(`/v1/users/${id}`)
.set('Authorization', `Bearer ${adminAccessToken}`)
.expect(httpStatus.NO_CONTENT)
.then(() => request(app).get('/v1/users'))
.then(async () => {
const users = await User.find({});
expect(users).to.have.lengthOf(1);
});
});
it('should report error "User does not exist" when user does not exists', () => {
return request(app)
.delete('/v1/users/palmeiras1914')
.set('Authorization', `Bearer ${adminAccessToken}`)
.expect(httpStatus.NOT_FOUND)
.then((res) => {
expect(res.body.code).to.be.equal(404);
expect(res.body.message).to.be.equal('User does not exist');
});
});
it('should report error when logged user is not the same as the requested one', async () => {
const id = (await User.findOne({ email: dbUsers.branStark.email }))._id;
return request(app)
.delete(`/v1/users/${id}`)
.set('Authorization', `Bearer ${userAccessToken}`)
.expect(httpStatus.FORBIDDEN)
.then((res) => {
expect(res.body.code).to.be.equal(httpStatus.FORBIDDEN);
expect(res.body.message).to.be.equal('Forbidden');
});
});
});
describe('GET /v1/users/profile', () => {
it('should get the logged user\'s info', () => {
delete dbUsers.jonSnow.password;
return request(app)
.get('/v1/users/profile')
.set('Authorization', `Bearer ${userAccessToken}`)
.expect(httpStatus.OK)
.then((res) => {
expect(res.body).to.include(dbUsers.jonSnow);
});
});
it('should report error without stacktrace when accessToken is expired', async () => {
// fake time
const clock = sinon.useFakeTimers();
const expiredAccessToken = (await User.findAndGenerateToken(dbUsers.branStark)).accessToken;
// move clock forward by minutes set in config + 1 minute
clock.tick((JWT_EXPIRATION * 60000) + 60000);
return request(app)
.get('/v1/users/profile')
.set('Authorization', `Bearer ${expiredAccessToken}`)
.expect(httpStatus.UNAUTHORIZED)
.then((res) => {
expect(res.body.code).to.be.equal(httpStatus.UNAUTHORIZED);
expect(res.body.message).to.be.equal('jwt expired');
expect(res.body).to.not.have.a.property('stack');
});
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment