aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/controllers/activitypub/client.ts2
-rw-r--r--server/helpers/activitypub.ts179
-rw-r--r--server/lib/activitypub/send/send-announce.ts2
-rw-r--r--server/lib/activitypub/send/send-view.ts2
-rw-r--r--server/lib/activitypub/send/utils.ts30
-rw-r--r--server/lib/job-queue/handlers/activitypub-http-broadcast.ts2
-rw-r--r--server/lib/job-queue/handlers/activitypub-http-unicast.ts2
-rw-r--r--server/lib/job-queue/handlers/utils/activitypub-http-utils.ts6
8 files changed, 121 insertions, 104 deletions
diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts
index 39f6d7231..2812bfe1e 100644
--- a/server/controllers/activitypub/client.ts
+++ b/server/controllers/activitypub/client.ts
@@ -234,7 +234,7 @@ async function videoAnnounceController (req: express.Request, res: express.Respo
234 234
235 const { activity } = await buildAnnounceWithVideoAudience(share.Actor, share, res.locals.videoAll, undefined) 235 const { activity } = await buildAnnounceWithVideoAudience(share.Actor, share, res.locals.videoAll, undefined)
236 236
237 return activityPubResponse(activityPubContextify(activity), res) 237 return activityPubResponse(activityPubContextify(activity, 'Announce'), res)
238} 238}
239 239
240async function videoAnnouncesController (req: express.Request, res: express.Response) { 240async function videoAnnouncesController (req: express.Request, res: express.Response) {
diff --git a/server/helpers/activitypub.ts b/server/helpers/activitypub.ts
index 22f8550ca..326785b68 100644
--- a/server/helpers/activitypub.ts
+++ b/server/helpers/activitypub.ts
@@ -8,93 +8,100 @@ import { pageToStartAndCount } from './core-utils'
8import { URL } from 'url' 8import { URL } from 'url'
9import { MActor, MVideoAccountLight } from '../typings/models' 9import { MActor, MVideoAccountLight } from '../typings/models'
10 10
11function activityPubContextify <T> (data: T) { 11export type ContextType = 'All' | 'View' | 'Announce'
12 return Object.assign(data, { 12
13function activityPubContextify <T> (data: T, type: ContextType = 'All') {
14 const base = {
15 RsaSignature2017: 'https://w3id.org/security#RsaSignature2017'
16 }
17
18 if (type === 'All') {
19 Object.assign(base, {
20 pt: 'https://joinpeertube.org/ns#',
21 sc: 'http://schema.org#',
22 Hashtag: 'as:Hashtag',
23 uuid: 'sc:identifier',
24 category: 'sc:category',
25 licence: 'sc:license',
26 subtitleLanguage: 'sc:subtitleLanguage',
27 sensitive: 'as:sensitive',
28 language: 'sc:inLanguage',
29 expires: 'sc:expires',
30 CacheFile: 'pt:CacheFile',
31 Infohash: 'pt:Infohash',
32 originallyPublishedAt: 'sc:datePublished',
33 views: {
34 '@type': 'sc:Number',
35 '@id': 'pt:views'
36 },
37 state: {
38 '@type': 'sc:Number',
39 '@id': 'pt:state'
40 },
41 size: {
42 '@type': 'sc:Number',
43 '@id': 'pt:size'
44 },
45 fps: {
46 '@type': 'sc:Number',
47 '@id': 'pt:fps'
48 },
49 startTimestamp: {
50 '@type': 'sc:Number',
51 '@id': 'pt:startTimestamp'
52 },
53 stopTimestamp: {
54 '@type': 'sc:Number',
55 '@id': 'pt:stopTimestamp'
56 },
57 position: {
58 '@type': 'sc:Number',
59 '@id': 'pt:position'
60 },
61 commentsEnabled: {
62 '@type': 'sc:Boolean',
63 '@id': 'pt:commentsEnabled'
64 },
65 downloadEnabled: {
66 '@type': 'sc:Boolean',
67 '@id': 'pt:downloadEnabled'
68 },
69 waitTranscoding: {
70 '@type': 'sc:Boolean',
71 '@id': 'pt:waitTranscoding'
72 },
73 support: {
74 '@type': 'sc:Text',
75 '@id': 'pt:support'
76 },
77 likes: {
78 '@id': 'as:likes',
79 '@type': '@id'
80 },
81 dislikes: {
82 '@id': 'as:dislikes',
83 '@type': '@id'
84 },
85 playlists: {
86 '@id': 'pt:playlists',
87 '@type': '@id'
88 },
89 shares: {
90 '@id': 'as:shares',
91 '@type': '@id'
92 },
93 comments: {
94 '@id': 'as:comments',
95 '@type': '@id'
96 }
97 })
98 }
99
100 return Object.assign({}, data, {
13 '@context': [ 101 '@context': [
14 'https://www.w3.org/ns/activitystreams', 102 'https://www.w3.org/ns/activitystreams',
15 'https://w3id.org/security/v1', 103 'https://w3id.org/security/v1',
16 { 104 base
17 RsaSignature2017: 'https://w3id.org/security#RsaSignature2017',
18 pt: 'https://joinpeertube.org/ns#',
19 sc: 'http://schema.org#',
20 Hashtag: 'as:Hashtag',
21 uuid: 'sc:identifier',
22 category: 'sc:category',
23 licence: 'sc:license',
24 subtitleLanguage: 'sc:subtitleLanguage',
25 sensitive: 'as:sensitive',
26 language: 'sc:inLanguage',
27 expires: 'sc:expires',
28 CacheFile: 'pt:CacheFile',
29 Infohash: 'pt:Infohash',
30 originallyPublishedAt: 'sc:datePublished',
31 views: {
32 '@type': 'sc:Number',
33 '@id': 'pt:views'
34 },
35 state: {
36 '@type': 'sc:Number',
37 '@id': 'pt:state'
38 },
39 size: {
40 '@type': 'sc:Number',
41 '@id': 'pt:size'
42 },
43 fps: {
44 '@type': 'sc:Number',
45 '@id': 'pt:fps'
46 },
47 startTimestamp: {
48 '@type': 'sc:Number',
49 '@id': 'pt:startTimestamp'
50 },
51 stopTimestamp: {
52 '@type': 'sc:Number',
53 '@id': 'pt:stopTimestamp'
54 },
55 position: {
56 '@type': 'sc:Number',
57 '@id': 'pt:position'
58 },
59 commentsEnabled: {
60 '@type': 'sc:Boolean',
61 '@id': 'pt:commentsEnabled'
62 },
63 downloadEnabled: {
64 '@type': 'sc:Boolean',
65 '@id': 'pt:downloadEnabled'
66 },
67 waitTranscoding: {
68 '@type': 'sc:Boolean',
69 '@id': 'pt:waitTranscoding'
70 },
71 support: {
72 '@type': 'sc:Text',
73 '@id': 'pt:support'
74 }
75 },
76 {
77 likes: {
78 '@id': 'as:likes',
79 '@type': '@id'
80 },
81 dislikes: {
82 '@id': 'as:dislikes',
83 '@type': '@id'
84 },
85 playlists: {
86 '@id': 'pt:playlists',
87 '@type': '@id'
88 },
89 shares: {
90 '@id': 'as:shares',
91 '@type': '@id'
92 },
93 comments: {
94 '@id': 'as:comments',
95 '@type': '@id'
96 }
97 }
98 ] 105 ]
99 }) 106 })
100} 107}
@@ -148,8 +155,8 @@ async function activityPubCollectionPagination (
148 155
149} 156}
150 157
151function buildSignedActivity (byActor: MActor, data: Object) { 158function buildSignedActivity (byActor: MActor, data: Object, contextType?: ContextType) {
152 const activity = activityPubContextify(data) 159 const activity = activityPubContextify(data, contextType)
153 160
154 return signJsonLDObject(byActor, activity) as Promise<Activity> 161 return signJsonLDObject(byActor, activity) as Promise<Activity>
155} 162}
diff --git a/server/lib/activitypub/send/send-announce.ts b/server/lib/activitypub/send/send-announce.ts
index a0f33852c..d03b358f1 100644
--- a/server/lib/activitypub/send/send-announce.ts
+++ b/server/lib/activitypub/send/send-announce.ts
@@ -28,7 +28,7 @@ async function sendVideoAnnounce (byActor: MActorLight, videoShare: MVideoShare,
28 logger.info('Creating job to send announce %s.', videoShare.url) 28 logger.info('Creating job to send announce %s.', videoShare.url)
29 29
30 const followersException = [ byActor ] 30 const followersException = [ byActor ]
31 return broadcastToFollowers(activity, byActor, actorsInvolvedInVideo, t, followersException) 31 return broadcastToFollowers(activity, byActor, actorsInvolvedInVideo, t, followersException, 'Announce')
32} 32}
33 33
34function buildAnnounceActivity (url: string, byActor: MActorLight, object: string, audience?: ActivityAudience): ActivityAnnounce { 34function buildAnnounceActivity (url: string, byActor: MActorLight, object: string, audience?: ActivityAudience): ActivityAnnounce {
diff --git a/server/lib/activitypub/send/send-view.ts b/server/lib/activitypub/send/send-view.ts
index 8809417f9..47482b9a9 100644
--- a/server/lib/activitypub/send/send-view.ts
+++ b/server/lib/activitypub/send/send-view.ts
@@ -16,7 +16,7 @@ async function sendView (byActor: ActorModel, video: MVideoAccountLight, t: Tran
16 return buildViewActivity(url, byActor, video, audience) 16 return buildViewActivity(url, byActor, video, audience)
17 } 17 }
18 18
19 return sendVideoRelatedActivity(activityBuilder, { byActor, video, transaction: t }) 19 return sendVideoRelatedActivity(activityBuilder, { byActor, video, transaction: t, contextType: 'View' })
20} 20}
21 21
22function buildViewActivity (url: string, byActor: MActorAudience, video: MVideoUrl, audience?: ActivityAudience): ActivityView { 22function buildViewActivity (url: string, byActor: MActorAudience, video: MVideoUrl, audience?: ActivityAudience): ActivityView {
diff --git a/server/lib/activitypub/send/utils.ts b/server/lib/activitypub/send/utils.ts
index 6fb4efd60..ce932eb1f 100644
--- a/server/lib/activitypub/send/utils.ts
+++ b/server/lib/activitypub/send/utils.ts
@@ -8,13 +8,15 @@ import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getRemoteVideoAud
8import { getServerActor } from '../../../helpers/utils' 8import { getServerActor } from '../../../helpers/utils'
9import { afterCommitIfTransaction } from '../../../helpers/database-utils' 9import { afterCommitIfTransaction } from '../../../helpers/database-utils'
10import { MActorWithInboxes, MActor, MActorId, MActorLight, MVideo, MVideoAccountLight } from '../../../typings/models' 10import { MActorWithInboxes, MActor, MActorId, MActorLight, MVideo, MVideoAccountLight } from '../../../typings/models'
11import { ContextType } from '@server/helpers/activitypub'
11 12
12async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: { 13async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: {
13 byActor: MActorLight 14 byActor: MActorLight
14 video: MVideoAccountLight 15 video: MVideoAccountLight
15 transaction?: Transaction 16 transaction?: Transaction,
17 contextType?: ContextType
16}) { 18}) {
17 const { byActor, video, transaction } = options 19 const { byActor, video, transaction, contextType } = options
18 20
19 const actorsInvolvedInVideo = await getActorsInvolvedInVideo(video, transaction) 21 const actorsInvolvedInVideo = await getActorsInvolvedInVideo(video, transaction)
20 22
@@ -24,7 +26,7 @@ async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAud
24 const activity = activityBuilder(audience) 26 const activity = activityBuilder(audience)
25 27
26 return afterCommitIfTransaction(transaction, () => { 28 return afterCommitIfTransaction(transaction, () => {
27 return unicastTo(activity, byActor, video.VideoChannel.Account.Actor.getSharedInbox()) 29 return unicastTo(activity, byActor, video.VideoChannel.Account.Actor.getSharedInbox(), contextType)
28 }) 30 })
29 } 31 }
30 32
@@ -34,7 +36,7 @@ async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAud
34 36
35 const actorsException = [ byActor ] 37 const actorsException = [ byActor ]
36 38
37 return broadcastToFollowers(activity, byActor, actorsInvolvedInVideo, transaction, actorsException) 39 return broadcastToFollowers(activity, byActor, actorsInvolvedInVideo, transaction, actorsException, contextType)
38} 40}
39 41
40async function forwardVideoRelatedActivity ( 42async function forwardVideoRelatedActivity (
@@ -90,11 +92,12 @@ async function broadcastToFollowers (
90 byActor: MActorId, 92 byActor: MActorId,
91 toFollowersOf: MActorId[], 93 toFollowersOf: MActorId[],
92 t: Transaction, 94 t: Transaction,
93 actorsException: MActorWithInboxes[] = [] 95 actorsException: MActorWithInboxes[] = [],
96 contextType?: ContextType
94) { 97) {
95 const uris = await computeFollowerUris(toFollowersOf, actorsException, t) 98 const uris = await computeFollowerUris(toFollowersOf, actorsException, t)
96 99
97 return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor)) 100 return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor, contextType))
98} 101}
99 102
100async function broadcastToActors ( 103async function broadcastToActors (
@@ -102,13 +105,14 @@ async function broadcastToActors (
102 byActor: MActorId, 105 byActor: MActorId,
103 toActors: MActor[], 106 toActors: MActor[],
104 t?: Transaction, 107 t?: Transaction,
105 actorsException: MActorWithInboxes[] = [] 108 actorsException: MActorWithInboxes[] = [],
109 contextType?: ContextType
106) { 110) {
107 const uris = await computeUris(toActors, actorsException) 111 const uris = await computeUris(toActors, actorsException)
108 return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor)) 112 return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor, contextType))
109} 113}
110 114
111function broadcastTo (uris: string[], data: any, byActor: MActorId) { 115function broadcastTo (uris: string[], data: any, byActor: MActorId, contextType?: ContextType) {
112 if (uris.length === 0) return undefined 116 if (uris.length === 0) return undefined
113 117
114 logger.debug('Creating broadcast job.', { uris }) 118 logger.debug('Creating broadcast job.', { uris })
@@ -116,19 +120,21 @@ function broadcastTo (uris: string[], data: any, byActor: MActorId) {
116 const payload = { 120 const payload = {
117 uris, 121 uris,
118 signatureActorId: byActor.id, 122 signatureActorId: byActor.id,
119 body: data 123 body: data,
124 contextType
120 } 125 }
121 126
122 return JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload }) 127 return JobQueue.Instance.createJob({ type: 'activitypub-http-broadcast', payload })
123} 128}
124 129
125function unicastTo (data: any, byActor: MActorId, toActorUrl: string) { 130function unicastTo (data: any, byActor: MActorId, toActorUrl: string, contextType?: ContextType) {
126 logger.debug('Creating unicast job.', { uri: toActorUrl }) 131 logger.debug('Creating unicast job.', { uri: toActorUrl })
127 132
128 const payload = { 133 const payload = {
129 uri: toActorUrl, 134 uri: toActorUrl,
130 signatureActorId: byActor.id, 135 signatureActorId: byActor.id,
131 body: data 136 body: data,
137 contextType
132 } 138 }
133 139
134 JobQueue.Instance.createJob({ type: 'activitypub-http-unicast', payload }) 140 JobQueue.Instance.createJob({ type: 'activitypub-http-unicast', payload })
diff --git a/server/lib/job-queue/handlers/activitypub-http-broadcast.ts b/server/lib/job-queue/handlers/activitypub-http-broadcast.ts
index 0ff7b44a0..7d9dd61e9 100644
--- a/server/lib/job-queue/handlers/activitypub-http-broadcast.ts
+++ b/server/lib/job-queue/handlers/activitypub-http-broadcast.ts
@@ -5,11 +5,13 @@ import { doRequest } from '../../../helpers/requests'
5import { buildGlobalHeaders, buildSignedRequestOptions, computeBody } from './utils/activitypub-http-utils' 5import { buildGlobalHeaders, buildSignedRequestOptions, computeBody } from './utils/activitypub-http-utils'
6import { BROADCAST_CONCURRENCY, JOB_REQUEST_TIMEOUT } from '../../../initializers/constants' 6import { BROADCAST_CONCURRENCY, JOB_REQUEST_TIMEOUT } from '../../../initializers/constants'
7import { ActorFollowScoreCache } from '../../files-cache' 7import { ActorFollowScoreCache } from '../../files-cache'
8import { ContextType } from '@server/helpers/activitypub'
8 9
9export type ActivitypubHttpBroadcastPayload = { 10export type ActivitypubHttpBroadcastPayload = {
10 uris: string[] 11 uris: string[]
11 signatureActorId?: number 12 signatureActorId?: number
12 body: any 13 body: any
14 contextType?: ContextType
13} 15}
14 16
15async function processActivityPubHttpBroadcast (job: Bull.Job) { 17async function processActivityPubHttpBroadcast (job: Bull.Job) {
diff --git a/server/lib/job-queue/handlers/activitypub-http-unicast.ts b/server/lib/job-queue/handlers/activitypub-http-unicast.ts
index c70ce3be9..6b71e2891 100644
--- a/server/lib/job-queue/handlers/activitypub-http-unicast.ts
+++ b/server/lib/job-queue/handlers/activitypub-http-unicast.ts
@@ -4,11 +4,13 @@ import { doRequest } from '../../../helpers/requests'
4import { buildGlobalHeaders, buildSignedRequestOptions, computeBody } from './utils/activitypub-http-utils' 4import { buildGlobalHeaders, buildSignedRequestOptions, computeBody } from './utils/activitypub-http-utils'
5import { JOB_REQUEST_TIMEOUT } from '../../../initializers/constants' 5import { JOB_REQUEST_TIMEOUT } from '../../../initializers/constants'
6import { ActorFollowScoreCache } from '../../files-cache' 6import { ActorFollowScoreCache } from '../../files-cache'
7import { ContextType } from '@server/helpers/activitypub'
7 8
8export type ActivitypubHttpUnicastPayload = { 9export type ActivitypubHttpUnicastPayload = {
9 uri: string 10 uri: string
10 signatureActorId?: number 11 signatureActorId?: number
11 body: any 12 body: any
13 contextType?: ContextType
12} 14}
13 15
14async function processActivityPubHttpUnicast (job: Bull.Job) { 16async function processActivityPubHttpUnicast (job: Bull.Job) {
diff --git a/server/lib/job-queue/handlers/utils/activitypub-http-utils.ts b/server/lib/job-queue/handlers/utils/activitypub-http-utils.ts
index a28f3596f..54b35840d 100644
--- a/server/lib/job-queue/handlers/utils/activitypub-http-utils.ts
+++ b/server/lib/job-queue/handlers/utils/activitypub-http-utils.ts
@@ -1,11 +1,11 @@
1import { buildSignedActivity } from '../../../../helpers/activitypub' 1import { buildSignedActivity, ContextType } from '../../../../helpers/activitypub'
2import { getServerActor } from '../../../../helpers/utils' 2import { getServerActor } from '../../../../helpers/utils'
3import { ActorModel } from '../../../../models/activitypub/actor' 3import { ActorModel } from '../../../../models/activitypub/actor'
4import { sha256 } from '../../../../helpers/core-utils' 4import { sha256 } from '../../../../helpers/core-utils'
5import { HTTP_SIGNATURE } from '../../../../initializers/constants' 5import { HTTP_SIGNATURE } from '../../../../initializers/constants'
6import { MActor } from '../../../../typings/models' 6import { MActor } from '../../../../typings/models'
7 7
8type Payload = { body: any, signatureActorId?: number } 8type Payload = { body: any, contextType?: ContextType, signatureActorId?: number }
9 9
10async function computeBody (payload: Payload) { 10async function computeBody (payload: Payload) {
11 let body = payload.body 11 let body = payload.body
@@ -13,7 +13,7 @@ async function computeBody (payload: Payload) {
13 if (payload.signatureActorId) { 13 if (payload.signatureActorId) {
14 const actorSignature = await ActorModel.load(payload.signatureActorId) 14 const actorSignature = await ActorModel.load(payload.signatureActorId)
15 if (!actorSignature) throw new Error('Unknown signature actor id.') 15 if (!actorSignature) throw new Error('Unknown signature actor id.')
16 body = await buildSignedActivity(actorSignature, payload.body) 16 body = await buildSignedActivity(actorSignature, payload.body, payload.contextType)
17 } 17 }
18 18
19 return body 19 return body