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