Skip to content

Commit

Permalink
feat(user-profile): user can view/update profile
Browse files Browse the repository at this point in the history
- add new fields to the existing ones to get more information from the
  user after signup
- create validations for each field so that each field can be independent
  of each other
- add more fields tothe user model- add more fields tothe user model
- create route for user to be able to update profile using patch request
  method
- create route for user to be able to view profile before or after update
  using the get method.
- write test for each both endpoints to make sure most of the real cases
  is covered

[Delivers #167749956]
  • Loading branch information
ldonjibson committed Sep 13, 2019
1 parent 3d1712e commit 7ba8b11
Show file tree
Hide file tree
Showing 15 changed files with 634 additions and 36 deletions.
21 changes: 9 additions & 12 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

196 changes: 196 additions & 0 deletions src/config/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,133 @@
}
}
}
},
"/user/profile/{email}": {
"patch": {
"tags": ["user profile"],
"summary": "Update user profile",
"description": "This endpoint updates a user profile",
"operationId": "updateProfile",
"produces": ["application/json"],
"security": [
{
"Bearer": []
}
],
"parameters": [
{
"name": "email",
"in": "path",
"required": true,
"description": "user email",
"schema": {
"type": "string",
"format": "email"
}
},
{
"in": "body",
"name": "body",
"description": "Information needed to update a user",
"required": true,
"schema": {
"$ref": "#/definitions/UserProfile"
}
}
],
"responses": {
"201": {
"description": "user account updated successfully",
"schema": {
"$ref": "#/definitions/UserProfileResponse"
}
},
"400": {
"description": "email is required, and should follow this format: myemail@domain.com"
},
"500": {
"description": "database error"
}
}
},
"get": {
"tags": ["user profile"],
"summary": "Retrieve user profile",
"description": "This endpoint retrieve a user profile",
"operationId": "retrieveProfile",
"produces": ["application/json"],
"security": [
{
"Bearer": []
}
],
"parameters": [
{
"name": "email",
"in": "path",
"required": true,
"description": "user email",
"schema": {
"type": "string",
"format": "email"
}
}
],
"responses": {
"200": {
"description": "user account retrieved successfully",
"schema": {
"$ref": "#/definitions/UserProfileResponse"
}
},
"400": {
"description": "email is required, and should follow this format: myemail@domain.com"
},
"500": {
"description": "database error"
}
}
}
},
"/requests": {
"post": {
"tags": ["request"],
"summary": "Book a travel request",
"description": "This endpoint books a one-way trip request",
"operationId": "bookTrip",
"consumes": ["application/json"],
"produces": ["application/json"],
"security": [
{
"Bearer": []
}
],
"parameters": [
{
"in": "body",
"name": "body",
"description": "data needed to book a trip",
"required": true,
"schema": {
"$ref": "#/definitions/BookTrip"
}
}
],
"responses": {
"201": {
"description": "message created successfully",
"schema": {
"$ref": "#/definitions/RequestResponse"
}
},
"400": {
"description": "departureDate is required"
},
"409": {
"description": "you already have a trip booked around this period, you may choose to cancel and make a multi-city request"
}
}
}
}
},
"definitions": {
Expand All @@ -154,6 +281,50 @@
}
}
},
"Signin": {
"type": "object",
"properties": {
"email": {
"type": "string"
},
"password": {
"type": "string",
"format": "password"
}
}
},
"UserProfile": {
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"phoneNumber": {
"type": "string"
},
"gender": {
"type": "string"
},
"preferredLanguage": {
"type": "string"
},
"birthDate": {
"type": "string"
},
"address": {
"type": "string"
},
"department": {
"type": "string"
},
"lineManager": {
"type": "string"
}
}
},
"BookTrip": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -186,6 +357,31 @@
}
}
},
"BookTrip": {
"type": "object",
"properties": {
"origin": {
"type": "string"
},
"destination": {
"type": "string"
},
"type": {
"type": "string",
"enum": ["one-way", "return"]
},
"departureDate": {
"type": "string",
"format": "date"
},
"reason": {
"type": "string"
},
"accommodation": {
"type": "string"
}
}
},
"AuthResponse": {
"type": "object",
"properties": {
Expand Down
55 changes: 54 additions & 1 deletion src/controllers/UserController.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import UserService from '../services/UserService';
import Responses from '../utils/Responses';
import Helper from '../utils/Helper';
import Responses from '../utils/Responses';

/**
* @class
Expand Down Expand Up @@ -55,4 +55,57 @@ export default class UserController {
return Responses.send(res);
});
}

/**
* @method updateUserProfile
* @description Implements userprofile settings endpoint
* @static
* @param {object} req - Request object
* @param {object} res - Response object
* @returns {object} JSON response
* @memberof UserController
*/
static updateUserProfile(req, res) {
const { body, user, params } = req;
if (user.email !== params.email){
Responses.setError(401, 'You are not allowed to edit this profile');
return Responses.send(res);
}
UserService.updateUser(body, user.id, params.email)
.then(updateUser => {
console.log(updateUser)
delete updateUser[0].dataValues.password;
Responses.setSuccess(201, 'user account updated successfully', updateUser[0]);
return Responses.send(res);
}).catch(() => {
Responses.setError(500, 'database error');
return Responses.send(res);
});
}

/**
* @method retrieveUserProfile
* @description Implements userprofile settings endpoint
* @static
* @param {object} req - Request object
* @param {object} res - Response object
* @returns {object} JSON response
* @memberof UserController
*/
static retrieveUserProfile(req, res) {
const {user, params} = req;
if (user.email !== params.email){
Responses.setError(401, 'You are not allowed to see this profile');
return Responses.send(res);
}
UserService.retrieveUser(user.id, params.email)
.then(retrieveUser => {
delete retrieveUser.dataValues.password;
Responses.setSuccess(200, 'user account retrieved successfully', retrieveUser);
return Responses.send(res);
}).catch(() => {
Responses.setError(500, 'database error');
return Responses.send(res);
});
}
}
15 changes: 13 additions & 2 deletions src/database/migrations/20190911082111-create-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,19 @@ module.exports = {
email: { type: Sequelize.STRING, allowNull: false, unique: true },
password: { type: Sequelize.STRING, allowNull: false },
isVerified: { type: Sequelize.BOOLEAN, defaultValue: false },
gender: {
type: Sequelize.ENUM('Male', 'Female', 'Other'),
allowNull: true
},
birthDate: { type: Sequelize.DATEONLY, allowNull: true },
preferredLanguage: { type: Sequelize.STRING, allowNull: true },
address: { type: Sequelize.TEXT, allowNull: true },
phoneNumber: { type: Sequelize.STRING, allowNull: true },
role: { type: Sequelize.STRING, allowNull: true },
department: { type: Sequelize.STRING, allowNull: true },
lineManager: { type: Sequelize.STRING, allowNull: true },
createdAt: { type: Sequelize.DATE, allowNull: false },
updatedAt: { type: Sequelize.DATE, allowNull: false }
updatedAt: { type: Sequelize.DATE, allowNull: false },
}),
down: queryInterface => queryInterface.dropTable('Users')
down: (queryInterface) => queryInterface.dropTable('Users')
};
12 changes: 11 additions & 1 deletion src/database/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@ module.exports = (sequelize, DataTypes) => {
lastName: { type: DataTypes.STRING, allowNull: false },
email: { type: DataTypes.STRING, allowNull: false, unique: true },
password: { type: DataTypes.STRING, allowNull: false },
isVerified: { type: DataTypes.BOOLEAN, defaultValue: false }
isVerified: { type: DataTypes.BOOLEAN, defaultValue: false },
gender: { type: DataTypes.ENUM('Male', 'Female', 'Other'),
allowNull: true
},
birthDate: { type: DataTypes.DATEONLY, allowNull: true },
preferredLanguage: { type: DataTypes.STRING, allowNull: true },
address: { type: DataTypes.TEXT, allowNull: true },
role: { type: DataTypes.STRING, allowNull: true },
department: { type: DataTypes.STRING, allowNull: true },
lineManager: { type: DataTypes.STRING, allowNull: true },
phoneNumber: { type: DataTypes.STRING, allowNull: true }
}, {});
User.associate = models => {
User.hasMany(models.Request, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,14 @@ module.exports = {
isVerified: true,
createdAt: new Date(),
updatedAt: new Date()
},
{
firstName: 'Mathr',
lastName: 'Jonson',
email: 'mathyr@gmail.com',
password: '$2b$10$s2GQR3odxFN2srZiHR0bYOBZnuhw0mqF4mM1eB/ZB0fHNjZWXHW6O',
isVerified: true,
createdAt: new Date(),
updatedAt: new Date()
}], {})
};
Loading

0 comments on commit 7ba8b11

Please sign in to comment.