Skip to content

Commit

Permalink
Merge b80c479 into daf7dc0
Browse files Browse the repository at this point in the history
  • Loading branch information
phembarl authored Jul 9, 2019
2 parents daf7dc0 + b80c479 commit ff302ea
Show file tree
Hide file tree
Showing 29 changed files with 3,686 additions and 102 deletions.
279 changes: 216 additions & 63 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "server.js",
"scripts": {
"build": "babel src -d lib",
"test": "mocha --timeout 50000 --require @babel/register --exit",
"test": "NODE_ENV=test nyc mocha --timeout 50000 --require @babel/register --exit",
"generate-lcov": "nyc report --reporter=text-lcov > lcov.info",
"coveralls-coverage": "coveralls < lcov.info",
"coverage": "nyc npm test && npm run generate-lcov && npm run coveralls-coverage",
Expand All @@ -28,13 +28,16 @@
"@babel/register": "^7.4.0",
"chai": "^4.2.0",
"chai-http": "^4.3.0",
"cloudinary": "^1.14.0",
"cors": "^2.8.4",
"dotenv": "^6.2.0",
"ejs": "^2.6.1",
"errorhandler": "^1.5.0",
"express": "^4.16.3",
"express-jwt": "^5.3.1",
"express-session": "^1.15.6",
"express-validator": "^6.1.1",
"file-type": "^12.0.1",
"jsonwebtoken": "^8.3.0",
"method-override": "^2.3.10",
"methods": "^1.1.2",
Expand All @@ -47,6 +50,8 @@
"passport-github": "^1.1.0",
"passport-google-oauth20": "^2.0.0",
"passport-twitter": "^1.0.4",
"multer": "^1.4.1",
"multer-storage-cloudinary": "^2.2.1",
"passport": "^0.4.0",
"passport-local": "^1.0.0",
"pg": "^7.11.0",
Expand Down
31 changes: 19 additions & 12 deletions src/controllers/Auth.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import auth from '../middleware/Auth';
import { Blacklist, User } from '../db/models';
/**
*
*
* @class AuthController
*/
class AuthController {
/**
*
*@description logs in autheticated user
* @static
* @param {object} req
* @param {object} res
*@description logs in autheticated user
* @param {object} req the request body
* @param {object} res the response body
* @returns {object} res
* @memberof AuthController
*/
Expand All @@ -22,6 +19,13 @@ class AuthController {
where: { email },
attributes: { exclude: ['password'] }
});

if (!user) {
return res.status(404).json({
status: 400,
error: 'User not found',
});
}
const { id } = user;
const userToken = auth.authenticate(id);
if (user) {
Expand All @@ -31,22 +35,25 @@ class AuthController {
data: userToken
});
}
return res.status(404).json({
status: 404,
message: 'User Not Found',
});
} catch (error) {
return res.status(500).json({
status: 500,
message: error,
message: error.message,
});
}
}

/**
*
*@static
*@description Logout a user
* @static
* @param {object} req
* @param {object} res
* @param {object} req the request body
* @param {object} res the response body
* @returns {object} res
* @memberof UserController
* @memberof AuthController
*/
static async logOut(req, res) {
const { token } = req.headers || req.body || req.query;
Expand Down
50 changes: 50 additions & 0 deletions src/controllers/likeController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Article, Like } from '../db/models';

/**
*@description This class handles all like requests
* @class LikeController
*/
class LikeController {
/**
*@description This function allows a user to like articles
* @static
* @param {object} req the request body
* @param {object} res the response body
* @returns {object} res
* @memberof LikeController
*/
static async likeArticle(req, res) {
const { slug } = req.params;
const userId = req.user;

try {
const article = await Article.findOne({
attributes: ['id', 'slug', 'body',
'tagList'],
where: { slug },
});

if (!article) {
return res.status(404).json({
status: 404,
error: 'Article not found',
});
}

await Like.create({ userId, articleId: article.id });

return res.status(201).json({
status: 201,
data: article,
message: 'You just liked this article',
});
} catch (error) {
return res.status(500).json({
status: 500,
error: error.message,
});
}
}
}

export default LikeController;
1 change: 0 additions & 1 deletion src/controllers/socialController.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ export default class socialController {
bio,
image
}

});
} catch (err) {
return res.status(500).json({
Expand Down
111 changes: 111 additions & 0 deletions src/controllers/userController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { User } from '../db/models';

/**
* @description This class handles user requests
* @class UserController
*/
class UserController {
/**
* @static
* @description this function gets all registered users
* @param {object} req the request body
* @param {object} res the response body
* @returns {object} res
* @memberof UserController
*/
static async getUserProfile(req, res) {
const { userName } = req.params;

try {
const userData = await User.findOne({
attributes: ['firstName', 'lastName', 'userName',
'email', 'bio', 'imageUrl'],
where: { userName },
});

if (!userData) {
return res.status(404).json({
status: 404,
error: 'User not found',
});
}

return res.status(200).json({
status: 200,
users: userData,
});
} catch (error) {
return res.status(500).json({
status: 500,
error: error.message
});
}
}

/**
*@static
*@description this function creates and updates user profile
* @param {object} req the request body
* @param {object} res the response body
* @returns {object} res
* @memberof UserController
*/
static async updateProfile(req, res) {
try {
const {
firstName, lastName, userName, bio,
} = req.body;

const avatar = req.file;
const userId = req.user;
let { id } = req.params;
id = Number(id);

let avatarValue;

if (avatar) avatarValue = avatar.url;

const userDetails = {
firstName,
lastName,
userName,
bio,
imageUrl: avatarValue,
};

const where = {
id,
};

const attributes = ['id', 'firstName', 'lastName', 'userName', 'bio', 'imageUrl'];

const userData = await User.findOne({ attributes, where });

if (id === userId) {
await userData.update(userDetails, { where });

return res.status(200).json({
status: 200,
user: userDetails,
});
}
return res.status(401).json({
status: 401,
error: 'You do not have permission to perform that operation',
});
} catch (error) {
if (error.routine === '_bt_check_unique') {
return res.status(400).json({
status: 400,
error: 'User with that username already exists',
});
}
return res.status(500).json({
status: 500,
error: error.message,
});
}
}
}

export default UserController;
14 changes: 11 additions & 3 deletions src/db/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,29 @@ module.exports = {
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE_DBNAME,
host: process.env.DATABASE_HOST,
dialect: 'postgres'
dialect: 'postgres',
logging: false,
},
test: {
username: process.env.TEST_DB_USERNAME,
password: process.env.TEST_DB_PASSWORD,
database: process.env.TEST_DB_DBNAME,
host: process.env.TEST_DB_HOST,
dialect: 'postgres'
dialect: 'postgres',
logging: false,
},
production: {
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE_DBNAME,
host: process.env.DATABASE_HOST,
dialect: 'postgres'
dialect: 'postgres',
logging: false,
},
cloudinaryConfig: {
cloud_name: process.env.CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_SECRET,
},
googleConfig: {
clientID: process.env.GOOGLE_CLIENT_ID,
Expand Down
4 changes: 1 addition & 3 deletions src/db/migrations/20190701212849-create-blacklist.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,5 @@ module.exports = {
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Blacklists');
}
down: (queryInterface, Sequelize) => queryInterface.dropTable('Blacklists'),
};
41 changes: 41 additions & 0 deletions src/db/migrations/20190709090055-create-like.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module.exports = {
up: (queryInterface, Sequelize) => queryInterface.createTable('Likes', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
userId: {
type: Sequelize.INTEGER,
required: true,
onUpdate: 'CASCADE',
onDelete: 'CASCADE',
references: {
model: 'Users',
key: 'id',
as: 'userId'
}
},
articleId: {
type: Sequelize.INTEGER,
required: true,
onUpdate: 'CASCADE',
onDelete: 'CASCADE',
references: {
model: 'Articles',
key: 'id',
as: 'articleId'
}
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
}),
down: (queryInterface, Sequelize) => queryInterface.dropTable('Likes'),
};
34 changes: 34 additions & 0 deletions src/db/migrations/20190709125502-create-tag.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module.exports = {
up: (queryInterface, Sequelize) => queryInterface.createTable('Tags', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
tagName: {
type: Sequelize.STRING
},
articleId: {
type: Sequelize.INTEGER,
allowNull: false,
required: true,
references: {
model: 'Articles',
key: 'id',
as: 'article'
},
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
}
}),
down: (queryInterface, Sequelize) => queryInterface.dropTable('Tags')
};
Loading

0 comments on commit ff302ea

Please sign in to comment.