aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2020-05-07 14:58:24 +0200
committerChocobozzz <me@florianbigard.com>2020-05-07 15:07:01 +0200
commit80fdaf064562aff968f4c9cea1cf220bc12a70da (patch)
treea0ec49f433b828660f741b394dfd87056cd2c6ef
parent3cc665f48fd233d09f778d7e887488dde6f03ef6 (diff)
downloadPeerTube-80fdaf064562aff968f4c9cea1cf220bc12a70da.tar.gz
PeerTube-80fdaf064562aff968f4c9cea1cf220bc12a70da.tar.zst
PeerTube-80fdaf064562aff968f4c9cea1cf220bc12a70da.zip
Add moderation helpers to plugins
-rw-r--r--scripts/create-import-video-file-job.ts2
-rwxr-xr-xscripts/create-transcoding-job.ts2
-rw-r--r--scripts/danger/clean/cleaner.ts2
-rw-r--r--scripts/migrations/peertube-2.1.ts2
-rw-r--r--scripts/optimize-old-videos.ts2
-rwxr-xr-xscripts/prune-storage.ts2
-rwxr-xr-xscripts/reset-password.ts2
-rwxr-xr-xscripts/update-host.ts2
-rw-r--r--server.ts2
-rw-r--r--server/controllers/api/users/my-history.ts2
-rw-r--r--server/controllers/api/videos/abuse.ts2
-rw-r--r--server/controllers/api/videos/blacklist.ts60
-rw-r--r--server/controllers/api/videos/comment.ts2
-rw-r--r--server/controllers/api/videos/ownership.ts2
-rw-r--r--server/initializers/index.ts3
-rw-r--r--server/lib/activitypub/process/process-announce.ts2
-rw-r--r--server/lib/activitypub/process/process-create.ts2
-rw-r--r--server/lib/activitypub/process/process-delete.ts2
-rw-r--r--server/lib/activitypub/process/process-dislike.ts2
-rw-r--r--server/lib/activitypub/process/process-flag.ts2
-rw-r--r--server/lib/activitypub/process/process-follow.ts2
-rw-r--r--server/lib/activitypub/process/process-like.ts2
-rw-r--r--server/lib/activitypub/process/process-reject.ts2
-rw-r--r--server/lib/activitypub/process/process-undo.ts2
-rw-r--r--server/lib/activitypub/process/process-update.ts2
-rw-r--r--server/lib/blocklist.ts4
-rw-r--r--server/lib/job-queue/handlers/video-transcoding.ts2
-rw-r--r--server/lib/plugins/plugin-helpers.ts78
-rw-r--r--server/lib/video-blacklist.ts80
-rw-r--r--server/middlewares/validators/blocklist.ts5
-rw-r--r--server/models/server/server.ts7
-rw-r--r--server/tests/fixtures/peertube-plugin-test-four/main.js107
-rw-r--r--server/tests/plugins/plugin-helpers.ts204
-rw-r--r--server/typings/plugins/register-server-option.model.ts38
34 files changed, 484 insertions, 150 deletions
diff --git a/scripts/create-import-video-file-job.ts b/scripts/create-import-video-file-job.ts
index 37738ca40..d71e82c14 100644
--- a/scripts/create-import-video-file-job.ts
+++ b/scripts/create-import-video-file-job.ts
@@ -4,7 +4,7 @@ registerTSPaths()
4import * as program from 'commander' 4import * as program from 'commander'
5import { resolve } from 'path' 5import { resolve } from 'path'
6import { VideoModel } from '../server/models/video/video' 6import { VideoModel } from '../server/models/video/video'
7import { initDatabaseModels } from '../server/initializers' 7import { initDatabaseModels } from '../server/initializers/database'
8import { JobQueue } from '../server/lib/job-queue' 8import { JobQueue } from '../server/lib/job-queue'
9 9
10program 10program
diff --git a/scripts/create-transcoding-job.ts b/scripts/create-transcoding-job.ts
index 1312e8952..7ee0050e3 100755
--- a/scripts/create-transcoding-job.ts
+++ b/scripts/create-transcoding-job.ts
@@ -3,7 +3,7 @@ registerTSPaths()
3 3
4import * as program from 'commander' 4import * as program from 'commander'
5import { VideoModel } from '../server/models/video/video' 5import { VideoModel } from '../server/models/video/video'
6import { initDatabaseModels } from '../server/initializers' 6import { initDatabaseModels } from '../server/initializers/database'
7import { JobQueue } from '../server/lib/job-queue' 7import { JobQueue } from '../server/lib/job-queue'
8import { computeResolutionsToTranscode } from '@server/helpers/ffmpeg-utils' 8import { computeResolutionsToTranscode } from '@server/helpers/ffmpeg-utils'
9import { VideoTranscodingPayload } from '@shared/models' 9import { VideoTranscodingPayload } from '@shared/models'
diff --git a/scripts/danger/clean/cleaner.ts b/scripts/danger/clean/cleaner.ts
index ed35ef79f..2d5366a91 100644
--- a/scripts/danger/clean/cleaner.ts
+++ b/scripts/danger/clean/cleaner.ts
@@ -3,7 +3,7 @@ registerTSPaths()
3 3
4import * as Promise from 'bluebird' 4import * as Promise from 'bluebird'
5import * as rimraf from 'rimraf' 5import * as rimraf from 'rimraf'
6import { initDatabaseModels, sequelizeTypescript } from '../../../server/initializers' 6import { initDatabaseModels, sequelizeTypescript } from '../../../server/initializers/database'
7import { CONFIG } from '../../../server/initializers/config' 7import { CONFIG } from '../../../server/initializers/config'
8 8
9initDatabaseModels(true) 9initDatabaseModels(true)
diff --git a/scripts/migrations/peertube-2.1.ts b/scripts/migrations/peertube-2.1.ts
index 892497a88..e17e58166 100644
--- a/scripts/migrations/peertube-2.1.ts
+++ b/scripts/migrations/peertube-2.1.ts
@@ -1,7 +1,7 @@
1import { registerTSPaths } from '../../server/helpers/register-ts-paths' 1import { registerTSPaths } from '../../server/helpers/register-ts-paths'
2registerTSPaths() 2registerTSPaths()
3 3
4import { initDatabaseModels, sequelizeTypescript } from '../../server/initializers' 4import { initDatabaseModels, sequelizeTypescript } from '../../server/initializers/database'
5import * as Sequelize from 'sequelize' 5import * as Sequelize from 'sequelize'
6import { join } from 'path' 6import { join } from 'path'
7import { HLS_STREAMING_PLAYLIST_DIRECTORY, STATIC_PATHS, WEBSERVER } from '@server/initializers/constants' 7import { HLS_STREAMING_PLAYLIST_DIRECTORY, STATIC_PATHS, WEBSERVER } from '@server/initializers/constants'
diff --git a/scripts/optimize-old-videos.ts b/scripts/optimize-old-videos.ts
index a84845068..9595efd9c 100644
--- a/scripts/optimize-old-videos.ts
+++ b/scripts/optimize-old-videos.ts
@@ -6,7 +6,7 @@ import { getDurationFromVideoFile, getVideoFileBitrate, getVideoFileFPS, getVide
6import { getMaxBitrate } from '../shared/models/videos' 6import { getMaxBitrate } from '../shared/models/videos'
7import { VideoModel } from '../server/models/video/video' 7import { VideoModel } from '../server/models/video/video'
8import { optimizeOriginalVideofile } from '../server/lib/video-transcoding' 8import { optimizeOriginalVideofile } from '../server/lib/video-transcoding'
9import { initDatabaseModels } from '../server/initializers' 9import { initDatabaseModels } from '../server/initializers/database'
10import { basename, dirname } from 'path' 10import { basename, dirname } from 'path'
11import { copy, move, remove } from 'fs-extra' 11import { copy, move, remove } from 'fs-extra'
12import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' 12import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent'
diff --git a/scripts/prune-storage.ts b/scripts/prune-storage.ts
index fa3d81744..2b04e906d 100755
--- a/scripts/prune-storage.ts
+++ b/scripts/prune-storage.ts
@@ -5,7 +5,7 @@ import * as prompt from 'prompt'
5import { join } from 'path' 5import { join } from 'path'
6import { CONFIG } from '../server/initializers/config' 6import { CONFIG } from '../server/initializers/config'
7import { VideoModel } from '../server/models/video/video' 7import { VideoModel } from '../server/models/video/video'
8import { initDatabaseModels } from '../server/initializers' 8import { initDatabaseModels } from '../server/initializers/database'
9import { readdir, remove } from 'fs-extra' 9import { readdir, remove } from 'fs-extra'
10import { VideoRedundancyModel } from '../server/models/redundancy/video-redundancy' 10import { VideoRedundancyModel } from '../server/models/redundancy/video-redundancy'
11import * as Bluebird from 'bluebird' 11import * as Bluebird from 'bluebird'
diff --git a/scripts/reset-password.ts b/scripts/reset-password.ts
index 6126c3cd0..863537500 100755
--- a/scripts/reset-password.ts
+++ b/scripts/reset-password.ts
@@ -2,7 +2,7 @@ import { registerTSPaths } from '../server/helpers/register-ts-paths'
2registerTSPaths() 2registerTSPaths()
3 3
4import * as program from 'commander' 4import * as program from 'commander'
5import { initDatabaseModels } from '../server/initializers' 5import { initDatabaseModels } from '../server/initializers/database'
6import { UserModel } from '../server/models/account/user' 6import { UserModel } from '../server/models/account/user'
7import { isUserPasswordValid } from '../server/helpers/custom-validators/users' 7import { isUserPasswordValid } from '../server/helpers/custom-validators/users'
8 8
diff --git a/scripts/update-host.ts b/scripts/update-host.ts
index 7b07dea04..2efe326a2 100755
--- a/scripts/update-host.ts
+++ b/scripts/update-host.ts
@@ -17,7 +17,7 @@ import { VideoCommentModel } from '../server/models/video/video-comment'
17import { AccountModel } from '../server/models/account/account' 17import { AccountModel } from '../server/models/account/account'
18import { VideoChannelModel } from '../server/models/video/video-channel' 18import { VideoChannelModel } from '../server/models/video/video-channel'
19import { VideoStreamingPlaylistModel } from '../server/models/video/video-streaming-playlist' 19import { VideoStreamingPlaylistModel } from '../server/models/video/video-streaming-playlist'
20import { initDatabaseModels } from '../server/initializers' 20import { initDatabaseModels } from '../server/initializers/database'
21import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' 21import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent'
22import { getServerActor } from '@server/models/application/application' 22import { getServerActor } from '@server/models/application/application'
23 23
diff --git a/server.ts b/server.ts
index b14ebf623..e18e2be5c 100644
--- a/server.ts
+++ b/server.ts
@@ -84,7 +84,7 @@ migrate()
84loadLanguages() 84loadLanguages()
85 85
86// ----------- PeerTube modules ----------- 86// ----------- PeerTube modules -----------
87import { installApplication } from './server/initializers' 87import { installApplication } from './server/initializers/installer'
88import { Emailer } from './server/lib/emailer' 88import { Emailer } from './server/lib/emailer'
89import { JobQueue } from './server/lib/job-queue' 89import { JobQueue } from './server/lib/job-queue'
90import { VideosPreviewCache, VideosCaptionCache } from './server/lib/files-cache' 90import { VideosPreviewCache, VideosCaptionCache } from './server/lib/files-cache'
diff --git a/server/controllers/api/users/my-history.ts b/server/controllers/api/users/my-history.ts
index 4da1f3496..77a15e5fc 100644
--- a/server/controllers/api/users/my-history.ts
+++ b/server/controllers/api/users/my-history.ts
@@ -9,7 +9,7 @@ import {
9} from '../../../middlewares' 9} from '../../../middlewares'
10import { getFormattedObjects } from '../../../helpers/utils' 10import { getFormattedObjects } from '../../../helpers/utils'
11import { UserVideoHistoryModel } from '../../../models/account/user-video-history' 11import { UserVideoHistoryModel } from '../../../models/account/user-video-history'
12import { sequelizeTypescript } from '../../../initializers' 12import { sequelizeTypescript } from '../../../initializers/database'
13 13
14const myVideosHistoryRouter = express.Router() 14const myVideosHistoryRouter = express.Router()
15 15
diff --git a/server/controllers/api/videos/abuse.ts b/server/controllers/api/videos/abuse.ts
index 3fe7f7e51..bce50aefb 100644
--- a/server/controllers/api/videos/abuse.ts
+++ b/server/controllers/api/videos/abuse.ts
@@ -2,7 +2,7 @@ import * as express from 'express'
2import { UserRight, VideoAbuseCreate, VideoAbuseState } from '../../../../shared' 2import { UserRight, VideoAbuseCreate, VideoAbuseState } from '../../../../shared'
3import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
4import { getFormattedObjects } from '../../../helpers/utils' 4import { getFormattedObjects } from '../../../helpers/utils'
5import { sequelizeTypescript } from '../../../initializers' 5import { sequelizeTypescript } from '../../../initializers/database'
6import { 6import {
7 asyncMiddleware, 7 asyncMiddleware,
8 asyncRetryTransactionMiddleware, 8 asyncRetryTransactionMiddleware,
diff --git a/server/controllers/api/videos/blacklist.ts b/server/controllers/api/videos/blacklist.ts
index abd09387c..3b25ceea2 100644
--- a/server/controllers/api/videos/blacklist.ts
+++ b/server/controllers/api/videos/blacklist.ts
@@ -1,7 +1,9 @@
1import * as express from 'express' 1import * as express from 'express'
2import { UserRight, VideoBlacklistCreate, VideoBlacklistType } from '../../../../shared' 2import { blacklistVideo, unblacklistVideo } from '@server/lib/video-blacklist'
3import { UserRight, VideoBlacklistCreate } from '../../../../shared'
3import { logger } from '../../../helpers/logger' 4import { logger } from '../../../helpers/logger'
4import { getFormattedObjects } from '../../../helpers/utils' 5import { getFormattedObjects } from '../../../helpers/utils'
6import { sequelizeTypescript } from '../../../initializers/database'
5import { 7import {
6 asyncMiddleware, 8 asyncMiddleware,
7 authenticate, 9 authenticate,
@@ -16,11 +18,6 @@ import {
16 videosBlacklistUpdateValidator 18 videosBlacklistUpdateValidator
17} from '../../../middlewares' 19} from '../../../middlewares'
18import { VideoBlacklistModel } from '../../../models/video/video-blacklist' 20import { VideoBlacklistModel } from '../../../models/video/video-blacklist'
19import { sequelizeTypescript } from '../../../initializers'
20import { Notifier } from '../../../lib/notifier'
21import { sendDeleteVideo } from '../../../lib/activitypub/send'
22import { federateVideoIfNeeded } from '../../../lib/activitypub/videos'
23import { MVideoBlacklistVideo } from '@server/typings/models'
24 21
25const blacklistRouter = express.Router() 22const blacklistRouter = express.Router()
26 23
@@ -28,7 +25,7 @@ blacklistRouter.post('/:videoId/blacklist',
28 authenticate, 25 authenticate,
29 ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST), 26 ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST),
30 asyncMiddleware(videosBlacklistAddValidator), 27 asyncMiddleware(videosBlacklistAddValidator),
31 asyncMiddleware(addVideoToBlacklist) 28 asyncMiddleware(addVideoToBlacklistController)
32) 29)
33 30
34blacklistRouter.get('/blacklist', 31blacklistRouter.get('/blacklist',
@@ -64,29 +61,15 @@ export {
64 61
65// --------------------------------------------------------------------------- 62// ---------------------------------------------------------------------------
66 63
67async function addVideoToBlacklist (req: express.Request, res: express.Response) { 64async function addVideoToBlacklistController (req: express.Request, res: express.Response) {
68 const videoInstance = res.locals.videoAll 65 const videoInstance = res.locals.videoAll
69 const body: VideoBlacklistCreate = req.body 66 const body: VideoBlacklistCreate = req.body
70 67
71 const toCreate = { 68 await blacklistVideo(videoInstance, body)
72 videoId: videoInstance.id,
73 unfederated: body.unfederate === true,
74 reason: body.reason,
75 type: VideoBlacklistType.MANUAL
76 }
77
78 const blacklist: MVideoBlacklistVideo = await VideoBlacklistModel.create(toCreate)
79 blacklist.Video = videoInstance
80
81 if (body.unfederate === true) {
82 await sendDeleteVideo(videoInstance, undefined)
83 }
84
85 Notifier.Instance.notifyOnVideoBlacklist(blacklist)
86 69
87 logger.info('Video %s blacklisted.', videoInstance.uuid) 70 logger.info('Video %s blacklisted.', videoInstance.uuid)
88 71
89 return res.type('json').status(204).end() 72 return res.type('json').sendStatus(204)
90} 73}
91 74
92async function updateVideoBlacklistController (req: express.Request, res: express.Response) { 75async function updateVideoBlacklistController (req: express.Request, res: express.Response) {
@@ -98,7 +81,7 @@ async function updateVideoBlacklistController (req: express.Request, res: expres
98 return videoBlacklist.save({ transaction: t }) 81 return videoBlacklist.save({ transaction: t })
99 }) 82 })
100 83
101 return res.type('json').status(204).end() 84 return res.type('json').sendStatus(204)
102} 85}
103 86
104async function listBlacklist (req: express.Request, res: express.Response) { 87async function listBlacklist (req: express.Request, res: express.Response) {
@@ -117,32 +100,9 @@ async function removeVideoFromBlacklistController (req: express.Request, res: ex
117 const videoBlacklist = res.locals.videoBlacklist 100 const videoBlacklist = res.locals.videoBlacklist
118 const video = res.locals.videoAll 101 const video = res.locals.videoAll
119 102
120 const videoBlacklistType = await sequelizeTypescript.transaction(async t => { 103 await unblacklistVideo(videoBlacklist, video)
121 const unfederated = videoBlacklist.unfederated
122 const videoBlacklistType = videoBlacklist.type
123
124 await videoBlacklist.destroy({ transaction: t })
125 video.VideoBlacklist = undefined
126
127 // Re federate the video
128 if (unfederated === true) {
129 await federateVideoIfNeeded(video, true, t)
130 }
131
132 return videoBlacklistType
133 })
134
135 Notifier.Instance.notifyOnVideoUnblacklist(video)
136
137 if (videoBlacklistType === VideoBlacklistType.AUTO_BEFORE_PUBLISHED) {
138 Notifier.Instance.notifyOnVideoPublishedAfterRemovedFromAutoBlacklist(video)
139
140 // Delete on object so new video notifications will send
141 delete video.VideoBlacklist
142 Notifier.Instance.notifyOnNewVideoIfNeeded(video)
143 }
144 104
145 logger.info('Video %s removed from blacklist.', video.uuid) 105 logger.info('Video %s removed from blacklist.', video.uuid)
146 106
147 return res.type('json').status(204).end() 107 return res.type('json').sendStatus(204)
148} 108}
diff --git a/server/controllers/api/videos/comment.ts b/server/controllers/api/videos/comment.ts
index 5f3fed5c0..5070bb3c0 100644
--- a/server/controllers/api/videos/comment.ts
+++ b/server/controllers/api/videos/comment.ts
@@ -4,7 +4,7 @@ import { ResultList } from '../../../../shared/models'
4import { VideoCommentCreate } from '../../../../shared/models/videos/video-comment.model' 4import { VideoCommentCreate } from '../../../../shared/models/videos/video-comment.model'
5import { logger } from '../../../helpers/logger' 5import { logger } from '../../../helpers/logger'
6import { getFormattedObjects } from '../../../helpers/utils' 6import { getFormattedObjects } from '../../../helpers/utils'
7import { sequelizeTypescript } from '../../../initializers' 7import { sequelizeTypescript } from '../../../initializers/database'
8import { buildFormattedCommentTree, createVideoComment, markCommentAsDeleted } from '../../../lib/video-comment' 8import { buildFormattedCommentTree, createVideoComment, markCommentAsDeleted } from '../../../lib/video-comment'
9import { 9import {
10 asyncMiddleware, 10 asyncMiddleware,
diff --git a/server/controllers/api/videos/ownership.ts b/server/controllers/api/videos/ownership.ts
index 190036f85..540a49010 100644
--- a/server/controllers/api/videos/ownership.ts
+++ b/server/controllers/api/videos/ownership.ts
@@ -1,6 +1,6 @@
1import * as express from 'express' 1import * as express from 'express'
2import { logger } from '../../../helpers/logger' 2import { logger } from '../../../helpers/logger'
3import { sequelizeTypescript } from '../../../initializers' 3import { sequelizeTypescript } from '../../../initializers/database'
4import { 4import {
5 asyncMiddleware, 5 asyncMiddleware,
6 asyncRetryTransactionMiddleware, 6 asyncRetryTransactionMiddleware,
diff --git a/server/initializers/index.ts b/server/initializers/index.ts
deleted file mode 100644
index 0fc1a7363..000000000
--- a/server/initializers/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
1export * from './database'
2export * from './installer'
3export * from './migrator'
diff --git a/server/lib/activitypub/process/process-announce.ts b/server/lib/activitypub/process/process-announce.ts
index 7e22125d5..26427aaa1 100644
--- a/server/lib/activitypub/process/process-announce.ts
+++ b/server/lib/activitypub/process/process-announce.ts
@@ -1,6 +1,6 @@
1import { ActivityAnnounce } from '../../../../shared/models/activitypub' 1import { ActivityAnnounce } from '../../../../shared/models/activitypub'
2import { retryTransactionWrapper } from '../../../helpers/database-utils' 2import { retryTransactionWrapper } from '../../../helpers/database-utils'
3import { sequelizeTypescript } from '../../../initializers' 3import { sequelizeTypescript } from '../../../initializers/database'
4import { VideoShareModel } from '../../../models/video/video-share' 4import { VideoShareModel } from '../../../models/video/video-share'
5import { forwardVideoRelatedActivity } from '../send/utils' 5import { forwardVideoRelatedActivity } from '../send/utils'
6import { getOrCreateVideoAndAccountAndChannel } from '../videos' 6import { getOrCreateVideoAndAccountAndChannel } from '../videos'
diff --git a/server/lib/activitypub/process/process-create.ts b/server/lib/activitypub/process/process-create.ts
index d375e29e3..566bf6992 100644
--- a/server/lib/activitypub/process/process-create.ts
+++ b/server/lib/activitypub/process/process-create.ts
@@ -2,7 +2,7 @@ import { ActivityCreate, CacheFileObject, VideoTorrentObject } from '../../../..
2import { VideoCommentObject } from '../../../../shared/models/activitypub/objects/video-comment-object' 2import { VideoCommentObject } from '../../../../shared/models/activitypub/objects/video-comment-object'
3import { retryTransactionWrapper } from '../../../helpers/database-utils' 3import { retryTransactionWrapper } from '../../../helpers/database-utils'
4import { logger } from '../../../helpers/logger' 4import { logger } from '../../../helpers/logger'
5import { sequelizeTypescript } from '../../../initializers' 5import { sequelizeTypescript } from '../../../initializers/database'
6import { resolveThread } from '../video-comments' 6import { resolveThread } from '../video-comments'
7import { getOrCreateVideoAndAccountAndChannel } from '../videos' 7import { getOrCreateVideoAndAccountAndChannel } from '../videos'
8import { forwardVideoRelatedActivity } from '../send/utils' 8import { forwardVideoRelatedActivity } from '../send/utils'
diff --git a/server/lib/activitypub/process/process-delete.ts b/server/lib/activitypub/process/process-delete.ts
index e76132f91..7c8dc83e8 100644
--- a/server/lib/activitypub/process/process-delete.ts
+++ b/server/lib/activitypub/process/process-delete.ts
@@ -1,7 +1,7 @@
1import { ActivityDelete } from '../../../../shared/models/activitypub' 1import { ActivityDelete } from '../../../../shared/models/activitypub'
2import { retryTransactionWrapper } from '../../../helpers/database-utils' 2import { retryTransactionWrapper } from '../../../helpers/database-utils'
3import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
4import { sequelizeTypescript } from '../../../initializers' 4import { sequelizeTypescript } from '../../../initializers/database'
5import { ActorModel } from '../../../models/activitypub/actor' 5import { ActorModel } from '../../../models/activitypub/actor'
6import { VideoModel } from '../../../models/video/video' 6import { VideoModel } from '../../../models/video/video'
7import { VideoCommentModel } from '../../../models/video/video-comment' 7import { VideoCommentModel } from '../../../models/video/video-comment'
diff --git a/server/lib/activitypub/process/process-dislike.ts b/server/lib/activitypub/process/process-dislike.ts
index debd8a67c..fcdd0b86e 100644
--- a/server/lib/activitypub/process/process-dislike.ts
+++ b/server/lib/activitypub/process/process-dislike.ts
@@ -1,7 +1,7 @@
1import { ActivityCreate, ActivityDislike } from '../../../../shared' 1import { ActivityCreate, ActivityDislike } from '../../../../shared'
2import { DislikeObject } from '../../../../shared/models/activitypub/objects' 2import { DislikeObject } from '../../../../shared/models/activitypub/objects'
3import { retryTransactionWrapper } from '../../../helpers/database-utils' 3import { retryTransactionWrapper } from '../../../helpers/database-utils'
4import { sequelizeTypescript } from '../../../initializers' 4import { sequelizeTypescript } from '../../../initializers/database'
5import { AccountVideoRateModel } from '../../../models/account/account-video-rate' 5import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
6import { getOrCreateVideoAndAccountAndChannel } from '../videos' 6import { getOrCreateVideoAndAccountAndChannel } from '../videos'
7import { forwardVideoRelatedActivity } from '../send/utils' 7import { forwardVideoRelatedActivity } from '../send/utils'
diff --git a/server/lib/activitypub/process/process-flag.ts b/server/lib/activitypub/process/process-flag.ts
index e6e9084de..9a488a473 100644
--- a/server/lib/activitypub/process/process-flag.ts
+++ b/server/lib/activitypub/process/process-flag.ts
@@ -2,7 +2,7 @@ import { ActivityCreate, ActivityFlag, VideoAbuseState } from '../../../../share
2import { VideoAbuseObject } from '../../../../shared/models/activitypub/objects' 2import { VideoAbuseObject } from '../../../../shared/models/activitypub/objects'
3import { retryTransactionWrapper } from '../../../helpers/database-utils' 3import { retryTransactionWrapper } from '../../../helpers/database-utils'
4import { logger } from '../../../helpers/logger' 4import { logger } from '../../../helpers/logger'
5import { sequelizeTypescript } from '../../../initializers' 5import { sequelizeTypescript } from '../../../initializers/database'
6import { VideoAbuseModel } from '../../../models/video/video-abuse' 6import { VideoAbuseModel } from '../../../models/video/video-abuse'
7import { getOrCreateVideoAndAccountAndChannel } from '../videos' 7import { getOrCreateVideoAndAccountAndChannel } from '../videos'
8import { Notifier } from '../../notifier' 8import { Notifier } from '../../notifier'
diff --git a/server/lib/activitypub/process/process-follow.ts b/server/lib/activitypub/process/process-follow.ts
index 8f7828e41..950d421dd 100644
--- a/server/lib/activitypub/process/process-follow.ts
+++ b/server/lib/activitypub/process/process-follow.ts
@@ -1,7 +1,7 @@
1import { ActivityFollow } from '../../../../shared/models/activitypub' 1import { ActivityFollow } from '../../../../shared/models/activitypub'
2import { retryTransactionWrapper } from '../../../helpers/database-utils' 2import { retryTransactionWrapper } from '../../../helpers/database-utils'
3import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
4import { sequelizeTypescript } from '../../../initializers' 4import { sequelizeTypescript } from '../../../initializers/database'
5import { ActorModel } from '../../../models/activitypub/actor' 5import { ActorModel } from '../../../models/activitypub/actor'
6import { ActorFollowModel } from '../../../models/activitypub/actor-follow' 6import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
7import { sendAccept, sendReject } from '../send' 7import { sendAccept, sendReject } from '../send'
diff --git a/server/lib/activitypub/process/process-like.ts b/server/lib/activitypub/process/process-like.ts
index 62be0de42..fba3c76a4 100644
--- a/server/lib/activitypub/process/process-like.ts
+++ b/server/lib/activitypub/process/process-like.ts
@@ -1,6 +1,6 @@
1import { ActivityLike } from '../../../../shared/models/activitypub' 1import { ActivityLike } from '../../../../shared/models/activitypub'
2import { retryTransactionWrapper } from '../../../helpers/database-utils' 2import { retryTransactionWrapper } from '../../../helpers/database-utils'
3import { sequelizeTypescript } from '../../../initializers' 3import { sequelizeTypescript } from '../../../initializers/database'
4import { AccountVideoRateModel } from '../../../models/account/account-video-rate' 4import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
5import { forwardVideoRelatedActivity } from '../send/utils' 5import { forwardVideoRelatedActivity } from '../send/utils'
6import { getOrCreateVideoAndAccountAndChannel } from '../videos' 6import { getOrCreateVideoAndAccountAndChannel } from '../videos'
diff --git a/server/lib/activitypub/process/process-reject.ts b/server/lib/activitypub/process/process-reject.ts
index 00e9afa10..9804436a2 100644
--- a/server/lib/activitypub/process/process-reject.ts
+++ b/server/lib/activitypub/process/process-reject.ts
@@ -1,5 +1,5 @@
1import { ActivityReject } from '../../../../shared/models/activitypub/activity' 1import { ActivityReject } from '../../../../shared/models/activitypub/activity'
2import { sequelizeTypescript } from '../../../initializers' 2import { sequelizeTypescript } from '../../../initializers/database'
3import { ActorFollowModel } from '../../../models/activitypub/actor-follow' 3import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
4import { APProcessorOptions } from '../../../typings/activitypub-processor.model' 4import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
5import { MActor } from '../../../typings/models' 5import { MActor } from '../../../typings/models'
diff --git a/server/lib/activitypub/process/process-undo.ts b/server/lib/activitypub/process/process-undo.ts
index 10643b2e9..9ef6a8a97 100644
--- a/server/lib/activitypub/process/process-undo.ts
+++ b/server/lib/activitypub/process/process-undo.ts
@@ -2,7 +2,7 @@ import { ActivityAnnounce, ActivityFollow, ActivityLike, ActivityUndo, CacheFile
2import { DislikeObject } from '../../../../shared/models/activitypub/objects' 2import { DislikeObject } from '../../../../shared/models/activitypub/objects'
3import { retryTransactionWrapper } from '../../../helpers/database-utils' 3import { retryTransactionWrapper } from '../../../helpers/database-utils'
4import { logger } from '../../../helpers/logger' 4import { logger } from '../../../helpers/logger'
5import { sequelizeTypescript } from '../../../initializers' 5import { sequelizeTypescript } from '../../../initializers/database'
6import { AccountVideoRateModel } from '../../../models/account/account-video-rate' 6import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
7import { ActorModel } from '../../../models/activitypub/actor' 7import { ActorModel } from '../../../models/activitypub/actor'
8import { ActorFollowModel } from '../../../models/activitypub/actor-follow' 8import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
diff --git a/server/lib/activitypub/process/process-update.ts b/server/lib/activitypub/process/process-update.ts
index 9579512b7..98ab0f83d 100644
--- a/server/lib/activitypub/process/process-update.ts
+++ b/server/lib/activitypub/process/process-update.ts
@@ -2,7 +2,7 @@ import { ActivityUpdate, CacheFileObject, VideoTorrentObject } from '../../../..
2import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor' 2import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor'
3import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils' 3import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils'
4import { logger } from '../../../helpers/logger' 4import { logger } from '../../../helpers/logger'
5import { sequelizeTypescript } from '../../../initializers' 5import { sequelizeTypescript } from '../../../initializers/database'
6import { AccountModel } from '../../../models/account/account' 6import { AccountModel } from '../../../models/account/account'
7import { ActorModel } from '../../../models/activitypub/actor' 7import { ActorModel } from '../../../models/activitypub/actor'
8import { VideoChannelModel } from '../../../models/video/video-channel' 8import { VideoChannelModel } from '../../../models/video/video-channel'
diff --git a/server/lib/blocklist.ts b/server/lib/blocklist.ts
index 28c69b46e..842eecb5b 100644
--- a/server/lib/blocklist.ts
+++ b/server/lib/blocklist.ts
@@ -1,7 +1,7 @@
1import { sequelizeTypescript } from '../initializers' 1import { sequelizeTypescript } from '@server/initializers/database'
2import { MAccountBlocklist, MServerBlocklist } from '@server/typings/models'
2import { AccountBlocklistModel } from '../models/account/account-blocklist' 3import { AccountBlocklistModel } from '../models/account/account-blocklist'
3import { ServerBlocklistModel } from '../models/server/server-blocklist' 4import { ServerBlocklistModel } from '../models/server/server-blocklist'
4import { MAccountBlocklist, MServerBlocklist } from '@server/typings/models'
5 5
6function addAccountInBlocklist (byAccountId: number, targetAccountId: number) { 6function addAccountInBlocklist (byAccountId: number, targetAccountId: number) {
7 return sequelizeTypescript.transaction(async t => { 7 return sequelizeTypescript.transaction(async t => {
diff --git a/server/lib/job-queue/handlers/video-transcoding.ts b/server/lib/job-queue/handlers/video-transcoding.ts
index 04aac515f..46d52e1cf 100644
--- a/server/lib/job-queue/handlers/video-transcoding.ts
+++ b/server/lib/job-queue/handlers/video-transcoding.ts
@@ -10,7 +10,7 @@ import { VideoModel } from '../../../models/video/video'
10import { JobQueue } from '../job-queue' 10import { JobQueue } from '../job-queue'
11import { federateVideoIfNeeded } from '../../activitypub/videos' 11import { federateVideoIfNeeded } from '../../activitypub/videos'
12import { retryTransactionWrapper } from '../../../helpers/database-utils' 12import { retryTransactionWrapper } from '../../../helpers/database-utils'
13import { sequelizeTypescript } from '../../../initializers' 13import { sequelizeTypescript } from '../../../initializers/database'
14import { computeResolutionsToTranscode } from '../../../helpers/ffmpeg-utils' 14import { computeResolutionsToTranscode } from '../../../helpers/ffmpeg-utils'
15import { generateHlsPlaylist, mergeAudioVideofile, optimizeOriginalVideofile, transcodeNewResolution } from '../../video-transcoding' 15import { generateHlsPlaylist, mergeAudioVideofile, optimizeOriginalVideofile, transcodeNewResolution } from '../../video-transcoding'
16import { Notifier } from '../../notifier' 16import { Notifier } from '../../notifier'
diff --git a/server/lib/plugins/plugin-helpers.ts b/server/lib/plugins/plugin-helpers.ts
index 608207e05..de82b4918 100644
--- a/server/lib/plugins/plugin-helpers.ts
+++ b/server/lib/plugins/plugin-helpers.ts
@@ -3,6 +3,15 @@ import { sequelizeTypescript } from '@server/initializers/database'
3import { buildLogger } from '@server/helpers/logger' 3import { buildLogger } from '@server/helpers/logger'
4import { VideoModel } from '@server/models/video/video' 4import { VideoModel } from '@server/models/video/video'
5import { WEBSERVER } from '@server/initializers/constants' 5import { WEBSERVER } from '@server/initializers/constants'
6import { ServerModel } from '@server/models/server/server'
7import { getServerActor } from '@server/models/application/application'
8import { addServerInBlocklist, removeServerFromBlocklist, addAccountInBlocklist, removeAccountFromBlocklist } from '../blocklist'
9import { ServerBlocklistModel } from '@server/models/server/server-blocklist'
10import { AccountModel } from '@server/models/account/account'
11import { VideoBlacklistCreate } from '@shared/models'
12import { blacklistVideo, unblacklistVideo } from '../video-blacklist'
13import { VideoBlacklistModel } from '@server/models/video/video-blacklist'
14import { AccountBlocklistModel } from '@server/models/account/account-blocklist'
6 15
7function buildPluginHelpers (npmName: string): PeerTubeHelpers { 16function buildPluginHelpers (npmName: string): PeerTubeHelpers {
8 const logger = buildPluginLogger(npmName) 17 const logger = buildPluginLogger(npmName)
@@ -12,11 +21,17 @@ function buildPluginHelpers (npmName: string): PeerTubeHelpers {
12 21
13 const config = buildConfigHelpers() 22 const config = buildConfigHelpers()
14 23
24 const server = buildServerHelpers()
25
26 const moderation = buildModerationHelpers()
27
15 return { 28 return {
16 logger, 29 logger,
17 database, 30 database,
18 videos, 31 videos,
19 config 32 config,
33 moderation,
34 server
20 } 35 }
21} 36}
22 37
@@ -36,8 +51,18 @@ function buildDatabaseHelpers () {
36 } 51 }
37} 52}
38 53
54function buildServerHelpers () {
55 return {
56 getServerActor: () => getServerActor()
57 }
58}
59
39function buildVideosHelpers () { 60function buildVideosHelpers () {
40 return { 61 return {
62 loadByUrl: (url: string) => {
63 return VideoModel.loadByUrl(url)
64 },
65
41 removeVideo: (id: number) => { 66 removeVideo: (id: number) => {
42 return sequelizeTypescript.transaction(async t => { 67 return sequelizeTypescript.transaction(async t => {
43 const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(id, t) 68 const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(id, t)
@@ -48,6 +73,57 @@ function buildVideosHelpers () {
48 } 73 }
49} 74}
50 75
76function buildModerationHelpers () {
77 return {
78 blockServer: async (options: { byAccountId: number, hostToBlock: string }) => {
79 const serverToBlock = await ServerModel.loadOrCreateByHost(options.hostToBlock)
80
81 await addServerInBlocklist(options.byAccountId, serverToBlock.id)
82 },
83
84 unblockServer: async (options: { byAccountId: number, hostToUnblock: string }) => {
85 const serverBlock = await ServerBlocklistModel.loadByAccountAndHost(options.byAccountId, options.hostToUnblock)
86 if (!serverBlock) return
87
88 await removeServerFromBlocklist(serverBlock)
89 },
90
91 blockAccount: async (options: { byAccountId: number, handleToBlock: string }) => {
92 const accountToBlock = await AccountModel.loadByNameWithHost(options.handleToBlock)
93 if (!accountToBlock) return
94
95 await addAccountInBlocklist(options.byAccountId, accountToBlock.id)
96 },
97
98 unblockAccount: async (options: { byAccountId: number, handleToUnblock: string }) => {
99 const targetAccount = await AccountModel.loadByNameWithHost(options.handleToUnblock)
100 if (!targetAccount) return
101
102 const accountBlock = await AccountBlocklistModel.loadByAccountAndTarget(options.byAccountId, targetAccount.id)
103 if (!accountBlock) return
104
105 await removeAccountFromBlocklist(accountBlock)
106 },
107
108 blacklistVideo: async (options: { videoIdOrUUID: number | string, createOptions: VideoBlacklistCreate }) => {
109 const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(options.videoIdOrUUID)
110 if (!video) return
111
112 await blacklistVideo(video, options.createOptions)
113 },
114
115 unblacklistVideo: async (options: { videoIdOrUUID: number | string }) => {
116 const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(options.videoIdOrUUID)
117 if (!video) return
118
119 const videoBlacklist = await VideoBlacklistModel.loadByVideoId(video.id)
120 if (!videoBlacklist) return
121
122 await unblacklistVideo(videoBlacklist, video)
123 }
124 }
125}
126
51function buildConfigHelpers () { 127function buildConfigHelpers () {
52 return { 128 return {
53 getWebserverUrl () { 129 getWebserverUrl () {
diff --git a/server/lib/video-blacklist.ts b/server/lib/video-blacklist.ts
index 3b90b1b94..bd60c6201 100644
--- a/server/lib/video-blacklist.ts
+++ b/server/lib/video-blacklist.ts
@@ -1,12 +1,22 @@
1import { Transaction } from 'sequelize' 1import { Transaction } from 'sequelize'
2import { sequelizeTypescript } from '@server/initializers/database'
3import {
4 MUser,
5 MVideoAccountLight,
6 MVideoBlacklist,
7 MVideoBlacklistVideo,
8 MVideoFullLight,
9 MVideoWithBlacklistLight
10} from '@server/typings/models'
11import { UserRight, VideoBlacklistCreate, VideoBlacklistType } from '../../shared/models'
12import { UserAdminFlag } from '../../shared/models/users/user-flag.model'
13import { logger } from '../helpers/logger'
2import { CONFIG } from '../initializers/config' 14import { CONFIG } from '../initializers/config'
3import { UserRight, VideoBlacklistType } from '../../shared/models'
4import { VideoBlacklistModel } from '../models/video/video-blacklist' 15import { VideoBlacklistModel } from '../models/video/video-blacklist'
5import { logger } from '../helpers/logger' 16import { sendDeleteVideo } from './activitypub/send'
6import { UserAdminFlag } from '../../shared/models/users/user-flag.model' 17import { federateVideoIfNeeded } from './activitypub/videos'
7import { Hooks } from './plugins/hooks'
8import { Notifier } from './notifier' 18import { Notifier } from './notifier'
9import { MUser, MVideoBlacklistVideo, MVideoWithBlacklistLight } from '@server/typings/models' 19import { Hooks } from './plugins/hooks'
10 20
11async function autoBlacklistVideoIfNeeded (parameters: { 21async function autoBlacklistVideoIfNeeded (parameters: {
12 video: MVideoWithBlacklistLight 22 video: MVideoWithBlacklistLight
@@ -49,6 +59,60 @@ async function autoBlacklistVideoIfNeeded (parameters: {
49 return true 59 return true
50} 60}
51 61
62async function blacklistVideo (videoInstance: MVideoAccountLight, options: VideoBlacklistCreate) {
63 const blacklist: MVideoBlacklistVideo = await VideoBlacklistModel.create({
64 videoId: videoInstance.id,
65 unfederated: options.unfederate === true,
66 reason: options.reason,
67 type: VideoBlacklistType.MANUAL
68 }
69 )
70 blacklist.Video = videoInstance
71
72 if (options.unfederate === true) {
73 await sendDeleteVideo(videoInstance, undefined)
74 }
75
76 Notifier.Instance.notifyOnVideoBlacklist(blacklist)
77}
78
79async function unblacklistVideo (videoBlacklist: MVideoBlacklist, video: MVideoFullLight) {
80 const videoBlacklistType = await sequelizeTypescript.transaction(async t => {
81 const unfederated = videoBlacklist.unfederated
82 const videoBlacklistType = videoBlacklist.type
83
84 await videoBlacklist.destroy({ transaction: t })
85 video.VideoBlacklist = undefined
86
87 // Re federate the video
88 if (unfederated === true) {
89 await federateVideoIfNeeded(video, true, t)
90 }
91
92 return videoBlacklistType
93 })
94
95 Notifier.Instance.notifyOnVideoUnblacklist(video)
96
97 if (videoBlacklistType === VideoBlacklistType.AUTO_BEFORE_PUBLISHED) {
98 Notifier.Instance.notifyOnVideoPublishedAfterRemovedFromAutoBlacklist(video)
99
100 // Delete on object so new video notifications will send
101 delete video.VideoBlacklist
102 Notifier.Instance.notifyOnNewVideoIfNeeded(video)
103 }
104}
105
106// ---------------------------------------------------------------------------
107
108export {
109 autoBlacklistVideoIfNeeded,
110 blacklistVideo,
111 unblacklistVideo
112}
113
114// ---------------------------------------------------------------------------
115
52function autoBlacklistNeeded (parameters: { 116function autoBlacklistNeeded (parameters: {
53 video: MVideoWithBlacklistLight 117 video: MVideoWithBlacklistLight
54 isRemote: boolean 118 isRemote: boolean
@@ -66,9 +130,3 @@ function autoBlacklistNeeded (parameters: {
66 130
67 return true 131 return true
68} 132}
69
70// ---------------------------------------------------------------------------
71
72export {
73 autoBlacklistVideoIfNeeded
74}
diff --git a/server/middlewares/validators/blocklist.ts b/server/middlewares/validators/blocklist.ts
index c00a7e4df..27224ff9b 100644
--- a/server/middlewares/validators/blocklist.ts
+++ b/server/middlewares/validators/blocklist.ts
@@ -84,10 +84,7 @@ const blockServerValidator = [
84 .end() 84 .end()
85 } 85 }
86 86
87 let server = await ServerModel.loadByHost(host) 87 const server = await ServerModel.loadOrCreateByHost(host)
88 if (!server) {
89 server = await ServerModel.create({ host })
90 }
91 88
92 res.locals.server = server 89 res.locals.server = server
93 90
diff --git a/server/models/server/server.ts b/server/models/server/server.ts
index 8b07115f1..5131257ec 100644
--- a/server/models/server/server.ts
+++ b/server/models/server/server.ts
@@ -71,6 +71,13 @@ export class ServerModel extends Model<ServerModel> {
71 return ServerModel.findOne(query) 71 return ServerModel.findOne(query)
72 } 72 }
73 73
74 static async loadOrCreateByHost (host: string) {
75 let server = await ServerModel.loadByHost(host)
76 if (!server) server = await ServerModel.create({ host })
77
78 return server
79 }
80
74 isBlocked () { 81 isBlocked () {
75 return this.BlockedByAccounts && this.BlockedByAccounts.length !== 0 82 return this.BlockedByAccounts && this.BlockedByAccounts.length !== 0
76 } 83 }
diff --git a/server/tests/fixtures/peertube-plugin-test-four/main.js b/server/tests/fixtures/peertube-plugin-test-four/main.js
index 2e81550c1..067c3fe15 100644
--- a/server/tests/fixtures/peertube-plugin-test-four/main.js
+++ b/server/tests/fixtures/peertube-plugin-test-four/main.js
@@ -1,30 +1,70 @@
1async function register ({ 1async function register ({
2 peertubeHelpers, 2 peertubeHelpers,
3 registerHook 3 registerHook,
4 getRouter
4}) { 5}) {
5 const logger = peertubeHelpers.logger 6 const logger = peertubeHelpers.logger
6 7
7 logger.info('Hello world from plugin four') 8 logger.info('Hello world from plugin four')
8 9
9 const username = 'root' 10 {
10 const results = await peertubeHelpers.database.query( 11 const username = 'root'
11 'SELECT "email" from "user" WHERE "username" = $username', 12 const results = await peertubeHelpers.database.query(
12 { 13 'SELECT "email" from "user" WHERE "username" = $username',
13 type: 'SELECT', 14 {
14 bind: { username } 15 type: 'SELECT',
15 } 16 bind: { username }
16 ) 17 }
18 )
19
20 logger.info('root email is ' + results[0]['email'])
21 }
22
23 {
24 registerHook({
25 target: 'action:api.video.viewed',
26 handler: async ({ video }) => {
27 const videoFromDB = await peertubeHelpers.videos.loadByUrl(video.url)
28 logger.info('video from DB uuid is %s.', videoFromDB.uuid)
29
30 await peertubeHelpers.videos.removeVideo(video.id)
17 31
18 logger.info('root email is ' + results[0]['email']) 32 logger.info('Video deleted by plugin four.')
33 }
34 })
35 }
19 36
20 registerHook({ 37 {
21 target: 'action:api.video.viewed', 38 const serverActor = await peertubeHelpers.server.getServerActor()
22 handler: async ({ video }) => { 39 logger.info('server actor name is %s', serverActor.preferredUsername)
23 await peertubeHelpers.videos.removeVideo(video.id) 40 }
24 41
25 logger.info('Video deleted by plugin four.') 42 {
43 logger.info('server url is %s', peertubeHelpers.config.getWebserverUrl())
44 }
45
46 {
47 const actions = {
48 blockServer,
49 unblockServer,
50 blockAccount,
51 unblockAccount,
52 blacklist,
53 unblacklist
26 } 54 }
27 }) 55
56 const router = getRouter()
57 router.post('/commander', async (req, res) => {
58 try {
59 await actions[req.body.command](peertubeHelpers, req.body)
60
61 res.sendStatus(204)
62 } catch (err) {
63 logger.error('Error in commander.', { err })
64 res.sendStatus(500)
65 }
66 })
67 }
28} 68}
29 69
30async function unregister () { 70async function unregister () {
@@ -37,3 +77,38 @@ module.exports = {
37} 77}
38 78
39// ########################################################################### 79// ###########################################################################
80
81async function blockServer (peertubeHelpers, body) {
82 const serverActor = await peertubeHelpers.server.getServerActor()
83
84 await peertubeHelpers.moderation.blockServer({ byAccountId: serverActor.Account.id, hostToBlock: body.hostToBlock })
85}
86
87async function unblockServer (peertubeHelpers, body) {
88 const serverActor = await peertubeHelpers.server.getServerActor()
89
90 await peertubeHelpers.moderation.unblockServer({ byAccountId: serverActor.Account.id, hostToUnblock: body.hostToUnblock })
91}
92
93async function blockAccount (peertubeHelpers, body) {
94 const serverActor = await peertubeHelpers.server.getServerActor()
95
96 await peertubeHelpers.moderation.blockAccount({ byAccountId: serverActor.Account.id, handleToBlock: body.handleToBlock })
97}
98
99async function unblockAccount (peertubeHelpers, body) {
100 const serverActor = await peertubeHelpers.server.getServerActor()
101
102 await peertubeHelpers.moderation.unblockAccount({ byAccountId: serverActor.Account.id, handleToUnblock: body.handleToUnblock })
103}
104
105async function blacklist (peertubeHelpers, body) {
106 await peertubeHelpers.moderation.blacklistVideo({
107 videoIdOrUUID: body.videoUUID,
108 createOptions: body
109 })
110}
111
112async function unblacklist (peertubeHelpers, body) {
113 await peertubeHelpers.moderation.unblacklistVideo({ videoIdOrUUID: body.videoUUID })
114}
diff --git a/server/tests/plugins/plugin-helpers.ts b/server/tests/plugins/plugin-helpers.ts
index dfe8ebe55..0915603d0 100644
--- a/server/tests/plugins/plugin-helpers.ts
+++ b/server/tests/plugins/plugin-helpers.ts
@@ -1,66 +1,210 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import 'mocha' 3import 'mocha'
4import { cleanupTests, flushAndRunServer, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
5import { 4import {
6 checkVideoFilesWereRemoved, 5 checkVideoFilesWereRemoved,
6 doubleFollow,
7 getPluginTestPath, 7 getPluginTestPath,
8 getVideo, 8 getVideo,
9 installPlugin, 9 installPlugin,
10 makePostBodyRequest,
10 setAccessTokensToServers, 11 setAccessTokensToServers,
11 uploadVideoAndGetId, 12 uploadVideoAndGetId,
12 viewVideo 13 viewVideo,
14 getVideosList,
15 waitJobs
13} from '../../../shared/extra-utils' 16} from '../../../shared/extra-utils'
17import { cleanupTests, flushAndRunMultipleServers, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
18import { expect } from 'chai'
19
20function postCommand (server: ServerInfo, command: string, bodyArg?: object) {
21 const body = { command }
22 if (bodyArg) Object.assign(body, bodyArg)
23
24 return makePostBodyRequest({
25 url: server.url,
26 path: '/plugins/test-four/router/commander',
27 fields: body,
28 statusCodeExpected: 204
29 })
30}
14 31
15describe('Test plugin helpers', function () { 32describe('Test plugin helpers', function () {
16 let server: ServerInfo 33 let servers: ServerInfo[]
17 34
18 before(async function () { 35 before(async function () {
19 this.timeout(30000) 36 this.timeout(60000)
37
38 servers = await flushAndRunMultipleServers(2)
39 await setAccessTokensToServers(servers)
20 40
21 server = await flushAndRunServer(1) 41 await doubleFollow(servers[0], servers[1])
22 await setAccessTokensToServers([ server ])
23 42
24 await installPlugin({ 43 await installPlugin({
25 url: server.url, 44 url: servers[0].url,
26 accessToken: server.accessToken, 45 accessToken: servers[0].accessToken,
27 path: getPluginTestPath('-four') 46 path: getPluginTestPath('-four')
28 }) 47 })
29 }) 48 })
30 49
31 it('Should have logged things', async function () { 50 describe('Logger', function () {
32 await waitUntilLog(server, 'localhost:' + server.port + ' peertube-plugin-test-four', 1, false) 51
33 await waitUntilLog(server, 'Hello world from plugin four', 1) 52 it('Should have logged things', async function () {
53 await waitUntilLog(servers[0], 'localhost:' + servers[0].port + ' peertube-plugin-test-four', 1, false)
54 await waitUntilLog(servers[0], 'Hello world from plugin four', 1)
55 })
34 }) 56 })
35 57
36 it('Should have made a query', async function () { 58 describe('Database', function () {
37 await waitUntilLog(server, `root email is admin${server.internalServerNumber}@example.com`, 1) 59
60 it('Should have made a query', async function () {
61 await waitUntilLog(servers[0], `root email is admin${servers[0].internalServerNumber}@example.com`)
62 })
63 })
64
65 describe('Config', function () {
66
67 it('Should have the correct webserver url', async function () {
68 await waitUntilLog(servers[0], `server url is http://localhost:${servers[0].port}`)
69 })
70 })
71
72 describe('Server', function () {
73
74 it('Should get the server actor', async function () {
75 await waitUntilLog(servers[0], 'server actor name is peertube')
76 })
77 })
78
79 describe('Moderation', function () {
80 let videoUUIDServer1: string
81
82 before(async function () {
83 this.timeout(15000)
84
85 {
86 const res = await uploadVideoAndGetId({ server: servers[0], videoName: 'video server 1' })
87 videoUUIDServer1 = res.uuid
88 }
89
90 {
91 await uploadVideoAndGetId({ server: servers[1], videoName: 'video server 2' })
92 }
93
94 await waitJobs(servers)
95
96 const res = await getVideosList(servers[0].url)
97 const videos = res.body.data
98
99 expect(videos).to.have.lengthOf(2)
100 })
101
102 it('Should mute server 2', async function () {
103 this.timeout(10000)
104 await postCommand(servers[0], 'blockServer', { hostToBlock: `localhost:${servers[1].port}` })
105
106 const res = await getVideosList(servers[0].url)
107 const videos = res.body.data
108
109 expect(videos).to.have.lengthOf(1)
110 expect(videos[0].name).to.equal('video server 1')
111 })
112
113 it('Should unmute server 2', async function () {
114 await postCommand(servers[0], 'unblockServer', { hostToUnblock: `localhost:${servers[1].port}` })
115
116 const res = await getVideosList(servers[0].url)
117 const videos = res.body.data
118
119 expect(videos).to.have.lengthOf(2)
120 })
121
122 it('Should mute account of server 2', async function () {
123 await postCommand(servers[0], 'blockAccount', { handleToBlock: `root@localhost:${servers[1].port}` })
124
125 const res = await getVideosList(servers[0].url)
126 const videos = res.body.data
127
128 expect(videos).to.have.lengthOf(1)
129 expect(videos[0].name).to.equal('video server 1')
130 })
131
132 it('Should unmute account of server 2', async function () {
133 await postCommand(servers[0], 'unblockAccount', { handleToUnblock: `root@localhost:${servers[1].port}` })
134
135 const res = await getVideosList(servers[0].url)
136 const videos = res.body.data
137
138 expect(videos).to.have.lengthOf(2)
139 })
140
141 it('Should blacklist video', async function () {
142 this.timeout(10000)
143
144 await postCommand(servers[0], 'blacklist', { videoUUID: videoUUIDServer1, unfederate: true })
145
146 await waitJobs(servers)
147
148 for (const server of servers) {
149 const res = await getVideosList(server.url)
150 const videos = res.body.data
151
152 expect(videos).to.have.lengthOf(1)
153 expect(videos[0].name).to.equal('video server 2')
154 }
155 })
156
157 it('Should unblacklist video', async function () {
158 this.timeout(10000)
159
160 await postCommand(servers[0], 'unblacklist', { videoUUID: videoUUIDServer1 })
161
162 await waitJobs(servers)
163
164 for (const server of servers) {
165 const res = await getVideosList(server.url)
166 const videos = res.body.data
167
168 expect(videos).to.have.lengthOf(2)
169 }
170 })
38 }) 171 })
39 172
40 it('Should remove a video after a view', async function () { 173 describe('Videos', function () {
41 this.timeout(20000) 174 let videoUUID: string
175
176 before(async () => {
177 const res = await uploadVideoAndGetId({ server: servers[0], videoName: 'video1' })
178 videoUUID = res.uuid
179 })
42 180
43 const videoUUID = (await uploadVideoAndGetId({ server: server, videoName: 'video1' })).uuid 181 it('Should remove a video after a view', async function () {
182 this.timeout(20000)
44 183
45 // Should not throw -> video exists 184 // Should not throw -> video exists
46 await getVideo(server.url, videoUUID) 185 await getVideo(servers[0].url, videoUUID)
47 // Should delete the video 186 // Should delete the video
48 await viewVideo(server.url, videoUUID) 187 await viewVideo(servers[0].url, videoUUID)
49 188
50 await waitUntilLog(server, 'Video deleted by plugin four.', 1) 189 await waitUntilLog(servers[0], 'Video deleted by plugin four.')
51 190
52 try { 191 try {
53 // Should throw because the video should have been deleted 192 // Should throw because the video should have been deleted
54 await getVideo(server.url, videoUUID) 193 await getVideo(servers[0].url, videoUUID)
55 throw new Error('Video exists') 194 throw new Error('Video exists')
56 } catch (err) { 195 } catch (err) {
57 if (err.message.includes('exists')) throw err 196 if (err.message.includes('exists')) throw err
58 } 197 }
59 198
60 await checkVideoFilesWereRemoved(videoUUID, server.internalServerNumber) 199 await checkVideoFilesWereRemoved(videoUUID, servers[0].internalServerNumber)
200 })
201
202 it('Should have fetched the video by URL', async function () {
203 await waitUntilLog(servers[0], `video from DB uuid is ${videoUUID}`)
204 })
61 }) 205 })
62 206
63 after(async function () { 207 after(async function () {
64 await cleanupTests([ server ]) 208 await cleanupTests(servers)
65 }) 209 })
66}) 210})
diff --git a/server/typings/plugins/register-server-option.model.ts b/server/typings/plugins/register-server-option.model.ts
index 7f933b43a..8f1d66007 100644
--- a/server/typings/plugins/register-server-option.model.ts
+++ b/server/typings/plugins/register-server-option.model.ts
@@ -1,19 +1,23 @@
1import { PluginSettingsManager } from '../../../shared/models/plugins/plugin-settings-manager.model' 1import * as Bluebird from 'bluebird'
2import { PluginStorageManager } from '../../../shared/models/plugins/plugin-storage-manager.model'
3import { RegisterServerHookOptions } from '../../../shared/models/plugins/register-server-hook.model'
4import { RegisterServerSettingOptions } from '../../../shared/models/plugins/register-server-setting.model'
5import { PluginVideoCategoryManager } from '../../../shared/models/plugins/plugin-video-category-manager.model'
6import { PluginVideoLanguageManager } from '../../../shared/models/plugins/plugin-video-language-manager.model'
7import { PluginVideoLicenceManager } from '../../../shared/models/plugins/plugin-video-licence-manager.model'
8import { Logger } from 'winston'
9import { Router } from 'express' 2import { Router } from 'express'
10import { PluginVideoPrivacyManager } from '@shared/models/plugins/plugin-video-privacy-manager.model' 3import { Logger } from 'winston'
4import { ActorModel } from '@server/models/activitypub/actor'
5import { VideoBlacklistCreate } from '@shared/models'
11import { PluginPlaylistPrivacyManager } from '@shared/models/plugins/plugin-playlist-privacy-manager.model' 6import { PluginPlaylistPrivacyManager } from '@shared/models/plugins/plugin-playlist-privacy-manager.model'
7import { PluginVideoPrivacyManager } from '@shared/models/plugins/plugin-video-privacy-manager.model'
12import { 8import {
13 RegisterServerAuthExternalOptions, 9 RegisterServerAuthExternalOptions,
14 RegisterServerAuthExternalResult, 10 RegisterServerAuthExternalResult,
15 RegisterServerAuthPassOptions 11 RegisterServerAuthPassOptions
16} from '@shared/models/plugins/register-server-auth.model' 12} from '@shared/models/plugins/register-server-auth.model'
13import { PluginSettingsManager } from '../../../shared/models/plugins/plugin-settings-manager.model'
14import { PluginStorageManager } from '../../../shared/models/plugins/plugin-storage-manager.model'
15import { PluginVideoCategoryManager } from '../../../shared/models/plugins/plugin-video-category-manager.model'
16import { PluginVideoLanguageManager } from '../../../shared/models/plugins/plugin-video-language-manager.model'
17import { PluginVideoLicenceManager } from '../../../shared/models/plugins/plugin-video-licence-manager.model'
18import { RegisterServerHookOptions } from '../../../shared/models/plugins/register-server-hook.model'
19import { RegisterServerSettingOptions } from '../../../shared/models/plugins/register-server-setting.model'
20import { MVideoThumbnail } from '../models'
17 21
18export type PeerTubeHelpers = { 22export type PeerTubeHelpers = {
19 logger: Logger 23 logger: Logger
@@ -23,12 +27,28 @@ export type PeerTubeHelpers = {
23 } 27 }
24 28
25 videos: { 29 videos: {
30 loadByUrl: (url: string) => Bluebird<MVideoThumbnail>
31
26 removeVideo: (videoId: number) => Promise<void> 32 removeVideo: (videoId: number) => Promise<void>
27 } 33 }
28 34
29 config: { 35 config: {
30 getWebserverUrl: () => string 36 getWebserverUrl: () => string
31 } 37 }
38
39 moderation: {
40 blockServer: (options: { byAccountId: number, hostToBlock: string }) => Promise<void>
41 unblockServer: (options: { byAccountId: number, hostToUnblock: string }) => Promise<void>
42 blockAccount: (options: { byAccountId: number, handleToBlock: string }) => Promise<void>
43 unblockAccount: (options: { byAccountId: number, handleToUnblock: string }) => Promise<void>
44
45 blacklistVideo: (options: { videoIdOrUUID: number | string, createOptions: VideoBlacklistCreate }) => Promise<void>
46 unblacklistVideo: (options: { videoIdOrUUID: number | string }) => Promise<void>
47 }
48
49 server: {
50 getServerActor: () => Promise<ActorModel>
51 }
32} 52}
33 53
34export type RegisterServerOptions = { 54export type RegisterServerOptions = {