From fde37dc99c0ca43021ac3d1b3537f095ee6114b7 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 5 May 2020 17:22:11 +0200 Subject: [PATCH] Add ability for video owners to delete comments --- .../comment/video-comment.component.ts | 1 + .../validators/videos/video-comments.ts | 17 ++++--- .../tests/api/check-params/video-comments.ts | 46 +++++++++++++++++-- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/client/src/app/videos/+video-watch/comment/video-comment.component.ts b/client/src/app/videos/+video-watch/comment/video-comment.component.ts index 1313b6585..868addd58 100644 --- a/client/src/app/videos/+video-watch/comment/video-comment.component.ts +++ b/client/src/app/videos/+video-watch/comment/video-comment.component.ts @@ -98,6 +98,7 @@ export class VideoCommentComponent implements OnInit, OnChanges { return this.comment.account && this.isUserLoggedIn() && ( this.user.account.id === this.comment.account.id || + this.user.account.id === this.video.account.id || this.user.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT) ) } diff --git a/server/middlewares/validators/videos/video-comments.ts b/server/middlewares/validators/videos/video-comments.ts index da2fafb10..8fa2d8561 100644 --- a/server/middlewares/validators/videos/video-comments.ts +++ b/server/middlewares/validators/videos/video-comments.ts @@ -9,8 +9,8 @@ import { areValidationErrors } from '../utils' import { Hooks } from '../../../lib/plugins/hooks' import { AcceptResult, isLocalVideoCommentReplyAccepted, isLocalVideoThreadAccepted } from '../../../lib/moderation' import { doesVideoExist } from '../../../helpers/middlewares' -import { MCommentOwner, MVideo, MVideoFullLight, MVideoId } from '../../../typings/models/video' -import { MUser } from '@server/typings/models' +import { MCommentOwner, MVideo, MVideoFullLight, MVideoId, MCommentOwnerVideoReply } from '../../../typings/models/video' +import { MUser, MUserAccountUrl } from '@server/typings/models' const listVideoCommentThreadsValidator = [ param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), @@ -188,7 +188,7 @@ function isVideoCommentsEnabled (video: MVideo, res: express.Response) { return true } -function checkUserCanDeleteVideoComment (user: MUser, videoComment: MCommentOwner, res: express.Response) { +function checkUserCanDeleteVideoComment (user: MUserAccountUrl, videoComment: MCommentOwnerVideoReply, res: express.Response) { if (videoComment.isDeleted()) { res.status(409) .json({ error: 'This comment is already deleted' }) @@ -196,11 +196,16 @@ function checkUserCanDeleteVideoComment (user: MUser, videoComment: MCommentOwne return false } - const account = videoComment.Account - if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT) === false && account.userId !== user.id) { + const userAccount = user.Account + + if ( + user.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT) === false && // Not a moderator + videoComment.accountId !== userAccount.id && // Not the comment owner + videoComment.Video.VideoChannel.accountId !== userAccount.id // Not the video owner + ) { res.status(403) .json({ error: 'Cannot remove video comment of another user' }) - .end() + return false } diff --git a/server/tests/api/check-params/video-comments.ts b/server/tests/api/check-params/video-comments.ts index 38f069503..181282ce1 100644 --- a/server/tests/api/check-params/video-comments.ts +++ b/server/tests/api/check-params/video-comments.ts @@ -29,6 +29,7 @@ describe('Test video comments API validator', function () { let server: ServerInfo let videoUUID: string let userAccessToken: string + let userAccessToken2: string let commentId: number // --------------------------------------------------------------- @@ -53,13 +54,16 @@ describe('Test video comments API validator', function () { } { - const user = { - username: 'user1', - password: 'my super password' - } + const user = { username: 'user1', password: 'my super password' } await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password }) userAccessToken = await userLogin(server, user) } + + { + const user = { username: 'user2', password: 'my super password' } + await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password }) + userAccessToken2 = await userLogin(server, user) + } }) describe('When listing video comment threads', function () { @@ -224,6 +228,40 @@ describe('Test video comments API validator', function () { await makeDeleteRequest({ url: server.url, path, token: server.accessToken, statusCodeExpected: 404 }) }) + it('Should succeed with the same user', async function () { + let commentToDelete: number + + { + const res = await addVideoCommentThread(server.url, userAccessToken, videoUUID, 'hello') + commentToDelete = res.body.comment.id + } + + const path = '/api/v1/videos/' + videoUUID + '/comments/' + commentToDelete + + await makeDeleteRequest({ url: server.url, path, token: userAccessToken2, statusCodeExpected: 403 }) + await makeDeleteRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 204 }) + }) + + it('Should succeed with the owner of the video', async function () { + let commentToDelete: number + let anotherVideoUUID: string + + { + const res = await uploadVideo(server.url, userAccessToken, { name: 'video' }) + anotherVideoUUID = res.body.video.uuid + } + + { + const res = await addVideoCommentThread(server.url, server.accessToken, anotherVideoUUID, 'hello') + commentToDelete = res.body.comment.id + } + + const path = '/api/v1/videos/' + anotherVideoUUID + '/comments/' + commentToDelete + + await makeDeleteRequest({ url: server.url, path, token: userAccessToken2, statusCodeExpected: 403 }) + await makeDeleteRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 204 }) + }) + it('Should succeed with the correct parameters', async function () { await makeDeleteRequest({ url: server.url, path: pathComment, token: server.accessToken, statusCodeExpected: 204 }) }) -- 2.25.1