aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/lib/moderation.ts4
-rw-r--r--server/middlewares/validators/videos/video-comments.ts5
-rw-r--r--server/tests/external-plugins/akismet.ts131
-rw-r--r--server/tests/external-plugins/index.ts1
4 files changed, 138 insertions, 3 deletions
diff --git a/server/lib/moderation.ts b/server/lib/moderation.ts
index 43c58c980..3cc92ca30 100644
--- a/server/lib/moderation.ts
+++ b/server/lib/moderation.ts
@@ -1,4 +1,4 @@
1import { VideoUploadFile } from 'express' 1import express, { VideoUploadFile } from 'express'
2import { PathLike } from 'fs-extra' 2import { PathLike } from 'fs-extra'
3import { Transaction } from 'sequelize/types' 3import { Transaction } from 'sequelize/types'
4import { AbuseAuditView, auditLoggerFactory } from '@server/helpers/audit-logger' 4import { AbuseAuditView, auditLoggerFactory } from '@server/helpers/audit-logger'
@@ -58,6 +58,7 @@ function isLocalLiveVideoAccepted (object: {
58 58
59// Stub function that can be filtered by plugins 59// Stub function that can be filtered by plugins
60function isLocalVideoThreadAccepted (_object: { 60function isLocalVideoThreadAccepted (_object: {
61 req: express.Request
61 commentBody: VideoCommentCreate 62 commentBody: VideoCommentCreate
62 video: VideoModel 63 video: VideoModel
63 user: UserModel 64 user: UserModel
@@ -67,6 +68,7 @@ function isLocalVideoThreadAccepted (_object: {
67 68
68// Stub function that can be filtered by plugins 69// Stub function that can be filtered by plugins
69function isLocalVideoCommentReplyAccepted (_object: { 70function isLocalVideoCommentReplyAccepted (_object: {
71 req: express.Request
70 commentBody: VideoCommentCreate 72 commentBody: VideoCommentCreate
71 parentComment: VideoCommentModel 73 parentComment: VideoCommentModel
72 video: VideoModel 74 video: VideoModel
diff --git a/server/middlewares/validators/videos/video-comments.ts b/server/middlewares/validators/videos/video-comments.ts
index 69062701b..133feb7bd 100644
--- a/server/middlewares/validators/videos/video-comments.ts
+++ b/server/middlewares/validators/videos/video-comments.ts
@@ -208,7 +208,8 @@ async function isVideoCommentAccepted (req: express.Request, res: express.Respon
208 const acceptParameters = { 208 const acceptParameters = {
209 video, 209 video,
210 commentBody: req.body, 210 commentBody: req.body,
211 user: res.locals.oauth.token.User 211 user: res.locals.oauth.token.User,
212 req
212 } 213 }
213 214
214 let acceptedResult: AcceptResult 215 let acceptedResult: AcceptResult
@@ -234,7 +235,7 @@ async function isVideoCommentAccepted (req: express.Request, res: express.Respon
234 235
235 res.fail({ 236 res.fail({
236 status: HttpStatusCode.FORBIDDEN_403, 237 status: HttpStatusCode.FORBIDDEN_403,
237 message: acceptedResult?.errorMessage || 'Refused local comment' 238 message: acceptedResult?.errorMessage || 'Comment has been rejected.'
238 }) 239 })
239 return false 240 return false
240 } 241 }
diff --git a/server/tests/external-plugins/akismet.ts b/server/tests/external-plugins/akismet.ts
new file mode 100644
index 000000000..557fc3daf
--- /dev/null
+++ b/server/tests/external-plugins/akismet.ts
@@ -0,0 +1,131 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import { expect } from 'chai'
4import { HttpStatusCode } from '@shared/models'
5import {
6 cleanupTests,
7 createMultipleServers,
8 doubleFollow,
9 PeerTubeServer,
10 setAccessTokensToServers,
11 waitJobs
12} from '@shared/server-commands'
13
14describe('Official plugin Akismet', function () {
15 let servers: PeerTubeServer[]
16 let videoUUID: string
17
18 before(async function () {
19 this.timeout(30000)
20
21 servers = await createMultipleServers(2)
22 await setAccessTokensToServers(servers)
23
24 await servers[0].plugins.install({ npmName: 'peertube-plugin-akismet' })
25
26 if (!process.env.AKISMET_KEY) throw new Error('Missing AKISMET_KEY from env')
27
28 await servers[0].plugins.updateSettings({
29 npmName: 'peertube-plugin-akismet',
30 settings: {
31 'akismet-api-key': process.env.AKISMET_KEY
32 }
33 })
34
35 await doubleFollow(servers[0], servers[1])
36 })
37
38 describe('Local threads/replies', function () {
39
40 before(async function () {
41 const { uuid } = await servers[0].videos.quickUpload({ name: 'video 1' })
42 videoUUID = uuid
43 })
44
45 it('Should not detect a thread as spam', async function () {
46 await servers[0].comments.createThread({ videoId: videoUUID, text: 'comment' })
47 })
48
49 it('Should not detect a reply as spam', async function () {
50 await servers[0].comments.addReplyToLastThread({ text: 'reply' })
51 })
52
53 it('Should detect a thread as spam', async function () {
54 await servers[0].comments.createThread({
55 videoId: videoUUID,
56 text: 'akismet-guaranteed-spam',
57 expectedStatus: HttpStatusCode.FORBIDDEN_403
58 })
59 })
60
61 it('Should detect a thread as spam', async function () {
62 await servers[0].comments.createThread({ videoId: videoUUID, text: 'comment' })
63 await servers[0].comments.addReplyToLastThread({ text: 'akismet-guaranteed-spam', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
64 })
65 })
66
67 describe('Remote threads/replies', function () {
68
69 before(async function () {
70 this.timeout(60000)
71
72 const { uuid } = await servers[0].videos.quickUpload({ name: 'video 1' })
73 videoUUID = uuid
74 })
75
76 it('Should not detect a thread as spam', async function () {
77 this.timeout(30000)
78
79 await servers[1].comments.createThread({ videoId: videoUUID, text: 'remote comment 1' })
80 await waitJobs(servers)
81
82 const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
83 expect(data).to.have.lengthOf(1)
84 })
85
86 it('Should not detect a reply as spam', async function () {
87 this.timeout(30000)
88
89 await servers[1].comments.addReplyToLastThread({ text: 'I agree with you' })
90 await waitJobs(servers)
91
92 const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
93 expect(data).to.have.lengthOf(1)
94
95 const tree = await servers[0].comments.getThread({ videoId: videoUUID, threadId: data[0].id })
96 expect(tree.children).to.have.lengthOf(1)
97 })
98
99 it('Should detect a thread as spam', async function () {
100 this.timeout(30000)
101
102 await servers[1].comments.createThread({ videoId: videoUUID, text: 'akismet-guaranteed-spam' })
103 await waitJobs(servers)
104
105 const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
106 expect(data).to.have.lengthOf(1)
107 })
108
109 it('Should detect a thread as spam', async function () {
110 this.timeout(30000)
111
112 await servers[1].comments.createThread({ videoId: videoUUID, text: 'remote comment 2' })
113 await servers[1].comments.addReplyToLastThread({ text: 'akismet-guaranteed-spam' })
114 await waitJobs(servers)
115
116 const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
117 expect(data).to.have.lengthOf(2)
118
119 for (const thread of data) {
120 const tree = await servers[0].comments.getThread({ videoId: videoUUID, threadId: thread.id })
121 if (tree.comment.text === 'remote comment 1') continue
122
123 expect(tree.children).to.have.lengthOf(0)
124 }
125 })
126 })
127
128 after(async function () {
129 await cleanupTests(servers)
130 })
131})
diff --git a/server/tests/external-plugins/index.ts b/server/tests/external-plugins/index.ts
index 31d818b51..815bbf1da 100644
--- a/server/tests/external-plugins/index.ts
+++ b/server/tests/external-plugins/index.ts
@@ -1,3 +1,4 @@
1import './akismet'
1import './auth-ldap' 2import './auth-ldap'
2import './auto-block-videos' 3import './auto-block-videos'
3import './auto-mute' 4import './auto-mute'