diff options
Diffstat (limited to 'server/lib/activitypub/process')
-rw-r--r-- | server/lib/activitypub/process/process-update.ts | 94 |
1 files changed, 91 insertions, 3 deletions
diff --git a/server/lib/activitypub/process/process-update.ts b/server/lib/activitypub/process/process-update.ts index bc8ae5cc6..05ea7d272 100644 --- a/server/lib/activitypub/process/process-update.ts +++ b/server/lib/activitypub/process/process-update.ts | |||
@@ -1,14 +1,18 @@ | |||
1 | import * as Bluebird from 'bluebird' | 1 | import * as Bluebird from 'bluebird' |
2 | import { ActivityUpdate } from '../../../../shared/models/activitypub' | 2 | import { ActivityUpdate } from '../../../../shared/models/activitypub' |
3 | import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor' | ||
4 | import { VideoTorrentObject } from '../../../../shared/models/activitypub/objects' | ||
3 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 5 | import { retryTransactionWrapper } from '../../../helpers/database-utils' |
4 | import { logger } from '../../../helpers/logger' | 6 | import { logger } from '../../../helpers/logger' |
5 | import { resetSequelizeInstance } from '../../../helpers/utils' | 7 | import { resetSequelizeInstance } from '../../../helpers/utils' |
6 | import { sequelizeTypescript } from '../../../initializers' | 8 | import { sequelizeTypescript } from '../../../initializers' |
9 | import { AccountModel } from '../../../models/account/account' | ||
7 | import { ActorModel } from '../../../models/activitypub/actor' | 10 | import { ActorModel } from '../../../models/activitypub/actor' |
11 | import { AvatarModel } from '../../../models/avatar/avatar' | ||
8 | import { TagModel } from '../../../models/video/tag' | 12 | import { TagModel } from '../../../models/video/tag' |
9 | import { VideoModel } from '../../../models/video/video' | 13 | import { VideoModel } from '../../../models/video/video' |
10 | import { VideoFileModel } from '../../../models/video/video-file' | 14 | import { VideoFileModel } from '../../../models/video/video-file' |
11 | import { getOrCreateActorAndServerAndModel } from '../actor' | 15 | import { fetchActorTotalItems, fetchAvatarIfExists, getOrCreateActorAndServerAndModel } from '../actor' |
12 | import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc' | 16 | import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc' |
13 | 17 | ||
14 | async function processUpdateActivity (activity: ActivityUpdate) { | 18 | async function processUpdateActivity (activity: ActivityUpdate) { |
@@ -16,6 +20,8 @@ async function processUpdateActivity (activity: ActivityUpdate) { | |||
16 | 20 | ||
17 | if (activity.object.type === 'Video') { | 21 | if (activity.object.type === 'Video') { |
18 | return processUpdateVideo(actor, activity) | 22 | return processUpdateVideo(actor, activity) |
23 | } else if (activity.object.type === 'Person') { | ||
24 | return processUpdateAccount(actor, activity) | ||
19 | } | 25 | } |
20 | 26 | ||
21 | return | 27 | return |
@@ -39,11 +45,11 @@ function processUpdateVideo (actor: ActorModel, activity: ActivityUpdate) { | |||
39 | } | 45 | } |
40 | 46 | ||
41 | async function updateRemoteVideo (actor: ActorModel, activity: ActivityUpdate) { | 47 | async function updateRemoteVideo (actor: ActorModel, activity: ActivityUpdate) { |
42 | const videoAttributesToUpdate = activity.object | 48 | const videoAttributesToUpdate = activity.object as VideoTorrentObject |
43 | 49 | ||
44 | logger.debug('Updating remote video "%s".', videoAttributesToUpdate.uuid) | 50 | logger.debug('Updating remote video "%s".', videoAttributesToUpdate.uuid) |
45 | let videoInstance: VideoModel | 51 | let videoInstance: VideoModel |
46 | let videoFieldsSave: object | 52 | let videoFieldsSave: any |
47 | 53 | ||
48 | try { | 54 | try { |
49 | await sequelizeTypescript.transaction(async t => { | 55 | await sequelizeTypescript.transaction(async t => { |
@@ -54,6 +60,8 @@ async function updateRemoteVideo (actor: ActorModel, activity: ActivityUpdate) { | |||
54 | const videoInstance = await VideoModel.loadByUrlAndPopulateAccount(videoAttributesToUpdate.id, t) | 60 | const videoInstance = await VideoModel.loadByUrlAndPopulateAccount(videoAttributesToUpdate.id, t) |
55 | if (!videoInstance) throw new Error('Video ' + videoAttributesToUpdate.id + ' not found.') | 61 | if (!videoInstance) throw new Error('Video ' + videoAttributesToUpdate.id + ' not found.') |
56 | 62 | ||
63 | videoFieldsSave = videoInstance.toJSON() | ||
64 | |||
57 | const videoChannel = videoInstance.VideoChannel | 65 | const videoChannel = videoInstance.VideoChannel |
58 | if (videoChannel.Account.Actor.id !== actor.id) { | 66 | if (videoChannel.Account.Actor.id !== actor.id) { |
59 | throw new Error('Account ' + actor.url + ' does not own video channel ' + videoChannel.Actor.url) | 67 | throw new Error('Account ' + actor.url + ' does not own video channel ' + videoChannel.Actor.url) |
@@ -102,3 +110,83 @@ async function updateRemoteVideo (actor: ActorModel, activity: ActivityUpdate) { | |||
102 | throw err | 110 | throw err |
103 | } | 111 | } |
104 | } | 112 | } |
113 | |||
114 | function processUpdateAccount (actor: ActorModel, activity: ActivityUpdate) { | ||
115 | const options = { | ||
116 | arguments: [ actor, activity ], | ||
117 | errorMessage: 'Cannot update the remote account with many retries' | ||
118 | } | ||
119 | |||
120 | return retryTransactionWrapper(updateRemoteAccount, options) | ||
121 | } | ||
122 | |||
123 | async function updateRemoteAccount (actor: ActorModel, activity: ActivityUpdate) { | ||
124 | const accountAttributesToUpdate = activity.object as ActivityPubActor | ||
125 | |||
126 | logger.debug('Updating remote account "%s".', accountAttributesToUpdate.uuid) | ||
127 | let actorInstance: ActorModel | ||
128 | let accountInstance: AccountModel | ||
129 | let actorFieldsSave: object | ||
130 | let accountFieldsSave: object | ||
131 | |||
132 | // Fetch icon? | ||
133 | const avatarName = await fetchAvatarIfExists(accountAttributesToUpdate) | ||
134 | |||
135 | try { | ||
136 | await sequelizeTypescript.transaction(async t => { | ||
137 | actorInstance = await ActorModel.loadByUrl(accountAttributesToUpdate.id, t) | ||
138 | if (!actorInstance) throw new Error('Actor ' + accountAttributesToUpdate.id + ' not found.') | ||
139 | |||
140 | actorFieldsSave = actorInstance.toJSON() | ||
141 | accountInstance = actorInstance.Account | ||
142 | accountFieldsSave = actorInstance.Account.toJSON() | ||
143 | |||
144 | const followersCount = await fetchActorTotalItems(accountAttributesToUpdate.followers) | ||
145 | const followingCount = await fetchActorTotalItems(accountAttributesToUpdate.following) | ||
146 | |||
147 | actorInstance.set('type', accountAttributesToUpdate.type) | ||
148 | actorInstance.set('uuid', accountAttributesToUpdate.uuid) | ||
149 | actorInstance.set('preferredUsername', accountAttributesToUpdate.preferredUsername) | ||
150 | actorInstance.set('url', accountAttributesToUpdate.id) | ||
151 | actorInstance.set('publicKey', accountAttributesToUpdate.publicKey.publicKeyPem) | ||
152 | actorInstance.set('followersCount', followersCount) | ||
153 | actorInstance.set('followingCount', followingCount) | ||
154 | actorInstance.set('inboxUrl', accountAttributesToUpdate.inbox) | ||
155 | actorInstance.set('outboxUrl', accountAttributesToUpdate.outbox) | ||
156 | actorInstance.set('sharedInboxUrl', accountAttributesToUpdate.endpoints.sharedInbox) | ||
157 | actorInstance.set('followersUrl', accountAttributesToUpdate.followers) | ||
158 | actorInstance.set('followingUrl', accountAttributesToUpdate.following) | ||
159 | |||
160 | if (avatarName !== undefined) { | ||
161 | if (actorInstance.avatarId) { | ||
162 | await actorInstance.Avatar.destroy({ transaction: t }) | ||
163 | } | ||
164 | |||
165 | const avatar = await AvatarModel.create({ | ||
166 | filename: avatarName | ||
167 | }, { transaction: t }) | ||
168 | |||
169 | actor.set('avatarId', avatar.id) | ||
170 | } | ||
171 | |||
172 | await actor.save({ transaction: t }) | ||
173 | |||
174 | actor.Account.set('name', accountAttributesToUpdate.name || accountAttributesToUpdate.preferredUsername) | ||
175 | await actor.Account.save({ transaction: t }) | ||
176 | }) | ||
177 | |||
178 | logger.info('Remote account with uuid %s updated', accountAttributesToUpdate.uuid) | ||
179 | } catch (err) { | ||
180 | if (actorInstance !== undefined && actorFieldsSave !== undefined) { | ||
181 | resetSequelizeInstance(actorInstance, actorFieldsSave) | ||
182 | } | ||
183 | |||
184 | if (accountInstance !== undefined && accountFieldsSave !== undefined) { | ||
185 | resetSequelizeInstance(accountInstance, accountFieldsSave) | ||
186 | } | ||
187 | |||
188 | // This is just a debug because we will retry the insert | ||
189 | logger.debug('Cannot update the remote account.', err) | ||
190 | throw err | ||
191 | } | ||
192 | } | ||