Skip to content

Commit

Permalink
Merge pull request #43 from andela/ft-update-profile-image-#164693172
Browse files Browse the repository at this point in the history
#164693172: Update user's profile image
  • Loading branch information
9jaswag committed Apr 1, 2019
2 parents 050b0ef + 71c936d commit 5e0a973
Show file tree
Hide file tree
Showing 15 changed files with 149 additions and 64 deletions.
4 changes: 2 additions & 2 deletions controllers/articles.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default class ArticleController {
* @returns {Object} class instance
*/
static async createArticle(req, res) {
const images = req.images || [];
const images = req.body.images || [];
const {
title, description, body, slug, categoryId
} = req.body;
Expand Down Expand Up @@ -94,7 +94,7 @@ export default class ArticleController {
* @returns {Object} class instance
*/
static async updateArticle(req, res) {
const images = req.images || [];
const images = req.body.images || [];
const {
title, description, body
} = req.body;
Expand Down
51 changes: 35 additions & 16 deletions controllers/profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default class ProfileController {
updatedAt
};

const splitNamesObject = splitName(foundUser);
const splitNamesObject = splitName(foundUser.name);

return res.status(200).json({
success: true,
Expand Down Expand Up @@ -72,25 +72,17 @@ export default class ProfileController {
static async editProfile(req, res) {
const { id } = req.user;
const { bio, firstname, lastname } = req.body;

const name = `${firstname} ${lastname}`;
try {
const updateResult = await User.update(
{ bio, name: `${firstname} ${lastname}` },
{
returning: true,
raw: true,
where: {
id
}
}
);

const updatedProfile = updateResult[1][0];

const [, [updatedProfile]] = await User.update({ bio, name }, {
returning: true,
raw: true,
where: { id }
});
delete updatedProfile.password;
delete updatedProfile.verificationId;

const splitNamesObject = splitName(updatedProfile);
const splitNamesObject = splitName(updatedProfile.name);

return res.status(205).json({
success: true,
Expand All @@ -103,4 +95,31 @@ export default class ProfileController {
});
}
}

/**
* @description - updates user's profile
* @static
* @param {object} req - HTTP Request
* @param {object} res - HTTP Response
* @memberof ProfileController
* @returns {object} User Profile
*/
static async updateProfileImage(req, res) {
const { user: { id }, body: { images } } = req;
const image = images[0];
try {
const [, [{
name, email, username, bio, image: profilePic, createdAt, updatedAt
}]] = await User.update({ image }, { returning: true, raw: true, where: { id } });
return res.status(205).json({
success: true,
message: 'Profile image successfully updated',
result: {
id, name, username, email, bio, image: profilePic, createdAt, updatedAt
}
});
} catch (error) {
return res.status(500).json({ success: false, errors: ['Error updating profile image'] });
}
}
}
4 changes: 2 additions & 2 deletions controllers/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ export default class UserController {
})
.catch((error) => {
const errors = [];
if (error.errors[0].path === 'username') {
if (error.errors && error.errors[0].path === 'username') {
errors.push(error.errors[0].message);
}
if (error.errors[0].path === 'email') {
if (error.errors && error.errors[0].path === 'email') {
errors.push(error.errors[0].message);
}
return res.status(409).json({
Expand Down
3 changes: 1 addition & 2 deletions helpers/splitName.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
* @returns {object} An object of the split names
*/
const splitName = (fullName) => {
const names = fullName.name;
const splitNames = names.split(' ', 2);
const splitNames = fullName.split(' ', 2);
const splitNamesObject = { firstname: splitNames[0], lastname: splitNames[1] };
return splitNamesObject;
};
Expand Down
4 changes: 2 additions & 2 deletions middleware/addImage.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ const storage = cloudinaryStorage({
allowedFormats: ['jpg', 'jpeg', 'png', 'gif'],
});

const imageParser = multer({ storage }).array('images', 5);
const imageParser = multer({ storage }).array('image', 5);

export default async (req, res, next) => {
await imageParser(req, res, (error) => {
if (error) return res.json({ success: false, error });
if (req.files) {
req.images = req.files.map(image => image.url);
req.body.images = req.files.map(image => image.url);
return next();
}
return next();
Expand Down
6 changes: 6 additions & 0 deletions middleware/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,9 @@ export const validateGetOrder = [
.custom(value => ['latest', 'ratings', 'comments'].indexOf(value) !== -1)
.withMessage('Order type should either be latest, ratings or comments')
];

export const validateImages = [
check('images')
.exists()
.withMessage('An image file should be uploaded to complete this request')
];
11 changes: 11 additions & 0 deletions migrations/20190319000245-addProfileImage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
up: (queryInterface, Sequelize) => queryInterface.addColumn(
'Users',
'image',
{
type: Sequelize.STRING,
}
),

down: queryInterface => queryInterface.removeColumn('Users', 'image')
};
5 changes: 5 additions & 0 deletions models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ module.exports = (sequelize, DataTypes) => {
allowNull: false,
defaultValue: 'user',
unique: false
},
image: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: 'https://img.icons8.com/ios-glyphs/30/000000/user-male.png'
}
};

Expand Down
55 changes: 22 additions & 33 deletions package-lock.json

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

12 changes: 9 additions & 3 deletions routes/v1.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
validateArticleRating,
validateGetOrder,
validateCommentExist,
validateImages,
} from '../middleware/validation';
import FollowController from '../controllers/follow';
import followVerification from '../middleware/follow';
Expand All @@ -45,16 +46,21 @@ const {
getAllArticles,
getArticlesByHighestField
} = ArticleController;
const { viewProfile, editProfile, updateProfileImage } = ProfileController;

const apiRoutes = express.Router();

apiRoutes.route('/user/signup')
.post(validateSignup, returnValidationErrors, UserController.registerUser);

apiRoutes.route('/userprofile')
.get(Auth.verifyUser, isUserVerified, ProfileController.viewProfile)
.patch(Auth.verifyUser, isUserVerified, validateProfileChange,
returnValidationErrors, ProfileController.editProfile);
.get(Auth.verifyUser, isUserVerified, viewProfile)
.patch(Auth.verifyUser, isUserVerified, addImages, validateProfileChange,
returnValidationErrors, editProfile);

apiRoutes.route('/userprofile/image')
.patch(Auth.verifyUser, isUserVerified, addImages,
validateImages, returnValidationErrors, updateProfileImage);

apiRoutes.route('/verify/:verification_id')
.get(UserController.verifyAccount);
Expand Down
17 changes: 17 additions & 0 deletions test/article.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/* eslint-disable prefer-destructuring */
import chai from 'chai';
import chaiHttp from 'chai-http';
import path from 'path';
import updateVerifiedStatus from './helpers/updateVerifiedStatus';
import app from '../index';
import { article1, user2 } from './helpers/dummyData';
Expand Down Expand Up @@ -67,6 +68,22 @@ describe('ARTICLES', () => {
expect(message).to.be.equal('New article created successfully');
});

it('Should create a new article with image.', async () => {
const res = await chai
.request(app)
.post('/api/v1/articles')
.set('authorization', token)
.attach('image', path.join(__dirname, 'assets', 'testImage.jpg'))
.type('form')
.field(article1);
const { status, body: { message, success, article } } = res;
expect(article.images).to.be.an('Array');
expect(article.images[0]).to.be.a('String');
expect(status).to.be.equal(201);
expect(success).to.be.equal(true);
expect(message).to.be.equal('New article created successfully');
});

it('should not create if title is not set.', (done) => {
article1.title = undefined;
chai
Expand Down
Binary file added test/assets/testImage.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions test/helpers/userDummyData.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ export const wrongLikeCommentUser = {
};

export const validUser1 = {
username: 'flippin',
email: 'flipping2234@gmail.com',
name: 'Flipping James',
username: 'fflippin',
email: 'fflipping2234@gmail.com',
name: 'Fflipping James',
password: '1234567'
};

Expand Down
2 changes: 1 addition & 1 deletion test/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import './comment.spec';
import './category.spec';
import './user.spec';
import './article.spec';
import './socialLoginSpec';
import './login.spec';
import './profile.spec';
import './article.spec';
import './updateVerifiedStatusHelper.spec';
import './resetpassword.spec';
import './follow.spec';
Expand Down
Loading

0 comments on commit 5e0a973

Please sign in to comment.