Skip to content

Commit

Permalink
Merge 12b981c into 131cac1
Browse files Browse the repository at this point in the history
  • Loading branch information
rafmme committed Jan 30, 2019
2 parents 131cac1 + 12b981c commit ee7d1e4
Show file tree
Hide file tree
Showing 16 changed files with 452 additions and 26 deletions.
138 changes: 138 additions & 0 deletions server/controllers/TagController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import db from '../models';
import response from '../helpers/response';


const { FollowedTags, Tag } = db;

/**
* @class TagController
*/
class TagController {
/**
* @static
* @description a function that handles following of a tag by user
* @param {object} req HTTP request object
* @param {object} res HTTP response object
* @returns {object} api route response
*/
static async follow(req, res) {
try {
const { userId } = req.user;
const { tagName } = req.params;
const tag = await Tag.findOne({ where: { name: tagName } });

if (!tag) {
return response(res, 404, 'failure', `${tagName} tag does not exist`);
}

FollowedTags.findOrCreate({
where: { tagName, followerId: userId, tagId: tag.id },
attributes: ['id', 'tagId', 'tagName', 'followerId']
}).spread((follow, created) => {
if (created) {
return response(
res,
201,
'success',
`You are now following the ${tagName} tag`
);
}
return response(
res,
409,
'failure',
`You are already following the ${tagName} tag`
);
});
} catch (error) {
return response(
res,
500,
'failure',
'Something went wrong on the server'
);
}
}

/**
* @static
* @description a function that handles getting all tags a user is following
* @param {object} req HTTP request object
* @param {object} res HTTP response object
* @returns {object} api route response
*/
static async getFollowedTags(req, res) {
try {
const { userId } = req.user;
const followedTags = await FollowedTags.findAll({
where: { followerId: userId }
});

if (followedTags.length === 0) {
return response(res, 200, 'success', 'You are currenly not following any tag');
}

response(
res,
200,
'success',
'Tags you are following',
null,
followedTags
);
} catch (error) {
return response(
res,
500,
'failure',
'Something went wrong on the server'
);
}
}

/**
* @static
* @description a function that handles unfollowing a tag
* @param {object} req HTTP request object
* @param {object} res HTTP response object
* @returns {object} api route response
*/
static async unFollow(req, res) {
try {
const { tagName } = req.params;
const { userId } = req.user;
const tag = await Tag.findOne({
where: { name: tagName }
});

if (!tag) {
return response(res, 404, 'failure', `${tagName} tag does not exist`);
}

const followingTag = await FollowedTags.findOne({
where: { followerId: userId, tagName }
});

if (!followingTag) {
return response(
res,
400,
'failure',
`You are not following the ${tagName} tag`
);
}

followingTag.destroy();
response(res, 200, 'success', `You have now unfollowed the ${tagName} tag`);
} catch (error) {
return response(
res,
500,
'failure',
'Something went wrong on the server'
);
}
}
}

export default TagController;
18 changes: 7 additions & 11 deletions server/controllers/UserController.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ class UserController {
}
});
} catch (err) {
res.status(400).send({
return res.status(400).send({
status: 'failure',
data: {
statusCode: 400,
Expand Down Expand Up @@ -250,7 +250,7 @@ class UserController {
}
});
} catch (err) {
res.status(400).send({
return res.status(400).send({
status: 'failure',
data: {
error: err
Expand Down Expand Up @@ -448,41 +448,37 @@ class UserController {
});

if (!findProfile) {
response(res, 404, 'failure', 'User not found');
return;
return response(res, 404, 'failure', 'User not found');
}

const checkUserName = await User.findAndCountAll({
where: { userName: req.body.userName }
});

if (checkUserName.count > 0) {
response(res, 409, 'failure', 'Username already exists');
return;
return response(res, 409, 'failure', 'Username already exists');
}

if (req.user.authTypeId === '15745c60-7b1a-11e8-9c9c-2d42b21b1a3e') {
await findProfile.update(req.body, {
fields: [...editableFeilds, 'passsword']
});
response(res, 200, 'success', 'Profile updated successfully');
return;
return response(res, 200, 'success', 'Profile updated successfully');
}

const updatedProfile = await findProfile.update(req.body, {
fields: [...editableFeilds]
});
response(
return response(
res,
200,
'success',
'Profile updated successfully',
null,
updatedProfile.dataValues
);
return;
} catch (error) {
response(res, 500, 'failure', 'An error occured on the server');
return response(res, 500, 'failure', 'An error occured on the server');
}
}

Expand Down
8 changes: 4 additions & 4 deletions server/middlewares/AuthMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ class AuthMiddleware {
} catch (error) {
const { name } = error;
if (name === 'TokenExpiredError' || name === 'JsonWebTokenError') {
return response(res, 401, 'failure', 'You need to log in again');
return response(res, 401, 'failure', 'You need to log in again.');
}

return response(res, 500, 'failure', 'An error occured on the server', error.message);
}
}
Expand All @@ -60,6 +59,7 @@ class AuthMiddleware {
} catch (error) {
req.isLoggedIn = false;
next();
return response(res, 500, 'failure', 'An error occured on the server');
}
}

Expand Down Expand Up @@ -93,7 +93,7 @@ class AuthMiddleware {
} catch (error) {
const { name } = error;
if (name === 'TokenExpiredError' || name === 'JsonWebTokenError') {
return response(res, 401, 'failure', 'You need to log in again');
return response(res, 401, 'failure', 'You need to log in again.');
}

return response(res, 500, 'failure', 'An error occured on the server', error);
Expand Down Expand Up @@ -129,7 +129,7 @@ class AuthMiddleware {
} catch (error) {
const { name } = error;
if (name === 'TokenExpiredError' || name === 'JsonWebTokenError') {
return response(res, 401, 'failure', 'You need to log in again');
return response(res, 401, 'failure', 'You need to log in again.');
}

return response(res, 500, 'failure', 'An error occured on the server', error);
Expand Down
38 changes: 38 additions & 0 deletions server/migrations/20190130065911-create-user-followed-tags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export default {
up: (queryInterface, Sequelize) => {
return queryInterface.sequelize.query('CREATE EXTENSION IF NOT EXISTS "uuid-ossp";')
.then(() => {
return queryInterface.createTable('FollowedTags', {
id: {
allowNull: false,
primaryKey: true,
type: Sequelize.UUID,
defaultValue: Sequelize.literal('uuid_generate_v4()')
},
tagId: {
type: Sequelize.UUID,
allowNull: false
},
tagName: {
type: Sequelize.STRING,
allowNull: false
},
followerId: {
type: Sequelize.UUID,
allowNull: false
},
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('FollowedTags')
};
32 changes: 32 additions & 0 deletions server/models/followedTags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module.exports = (sequelize, DataTypes) => {
const FollowedTags = sequelize.define(
'FollowedTags',
{
tagId: {
type: DataTypes.UUID,
allowNull: false
},
tagName: {
type: DataTypes.STRING,
allowNull: false,
},
followerId: {
type: DataTypes.UUID,
allowNull: false
}
},
{}
);
FollowedTags.associate = (models) => {
const { Tag, User } = models;
FollowedTags.belongsTo(Tag, {
foreignKey: 'tagId',
onDelete: 'CASCADE'
});
FollowedTags.belongsTo(User, {
foreignKey: 'followerId',
onDelete: 'CASCADE'
});
};
return FollowedTags;
};
7 changes: 6 additions & 1 deletion server/models/tag.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ module.exports = (sequelize, DataTypes) => {
{}
);
Tag.associate = (models) => {
Tag.belongsToMany(models.Article, {
const { Article, User } = models;
Tag.belongsToMany(Article, {
through: 'ArticleTag',
as: 'articles',
foreignKey: 'tagId'
});
Tag.belongsToMany(User, {
through: 'FollowedTags',
foreignKey: 'tagId'
});
};
return Tag;
};
8 changes: 7 additions & 1 deletion server/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ export default (sequelize, DataTypes) => {
Role,
Report,
ArticleLikesDislike,
ReadingStats
ReadingStats,
Tag
} = models;
User.hasMany(Article, {
as: 'articles',
Expand Down Expand Up @@ -155,6 +156,11 @@ export default (sequelize, DataTypes) => {
User.hasMany(ReadingStats, {
foreignKey: 'userId'
});
User.belongsToMany(Tag, {
through: 'FollowedTags',
as: 'followedTags',
foreignKey: 'followerId'
});
};
return User;
};
1 change: 1 addition & 0 deletions server/routes/api/article.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import AuthMiddleware from '../../middlewares/AuthMiddleware';
import FollowFeedContoller from '../../controllers/FollowFeedController';



const articleRoutes = Router();
articleRoutes.get('/search', ArticleController.search);
articleRoutes.post(
Expand Down
26 changes: 26 additions & 0 deletions server/routes/api/tag.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Router } from 'express';
import TagController from '../../controllers/TagController';
import AuthMiddleware from '../../middlewares/AuthMiddleware';


const tagRoutes = Router();

tagRoutes.post(
'/tags/:tagName/follow',
AuthMiddleware.checkIfUserIsAuthenticated,
TagController.follow
);

tagRoutes.delete(
'/tags/:tagName/unfollow',
AuthMiddleware.checkIfUserIsAuthenticated,
TagController.unFollow
);

tagRoutes.get(
'/tags/followedTags',
AuthMiddleware.checkIfUserIsAuthenticated,
TagController.getFollowedTags
);

export default tagRoutes;
Loading

0 comments on commit ee7d1e4

Please sign in to comment.