diff options
Diffstat (limited to 'server/lib')
-rw-r--r-- | server/lib/activitypub/process/process-create.ts | 23 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-delete.ts | 12 | ||||
-rw-r--r-- | server/lib/blocklist.ts | 25 | ||||
-rw-r--r-- | server/lib/notifier.ts | 55 | ||||
-rw-r--r-- | server/lib/video-comment.ts | 29 |
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 @@ | |||
1 | import { isRedundancyAccepted } from '@server/lib/redundancy' | ||
1 | import { ActivityCreate, CacheFileObject, VideoTorrentObject } from '../../../../shared' | 2 | import { ActivityCreate, CacheFileObject, VideoTorrentObject } from '../../../../shared' |
3 | import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object' | ||
2 | import { VideoCommentObject } from '../../../../shared/models/activitypub/objects/video-comment-object' | 4 | import { VideoCommentObject } from '../../../../shared/models/activitypub/objects/video-comment-object' |
3 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 5 | import { retryTransactionWrapper } from '../../../helpers/database-utils' |
4 | import { logger } from '../../../helpers/logger' | 6 | import { logger } from '../../../helpers/logger' |
5 | import { sequelizeTypescript } from '../../../initializers/database' | 7 | import { sequelizeTypescript } from '../../../initializers/database' |
6 | import { resolveThread } from '../video-comments' | ||
7 | import { getOrCreateVideoAndAccountAndChannel } from '../videos' | ||
8 | import { forwardVideoRelatedActivity } from '../send/utils' | ||
9 | import { createOrUpdateCacheFile } from '../cache-file' | ||
10 | import { Notifier } from '../../notifier' | ||
11 | import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object' | ||
12 | import { createOrUpdateVideoPlaylist } from '../playlist' | ||
13 | import { APProcessorOptions } from '../../../typings/activitypub-processor.model' | 8 | import { APProcessorOptions } from '../../../typings/activitypub-processor.model' |
14 | import { MActorSignature, MCommentOwnerVideo, MVideoAccountLightBlacklistAllFiles } from '../../../typings/models' | 9 | import { MActorSignature, MCommentOwnerVideo, MVideoAccountLightBlacklistAllFiles } from '../../../typings/models' |
15 | import { isRedundancyAccepted } from '@server/lib/redundancy' | 10 | import { Notifier } from '../../notifier' |
11 | import { createOrUpdateCacheFile } from '../cache-file' | ||
12 | import { createOrUpdateVideoPlaylist } from '../playlist' | ||
13 | import { forwardVideoRelatedActivity } from '../send/utils' | ||
14 | import { resolveThread } from '../video-comments' | ||
15 | import { getOrCreateVideoAndAccountAndChannel } from '../videos' | ||
16 | import { isBlockedByServerOrAccount } from '@server/lib/blocklist' | ||
16 | 17 | ||
17 | async function processCreateActivity (options: APProcessorOptions<ActivityCreate>) { | 18 | async 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 @@ | |||
1 | import { Transaction } from 'sequelize' | 1 | import { Transaction } from 'sequelize' |
2 | import { getServerActor } from '@server/models/application/application' | ||
2 | import { ActivityAudience, ActivityDelete } from '../../../../shared/models/activitypub' | 3 | import { ActivityAudience, ActivityDelete } from '../../../../shared/models/activitypub' |
4 | import { logger } from '../../../helpers/logger' | ||
3 | import { ActorModel } from '../../../models/activitypub/actor' | 5 | import { ActorModel } from '../../../models/activitypub/actor' |
4 | import { VideoCommentModel } from '../../../models/video/video-comment' | 6 | import { VideoCommentModel } from '../../../models/video/video-comment' |
5 | import { VideoShareModel } from '../../../models/video/video-share' | 7 | import { VideoShareModel } from '../../../models/video/video-share' |
8 | import { MActorUrl } from '../../../typings/models' | ||
9 | import { MCommentOwnerVideo, MVideoAccountLight, MVideoPlaylistFullSummary } from '../../../typings/models/video' | ||
10 | import { audiencify, getActorsInvolvedInVideo, getVideoCommentAudience } from '../audience' | ||
6 | import { getDeleteActivityPubUrl } from '../url' | 11 | import { getDeleteActivityPubUrl } from '../url' |
7 | import { broadcastToActors, broadcastToFollowers, sendVideoRelatedActivity, unicastTo } from './utils' | 12 | import { broadcastToActors, broadcastToFollowers, sendVideoRelatedActivity, unicastTo } from './utils' |
8 | import { audiencify, getActorsInvolvedInVideo, getVideoCommentAudience } from '../audience' | ||
9 | import { logger } from '../../../helpers/logger' | ||
10 | import { MCommentOwnerVideoReply, MVideoAccountLight, MVideoPlaylistFullSummary } from '../../../typings/models/video' | ||
11 | import { MActorUrl } from '../../../typings/models' | ||
12 | import { getServerActor } from '@server/models/application/application' | ||
13 | 13 | ||
14 | async function sendDeleteVideo (video: MVideoAccountLight, transaction: Transaction) { | 14 | async 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 | ||
45 | async function sendDeleteVideoComment (videoComment: MCommentOwnerVideoReply, t: Transaction) { | 45 | async 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 @@ | |||
1 | import { sequelizeTypescript } from '@server/initializers/database' | 1 | import { sequelizeTypescript } from '@server/initializers/database' |
2 | import { MAccountBlocklist, MServerBlocklist } from '@server/typings/models' | 2 | import { getServerActor } from '@server/models/application/application' |
3 | import { MAccountBlocklist, MAccountId, MAccountServer, MServerBlocklist } from '@server/typings/models' | ||
3 | import { AccountBlocklistModel } from '../models/account/account-blocklist' | 4 | import { AccountBlocklistModel } from '../models/account/account-blocklist' |
4 | import { ServerBlocklistModel } from '../models/server/server-blocklist' | 5 | import { ServerBlocklistModel } from '../models/server/server-blocklist' |
5 | 6 | ||
@@ -33,9 +34,29 @@ function removeServerFromBlocklist (serverBlock: MServerBlocklist) { | |||
33 | }) | 34 | }) |
34 | } | 35 | } |
35 | 36 | ||
37 | async 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 | |||
36 | export { | 56 | export { |
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 @@ | |||
1 | import { getServerActor } from '@server/models/application/application' | ||
2 | import { ServerBlocklistModel } from '@server/models/server/server-blocklist' | ||
3 | import { | ||
4 | MUser, | ||
5 | MUserAccount, | ||
6 | MUserDefault, | ||
7 | MUserNotifSettingAccount, | ||
8 | MUserWithNotificationSetting, | ||
9 | UserNotificationModelForApi | ||
10 | } from '@server/typings/models/user' | ||
11 | import { MVideoImportVideo } from '@server/typings/models/video/video-import' | ||
1 | import { UserNotificationSettingValue, UserNotificationType, UserRight } from '../../shared/models/users' | 12 | import { UserNotificationSettingValue, UserNotificationType, UserRight } from '../../shared/models/users' |
13 | import { VideoAbuse, VideoPrivacy, VideoState } from '../../shared/models/videos' | ||
2 | import { logger } from '../helpers/logger' | 14 | import { logger } from '../helpers/logger' |
3 | import { Emailer } from './emailer' | ||
4 | import { UserNotificationModel } from '../models/account/user-notification' | ||
5 | import { UserModel } from '../models/account/user' | ||
6 | import { PeerTubeSocket } from './peertube-socket' | ||
7 | import { CONFIG } from '../initializers/config' | 15 | import { CONFIG } from '../initializers/config' |
8 | import { VideoPrivacy, VideoState, VideoAbuse } from '../../shared/models/videos' | ||
9 | import { AccountBlocklistModel } from '../models/account/account-blocklist' | 16 | import { AccountBlocklistModel } from '../models/account/account-blocklist' |
17 | import { UserModel } from '../models/account/user' | ||
18 | import { UserNotificationModel } from '../models/account/user-notification' | ||
19 | import { MAccountServer, MActorFollowFull } from '../typings/models' | ||
10 | import { | 20 | import { |
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' |
18 | import { | 28 | import { isBlockedByServerOrAccount } from './blocklist' |
19 | MUser, | 29 | import { Emailer } from './emailer' |
20 | MUserAccount, | 30 | import { PeerTubeSocket } from './peertube-socket' |
21 | MUserDefault, | ||
22 | MUserNotifSettingAccount, | ||
23 | MUserWithNotificationSetting, | ||
24 | UserNotificationModelForApi | ||
25 | } from '@server/typings/models/user' | ||
26 | import { MAccountDefault, MActorFollowFull } from '../typings/models' | ||
27 | import { MVideoImportVideo } from '@server/typings/models/video/video-import' | ||
28 | import { ServerBlocklistModel } from '@server/models/server/server-blocklist' | ||
29 | import { getServerActor } from '@server/models/application/application' | ||
30 | 31 | ||
31 | class Notifier { | 32 | class 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 @@ | |||
1 | import { cloneDeep } from 'lodash' | ||
1 | import * as Sequelize from 'sequelize' | 2 | import * as Sequelize from 'sequelize' |
3 | import { logger } from '@server/helpers/logger' | ||
4 | import { sequelizeTypescript } from '@server/initializers/database' | ||
2 | import { ResultList } from '../../shared/models' | 5 | import { ResultList } from '../../shared/models' |
3 | import { VideoCommentThreadTree } from '../../shared/models/videos/video-comment.model' | 6 | import { VideoCommentThreadTree } from '../../shared/models/videos/video-comment.model' |
4 | import { VideoCommentModel } from '../models/video/video-comment' | 7 | import { VideoCommentModel } from '../models/video/video-comment' |
8 | import { MAccountDefault, MComment, MCommentOwnerVideoReply, MVideoFullLight, MCommentOwnerVideo } from '../typings/models' | ||
9 | import { sendCreateVideoComment, sendDeleteVideoComment } from './activitypub/send' | ||
5 | import { getVideoCommentActivityPubUrl } from './activitypub/url' | 10 | import { getVideoCommentActivityPubUrl } from './activitypub/url' |
6 | import { sendCreateVideoComment } from './activitypub/send' | 11 | import { Hooks } from './plugins/hooks' |
7 | import { MAccountDefault, MComment, MCommentOwnerVideoReply, MVideoFullLight } from '../typings/models' | 12 | |
13 | async 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 | ||
9 | async function createVideoComment (obj: { | 31 | async 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 | ||
76 | function markCommentAsDeleted (comment: MCommentOwnerVideoReply): void { | 98 | function 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 | ||
84 | export { | 106 | export { |
107 | removeComment, | ||
85 | createVideoComment, | 108 | createVideoComment, |
86 | buildFormattedCommentTree, | 109 | buildFormattedCommentTree, |
87 | markCommentAsDeleted | 110 | markCommentAsDeleted |