-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
takuyadev
committed
Nov 5, 2022
1 parent
2025183
commit 47c6e0e
Showing
7 changed files
with
218 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
const Courses = require('../model/Courses') | ||
const Review = require('../model/Review') | ||
const asyncHandler = require('../middleware/async'); | ||
const ErrorResponse = require('../utils/errorResponse'); | ||
const Bootcamp = require('../model/Bootcamp'); | ||
|
||
|
||
// @desc Get all reviews | ||
// @route GET /api/v1/reviews | ||
// @route GET /api/v1/bootcamps/:bootcampId/reviews | ||
// @access Public | ||
exports.getReviews = asyncHandler(async (req, res, next) => { | ||
|
||
// If parameter is filled out | ||
if (req.params.bootcampId) { | ||
const reviews = await Review.find({ bootcamp: req.params.bootcampId }) | ||
return res.status(200).json({ | ||
success: true, | ||
count: reviews.length, | ||
data: reviews | ||
}) | ||
} else { | ||
res.status(200).json(res.advancedResults) | ||
} | ||
}) | ||
|
||
|
||
// @desc Get single review | ||
// @route GET /api/v1/reviews/:id | ||
// @access Public | ||
exports.getReview = asyncHandler(async (req, res, next) => { | ||
const review = await Review.findById(req.params.id).populate({ | ||
path: 'bootcamp', | ||
select: 'name description' | ||
}) | ||
|
||
if (!review) { | ||
return next(new ErrorResponse(`No review found with the id of ${req.params.id}.`), 404) | ||
} | ||
res.status(200).json({ | ||
success: true, | ||
data: review | ||
}) | ||
}) | ||
|
||
// @desc Create review | ||
// @route POST /api/v1/reviews | ||
// @access Private | ||
exports.addReview = asyncHandler(async (req, res, next) => { | ||
req.body.bootcamp = req.params.bootcampId | ||
req.body.user = req.user.id; | ||
|
||
const bootcamp = await Bootcamp.findById(req.params.bootcampId) | ||
|
||
if (!bootcamp) { | ||
return next(new ErrorResponse(`No not bootcamp with the id of ${req.params.bootcampId}.`), 404) | ||
} | ||
|
||
const review = await Review.create(req.body) | ||
|
||
res.status(201).json({ | ||
success: true, | ||
data: review | ||
}) | ||
}) | ||
|
||
// @desc Update review | ||
// @route PUT /api/v1/reviews/:id | ||
// @access Private | ||
exports.updateReview = asyncHandler(async (req, res, next) => { | ||
|
||
let review = await Review.findById(req.params.id) | ||
|
||
if (!review) { | ||
return next(new ErrorResponse(`No review found with the id of ${req.params.id}.`), 404) | ||
} | ||
|
||
// Make sure review belongs to user or user is admin | ||
if (review.user.toString() !== req.user.id && req.user.role !== 'admin') { | ||
return next(new ErrorResponse(`Not authorized to update review`), 401) | ||
|
||
} | ||
|
||
review = await Review.findByIdAndUpdate(req.params.id, req.body, { | ||
new: true, | ||
runValidators: true | ||
}) | ||
|
||
res.status(200).json({ | ||
success: true, | ||
data: review | ||
}) | ||
}) | ||
|
||
// @desc Delete Review | ||
// @route DELETE /api/v1/reviews/:id | ||
// @access Private | ||
exports.deleteReview = asyncHandler(async (req, res, next) => { | ||
|
||
let review = await Review.findById(req.params.id) | ||
|
||
if (!review) { | ||
return next(new ErrorResponse(`No review found with the id of ${req.params.id}.`), 404) | ||
} | ||
|
||
// Make sure review belongs to user or user is admin | ||
if (review.user.toString() !== req.user.id && req.user.role !== 'admin') { | ||
return next(new ErrorResponse(`Not authorized to update review`), 401) | ||
} | ||
|
||
await review.remove() | ||
|
||
res.status(200).json({ | ||
success: true, | ||
data: {} | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
const mongoose = require('mongoose') | ||
|
||
const ReviewSchema = new mongoose.Schema({ | ||
title: { | ||
type: String, | ||
trim: true, | ||
required: [true, 'Please add a title for the review'], | ||
maxlength: 100 | ||
}, | ||
text: { | ||
type: String, | ||
required: [true, 'Please add some text'] | ||
}, | ||
rating: { | ||
type: Number, | ||
min: 1, | ||
max: 10, | ||
required: [true, "Please add a review rating"] | ||
}, | ||
bootcamp: { | ||
type: mongoose.Schema.ObjectId, | ||
// Reference to Schema, not database | ||
ref: 'Bootcamp', | ||
required: true | ||
}, | ||
user: { | ||
type: mongoose.Schema.ObjectId, | ||
// Reference to Schema, not database | ||
ref: 'User', | ||
required: true | ||
} | ||
}) | ||
|
||
ReviewSchema.index({ bootcamp: 1, user: 1 }, { unique: true }) | ||
|
||
// static method to get avg rating and save | ||
ReviewSchema.statics.getAverageRating = async function (bootcampId) { | ||
const obj = await this.aggregate( | ||
[ | ||
{ | ||
$match: { bootcamp: bootcampId } | ||
}, | ||
{ | ||
$group: { | ||
_id: '$bootcamp', | ||
averageRating: { $avg: '$rating' } | ||
} | ||
} | ||
] | ||
) | ||
try { | ||
await this.model('Bootcamp').findByIdAndUpdate(bootcampId, { | ||
averageRating: obj[0].averageRating | ||
}) | ||
} catch (err) { | ||
console.error(err) | ||
} | ||
} | ||
|
||
// Call getAverageRating after save | ||
ReviewSchema.post('save', async function () { | ||
await this.constructor.getAverageRating(this.bootcamp) | ||
}) | ||
|
||
// Call getAverageRating before remove | ||
ReviewSchema.pre('remove', async function () { | ||
await this.constructor.getAverageRating(this.bootcamp) | ||
}) | ||
|
||
|
||
module.exports = mongoose.model('Review', ReviewSchema) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
const express = require('express') | ||
const { getReviews, getReview, addReview, updateReview, deleteReview } = require('../controllers/reviews') | ||
const router = express.Router({ mergeParams: true }); | ||
|
||
const Review = require('../model/Review') | ||
const advancedResults = require('../middleware/advancedResults') | ||
const { protect, authorize } = require('../middleware/auth') | ||
|
||
router.route('/') | ||
.get(advancedResults(Review, { | ||
path: 'bootcamp', | ||
select: 'name description' | ||
}), getReviews) | ||
.post(protect, authorize('user', 'admin'), addReview) | ||
|
||
router.route('/:id') | ||
.get(getReview) | ||
.put(protect, authorize("user", "admin"), updateReview) | ||
.delete(protect, authorize("user", "admin"), deleteReview) | ||
|
||
module.exports = router |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters