Skip to content

Commit

Permalink
Merge 34afba1 into 281b3a7
Browse files Browse the repository at this point in the history
  • Loading branch information
chrismeeky committed Aug 29, 2019
2 parents 281b3a7 + 34afba1 commit 7db4ba0
Show file tree
Hide file tree
Showing 12 changed files with 483 additions and 8,161 deletions.
7,908 changes: 0 additions & 7,908 deletions package-lock.json

This file was deleted.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"request": "^2.87.0",
"sequelize": "^5.14.0",
"sequelize-cli": "^5.5.0",
"sinon": "^7.4.1",
"swagger-ui-express": "^4.0.7",
"underscore": "^1.9.1"
},
Expand Down
64 changes: 60 additions & 4 deletions src/controllers/UserController.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ class UserController {
const { email, password } = req.body;
const userFound = await User.findOne({ where: { email } });
if (!userFound) {
return HelperMethods.clientError(res, {
success: false,
message: 'Email or password does not exist',
}, 400);
return HelperMethods.clientError(res, 'Email or password does not exist', 400);
}
if (!userFound.dataValues.isVerified) {
return HelperMethods.clientError(res, {
Expand Down Expand Up @@ -147,6 +144,65 @@ class UserController {
}
}

/**
*
* @description method that updates user's profile
* @static
* @param {object} req HTTP Request object
* @param {object} res HTTP Response object
* @returns {object} HTTP Response object
* @memberof ProfileController
*/
static async updateProfile(req, res) {
try {
const userExist = await User.findByPk(req.body.id);
if (userExist && userExist.dataValues.id) {
if (userExist.dataValues.isVerified === false) {
return HelperMethods.clientError(
res, 'You cannot perform this action. You are not a verified user.', 400
);
}
await userExist.update(req.body, { returning: true, hooks: false });
return HelperMethods
.requestSuccessful(res, {
success: true,
message: 'profile updated successfully',
}, 200);
}
return HelperMethods.clientError(res, 'User does not exist', 404);
} catch (error) {
if (error.errors) return HelperMethods.sequelizeValidationError(res, error);
return HelperMethods.serverError(res);
}
}

/**
*
* @description method that gets current user's settings
* @static
* @param {object} req client request
* @param {object} res server response
* @returns {object} server response object
* @memberof ProfileController
*/
static async getProfile(req, res) {
try {
const user = await User.findByPk(req.decoded.id, {
attributes: { exclude: ['password', 'isVerified'] }
});
if (user) {
return HelperMethods.requestSuccessful(res, {
success: true,
userDetails: user,
}, 200);
}
return HelperMethods.clientError(res, 'User not found', 404);
} catch (error) {
if (error.errors) return HelperMethods.sequelizeValidationError(res, error);
return HelperMethods.serverError(res);
}
}

/**
* Verify a user's email
* Route: POST: /auth/verify_email
Expand Down
20 changes: 20 additions & 0 deletions src/middlewares/authorization.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,26 @@ class Authorization {
req.decoded = verifiedToken;
next();
}

/**
*
* @param {object} req - Request object
* @param {object} res - Response object
* @param {callback} next - The callback that passes the request
* to the next handler
* @returns {callback} next - The callback that passes the request
* to the next handler
* @returns {object} res - Response object containing an error due
* to unauthorized user
*/
static async confirmUser(req, res, next) {
if (req.decoded.id !== req.body.id) {
return HelperMethods.clientError(res,
'You can only update your profile',
400);
}
next();
}
}

export default Authorization;
44 changes: 39 additions & 5 deletions src/migrations/01-create-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,45 @@ module.exports = {
type: Sequelize.STRING,
allowNull: false,
},
gender: {
type: Sequelize.STRING
},
birthdate: {
type: Sequelize.DATE
},
preferredLanguage: {
type: Sequelize.STRING
},
preferredCurrency: {
type: Sequelize.STRING
},
city: {
type: Sequelize.STRING
},
state: {
type: Sequelize.STRING
},
zip: {
type: Sequelize.STRING
},
country: {
type: Sequelize.STRING
},
role: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: 'Requester'
},
department: {
type: Sequelize.STRING
},
lineManager: {
type: Sequelize.STRING
},
hasProfile: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
isVerified: {
type: Sequelize.BOOLEAN,
defaultValue: false
Expand All @@ -32,11 +71,6 @@ module.exports = {
profileImage: {
type: Sequelize.STRING,
},
role: {
type: Sequelize.STRING,
allowNull: false,
defaultValue: 'Requester'
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
Expand Down
103 changes: 97 additions & 6 deletions src/models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,101 @@ export default (sequelize, DataTypes) => {
}
},
},
gender: {
type: DataTypes.STRING,
validate: {
len: {
args: [4],
msg: 'Gender must be at least 4 characters long.'
},
}
},
birthdate: {
type: DataTypes.DATE,
validate: {
isDate: true,
}
},
preferredLanguage: {
type: DataTypes.STRING,
validate: {
len: {
args: [4],
msg: 'Language must be at least 4 characters long.'
},
}
},
preferredCurrency: {
type: DataTypes.STRING,
validate: {
len: {
args: [3],
msg: 'Currency must be at least 3 characters long.'
},
}
},
city: {
type: DataTypes.STRING,
validate: {
len: {
args: [3],
msg: 'City must be at least 3 characters long.'
},
}
},
state: {
type: DataTypes.STRING,
validate: {
len: {
args: [3],
msg: 'State must be at least 3 characters long.'
},
}
},
zip: {
type: DataTypes.STRING,
validate: {
len: {
args: [3],
msg: 'Zip must be at least 3 characters long.'
},
}
},
country: {
type: DataTypes.STRING,
validate: {
len: {
args: [3],
msg: 'Country must be at least 3 characters long.'
},
}
},
role: {
type: DataTypes.ENUM(['Super Administrator', 'Travel Administrator',
'Travel Team Member', 'Manager', 'Requester'])
},
department: {
type: DataTypes.STRING,
validate: {
len: {
args: [6],
msg: 'Department must be at least 6 characters long.'
},
}
},
lineManager: {
type: DataTypes.STRING,
validate: {
len: {
args: [6],
msg: 'Line manager must be at least 6 characters long.'
},
}
},
hasProfile: {
type: DataTypes.BOOLEAN,
defaultValue: false,
},
isVerified: {
type: DataTypes.BOOLEAN,
defaultValue: false,
Expand All @@ -72,11 +167,7 @@ export default (sequelize, DataTypes) => {
args: [6, 150],
msg: 'Password must be more than 5 characters'
}
},
},
role: {
type: DataTypes.ENUM(['Super Administrator', 'Travel Administrator',
'Travel Team Member', 'Manager', 'Requester'])
}
},
profileImage: {
type: DataTypes.STRING,
Expand All @@ -85,7 +176,7 @@ export default (sequelize, DataTypes) => {
msg: 'The URL sent is not a valid URL.'
}
}
}
},
},
{
classMethods: {
Expand Down
18 changes: 16 additions & 2 deletions src/routes/userRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,24 @@ import Authorization from '../middlewares';
import Validate from '../validation';

const userRoutes = app => {
app.patch('/api/v1/update_user',
app.patch(
'/api/v1/update_user',
Authorization.checkToken,
Validate.validateRoleUpdate,
UserController.updateUserRole);
UserController.updateUserRole
);
app.patch(
'/api/v1/profile',
Authorization.checkToken,
Authorization.confirmUser,
Validate.validateUpdateProfile,
UserController.updateProfile
);
app.get(
'/api/v1/profile',
Authorization.checkToken,
UserController.getProfile
);
};

export default userRoutes;
2 changes: 1 addition & 1 deletion src/test/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import './integrationTests';
import './unitTests';
import './integrationTests';
Loading

0 comments on commit 7db4ba0

Please sign in to comment.