Skip to content

Commit

Permalink
Merge cddc2d1 into 9c47b15
Browse files Browse the repository at this point in the history
  • Loading branch information
fxola committed Jul 15, 2019
2 parents 9c47b15 + cddc2d1 commit 9caa326
Show file tree
Hide file tree
Showing 21 changed files with 466 additions and 116 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ node_modules

# Optional npm cache directory
.npm
uploads

# Optional REPL history
.node_repl_history
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"scripts": {
"test": "NODE_ENV=test npm run db:drop && npm run migration-rollback && npm run db-migration && nyc mocha src/**/*.spec.js --require @babel/register --exit --timeout 100000|| true",
"test-watch": "nodemon --exec \"npm test\"",
"table-reset": "sequelize db:drop && sequelize db:create",
"start": "nodemon --exec babel-node src/index.js",
"build": "npm run db-migration && npm run clean && npm run babel-build",
"clean": "rm -rf dist",
Expand Down
15 changes: 12 additions & 3 deletions src/controllers/auth.controllers.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import fs from 'fs';
import {
loginService,
signUpService,
Expand All @@ -7,7 +8,7 @@ import {
saveToBlackListServices
} from '../services/auth.service';
import Helper from '../services/helper';
import upload from '../helpers/image.helper';
import { upload } from '../helpers/image.helper';

const { failResponse, successResponse } = Helper;

Expand Down Expand Up @@ -120,7 +121,7 @@ export default {
/**
*
* @description Handles the Logic for Updating a User profile
* Route: PUT: /users/profileupdate
* Route: PUT: /users
* @param {object} request
* @param {object} response
* @param {function} next
Expand All @@ -141,10 +142,18 @@ export default {
'avatar'
);
uploadedImage = imageResponse.secure_url;
fs.unlinkSync(imagePath);
}

const fields = {
...request.body,
firstName: request.body.firstName || request.foundUser.firstName,
lastName: request.body.lastName || request.foundUser.lastName,
bio: request.body.bio || request.foundUser.bio,
userName: request.body.userName || request.foundUser.userName,
twitterHandle:
request.body.twitterHandle || request.foundUser.twitterHandle,
facebookHandle:
request.body.facebookHandle || request.foundUser.facebookHandle,
image: uploadedImage || previousImage
};
const updatedUser = await request.foundUser.update(fields);
Expand Down
30 changes: 28 additions & 2 deletions src/controllers/user.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
adminDeleteUserService,
adminUpdateUserService,
followUserService,
getUserFollowersService
getUserFollowersService,
getUserProfile
} from '../services/user.service';
import { isUserExist } from '../services/auth.service';
import Helper from '../services/helper';
Expand Down Expand Up @@ -160,11 +161,36 @@ const getFollowers = async (request, response, next) => {
}
};

/**
* @method viewProfile
* Route: GET profiles/:username
* Handles the logic to view a user's profile
* @param {object} request
* @param {object} response
* @returns {object} API response object
*/

const viewProfile = async (request, response, next) => {
try {
const { username } = request.params;
const user = await getUserProfile(username, request.user.id);
if (!user) {
return Helper.failResponse(response, 404, {
message: 'User does not exist'
});
}
return Helper.successResponse(response, 200, user);
} catch (error) {
return next(error);
}
};

export default {
getUsers,
adminCreateUser,
adminUpdateUser,
adminDeleteUser,
followUser,
getFollowers
getFollowers,
viewProfile
};
12 changes: 12 additions & 0 deletions src/db/migrations/20190627124710-create-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ module.exports = {
allowNull: true,
defaultValue: 'author'
},
bio: {
type: Sequelize.TEXT,
allowNull: true
},
facebookHandle: {
type: Sequelize.STRING,
allowNull: true
},
twitterHandle: {
type: Sequelize.STRING,
allowNull: true
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
Expand Down
11 changes: 0 additions & 11 deletions src/db/migrations/add-bio.js

This file was deleted.

11 changes: 0 additions & 11 deletions src/db/migrations/add-facebook-handle.js

This file was deleted.

11 changes: 0 additions & 11 deletions src/db/migrations/add-twitter-handle.js

This file was deleted.

1 change: 1 addition & 0 deletions src/db/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export default (sequelize, DataTypes) => {
});

User.associate = models => {
// associations can be defined here
User.hasMany(models.Follow, {
foreignKey: 'userId',
as: 'followers'
Expand Down
7 changes: 2 additions & 5 deletions src/helpers/image.helper.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import cloudinary from 'cloudinary';
import fs from 'fs';
import dotenv from 'dotenv';

dotenv.config();
Expand All @@ -17,7 +16,8 @@ cloudinary.config({
* @returns {object} uploaded image response
*/

const upload = async (path, uniqueFilename, destination) => {
// eslint-disable-next-line import/prefer-default-export
export const upload = async (path, uniqueFilename, destination) => {
let publicId;
let tags;
/* istanbul ignore next */
Expand All @@ -37,11 +37,8 @@ const upload = async (path, uniqueFilename, destination) => {
path,
{ public_id: publicId, tags }, // directory and tags are optional
image => {
// remove file from server
fs.unlinkSync(path);
// return image details
return image;
}
);
};
export default upload;
12 changes: 12 additions & 0 deletions src/helpers/utilities.helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* @method isNumber
* Checks if the string provided is a number
* @param {string} value
* @returns {boolean}
*/

const isNumeric = async value => {
return !!Number(value);
};

export default isNumeric;
32 changes: 32 additions & 0 deletions src/middlewares/profileUpdateCheck.middleware.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { findByUserName, findUserById } from '../services/auth.service';
import Helper from '../services/helper';

/**
*
* @description Handles neccessary checks on profile update
Expand All @@ -10,12 +11,43 @@ import Helper from '../services/helper';
*/
const profileChecks = async (request, response, next) => {
try {
const errors = [];
if ('firstName' in request.body) {
if (!request.body.firstName) errors.push('firstName cannot be empty');
}
if ('lastName' in request.body) {
if (!request.body.lastName) errors.push('lastName cannot be empty');
}
if ('bio' in request.body) {
if (!request.body.bio) errors.push('bio cannot be empty');
}
if ('userName' in request.body) {
if (!request.body.userName) errors.push('userName cannot be empty');
}
if ('twitterHandle' in request.body) {
if (!request.body.twitterHandle) {
errors.push('twitterHandle cannot be empty');
}
}
if ('facebookHandle' in request.body) {
if (!request.body.facebookHandle) {
errors.push('facebookHandle cannot be empty');
}
}
if (errors.length > 0) {
return Helper.failResponse(response, 400, errors[0]);
}
const userInstance = await findUserById(request.user.id);
if (!userInstance) {
return Helper.failResponse(response, 404, {
message: 'User account does not exist'
});
}
if (Object.keys(request.body).length < 1) {
return Helper.failResponse(response, 400, {
message: 'Field(s) to update cannot be empty'
});
}

if (request.body.userName) {
const userNameExists = await findByUserName(request.body.userName);
Expand Down
2 changes: 1 addition & 1 deletion src/routes/v1/auth.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ router
.get('/logout', verifyToken, logout);

router.put(
'/profileupdate',
'/',
verifyToken,
upload.single('image'),
profileChecks,
Expand Down
2 changes: 2 additions & 0 deletions src/routes/v1/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import auth from './auth.route';
import users from './user.route';
import article from './article.route';
import profile from './profile.route';

export default app => {
app.use(`${process.env.API_VERSION}/users`, auth);
app.use(`${process.env.API_VERSION}/users/`, users);
app.use(`${process.env.API_VERSION}/articles/`, article);
app.use(`${process.env.API_VERSION}/profiles`, profile);
};
9 changes: 9 additions & 0 deletions src/routes/v1/profile.route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import express from 'express';
import userController from '../../controllers/user.controller';
import authorization from '../../middlewares/auth.middleware';

const { verifyToken } = authorization;
const { viewProfile } = userController;
const router = express.Router();
router.get('/:username', verifyToken, viewProfile);
export default router;
9 changes: 7 additions & 2 deletions src/services/article.service.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'fs';
import models from '../db/models';
import upload from '../helpers/image.helper';
import { upload } from '../helpers/image.helper';

const { Article, User } = models;
/** Istanbul ignore next */
Expand All @@ -18,7 +19,7 @@ export const createArticleService = async data => {

const uploadedImage = [];
const images = data.files;

const imagePaths = [];
const loopUpload = async image => {
// eslint-disable-next-line no-restricted-syntax
for (const imageItem of image) {
Expand All @@ -27,11 +28,15 @@ export const createArticleService = async data => {
// eslint-disable-next-line no-await-in-loop
const imageResponse = await upload(imagePath, imageUniqueName, 'post');
uploadedImage.push(imageResponse.secure_url);
imagePaths.push(imagePath);
}
};

if (images) {
await loopUpload(images);
imagePaths.forEach(path => {
fs.unlinkSync(path);
});
}
const finalUploads = JSON.stringify(Object.assign({}, uploadedImage));
const article = await Article.create({
Expand Down
34 changes: 33 additions & 1 deletion src/services/user.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,38 @@ export const getUserFollowersService = async userId => {
if (followers.length === 0) {
return 'User has no follower';
}

return followers;
};

/**
* Queries the database to get a user profile
* @method getUserProfile
* Route: GET profiles/:username
* @param {string} username
* @returns {object|boolean} response object or false if no user is found
*/

export const getUserProfile = async (username, id) => {
let isfollowing = false;
const user = await User.findOne({
where: { userName: username }
});
if (user) {
const follower = await Follow.findOne({
where: { friendUserId: user.dataValues.id, userId: id }
});
if (follower) {
isfollowing = follower.dataValues.isFollowing;
}
const response = {
firstName: user.dataValues.firstName,
lastName: user.dataValues.lastName,
userName: username,
bio: user.dataValues.bio,
image: user.dataValues.image,
following: isfollowing
};
return response;
}
return false;
};
Loading

0 comments on commit 9caa326

Please sign in to comment.