aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/activitypub
diff options
context:
space:
mode:
authorChocobozzz <florian.bigard@gmail.com>2017-11-17 15:20:42 +0100
committerChocobozzz <florian.bigard@gmail.com>2017-11-27 19:40:52 +0100
commit9a27cdc27c900feaae5f6db4315c4ccdfc0c4493 (patch)
treef91fcfa0fa1a2e45aae1c5333ef2f7ec60e56ef0 /server/lib/activitypub
parent975e6e0e44e2f2b25f804cd48a62e2a8d9e8117a (diff)
downloadPeerTube-9a27cdc27c900feaae5f6db4315c4ccdfc0c4493.tar.gz
PeerTube-9a27cdc27c900feaae5f6db4315c4ccdfc0c4493.tar.zst
PeerTube-9a27cdc27c900feaae5f6db4315c4ccdfc0c4493.zip
Optimize signature verification
Diffstat (limited to 'server/lib/activitypub')
-rw-r--r--server/lib/activitypub/misc.ts16
-rw-r--r--server/lib/activitypub/process-add.ts15
-rw-r--r--server/lib/activitypub/process-update.ts1
-rw-r--r--server/lib/activitypub/send-request.ts37
4 files changed, 48 insertions, 21 deletions
diff --git a/server/lib/activitypub/misc.ts b/server/lib/activitypub/misc.ts
index c07d9f654..4c210eb10 100644
--- a/server/lib/activitypub/misc.ts
+++ b/server/lib/activitypub/misc.ts
@@ -2,11 +2,12 @@ import * as magnetUtil from 'magnet-uri'
2import { VideoTorrentObject } from '../../../shared' 2import { VideoTorrentObject } from '../../../shared'
3import { VideoChannelObject } from '../../../shared/models/activitypub/objects/video-channel-object' 3import { VideoChannelObject } from '../../../shared/models/activitypub/objects/video-channel-object'
4import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos' 4import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos'
5import { VIDEO_MIMETYPE_EXT } from '../../initializers/constants' 5import { ACTIVITY_PUB, VIDEO_MIMETYPE_EXT } from '../../initializers/constants'
6import { AccountInstance } from '../../models/account/account-interface' 6import { AccountInstance } from '../../models/account/account-interface'
7import { VideoChannelInstance } from '../../models/video/video-channel-interface' 7import { VideoChannelInstance } from '../../models/video/video-channel-interface'
8import { VideoFileAttributes } from '../../models/video/video-file-interface' 8import { VideoFileAttributes } from '../../models/video/video-file-interface'
9import { VideoAttributes, VideoInstance } from '../../models/video/video-interface' 9import { VideoAttributes, VideoInstance } from '../../models/video/video-interface'
10import { VideoPrivacy } from '../../../shared/models/videos/video-privacy.enum'
10 11
11function videoChannelActivityObjectToDBAttributes (videoChannelObject: VideoChannelObject, account: AccountInstance) { 12function videoChannelActivityObjectToDBAttributes (videoChannelObject: VideoChannelObject, account: AccountInstance) {
12 return { 13 return {
@@ -23,8 +24,14 @@ function videoChannelActivityObjectToDBAttributes (videoChannelObject: VideoChan
23 24
24async function videoActivityObjectToDBAttributes ( 25async function videoActivityObjectToDBAttributes (
25 videoChannel: VideoChannelInstance, 26 videoChannel: VideoChannelInstance,
26 videoObject: VideoTorrentObject 27 videoObject: VideoTorrentObject,
28 to: string[] = [],
29 cc: string[] = []
27) { 30) {
31 let privacy = VideoPrivacy.PRIVATE
32 if (to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1) privacy = VideoPrivacy.PUBLIC
33 else if (cc.indexOf(ACTIVITY_PUB.PUBLIC) !== -1) privacy = VideoPrivacy.UNLISTED
34
28 const duration = videoObject.duration.replace(/[^\d]+/, '') 35 const duration = videoObject.duration.replace(/[^\d]+/, '')
29 const videoData: VideoAttributes = { 36 const videoData: VideoAttributes = {
30 name: videoObject.name, 37 name: videoObject.name,
@@ -43,11 +50,8 @@ async function videoActivityObjectToDBAttributes (
43 views: videoObject.views, 50 views: videoObject.views,
44 likes: 0, 51 likes: 0,
45 dislikes: 0, 52 dislikes: 0,
46 // likes: videoToCreateData.likes,
47 // dislikes: videoToCreateData.dislikes,
48 remote: true, 53 remote: true,
49 privacy: 1 54 privacy
50 // privacy: videoToCreateData.privacy
51 } 55 }
52 56
53 return videoData 57 return videoData
diff --git a/server/lib/activitypub/process-add.ts b/server/lib/activitypub/process-add.ts
index 72c5b1932..c83d9e98e 100644
--- a/server/lib/activitypub/process-add.ts
+++ b/server/lib/activitypub/process-add.ts
@@ -17,7 +17,7 @@ async function processAddActivity (activity: ActivityAdd) {
17 const videoChannelUrl = activity.target 17 const videoChannelUrl = activity.target
18 const videoChannel = await getOrCreateVideoChannel(account, videoChannelUrl) 18 const videoChannel = await getOrCreateVideoChannel(account, videoChannelUrl)
19 19
20 return processAddVideo(account, videoChannel, activityObject as VideoTorrentObject) 20 return processAddVideo(account, activity, videoChannel, activityObject as VideoTorrentObject)
21 } 21 }
22 22
23 logger.warn('Unknown activity object type %s when creating activity.', activityType, { activity: activity.id }) 23 logger.warn('Unknown activity object type %s when creating activity.', activityType, { activity: activity.id })
@@ -32,16 +32,21 @@ export {
32 32
33// --------------------------------------------------------------------------- 33// ---------------------------------------------------------------------------
34 34
35function processAddVideo (account: AccountInstance, videoChannel: VideoChannelInstance, video: VideoTorrentObject) { 35function processAddVideo (account: AccountInstance, activity: ActivityAdd, videoChannel: VideoChannelInstance, video: VideoTorrentObject) {
36 const options = { 36 const options = {
37 arguments: [ account, videoChannel, video ], 37 arguments: [ account, activity, videoChannel, video ],
38 errorMessage: 'Cannot insert the remote video with many retries.' 38 errorMessage: 'Cannot insert the remote video with many retries.'
39 } 39 }
40 40
41 return retryTransactionWrapper(addRemoteVideo, options) 41 return retryTransactionWrapper(addRemoteVideo, options)
42} 42}
43 43
44function addRemoteVideo (account: AccountInstance, videoChannel: VideoChannelInstance, videoToCreateData: VideoTorrentObject) { 44function addRemoteVideo (
45 account: AccountInstance,
46 activity: ActivityAdd,
47 videoChannel: VideoChannelInstance,
48 videoToCreateData: VideoTorrentObject
49) {
45 logger.debug('Adding remote video %s.', videoToCreateData.url) 50 logger.debug('Adding remote video %s.', videoToCreateData.url)
46 51
47 return db.sequelize.transaction(async t => { 52 return db.sequelize.transaction(async t => {
@@ -54,7 +59,7 @@ function addRemoteVideo (account: AccountInstance, videoChannel: VideoChannelIns
54 const videoFromDatabase = await db.Video.loadByUUIDOrURL(videoToCreateData.uuid, videoToCreateData.id, t) 59 const videoFromDatabase = await db.Video.loadByUUIDOrURL(videoToCreateData.uuid, videoToCreateData.id, t)
55 if (videoFromDatabase) throw new Error('Video with this UUID/Url already exists.') 60 if (videoFromDatabase) throw new Error('Video with this UUID/Url already exists.')
56 61
57 const videoData = await videoActivityObjectToDBAttributes(videoChannel, videoToCreateData) 62 const videoData = await videoActivityObjectToDBAttributes(videoChannel, videoToCreateData, activity.to, activity.cc)
58 const video = db.Video.build(videoData) 63 const video = db.Video.build(videoData)
59 64
60 // Don't block on request 65 // Don't block on request
diff --git a/server/lib/activitypub/process-update.ts b/server/lib/activitypub/process-update.ts
index 4aefd1b9b..b732fce33 100644
--- a/server/lib/activitypub/process-update.ts
+++ b/server/lib/activitypub/process-update.ts
@@ -70,7 +70,6 @@ async function updateRemoteVideo (account: AccountInstance, videoAttributesToUpd
70 videoInstance.set('views', videoData.views) 70 videoInstance.set('views', videoData.views)
71 // videoInstance.set('likes', videoData.likes) 71 // videoInstance.set('likes', videoData.likes)
72 // videoInstance.set('dislikes', videoData.dislikes) 72 // videoInstance.set('dislikes', videoData.dislikes)
73 // videoInstance.set('privacy', videoData.privacy)
74 73
75 await videoInstance.save(sequelizeOptions) 74 await videoInstance.save(sequelizeOptions)
76 75
diff --git a/server/lib/activitypub/send-request.ts b/server/lib/activitypub/send-request.ts
index 8d013fa87..68a631a36 100644
--- a/server/lib/activitypub/send-request.ts
+++ b/server/lib/activitypub/send-request.ts
@@ -13,6 +13,8 @@ import { database as db } from '../../initializers'
13import { AccountInstance, VideoChannelInstance, VideoInstance } from '../../models' 13import { AccountInstance, VideoChannelInstance, VideoInstance } from '../../models'
14import { VideoAbuseInstance } from '../../models/video/video-abuse-interface' 14import { VideoAbuseInstance } from '../../models/video/video-abuse-interface'
15import { activitypubHttpJobScheduler } from '../jobs' 15import { activitypubHttpJobScheduler } from '../jobs'
16import { ACTIVITY_PUB } from '../../initializers/constants'
17import { VideoPrivacy } from '../../../shared/models/videos/video-privacy.enum'
16 18
17async function sendCreateVideoChannel (videoChannel: VideoChannelInstance, t: Transaction) { 19async function sendCreateVideoChannel (videoChannel: VideoChannelInstance, t: Transaction) {
18 const byAccount = videoChannel.Account 20 const byAccount = videoChannel.Account
@@ -50,7 +52,7 @@ async function sendAddVideo (video: VideoInstance, t: Transaction) {
50 const byAccount = video.VideoChannel.Account 52 const byAccount = video.VideoChannel.Account
51 53
52 const videoObject = video.toActivityPubObject() 54 const videoObject = video.toActivityPubObject()
53 const data = await addActivityData(video.url, byAccount, video.VideoChannel.url, videoObject) 55 const data = await addActivityData(video.url, byAccount, video, video.VideoChannel.url, videoObject)
54 56
55 return broadcastToFollowers(data, byAccount, [ byAccount ], t) 57 return broadcastToFollowers(data, byAccount, [ byAccount ], t)
56} 58}
@@ -96,7 +98,7 @@ async function sendVideoAnnounce (byAccount: AccountInstance, video: VideoInstan
96 const url = getActivityPubUrl('video', video.uuid) + '#announce' 98 const url = getActivityPubUrl('video', video.uuid) + '#announce'
97 99
98 const videoChannel = video.VideoChannel 100 const videoChannel = video.VideoChannel
99 const announcedActivity = await addActivityData(url, videoChannel.Account, videoChannel.url, video.toActivityPubObject()) 101 const announcedActivity = await addActivityData(url, videoChannel.Account, video, videoChannel.url, video.toActivityPubObject())
100 102
101 const data = await announceActivityData(url, byAccount, announcedActivity) 103 const data = await announceActivityData(url, byAccount, announcedActivity)
102 return broadcastToFollowers(data, byAccount, [ byAccount ], t) 104 return broadcastToFollowers(data, byAccount, [ byAccount ], t)
@@ -167,19 +169,32 @@ async function unicastTo (data: any, byAccount: AccountInstance, toAccountUrl: s
167 return activitypubHttpJobScheduler.createJob(t, 'activitypubHttpUnicastHandler', jobPayload) 169 return activitypubHttpJobScheduler.createJob(t, 'activitypubHttpUnicastHandler', jobPayload)
168} 170}
169 171
170async function getPublicActivityTo (account: AccountInstance) { 172async function getAudience (accountSender: AccountInstance, isPublic = true) {
171 const inboxUrls = await account.getFollowerSharedInboxUrls() 173 const followerInboxUrls = await accountSender.getFollowerSharedInboxUrls()
172 174
173 return inboxUrls.concat('https://www.w3.org/ns/activitystreams#Public') 175 // Thanks Mastodon: https://github.com/tootsuite/mastodon/blob/master/app/lib/activitypub/tag_manager.rb#L47
176 let to = []
177 let cc = []
178
179 if (isPublic) {
180 to = [ ACTIVITY_PUB.PUBLIC ]
181 cc = followerInboxUrls
182 } else { // Unlisted
183 to = followerInboxUrls
184 cc = [ ACTIVITY_PUB.PUBLIC ]
185 }
186
187 return { to, cc }
174} 188}
175 189
176async function createActivityData (url: string, byAccount: AccountInstance, object: any) { 190async function createActivityData (url: string, byAccount: AccountInstance, object: any) {
177 const to = await getPublicActivityTo(byAccount) 191 const { to, cc } = await getAudience(byAccount)
178 const activity: ActivityCreate = { 192 const activity: ActivityCreate = {
179 type: 'Create', 193 type: 'Create',
180 id: url, 194 id: url,
181 actor: byAccount.url, 195 actor: byAccount.url,
182 to, 196 to,
197 cc,
183 object 198 object
184 } 199 }
185 200
@@ -187,12 +202,13 @@ async function createActivityData (url: string, byAccount: AccountInstance, obje
187} 202}
188 203
189async function updateActivityData (url: string, byAccount: AccountInstance, object: any) { 204async function updateActivityData (url: string, byAccount: AccountInstance, object: any) {
190 const to = await getPublicActivityTo(byAccount) 205 const { to, cc } = await getAudience(byAccount)
191 const activity: ActivityUpdate = { 206 const activity: ActivityUpdate = {
192 type: 'Update', 207 type: 'Update',
193 id: url, 208 id: url,
194 actor: byAccount.url, 209 actor: byAccount.url,
195 to, 210 to,
211 cc,
196 object 212 object
197 } 213 }
198 214
@@ -209,13 +225,16 @@ async function deleteActivityData (url: string, byAccount: AccountInstance) {
209 return activity 225 return activity
210} 226}
211 227
212async function addActivityData (url: string, byAccount: AccountInstance, target: string, object: any) { 228async function addActivityData (url: string, byAccount: AccountInstance, video: VideoInstance, target: string, object: any) {
213 const to = await getPublicActivityTo(byAccount) 229 const videoPublic = video.privacy === VideoPrivacy.PUBLIC
230
231 const { to, cc } = await getAudience(byAccount, videoPublic)
214 const activity: ActivityAdd = { 232 const activity: ActivityAdd = {
215 type: 'Add', 233 type: 'Add',
216 id: url, 234 id: url,
217 actor: byAccount.url, 235 actor: byAccount.url,
218 to, 236 to,
237 cc,
219 object, 238 object,
220 target 239 target
221 } 240 }