aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib')
-rw-r--r--server/lib/activitypub/actor.ts87
-rw-r--r--server/lib/activitypub/url.ts2
2 files changed, 59 insertions, 30 deletions
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts
index e590dc72d..e557896e8 100644
--- a/server/lib/activitypub/actor.ts
+++ b/server/lib/activitypub/actor.ts
@@ -1,16 +1,20 @@
1import * as Bluebird from 'bluebird' 1import * as Bluebird from 'bluebird'
2import { join } from 'path'
2import { Transaction } from 'sequelize' 3import { Transaction } from 'sequelize'
3import * as url from 'url' 4import * as url from 'url'
5import * as uuidv4 from 'uuid/v4'
4import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/activitypub' 6import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/activitypub'
5import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects' 7import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects'
6import { isRemoteActorValid } from '../../helpers/custom-validators/activitypub/actor' 8import { isRemoteActorValid } from '../../helpers/custom-validators/activitypub/actor'
9import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
7import { retryTransactionWrapper } from '../../helpers/database-utils' 10import { retryTransactionWrapper } from '../../helpers/database-utils'
8import { logger } from '../../helpers/logger' 11import { logger } from '../../helpers/logger'
9import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto' 12import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto'
10import { doRequest } from '../../helpers/requests' 13import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests'
11import { CONFIG, sequelizeTypescript } from '../../initializers' 14import { CONFIG, sequelizeTypescript } from '../../initializers'
12import { AccountModel } from '../../models/account/account' 15import { AccountModel } from '../../models/account/account'
13import { ActorModel } from '../../models/activitypub/actor' 16import { ActorModel } from '../../models/activitypub/actor'
17import { AvatarModel } from '../../models/avatar/avatar'
14import { ServerModel } from '../../models/server/server' 18import { ServerModel } from '../../models/server/server'
15import { VideoChannelModel } from '../../models/video/video-channel' 19import { VideoChannelModel } from '../../models/video/video-channel'
16 20
@@ -62,6 +66,32 @@ async function getOrCreateActorAndServerAndModel (actorUrl: string, recurseIfNee
62 return actor 66 return actor
63} 67}
64 68
69function buildActorInstance (type: ActivityPubActorType, url: string, preferredUsername: string, uuid?: string) {
70 return new ActorModel({
71 type,
72 url,
73 preferredUsername,
74 uuid,
75 publicKey: null,
76 privateKey: null,
77 followersCount: 0,
78 followingCount: 0,
79 inboxUrl: url + '/inbox',
80 outboxUrl: url + '/outbox',
81 sharedInboxUrl: CONFIG.WEBSERVER.URL + '/inbox',
82 followersUrl: url + '/followers',
83 followingUrl: url + '/following'
84 })
85}
86
87export {
88 getOrCreateActorAndServerAndModel,
89 buildActorInstance,
90 setAsyncActorKeys
91}
92
93// ---------------------------------------------------------------------------
94
65function saveActorAndServerAndModelIfNotExist ( 95function saveActorAndServerAndModelIfNotExist (
66 result: FetchRemoteActorResult, 96 result: FetchRemoteActorResult,
67 ownerActor?: ActorModel, 97 ownerActor?: ActorModel,
@@ -90,6 +120,14 @@ function saveActorAndServerAndModelIfNotExist (
90 // Save our new account in database 120 // Save our new account in database
91 actor.set('serverId', server.id) 121 actor.set('serverId', server.id)
92 122
123 // Avatar?
124 if (result.avatarName) {
125 const avatar = await AvatarModel.create({
126 filename: result.avatarName
127 }, { transaction: t })
128 actor.set('avatarId', avatar.id)
129 }
130
93 // Force the actor creation, sometimes Sequelize skips the save() when it thinks the instance already exists 131 // Force the actor creation, sometimes Sequelize skips the save() when it thinks the instance already exists
94 // (which could be false in a retried query) 132 // (which could be false in a retried query)
95 const actorCreated = await ActorModel.create(actor.toJSON(), { transaction: t }) 133 const actorCreated = await ActorModel.create(actor.toJSON(), { transaction: t })
@@ -112,6 +150,7 @@ type FetchRemoteActorResult = {
112 actor: ActorModel 150 actor: ActorModel
113 name: string 151 name: string
114 summary: string 152 summary: string
153 avatarName?: string
115 attributedTo: ActivityPubAttributedTo[] 154 attributedTo: ActivityPubAttributedTo[]
116} 155}
117async function fetchRemoteActor (actorUrl: string): Promise<FetchRemoteActorResult> { 156async function fetchRemoteActor (actorUrl: string): Promise<FetchRemoteActorResult> {
@@ -151,43 +190,33 @@ async function fetchRemoteActor (actorUrl: string): Promise<FetchRemoteActorResu
151 followingUrl: actorJSON.following 190 followingUrl: actorJSON.following
152 }) 191 })
153 192
193 // Fetch icon?
194 let avatarName: string = undefined
195 if (
196 actorJSON.icon && actorJSON.icon.type === 'Image' && actorJSON.icon.mediaType === 'image/png' &&
197 isActivityPubUrlValid(actorJSON.icon.url)
198 ) {
199 const extension = actorJSON.icon.mediaType === 'image/png' ? '.png' : '.jpg'
200
201 avatarName = uuidv4() + extension
202 const destPath = join(CONFIG.STORAGE.AVATARS_DIR, avatarName)
203
204 await doRequestAndSaveToFile({
205 method: 'GET',
206 uri: actorJSON.icon.url
207 }, destPath)
208 }
209
154 const name = actorJSON.name || actorJSON.preferredUsername 210 const name = actorJSON.name || actorJSON.preferredUsername
155 return { 211 return {
156 actor, 212 actor,
157 name, 213 name,
214 avatarName,
158 summary: actorJSON.summary, 215 summary: actorJSON.summary,
159 attributedTo: actorJSON.attributedTo 216 attributedTo: actorJSON.attributedTo
160 } 217 }
161} 218}
162 219
163function buildActorInstance (type: ActivityPubActorType, url: string, preferredUsername: string, uuid?: string) {
164 return new ActorModel({
165 type,
166 url,
167 preferredUsername,
168 uuid,
169 publicKey: null,
170 privateKey: null,
171 followersCount: 0,
172 followingCount: 0,
173 inboxUrl: url + '/inbox',
174 outboxUrl: url + '/outbox',
175 sharedInboxUrl: CONFIG.WEBSERVER.URL + '/inbox',
176 followersUrl: url + '/followers',
177 followingUrl: url + '/following'
178 })
179}
180
181export {
182 getOrCreateActorAndServerAndModel,
183 saveActorAndServerAndModelIfNotExist,
184 fetchRemoteActor,
185 buildActorInstance,
186 setAsyncActorKeys
187}
188
189// ---------------------------------------------------------------------------
190
191async function fetchActorTotalItems (url: string) { 220async function fetchActorTotalItems (url: string) {
192 const options = { 221 const options = {
193 uri: url, 222 uri: url,
diff --git a/server/lib/activitypub/url.ts b/server/lib/activitypub/url.ts
index 3d5f0523c..0d76922e0 100644
--- a/server/lib/activitypub/url.ts
+++ b/server/lib/activitypub/url.ts
@@ -18,7 +18,7 @@ function getVideoChannelActivityPubUrl (videoChannelUUID: string) {
18} 18}
19 19
20function getAccountActivityPubUrl (accountName: string) { 20function getAccountActivityPubUrl (accountName: string) {
21 return CONFIG.WEBSERVER.URL + '/account/' + accountName 21 return CONFIG.WEBSERVER.URL + '/accounts/' + accountName
22} 22}
23 23
24function getVideoAbuseActivityPubUrl (videoAbuse: VideoAbuseModel) { 24function getVideoAbuseActivityPubUrl (videoAbuse: VideoAbuseModel) {