Skip to content

Commit

Permalink
Merge pull request #71 from andela/ft-user-profile-image-168405336
Browse files Browse the repository at this point in the history
#168405336 Allow users to update their profile image
  • Loading branch information
tejiri4 committed Sep 15, 2019
2 parents 8d85914 + 098aeb6 commit cad36b5
Show file tree
Hide file tree
Showing 19 changed files with 445 additions and 236 deletions.
2 changes: 2 additions & 0 deletions .env-sample
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,5 @@ CLOUDINARY_CLOUD_NAME= ""
CLOUDINARY_API_KEY= ""
CLOUDINARY_API_SECRET= ""
CLOUDINARY_ENVIRONMENT_VAR= ""

DEFAULT_PROFILE_PIC=""
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"bcrypt": "^3.0.6",
"cloudinary": "^1.14.0",
"cors": "^2.8.5",
"datauri": "^2.0.0",
"debug": "^4.1.1",
"dotenv": "^8.0.0",
"express": "^4.17.1",
Expand All @@ -48,7 +49,6 @@
"moment": "^2.24.0",
"morgan-body": "^2.4.7",
"multer": "^1.4.2",
"multer-storage-cloudinary": "^2.2.1",
"passport": "^0.4.0",
"passport-facebook": "^3.0.0",
"passport-google-oauth2": "^0.2.0",
Expand All @@ -66,7 +66,6 @@
"devDependencies": {
"@babel/node": "^7.5.5",
"babel-plugin-istanbul": "^5.2.0",
"bcrypt": "^3.0.0",
"chai": "^4.2.0",
"chai-http": "^4.3.0",
"coveralls": "^3.0.6",
Expand Down Expand Up @@ -109,4 +108,4 @@
"sourceMap": false,
"instrument": false
}
}
}
3 changes: 2 additions & 1 deletion src/config/cloudinaryConfig.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { config, uploader } from 'cloudinary';
import { config, v2 } from 'cloudinary';
import './env';

const cloudinaryConfig = (req, res, next) => {
Expand All @@ -10,4 +10,5 @@ const cloudinaryConfig = (req, res, next) => {
next();
};

const { uploader } = v2;
export { cloudinaryConfig, uploader };
5 changes: 4 additions & 1 deletion src/controllers/userController.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ const updateUserDetails = async (req, res) => {
}
});
if (phoneNoExists) return response(res, 409, 'error', { message: phoneExists });

const [profileImageUrl] = req.imageUrls;
const userInfo = {
firstName,
lastName,
Expand All @@ -157,7 +159,8 @@ const updateUserDetails = async (req, res) => {
preferredLanguage,
preferredCurrency,
gender,
currentLocation
currentLocation,
profileImageUrl: profileImageUrl || process.env.DEFAULT_PROFILE_PIC,
};
const options = {
returning: true,
Expand Down
2 changes: 1 addition & 1 deletion src/database/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module.exports = {
use_env_variable: 'DATABASE_URL',
dialect: 'postgres',
dialectOptions: {
"ssl": {"require":true }
"ssl": { "require": true }
}
},
test: {
Expand Down
11 changes: 7 additions & 4 deletions src/database/migrations/20190815205048-create-user.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
'use strict';
module.exports = {
export default {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
Expand Down Expand Up @@ -84,8 +83,12 @@ module.exports = {
allowNull: true,
type: Sequelize.BOOLEAN,
defaultValue: true
}
})
},
profileImageUrl: {
allowNull: true,
type: Sequelize.STRING,
},
})
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Users');
Expand Down
74 changes: 74 additions & 0 deletions src/middlewares/imageUploader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import Datauri from 'datauri';
import path from 'path';
import response from '../utils/response';
import messages from '../utils/messages';
import { uploader } from '../config/cloudinaryConfig';

const dUri = new Datauri();
let ownerId = '';

/**
* extract the content of a raw file
* @param {Object} rawFile - the raw file
* @returns {Object} - return the content of the raw file
*/
const extractSingleFile = (rawFile) => {
const { originalname, buffer } = rawFile;
return dUri.format(path.extname(originalname).toString(), buffer).content;
};

/**
* extract the content of the supplied raw files
* @param {Object} rawFiles - the list of the raw files
* @returns {Object} - return the list of the content of the raw files
*/
const extractFiles = (rawFiles) => rawFiles.map(
(rawFile) => extractSingleFile(rawFile)
);

/**
* a function that is used to upload the supplied image to the cloud
* @param {Object} file - a proccessed file
* @param {Object} index - the index of the file
* @returns {Object} - return the uploaded image url
*/
const uploadSingleFile = async (file, index) => {
const { secure_url: imageUrl } = await uploader.upload(file, {
public_id: `${ownerId}-${index}`,
overwrite: true,
folder: 'rk-items',
transformation: [{
width: 500, height: 250, crop: 'scale', quality: 'auto'
}],
allowedFormats: ['jpg', 'jpeg', 'png', 'gif', 'svg'],
});

return imageUrl;
};

/**
* a middleware to upload image
* @param {Object} req - request object
* @param {Oject} res - response object
* @param {Function} next - next function
* @returns {Object} - Returns Object
*/
const uploadImage = async (req, res, next) => {
try {
const { files: rawFiles, decoded } = req;
if (!rawFiles) {
return next();
}
const { id } = decoded;
ownerId = id;
const files = extractFiles(rawFiles);
const imageUrls = await Promise.all(files.map((file, index) => uploadSingleFile(file, index)));
req.imageUrls = imageUrls;

return next();
} catch (error) {
return response(res, 400, 'error', { message: messages.imageError });
}
};

export default uploadImage;
2 changes: 1 addition & 1 deletion src/middlewares/multer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import multer from 'multer';
import storage from '../utils/cloudinaryStorage';

const storage = multer.memoryStorage();
const multerUploads = multer({ storage }).array('images', 10);

export default multerUploads;
6 changes: 5 additions & 1 deletion src/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ export default (Sequelize, DataTypes) => {
allowNull: true,
type: DataTypes.BOOLEAN,
defaultValue: true
}
},
profileImageUrl: {
allowNull: true,
type: DataTypes.STRING,
},
}, {});

User.associate = (models) => {
Expand Down
Loading

0 comments on commit cad36b5

Please sign in to comment.