aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib')
-rw-r--r--server/lib/activitypub/process/process-create.ts23
-rw-r--r--server/lib/activitypub/send/send-delete.ts12
-rw-r--r--server/lib/blocklist.ts25
-rw-r--r--server/lib/notifier.ts55
-rw-r--r--server/lib/video-comment.ts29
5 files changed, 95 insertions, 49 deletions
diff --git a/server/lib/activitypub/process/process-create.ts b/server/lib/activitypub/process/process-create.ts
index 566bf6992..f8f9b80c6 100644
--- a/server/lib/activitypub/process/process-create.ts
+++ b/server/lib/activitypub/process/process-create.ts
@@ -1,18 +1,19 @@
1import { isRedundancyAccepted } from '@server/lib/redundancy'
1import { ActivityCreate, CacheFileObject, VideoTorrentObject } from '../../../../shared' 2import { ActivityCreate, CacheFileObject, VideoTorrentObject } from '../../../../shared'
3import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object'
2import { VideoCommentObject } from '../../../../shared/models/activitypub/objects/video-comment-object' 4import { VideoCommentObject } from '../../../../shared/models/activitypub/objects/video-comment-object'
3import { retryTransactionWrapper } from '../../../helpers/database-utils' 5import { retryTransactionWrapper } from '../../../helpers/database-utils'
4import { logger } from '../../../helpers/logger' 6import { logger } from '../../../helpers/logger'
5import { sequelizeTypescript } from '../../../initializers/database' 7import { sequelizeTypescript } from '../../../initializers/database'
6import { resolveThread } from '../video-comments'
7import { getOrCreateVideoAndAccountAndChannel } from '../videos'
8import { forwardVideoRelatedActivity } from '../send/utils'
9import { createOrUpdateCacheFile } from '../cache-file'
10import { Notifier } from '../../notifier'
11import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object'
12import { createOrUpdateVideoPlaylist } from '../playlist'
13import { APProcessorOptions } from '../../../typings/activitypub-processor.model' 8import { APProcessorOptions } from '../../../typings/activitypub-processor.model'
14import { MActorSignature, MCommentOwnerVideo, MVideoAccountLightBlacklistAllFiles } from '../../../typings/models' 9import { MActorSignature, MCommentOwnerVideo, MVideoAccountLightBlacklistAllFiles } from '../../../typings/models'
15import { isRedundancyAccepted } from '@server/lib/redundancy' 10import { Notifier } from '../../notifier'
11import { createOrUpdateCacheFile } from '../cache-file'
12import { createOrUpdateVideoPlaylist } from '../playlist'
13import { forwardVideoRelatedActivity } from '../send/utils'
14import { resolveThread } from '../video-comments'
15import { getOrCreateVideoAndAccountAndChannel } from '../videos'
16import { isBlockedByServerOrAccount } from '@server/lib/blocklist'
16 17
17async function processCreateActivity (options: APProcessorOptions<ActivityCreate>) { 18async function processCreateActivity (options: APProcessorOptions<ActivityCreate>) {
18 const { activity, byActor } = options 19 const { activity, byActor } = options
@@ -101,6 +102,12 @@ async function processCreateVideoComment (activity: ActivityCreate, byActor: MAc
101 return 102 return
102 } 103 }
103 104
105 // Try to not forward unwanted commments on our videos
106 if (video.isOwned() && await isBlockedByServerOrAccount(comment.Account, video.VideoChannel.Account)) {
107 logger.info('Skip comment forward from blocked account or server %s.', comment.Account.Actor.url)
108 return
109 }
110
104 if (video.isOwned() && created === true) { 111 if (video.isOwned() && created === true) {
105 // Don't resend the activity to the sender 112 // Don't resend the activity to the sender
106 const exceptions = [ byActor ] 113 const exceptions = [ byActor ]
diff --git a/server/lib/activitypub/send/send-delete.ts b/server/lib/activitypub/send/send-delete.ts
index fd3f06dec..2afd2c05d 100644
--- a/server/lib/activitypub/send/send-delete.ts
+++ b/server/lib/activitypub/send/send-delete.ts
@@ -1,15 +1,15 @@
1import { Transaction } from 'sequelize' 1import { Transaction } from 'sequelize'
2import { getServerActor } from '@server/models/application/application'
2import { ActivityAudience, ActivityDelete } from '../../../../shared/models/activitypub' 3import { ActivityAudience, ActivityDelete } from '../../../../shared/models/activitypub'
4import { logger } from '../../../helpers/logger'
3import { ActorModel } from '../../../models/activitypub/actor' 5import { ActorModel } from '../../../models/activitypub/actor'
4import { VideoCommentModel } from '../../../models/video/video-comment' 6import { VideoCommentModel } from '../../../models/video/video-comment'
5import { VideoShareModel } from '../../../models/video/video-share' 7import { VideoShareModel } from '../../../models/video/video-share'
8import { MActorUrl } from '../../../typings/models'
9import { MCommentOwnerVideo, MVideoAccountLight, MVideoPlaylistFullSummary } from '../../../typings/models/video'
10import { audiencify, getActorsInvolvedInVideo, getVideoCommentAudience } from '../audience'
6import { getDeleteActivityPubUrl } from '../url' 11import { getDeleteActivityPubUrl } from '../url'
7import { broadcastToActors, broadcastToFollowers, sendVideoRelatedActivity, unicastTo } from './utils' 12import { broadcastToActors, broadcastToFollowers, sendVideoRelatedActivity, unicastTo } from './utils'
8import { audiencify, getActorsInvolvedInVideo, getVideoCommentAudience } from '../audience'
9import { logger } from '../../../helpers/logger'
10import { MCommentOwnerVideoReply, MVideoAccountLight, MVideoPlaylistFullSummary } from '../../../typings/models/video'
11import { MActorUrl } from '../../../typings/models'
12import { getServerActor } from '@server/models/application/application'
13 13
14async function sendDeleteVideo (video: MVideoAccountLight, transaction: Transaction) { 14async function sendDeleteVideo (video: MVideoAccountLight, transaction: Transaction) {
15 logger.info('Creating job to broadcast delete of video %s.', video.url) 15 logger.info('Creating job to broadcast delete of video %s.', video.url)
@@ -42,7 +42,7 @@ async function sendDeleteActor (byActor: ActorModel, t: Transaction) {
42 return broadcastToFollowers(activity, byActor, actorsInvolved, t) 42 return broadcastToFollowers(activity, byActor, actorsInvolved, t)
43} 43}
44 44
45async function sendDeleteVideoComment (videoComment: MCommentOwnerVideoReply, t: Transaction) { 45async function sendDeleteVideoComment (videoComment: MCommentOwnerVideo, t: Transaction) {
46 logger.info('Creating job to send delete of comment %s.', videoComment.url) 46 logger.info('Creating job to send delete of comment %s.', videoComment.url)
47 47
48 const isVideoOrigin = videoComment.Video.isOwned() 48 const isVideoOrigin = videoComment.Video.isOwned()
diff --git a/server/lib/blocklist.ts b/server/lib/blocklist.ts
index 842eecb5b..d282d091b 100644
--- a/server/lib/blocklist.ts
+++ b/server/lib/blocklist.ts
@@ -1,5 +1,6 @@
1import { sequelizeTypescript } from '@server/initializers/database' 1import { sequelizeTypescript } from '@server/initializers/database'
2import { MAccountBlocklist, MServerBlocklist } from '@server/typings/models' 2import { getServerActor } from '@server/models/application/application'
3import { MAccountBlocklist, MAccountId, MAccountServer, MServerBlocklist } from '@server/typings/models'
3import { AccountBlocklistModel } from '../models/account/account-blocklist' 4import { AccountBlocklistModel } from '../models/account/account-blocklist'
4import { ServerBlocklistModel } from '../models/server/server-blocklist' 5import { ServerBlocklistModel } from '../models/server/server-blocklist'
5 6
@@ -33,9 +34,29 @@ function removeServerFromBlocklist (serverBlock: MServerBlocklist) {
33 }) 34 })
34} 35}
35 36
37async function isBlockedByServerOrAccount (targetAccount: MAccountServer, userAccount?: MAccountId) {
38 const serverAccountId = (await getServerActor()).Account.id
39 const sourceAccounts = [ serverAccountId ]
40
41 if (userAccount) sourceAccounts.push(userAccount.id)
42
43 const accountMutedHash = await AccountBlocklistModel.isAccountMutedByMulti(sourceAccounts, targetAccount.id)
44 if (accountMutedHash[serverAccountId] || (userAccount && accountMutedHash[userAccount.id])) {
45 return true
46 }
47
48 const instanceMutedHash = await ServerBlocklistModel.isServerMutedByMulti(sourceAccounts, targetAccount.Actor.serverId)
49 if (instanceMutedHash[serverAccountId] || (userAccount && instanceMutedHash[userAccount.id])) {
50 return true
51 }
52
53 return false
54}
55
36export { 56export {
37 addAccountInBlocklist, 57 addAccountInBlocklist,
38 addServerInBlocklist, 58 addServerInBlocklist,
39 removeAccountFromBlocklist, 59 removeAccountFromBlocklist,
40 removeServerFromBlocklist 60 removeServerFromBlocklist,
61 isBlockedByServerOrAccount
41} 62}
diff --git a/server/lib/notifier.ts b/server/lib/notifier.ts
index 017739523..89f91e031 100644
--- a/server/lib/notifier.ts
+++ b/server/lib/notifier.ts
@@ -1,12 +1,22 @@
1import { getServerActor } from '@server/models/application/application'
2import { ServerBlocklistModel } from '@server/models/server/server-blocklist'
3import {
4 MUser,
5 MUserAccount,
6 MUserDefault,
7 MUserNotifSettingAccount,
8 MUserWithNotificationSetting,
9 UserNotificationModelForApi
10} from '@server/typings/models/user'
11import { MVideoImportVideo } from '@server/typings/models/video/video-import'
1import { UserNotificationSettingValue, UserNotificationType, UserRight } from '../../shared/models/users' 12import { UserNotificationSettingValue, UserNotificationType, UserRight } from '../../shared/models/users'
13import { VideoAbuse, VideoPrivacy, VideoState } from '../../shared/models/videos'
2import { logger } from '../helpers/logger' 14import { logger } from '../helpers/logger'
3import { Emailer } from './emailer'
4import { UserNotificationModel } from '../models/account/user-notification'
5import { UserModel } from '../models/account/user'
6import { PeerTubeSocket } from './peertube-socket'
7import { CONFIG } from '../initializers/config' 15import { CONFIG } from '../initializers/config'
8import { VideoPrivacy, VideoState, VideoAbuse } from '../../shared/models/videos'
9import { AccountBlocklistModel } from '../models/account/account-blocklist' 16import { AccountBlocklistModel } from '../models/account/account-blocklist'
17import { UserModel } from '../models/account/user'
18import { UserNotificationModel } from '../models/account/user-notification'
19import { MAccountServer, MActorFollowFull } from '../typings/models'
10import { 20import {
11 MCommentOwnerVideo, 21 MCommentOwnerVideo,
12 MVideoAbuseVideo, 22 MVideoAbuseVideo,
@@ -15,18 +25,9 @@ import {
15 MVideoBlacklistVideo, 25 MVideoBlacklistVideo,
16 MVideoFullLight 26 MVideoFullLight
17} from '../typings/models/video' 27} from '../typings/models/video'
18import { 28import { isBlockedByServerOrAccount } from './blocklist'
19 MUser, 29import { Emailer } from './emailer'
20 MUserAccount, 30import { PeerTubeSocket } from './peertube-socket'
21 MUserDefault,
22 MUserNotifSettingAccount,
23 MUserWithNotificationSetting,
24 UserNotificationModelForApi
25} from '@server/typings/models/user'
26import { MAccountDefault, MActorFollowFull } from '../typings/models'
27import { MVideoImportVideo } from '@server/typings/models/video/video-import'
28import { ServerBlocklistModel } from '@server/models/server/server-blocklist'
29import { getServerActor } from '@server/models/application/application'
30 31
31class Notifier { 32class Notifier {
32 33
@@ -169,7 +170,7 @@ class Notifier {
169 // Not our user or user comments its own video 170 // Not our user or user comments its own video
170 if (!user || comment.Account.userId === user.id) return 171 if (!user || comment.Account.userId === user.id) return
171 172
172 if (await this.isBlockedByServerOrAccount(user, comment.Account)) return 173 if (await this.isBlockedByServerOrUser(comment.Account, user)) return
173 174
174 logger.info('Notifying user %s of new comment %s.', user.username, comment.url) 175 logger.info('Notifying user %s of new comment %s.', user.username, comment.url)
175 176
@@ -270,7 +271,7 @@ class Notifier {
270 const followerAccount = actorFollow.ActorFollower.Account 271 const followerAccount = actorFollow.ActorFollower.Account
271 const followerAccountWithActor = Object.assign(followerAccount, { Actor: actorFollow.ActorFollower }) 272 const followerAccountWithActor = Object.assign(followerAccount, { Actor: actorFollow.ActorFollower })
272 273
273 if (await this.isBlockedByServerOrAccount(user, followerAccountWithActor)) return 274 if (await this.isBlockedByServerOrUser(followerAccountWithActor, user)) return
274 275
275 logger.info('Notifying user %s of new follower: %s.', user.username, followerAccount.getDisplayName()) 276 logger.info('Notifying user %s of new follower: %s.', user.username, followerAccount.getDisplayName())
276 277
@@ -299,6 +300,9 @@ class Notifier {
299 private async notifyAdminsOfNewInstanceFollow (actorFollow: MActorFollowFull) { 300 private async notifyAdminsOfNewInstanceFollow (actorFollow: MActorFollowFull) {
300 const admins = await UserModel.listWithRight(UserRight.MANAGE_SERVER_FOLLOW) 301 const admins = await UserModel.listWithRight(UserRight.MANAGE_SERVER_FOLLOW)
301 302
303 const follower = Object.assign(actorFollow.ActorFollower.Account, { Actor: actorFollow.ActorFollower })
304 if (await this.isBlockedByServerOrUser(follower)) return
305
302 logger.info('Notifying %d administrators of new instance follower: %s.', admins.length, actorFollow.ActorFollower.url) 306 logger.info('Notifying %d administrators of new instance follower: %s.', admins.length, actorFollow.ActorFollower.url)
303 307
304 function settingGetter (user: MUserWithNotificationSetting) { 308 function settingGetter (user: MUserWithNotificationSetting) {
@@ -590,17 +594,8 @@ class Notifier {
590 return value & UserNotificationSettingValue.WEB 594 return value & UserNotificationSettingValue.WEB
591 } 595 }
592 596
593 private async isBlockedByServerOrAccount (user: MUserAccount, targetAccount: MAccountDefault) { 597 private isBlockedByServerOrUser (targetAccount: MAccountServer, user?: MUserAccount) {
594 const serverAccountId = (await getServerActor()).Account.id 598 return isBlockedByServerOrAccount(targetAccount, user?.Account)
595 const sourceAccounts = [ serverAccountId, user.Account.id ]
596
597 const accountMutedHash = await AccountBlocklistModel.isAccountMutedByMulti(sourceAccounts, targetAccount.id)
598 if (accountMutedHash[serverAccountId] || accountMutedHash[user.Account.id]) return true
599
600 const instanceMutedHash = await ServerBlocklistModel.isServerMutedByMulti(sourceAccounts, targetAccount.Actor.serverId)
601 if (instanceMutedHash[serverAccountId] || instanceMutedHash[user.Account.id]) return true
602
603 return false
604 } 599 }
605 600
606 static get Instance () { 601 static get Instance () {
diff --git a/server/lib/video-comment.ts b/server/lib/video-comment.ts
index 516c912a9..97aa639fb 100644
--- a/server/lib/video-comment.ts
+++ b/server/lib/video-comment.ts
@@ -1,10 +1,32 @@
1import { cloneDeep } from 'lodash'
1import * as Sequelize from 'sequelize' 2import * as Sequelize from 'sequelize'
3import { logger } from '@server/helpers/logger'
4import { sequelizeTypescript } from '@server/initializers/database'
2import { ResultList } from '../../shared/models' 5import { ResultList } from '../../shared/models'
3import { VideoCommentThreadTree } from '../../shared/models/videos/video-comment.model' 6import { VideoCommentThreadTree } from '../../shared/models/videos/video-comment.model'
4import { VideoCommentModel } from '../models/video/video-comment' 7import { VideoCommentModel } from '../models/video/video-comment'
8import { MAccountDefault, MComment, MCommentOwnerVideoReply, MVideoFullLight, MCommentOwnerVideo } from '../typings/models'
9import { sendCreateVideoComment, sendDeleteVideoComment } from './activitypub/send'
5import { getVideoCommentActivityPubUrl } from './activitypub/url' 10import { getVideoCommentActivityPubUrl } from './activitypub/url'
6import { sendCreateVideoComment } from './activitypub/send' 11import { Hooks } from './plugins/hooks'
7import { MAccountDefault, MComment, MCommentOwnerVideoReply, MVideoFullLight } from '../typings/models' 12
13async function removeComment (videoCommentInstance: MCommentOwnerVideo) {
14 const videoCommentInstanceBefore = cloneDeep(videoCommentInstance)
15
16 await sequelizeTypescript.transaction(async t => {
17 if (videoCommentInstance.isOwned() || videoCommentInstance.Video.isOwned()) {
18 await sendDeleteVideoComment(videoCommentInstance, t)
19 }
20
21 markCommentAsDeleted(videoCommentInstance)
22
23 await videoCommentInstance.save()
24 })
25
26 logger.info('Video comment %d deleted.', videoCommentInstance.id)
27
28 Hooks.runAction('action:api.video-comment.deleted', { comment: videoCommentInstanceBefore })
29}
8 30
9async function createVideoComment (obj: { 31async function createVideoComment (obj: {
10 text: string 32 text: string
@@ -73,7 +95,7 @@ function buildFormattedCommentTree (resultList: ResultList<VideoCommentModel>):
73 return thread 95 return thread
74} 96}
75 97
76function markCommentAsDeleted (comment: MCommentOwnerVideoReply): void { 98function markCommentAsDeleted (comment: MComment): void {
77 comment.text = '' 99 comment.text = ''
78 comment.deletedAt = new Date() 100 comment.deletedAt = new Date()
79 comment.accountId = null 101 comment.accountId = null
@@ -82,6 +104,7 @@ function markCommentAsDeleted (comment: MCommentOwnerVideoReply): void {
82// --------------------------------------------------------------------------- 104// ---------------------------------------------------------------------------
83 105
84export { 106export {
107 removeComment,
85 createVideoComment, 108 createVideoComment,
86 buildFormattedCommentTree, 109 buildFormattedCommentTree,
87 markCommentAsDeleted 110 markCommentAsDeleted