Skip to content

Commit

Permalink
Merge c7e0a70 into b866ecf
Browse files Browse the repository at this point in the history
  • Loading branch information
Rythae committed Aug 26, 2019
2 parents b866ecf + c7e0a70 commit d685ff8
Show file tree
Hide file tree
Showing 8 changed files with 318 additions and 10 deletions.
46 changes: 46 additions & 0 deletions docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,52 @@ paths:
type: string
example: error occured

/novels/:novelId/bookmarks:
post:
tags:
- Novels
summary: Bookmark Novels
requestBody:
description: User should be able to bookmark a novel
content:
application/json:
schema:
$ref: '#/components/schemas/NovelInput'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/NovelInput'
required: true
responses:
201:
description: Bookmark Novels
404:
description: Not found
500:
description: internal server error

/novels/bookmarks:
get:
tags:
- Novels
summary: Fetch Bookmarks
requestBody:
description: Bookmarks fetched successfully
content:
application/json:
schema:
$ref: '#/components/schemas/NovelInput'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/NovelInput'
required: true
responses:
201:
description: Bookmarks fetched successfully
404:
description: Not found
500:
description: internal server error

components:
schemas:
token:
Expand Down
67 changes: 65 additions & 2 deletions src/controllers/novelController.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ const {
} = helpers;
const { Novel } = models;
const {
novelServices: { addNovel, findGenre, findAllNovels },
novelServices: {
addNovel, findGenre, findAllNovels, findNovelById, bookmarkNovel, getAllBookmark
},
notificationServices: { addNotification }
} = services;

Expand Down Expand Up @@ -113,4 +115,65 @@ const createGenre = async (request, response) => {
}
};

export default { createNovel, getNovels, createGenre };
/**
* createBookmark
* @param {object} req
* @param {object} res
* @returns {object} json
*/

const postBookmark = async (req, res) => {
const { novelId } = req.params;
const {
id: userId
} = req.user;

try {
const novel = await findNovelById(novelId);
if (!novel) {
return responseMessage(res, 404, { error: 'novel not found' });
}

const newBookmark = await bookmarkNovel(userId, novel.id);
res.status(201).json({
bookmark: {
novelId: novel.id,
title: novel.title,
updatedAt: newBookmark.updatedAt
}
});
} catch (error) {
return responseMessage(res, 500, { error: error.message });
}
};

/**
* getAllBookmark
* @param {object} req
* @param {object} res
* @returns {object} json
*/

const fetchBookmarks = async (req, res) => {
const {
id: userId
} = req.user;

try {
const bookmarks = await getAllBookmark(userId);
return successResponse(res, 201, {
message: 'Bookmarks fetched successfully',
bookmarks
});
} catch (error) {
return responseMessage(res, 500, { error: error.message });
}
};

export default {
createNovel,
getNovels,
postBookmark,
fetchBookmarks,
createGenre
};
32 changes: 32 additions & 0 deletions src/database/migrations/20190812055421-create-bookmark.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export const up = (queryInterface, Sequelize) => queryInterface.createTable('Bookmarks', {
id: {
allowNull: false,
primaryKey: true,
type: Sequelize.UUID,
},
userId: {
allowNull: false,
type: Sequelize.UUID,
references: {
model: 'Users',
key: 'id'
},
},
novelId: {
allowNull: true,
type: Sequelize.UUID,
references: {
model: 'Novels',
key: 'id'
},
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
export const down = queryInterface => queryInterface.dropTable('Bookmarks');
30 changes: 30 additions & 0 deletions src/database/models/bookmark.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export default (sequelize, DataTypes) => {
const Bookmark = sequelize.define('Bookmark', {
id: {
allowNull: false,
primaryKey: true,
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
},
userId: {
allowNull: false,
type: DataTypes.UUID
},
novelId: {
allowNull: false,
type: DataTypes.UUID
}
}, {});
Bookmark.associate = (models) => {
Bookmark.belongsTo(models.User, {
foreignKey: 'userId',
onDelete: 'CASCADE'
});

Bookmark.belongsTo(models.Novel, {
foreignKey: 'novelId',
onDelete: 'CASCADE'
});
};
return Bookmark;
};
5 changes: 5 additions & 0 deletions src/database/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ export default (Sequelize, DataTypes) => {
foreignKey: 'userId',
onDelete: 'CASCADE'
});

User.hasMany(models.Bookmark, {
foreignKey: 'userId',
onDelete: 'CASCADE'
});
};
return User;
};
10 changes: 8 additions & 2 deletions src/routes/novel.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ const {
createNovelValidator, getNovelValidator, genreValidator
},
verifyToken,
authorizeUser
authorizeUser,
} = middlewares;
const { createNovel, getNovels, createGenre } = novelController;
const {
createNovel, getNovels, createGenre, postBookmark, fetchBookmarks
} = novelController;

// Route to create a novel
novel.post(`${NOVEL_URL}`, verifyToken, authorizeUser(['author', 'admin', 'superadmin']), createNovelValidator, createNovel);
Expand All @@ -24,6 +26,10 @@ novel.post(`${NOVEL_URL}/:slug/like`, verifyToken, authorizeUser(['author', 'adm
// Route to create a genre
novel.post('/genres', verifyToken, authorizeUser(['author', 'admin', 'superadmin']), genreValidator, createGenre);


novel.post(`${NOVEL_URL}/:novelId/bookmarks`, verifyToken, postBookmark);
novel.get(`${NOVEL_URL}/bookmarks`, verifyToken, fetchBookmarks);

// Route to get novels
novel.get(`${NOVEL_URL}`, verifyToken, getNovelValidator, getNovels);

Expand Down
54 changes: 49 additions & 5 deletions src/services/novelService.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Op } from 'sequelize';
import models from '../database/models';

const {
Genre, Novel, Like
User, Genre, Novel, Like, Bookmark
} = models;

/**
Expand All @@ -18,6 +18,16 @@ const findNovel = async (param) => {
return novel;
};

/**
* Finds a novel from the database by id
* @param {string} param
* @returns {object} a novel object
*/

const findNovelById = param => Novel.findOne({
where: { id: param }
});

/**
* Finds a novelLikes from the database by userid and novelId
* @param {string} userId
Expand All @@ -44,6 +54,38 @@ const removeNovelLike = (userId, novelId) => Like.destroy({
}
});

/**
*
*
* @param {string} userId
* @param {string} novelId
* @returns {object} json
*/
const bookmarkNovel = async (userId, novelId) => {
const createBookmark = await Bookmark.create({
userId,
novelId
});
return {
novelId: createBookmark.novelId,
title: createBookmark.title,
updatedAt: createBookmark.updatedAt
};
};

/**
*
*
* @param {string} userId
* @returns {object} json
*/
const getAllBookmark = async (userId) => {
const bookmarks = await Bookmark.findAll({
where: { userId }
});
return bookmarks;
};

/**
*
*
Expand Down Expand Up @@ -93,14 +135,13 @@ const addNovel = async (novel, author) => {
*
* @param {object} offset
* @param {object} limit
* @param {object} queryFilter
* @returns {object} json
*/
const findAllNovels = async (offset, limit, queryFilter) => {
const findAllNovels = async (offset, limit) => {
const novels = await Novel.findAll({
offset,
limit,
...queryFilter
include: [{ model: User }, { model: Genre }]
});
return novels;
};
Expand All @@ -120,7 +161,10 @@ export default {
findGenre,
findNovel,
addNovel,
findNovelById,
findNovelLike,
removeNovelLike,
findAllNovels
findAllNovels,
bookmarkNovel,
getAllBookmark
};
Loading

0 comments on commit d685ff8

Please sign in to comment.