diff options
Diffstat (limited to 'server/lib/activitypub/actor.ts')
-rw-r--r-- | server/lib/activitypub/actor.ts | 75 |
1 files changed, 52 insertions, 23 deletions
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index 9f5d12eb4..7862b0f00 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts | |||
@@ -22,13 +22,25 @@ import { JobQueue } from '../job-queue' | |||
22 | import { getServerActor } from '../../helpers/utils' | 22 | import { getServerActor } from '../../helpers/utils' |
23 | import { ActorFetchByUrlType, fetchActorByUrl } from '../../helpers/actor' | 23 | import { ActorFetchByUrlType, fetchActorByUrl } from '../../helpers/actor' |
24 | import { sequelizeTypescript } from '../../initializers/database' | 24 | import { sequelizeTypescript } from '../../initializers/database' |
25 | import { | ||
26 | MAccount, | ||
27 | MActor, | ||
28 | MActorAccountChannelId, | ||
29 | MActorAccountId, | ||
30 | MActorDefault, | ||
31 | MActorFull, | ||
32 | MActorId, | ||
33 | MActorAccountChannelIdActor, | ||
34 | MChannel, | ||
35 | MActorFullActor, MAccountActorDefault, MChannelActorDefault, MChannelActorAccountDefault | ||
36 | } from '../../typings/models' | ||
25 | 37 | ||
26 | // Set account keys, this could be long so process after the account creation and do not block the client | 38 | // Set account keys, this could be long so process after the account creation and do not block the client |
27 | function setAsyncActorKeys (actor: ActorModel) { | 39 | function setAsyncActorKeys (actor: MActor) { |
28 | return createPrivateAndPublicKeys() | 40 | return createPrivateAndPublicKeys() |
29 | .then(({ publicKey, privateKey }) => { | 41 | .then(({ publicKey, privateKey }) => { |
30 | actor.set('publicKey', publicKey) | 42 | actor.publicKey = publicKey |
31 | actor.set('privateKey', privateKey) | 43 | actor.privateKey = privateKey |
32 | return actor.save() | 44 | return actor.save() |
33 | }) | 45 | }) |
34 | .catch(err => { | 46 | .catch(err => { |
@@ -37,12 +49,26 @@ function setAsyncActorKeys (actor: ActorModel) { | |||
37 | }) | 49 | }) |
38 | } | 50 | } |
39 | 51 | ||
52 | function getOrCreateActorAndServerAndModel ( | ||
53 | activityActor: string | ActivityPubActor, | ||
54 | fetchType: 'all', | ||
55 | recurseIfNeeded?: boolean, | ||
56 | updateCollections?: boolean | ||
57 | ): Promise<MActorFullActor> | ||
58 | |||
59 | function getOrCreateActorAndServerAndModel ( | ||
60 | activityActor: string | ActivityPubActor, | ||
61 | fetchType?: 'association-ids', | ||
62 | recurseIfNeeded?: boolean, | ||
63 | updateCollections?: boolean | ||
64 | ): Promise<MActorAccountChannelId> | ||
65 | |||
40 | async function getOrCreateActorAndServerAndModel ( | 66 | async function getOrCreateActorAndServerAndModel ( |
41 | activityActor: string | ActivityPubActor, | 67 | activityActor: string | ActivityPubActor, |
42 | fetchType: ActorFetchByUrlType = 'actor-and-association-ids', | 68 | fetchType: ActorFetchByUrlType = 'association-ids', |
43 | recurseIfNeeded = true, | 69 | recurseIfNeeded = true, |
44 | updateCollections = false | 70 | updateCollections = false |
45 | ) { | 71 | ): Promise<MActorFullActor | MActorAccountChannelId> { |
46 | const actorUrl = getAPId(activityActor) | 72 | const actorUrl = getAPId(activityActor) |
47 | let created = false | 73 | let created = false |
48 | let accountPlaylistsUrl: string | 74 | let accountPlaylistsUrl: string |
@@ -61,7 +87,7 @@ async function getOrCreateActorAndServerAndModel ( | |||
61 | 87 | ||
62 | // Create the attributed to actor | 88 | // Create the attributed to actor |
63 | // In PeerTube a video channel is owned by an account | 89 | // In PeerTube a video channel is owned by an account |
64 | let ownerActor: ActorModel = undefined | 90 | let ownerActor: MActorFullActor |
65 | if (recurseIfNeeded === true && result.actor.type === 'Group') { | 91 | if (recurseIfNeeded === true && result.actor.type === 'Group') { |
66 | const accountAttributedTo = result.attributedTo.find(a => a.type === 'Person') | 92 | const accountAttributedTo = result.attributedTo.find(a => a.type === 'Person') |
67 | if (!accountAttributedTo) throw new Error('Cannot find account attributed to video channel ' + actor.url) | 93 | if (!accountAttributedTo) throw new Error('Cannot find account attributed to video channel ' + actor.url) |
@@ -85,8 +111,8 @@ async function getOrCreateActorAndServerAndModel ( | |||
85 | accountPlaylistsUrl = result.playlists | 111 | accountPlaylistsUrl = result.playlists |
86 | } | 112 | } |
87 | 113 | ||
88 | if (actor.Account) actor.Account.Actor = actor | 114 | if (actor.Account) (actor as MActorAccountChannelIdActor).Account.Actor = actor |
89 | if (actor.VideoChannel) actor.VideoChannel.Actor = actor | 115 | if (actor.VideoChannel) (actor as MActorAccountChannelIdActor).VideoChannel.Actor = actor |
90 | 116 | ||
91 | const { actor: actorRefreshed, refreshed } = await retryTransactionWrapper(refreshActorIfNeeded, actor, fetchType) | 117 | const { actor: actorRefreshed, refreshed } = await retryTransactionWrapper(refreshActorIfNeeded, actor, fetchType) |
92 | if (!actorRefreshed) throw new Error('Actor ' + actorRefreshed.url + ' does not exist anymore.') | 118 | if (!actorRefreshed) throw new Error('Actor ' + actorRefreshed.url + ' does not exist anymore.') |
@@ -140,7 +166,8 @@ async function updateActorInstance (actorInstance: ActorModel, attributes: Activ | |||
140 | actorInstance.followingUrl = attributes.following | 166 | actorInstance.followingUrl = attributes.following |
141 | } | 167 | } |
142 | 168 | ||
143 | async function updateActorAvatarInstance (actor: ActorModel, info: { name: string, onDisk: boolean, fileUrl: string }, t: Transaction) { | 169 | type AvatarInfo = { name: string, onDisk: boolean, fileUrl: string } |
170 | async function updateActorAvatarInstance (actor: MActorDefault, info: AvatarInfo, t: Transaction) { | ||
144 | if (info.name !== undefined) { | 171 | if (info.name !== undefined) { |
145 | if (actor.avatarId) { | 172 | if (actor.avatarId) { |
146 | try { | 173 | try { |
@@ -212,14 +239,16 @@ async function addFetchOutboxJob (actor: Pick<ActorModel, 'id' | 'outboxUrl'>) { | |||
212 | return JobQueue.Instance.createJob({ type: 'activitypub-http-fetcher', payload }) | 239 | return JobQueue.Instance.createJob({ type: 'activitypub-http-fetcher', payload }) |
213 | } | 240 | } |
214 | 241 | ||
215 | async function refreshActorIfNeeded ( | 242 | async function refreshActorIfNeeded <T extends MActorFull | MActorAccountChannelId> ( |
216 | actorArg: ActorModel, | 243 | actorArg: T, |
217 | fetchedType: ActorFetchByUrlType | 244 | fetchedType: ActorFetchByUrlType |
218 | ): Promise<{ actor: ActorModel, refreshed: boolean }> { | 245 | ): Promise<{ actor: T | MActorFull, refreshed: boolean }> { |
219 | if (!actorArg.isOutdated()) return { actor: actorArg, refreshed: false } | 246 | if (!actorArg.isOutdated()) return { actor: actorArg, refreshed: false } |
220 | 247 | ||
221 | // We need more attributes | 248 | // We need more attributes |
222 | const actor = fetchedType === 'all' ? actorArg : await ActorModel.loadByUrlAndPopulateAccountAndChannel(actorArg.url) | 249 | const actor = fetchedType === 'all' |
250 | ? actorArg as MActorFull | ||
251 | : await ActorModel.loadByUrlAndPopulateAccountAndChannel(actorArg.url) | ||
223 | 252 | ||
224 | try { | 253 | try { |
225 | let actorUrl: string | 254 | let actorUrl: string |
@@ -297,9 +326,9 @@ export { | |||
297 | 326 | ||
298 | function saveActorAndServerAndModelIfNotExist ( | 327 | function saveActorAndServerAndModelIfNotExist ( |
299 | result: FetchRemoteActorResult, | 328 | result: FetchRemoteActorResult, |
300 | ownerActor?: ActorModel, | 329 | ownerActor?: MActorFullActor, |
301 | t?: Transaction | 330 | t?: Transaction |
302 | ): Bluebird<ActorModel> | Promise<ActorModel> { | 331 | ): Bluebird<MActorFullActor> | Promise<MActorFullActor> { |
303 | let actor = result.actor | 332 | let actor = result.actor |
304 | 333 | ||
305 | if (t !== undefined) return save(t) | 334 | if (t !== undefined) return save(t) |
@@ -336,7 +365,7 @@ function saveActorAndServerAndModelIfNotExist ( | |||
336 | 365 | ||
337 | // Force the actor creation, sometimes Sequelize skips the save() when it thinks the instance already exists | 366 | // Force the actor creation, sometimes Sequelize skips the save() when it thinks the instance already exists |
338 | // (which could be false in a retried query) | 367 | // (which could be false in a retried query) |
339 | const [ actorCreated ] = await ActorModel.findOrCreate({ | 368 | const [ actorCreated ] = await ActorModel.findOrCreate<MActorFullActor>({ |
340 | defaults: actor.toJSON(), | 369 | defaults: actor.toJSON(), |
341 | where: { | 370 | where: { |
342 | url: actor.url | 371 | url: actor.url |
@@ -345,10 +374,10 @@ function saveActorAndServerAndModelIfNotExist ( | |||
345 | }) | 374 | }) |
346 | 375 | ||
347 | if (actorCreated.type === 'Person' || actorCreated.type === 'Application') { | 376 | if (actorCreated.type === 'Person' || actorCreated.type === 'Application') { |
348 | actorCreated.Account = await saveAccount(actorCreated, result, t) | 377 | actorCreated.Account = await saveAccount(actorCreated, result, t) as MAccountActorDefault |
349 | actorCreated.Account.Actor = actorCreated | 378 | actorCreated.Account.Actor = actorCreated |
350 | } else if (actorCreated.type === 'Group') { // Video channel | 379 | } else if (actorCreated.type === 'Group') { // Video channel |
351 | actorCreated.VideoChannel = await saveVideoChannel(actorCreated, result, ownerActor, t) | 380 | actorCreated.VideoChannel = await saveVideoChannel(actorCreated, result, ownerActor, t) as MChannelActorAccountDefault |
352 | actorCreated.VideoChannel.Actor = actorCreated | 381 | actorCreated.VideoChannel.Actor = actorCreated |
353 | actorCreated.VideoChannel.Account = ownerActor.Account | 382 | actorCreated.VideoChannel.Account = ownerActor.Account |
354 | } | 383 | } |
@@ -360,7 +389,7 @@ function saveActorAndServerAndModelIfNotExist ( | |||
360 | } | 389 | } |
361 | 390 | ||
362 | type FetchRemoteActorResult = { | 391 | type FetchRemoteActorResult = { |
363 | actor: ActorModel | 392 | actor: MActor |
364 | name: string | 393 | name: string |
365 | summary: string | 394 | summary: string |
366 | support?: string | 395 | support?: string |
@@ -429,7 +458,7 @@ async function fetchRemoteActor (actorUrl: string): Promise<{ statusCode?: numbe | |||
429 | } | 458 | } |
430 | } | 459 | } |
431 | 460 | ||
432 | async function saveAccount (actor: ActorModel, result: FetchRemoteActorResult, t: Transaction) { | 461 | async function saveAccount (actor: MActorId, result: FetchRemoteActorResult, t: Transaction) { |
433 | const [ accountCreated ] = await AccountModel.findOrCreate({ | 462 | const [ accountCreated ] = await AccountModel.findOrCreate({ |
434 | defaults: { | 463 | defaults: { |
435 | name: result.name, | 464 | name: result.name, |
@@ -442,10 +471,10 @@ async function saveAccount (actor: ActorModel, result: FetchRemoteActorResult, t | |||
442 | transaction: t | 471 | transaction: t |
443 | }) | 472 | }) |
444 | 473 | ||
445 | return accountCreated | 474 | return accountCreated as MAccount |
446 | } | 475 | } |
447 | 476 | ||
448 | async function saveVideoChannel (actor: ActorModel, result: FetchRemoteActorResult, ownerActor: ActorModel, t: Transaction) { | 477 | async function saveVideoChannel (actor: MActorId, result: FetchRemoteActorResult, ownerActor: MActorAccountId, t: Transaction) { |
449 | const [ videoChannelCreated ] = await VideoChannelModel.findOrCreate({ | 478 | const [ videoChannelCreated ] = await VideoChannelModel.findOrCreate({ |
450 | defaults: { | 479 | defaults: { |
451 | name: result.name, | 480 | name: result.name, |
@@ -460,5 +489,5 @@ async function saveVideoChannel (actor: ActorModel, result: FetchRemoteActorResu | |||
460 | transaction: t | 489 | transaction: t |
461 | }) | 490 | }) |
462 | 491 | ||
463 | return videoChannelCreated | 492 | return videoChannelCreated as MChannel |
464 | } | 493 | } |