aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/activitypub/actor.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2019-02-11 14:09:23 +0100
committerChocobozzz <me@florianbigard.com>2019-02-11 14:09:23 +0100
commitb718fd22374d64534bcfe69932cf562894abed6a (patch)
tree311d3c67e2a4d1f33ebdd1dc163527de9d33d0f7 /server/lib/activitypub/actor.ts
parentadb115f5522bea4d52456a9fc5eb4140bb064476 (diff)
parent501e961199578129629cf0567033d13efced9904 (diff)
downloadPeerTube-b718fd22374d64534bcfe69932cf562894abed6a.tar.gz
PeerTube-b718fd22374d64534bcfe69932cf562894abed6a.tar.zst
PeerTube-b718fd22374d64534bcfe69932cf562894abed6a.zip
Merge branch 'develop' into pr/1285
Diffstat (limited to 'server/lib/activitypub/actor.ts')
-rw-r--r--server/lib/activitypub/actor.ts130
1 files changed, 69 insertions, 61 deletions
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts
index f7bf7c65a..a3f379b76 100644
--- a/server/lib/activitypub/actor.ts
+++ b/server/lib/activitypub/actor.ts
@@ -4,7 +4,7 @@ import * as url from 'url'
4import * as uuidv4 from 'uuid/v4' 4import * as uuidv4 from 'uuid/v4'
5import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/activitypub' 5import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/activitypub'
6import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects' 6import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects'
7import { checkUrlsSameHost, getAPUrl } from '../../helpers/activitypub' 7import { checkUrlsSameHost, getAPId } from '../../helpers/activitypub'
8import { isActorObjectValid, normalizeActor } from '../../helpers/custom-validators/activitypub/actor' 8import { isActorObjectValid, normalizeActor } from '../../helpers/custom-validators/activitypub/actor'
9import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 9import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
10import { retryTransactionWrapper, updateInstanceWithAnother } from '../../helpers/database-utils' 10import { retryTransactionWrapper, updateInstanceWithAnother } from '../../helpers/database-utils'
@@ -42,7 +42,7 @@ async function getOrCreateActorAndServerAndModel (
42 recurseIfNeeded = true, 42 recurseIfNeeded = true,
43 updateCollections = false 43 updateCollections = false
44) { 44) {
45 const actorUrl = getAPUrl(activityActor) 45 const actorUrl = getAPId(activityActor)
46 let created = false 46 let created = false
47 47
48 let actor = await fetchActorByUrl(actorUrl, fetchType) 48 let actor = await fetchActorByUrl(actorUrl, fetchType)
@@ -201,6 +201,69 @@ async function addFetchOutboxJob (actor: ActorModel) {
201 return JobQueue.Instance.createJob({ type: 'activitypub-http-fetcher', payload }) 201 return JobQueue.Instance.createJob({ type: 'activitypub-http-fetcher', payload })
202} 202}
203 203
204async function refreshActorIfNeeded (
205 actorArg: ActorModel,
206 fetchedType: ActorFetchByUrlType
207): Promise<{ actor: ActorModel, refreshed: boolean }> {
208 if (!actorArg.isOutdated()) return { actor: actorArg, refreshed: false }
209
210 // We need more attributes
211 const actor = fetchedType === 'all' ? actorArg : await ActorModel.loadByUrlAndPopulateAccountAndChannel(actorArg.url)
212
213 try {
214 let actorUrl: string
215 try {
216 actorUrl = await getUrlFromWebfinger(actor.preferredUsername + '@' + actor.getHost())
217 } catch (err) {
218 logger.warn('Cannot get actor URL from webfinger, keeping the old one.', err)
219 actorUrl = actor.url
220 }
221
222 const { result, statusCode } = await fetchRemoteActor(actorUrl)
223
224 if (statusCode === 404) {
225 logger.info('Deleting actor %s because there is a 404 in refresh actor.', actor.url)
226 actor.Account ? actor.Account.destroy() : actor.VideoChannel.destroy()
227 return { actor: undefined, refreshed: false }
228 }
229
230 if (result === undefined) {
231 logger.warn('Cannot fetch remote actor in refresh actor.')
232 return { actor, refreshed: false }
233 }
234
235 return sequelizeTypescript.transaction(async t => {
236 updateInstanceWithAnother(actor, result.actor)
237
238 if (result.avatarName !== undefined) {
239 await updateActorAvatarInstance(actor, result.avatarName, t)
240 }
241
242 // Force update
243 actor.setDataValue('updatedAt', new Date())
244 await actor.save({ transaction: t })
245
246 if (actor.Account) {
247 actor.Account.set('name', result.name)
248 actor.Account.set('description', result.summary)
249
250 await actor.Account.save({ transaction: t })
251 } else if (actor.VideoChannel) {
252 actor.VideoChannel.set('name', result.name)
253 actor.VideoChannel.set('description', result.summary)
254 actor.VideoChannel.set('support', result.support)
255
256 await actor.VideoChannel.save({ transaction: t })
257 }
258
259 return { refreshed: true, actor }
260 })
261 } catch (err) {
262 logger.warn('Cannot refresh actor.', { err })
263 return { actor, refreshed: false }
264 }
265}
266
204export { 267export {
205 getOrCreateActorAndServerAndModel, 268 getOrCreateActorAndServerAndModel,
206 buildActorInstance, 269 buildActorInstance,
@@ -208,6 +271,7 @@ export {
208 fetchActorTotalItems, 271 fetchActorTotalItems,
209 fetchAvatarIfExists, 272 fetchAvatarIfExists,
210 updateActorInstance, 273 updateActorInstance,
274 refreshActorIfNeeded,
211 updateActorAvatarInstance, 275 updateActorAvatarInstance,
212 addFetchOutboxJob 276 addFetchOutboxJob
213} 277}
@@ -291,12 +355,12 @@ async function fetchRemoteActor (actorUrl: string): Promise<{ statusCode?: numbe
291 355
292 logger.info('Fetching remote actor %s.', actorUrl) 356 logger.info('Fetching remote actor %s.', actorUrl)
293 357
294 const requestResult = await doRequest(options) 358 const requestResult = await doRequest<ActivityPubActor>(options)
295 normalizeActor(requestResult.body) 359 normalizeActor(requestResult.body)
296 360
297 const actorJSON: ActivityPubActor = requestResult.body 361 const actorJSON = requestResult.body
298 if (isActorObjectValid(actorJSON) === false) { 362 if (isActorObjectValid(actorJSON) === false) {
299 logger.debug('Remote actor JSON is not valid.', { actorJSON: actorJSON }) 363 logger.debug('Remote actor JSON is not valid.', { actorJSON })
300 return { result: undefined, statusCode: requestResult.response.statusCode } 364 return { result: undefined, statusCode: requestResult.response.statusCode }
301 } 365 }
302 366
@@ -372,59 +436,3 @@ async function saveVideoChannel (actor: ActorModel, result: FetchRemoteActorResu
372 436
373 return videoChannelCreated 437 return videoChannelCreated
374} 438}
375
376async function refreshActorIfNeeded (
377 actorArg: ActorModel,
378 fetchedType: ActorFetchByUrlType
379): Promise<{ actor: ActorModel, refreshed: boolean }> {
380 if (!actorArg.isOutdated()) return { actor: actorArg, refreshed: false }
381
382 // We need more attributes
383 const actor = fetchedType === 'all' ? actorArg : await ActorModel.loadByUrlAndPopulateAccountAndChannel(actorArg.url)
384
385 try {
386 const actorUrl = await getUrlFromWebfinger(actor.preferredUsername + '@' + actor.getHost())
387 const { result, statusCode } = await fetchRemoteActor(actorUrl)
388
389 if (statusCode === 404) {
390 logger.info('Deleting actor %s because there is a 404 in refresh actor.', actor.url)
391 actor.Account ? actor.Account.destroy() : actor.VideoChannel.destroy()
392 return { actor: undefined, refreshed: false }
393 }
394
395 if (result === undefined) {
396 logger.warn('Cannot fetch remote actor in refresh actor.')
397 return { actor, refreshed: false }
398 }
399
400 return sequelizeTypescript.transaction(async t => {
401 updateInstanceWithAnother(actor, result.actor)
402
403 if (result.avatarName !== undefined) {
404 await updateActorAvatarInstance(actor, result.avatarName, t)
405 }
406
407 // Force update
408 actor.setDataValue('updatedAt', new Date())
409 await actor.save({ transaction: t })
410
411 if (actor.Account) {
412 actor.Account.set('name', result.name)
413 actor.Account.set('description', result.summary)
414
415 await actor.Account.save({ transaction: t })
416 } else if (actor.VideoChannel) {
417 actor.VideoChannel.set('name', result.name)
418 actor.VideoChannel.set('description', result.summary)
419 actor.VideoChannel.set('support', result.support)
420
421 await actor.VideoChannel.save({ transaction: t })
422 }
423
424 return { refreshed: true, actor }
425 })
426 } catch (err) {
427 logger.warn('Cannot refresh actor.', { err })
428 return { actor, refreshed: false }
429 }
430}