diff options
author | Chocobozzz <me@florianbigard.com> | 2019-10-23 11:33:53 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2019-10-23 11:33:53 +0200 |
commit | 47581df0737ebcc058a5863143c752f9112a4424 (patch) | |
tree | 3b64e3fc49de4bea41d8fd852201ba3abb6b4994 | |
parent | a0e6d267598839c8a5508a65876ce0e07d1b3d74 (diff) | |
download | PeerTube-47581df0737ebcc058a5863143c752f9112a4424.tar.gz PeerTube-47581df0737ebcc058a5863143c752f9112a4424.tar.zst PeerTube-47581df0737ebcc058a5863143c752f9112a4424.zip |
Fix federation with some actors
That don't have a shared inbox, or a URL
-rw-r--r-- | server/controllers/activitypub/inbox.ts | 1 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/actor.ts | 15 | ||||
-rw-r--r-- | server/initializers/constants.ts | 6 | ||||
-rw-r--r-- | server/initializers/migrations/0445-shared-inbox-optional.ts | 26 | ||||
-rw-r--r-- | server/lib/activitypub/actor.ts | 12 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-create.ts | 2 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-delete.ts | 2 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-flag.ts | 2 | ||||
-rw-r--r-- | server/lib/activitypub/send/utils.ts | 22 | ||||
-rw-r--r-- | server/models/activitypub/actor-follow.ts | 8 | ||||
-rw-r--r-- | server/models/activitypub/actor.ts | 11 | ||||
-rw-r--r-- | server/typings/models/account/actor.ts | 2 | ||||
-rw-r--r-- | shared/models/activitypub/activitypub-actor.ts | 2 |
13 files changed, 78 insertions, 33 deletions
diff --git a/server/controllers/activitypub/inbox.ts b/server/controllers/activitypub/inbox.ts index d9df253aa..ca42106b8 100644 --- a/server/controllers/activitypub/inbox.ts +++ b/server/controllers/activitypub/inbox.ts | |||
@@ -6,7 +6,6 @@ import { processActivities } from '../../lib/activitypub/process/process' | |||
6 | import { asyncMiddleware, checkSignature, localAccountValidator, localVideoChannelValidator, signatureValidator } from '../../middlewares' | 6 | import { asyncMiddleware, checkSignature, localAccountValidator, localVideoChannelValidator, signatureValidator } from '../../middlewares' |
7 | import { activityPubValidator } from '../../middlewares/validators/activitypub/activity' | 7 | import { activityPubValidator } from '../../middlewares/validators/activitypub/activity' |
8 | import { queue } from 'async' | 8 | import { queue } from 'async' |
9 | import { ActorModel } from '../../models/activitypub/actor' | ||
10 | import { MActorDefault, MActorSignature } from '../../typings/models' | 9 | import { MActorDefault, MActorSignature } from '../../typings/models' |
11 | 10 | ||
12 | const inboxRouter = express.Router() | 11 | const inboxRouter = express.Router() |
diff --git a/server/helpers/custom-validators/activitypub/actor.ts b/server/helpers/custom-validators/activitypub/actor.ts index 4e9aabf0e..ec4dd6f96 100644 --- a/server/helpers/custom-validators/activitypub/actor.ts +++ b/server/helpers/custom-validators/activitypub/actor.ts | |||
@@ -6,7 +6,12 @@ import { isHostValid } from '../servers' | |||
6 | import { peertubeTruncate } from '@server/helpers/core-utils' | 6 | import { peertubeTruncate } from '@server/helpers/core-utils' |
7 | 7 | ||
8 | function isActorEndpointsObjectValid (endpointObject: any) { | 8 | function isActorEndpointsObjectValid (endpointObject: any) { |
9 | return isActivityPubUrlValid(endpointObject.sharedInbox) | 9 | if (endpointObject && endpointObject.sharedInbox) { |
10 | return isActivityPubUrlValid(endpointObject.sharedInbox) | ||
11 | } | ||
12 | |||
13 | // Shared inbox is optional | ||
14 | return true | ||
10 | } | 15 | } |
11 | 16 | ||
12 | function isActorPublicKeyObjectValid (publicKeyObject: any) { | 17 | function isActorPublicKeyObjectValid (publicKeyObject: any) { |
@@ -16,7 +21,7 @@ function isActorPublicKeyObjectValid (publicKeyObject: any) { | |||
16 | } | 21 | } |
17 | 22 | ||
18 | function isActorTypeValid (type: string) { | 23 | function isActorTypeValid (type: string) { |
19 | return type === 'Person' || type === 'Application' || type === 'Group' | 24 | return type === 'Person' || type === 'Application' || type === 'Group' || type === 'Service' || type === 'Organization' |
20 | } | 25 | } |
21 | 26 | ||
22 | function isActorPublicKeyValid (publicKey: string) { | 27 | function isActorPublicKeyValid (publicKey: string) { |
@@ -81,9 +86,11 @@ function sanitizeAndCheckActorObject (object: any) { | |||
81 | } | 86 | } |
82 | 87 | ||
83 | function normalizeActor (actor: any) { | 88 | function normalizeActor (actor: any) { |
84 | if (!actor || !actor.url) return | 89 | if (!actor) return |
85 | 90 | ||
86 | if (typeof actor.url !== 'string') { | 91 | if (!actor.url) { |
92 | actor.url = actor.id | ||
93 | } else if (typeof actor.url !== 'string') { | ||
87 | actor.url = actor.url.href || actor.url.url | 94 | actor.url = actor.url.href || actor.url.url |
88 | } | 95 | } |
89 | 96 | ||
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 10f95f5ab..190fd427a 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -14,7 +14,7 @@ import { CONFIG, registerConfigChangedHandler } from './config' | |||
14 | 14 | ||
15 | // --------------------------------------------------------------------------- | 15 | // --------------------------------------------------------------------------- |
16 | 16 | ||
17 | const LAST_MIGRATION_VERSION = 440 | 17 | const LAST_MIGRATION_VERSION = 445 |
18 | 18 | ||
19 | // --------------------------------------------------------------------------- | 19 | // --------------------------------------------------------------------------- |
20 | 20 | ||
@@ -459,7 +459,9 @@ const ACTIVITY_PUB = { | |||
459 | const ACTIVITY_PUB_ACTOR_TYPES: { [ id: string ]: ActivityPubActorType } = { | 459 | const ACTIVITY_PUB_ACTOR_TYPES: { [ id: string ]: ActivityPubActorType } = { |
460 | GROUP: 'Group', | 460 | GROUP: 'Group', |
461 | PERSON: 'Person', | 461 | PERSON: 'Person', |
462 | APPLICATION: 'Application' | 462 | APPLICATION: 'Application', |
463 | ORGANIZATION: 'Organization', | ||
464 | SERVICE: 'Service' | ||
463 | } | 465 | } |
464 | 466 | ||
465 | const HTTP_SIGNATURE = { | 467 | const HTTP_SIGNATURE = { |
diff --git a/server/initializers/migrations/0445-shared-inbox-optional.ts b/server/initializers/migrations/0445-shared-inbox-optional.ts new file mode 100644 index 000000000..dad2d6569 --- /dev/null +++ b/server/initializers/migrations/0445-shared-inbox-optional.ts | |||
@@ -0,0 +1,26 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | async function up (utils: { | ||
4 | transaction: Sequelize.Transaction, | ||
5 | queryInterface: Sequelize.QueryInterface, | ||
6 | sequelize: Sequelize.Sequelize, | ||
7 | db: any | ||
8 | }): Promise<void> { | ||
9 | { | ||
10 | const data = { | ||
11 | type: Sequelize.STRING, | ||
12 | allowNull: true | ||
13 | } | ||
14 | |||
15 | await utils.queryInterface.changeColumn('actor', 'sharedInboxUrl', data) | ||
16 | } | ||
17 | } | ||
18 | |||
19 | function down (options) { | ||
20 | throw new Error('Not implemented.') | ||
21 | } | ||
22 | |||
23 | export { | ||
24 | up, | ||
25 | down | ||
26 | } | ||
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index 13b73077e..cad9af5e0 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts | |||
@@ -163,9 +163,12 @@ async function updateActorInstance (actorInstance: ActorModel, attributes: Activ | |||
163 | actorInstance.followingCount = followingCount | 163 | actorInstance.followingCount = followingCount |
164 | actorInstance.inboxUrl = attributes.inbox | 164 | actorInstance.inboxUrl = attributes.inbox |
165 | actorInstance.outboxUrl = attributes.outbox | 165 | actorInstance.outboxUrl = attributes.outbox |
166 | actorInstance.sharedInboxUrl = attributes.endpoints.sharedInbox | ||
167 | actorInstance.followersUrl = attributes.followers | 166 | actorInstance.followersUrl = attributes.followers |
168 | actorInstance.followingUrl = attributes.following | 167 | actorInstance.followingUrl = attributes.following |
168 | |||
169 | if (attributes.endpoints && attributes.endpoints.sharedInbox) { | ||
170 | actorInstance.sharedInboxUrl = attributes.endpoints.sharedInbox | ||
171 | } | ||
169 | } | 172 | } |
170 | 173 | ||
171 | type AvatarInfo = { name: string, onDisk: boolean, fileUrl: string } | 174 | type AvatarInfo = { name: string, onDisk: boolean, fileUrl: string } |
@@ -437,9 +440,12 @@ async function fetchRemoteActor (actorUrl: string): Promise<{ statusCode?: numbe | |||
437 | followingCount: followingCount, | 440 | followingCount: followingCount, |
438 | inboxUrl: actorJSON.inbox, | 441 | inboxUrl: actorJSON.inbox, |
439 | outboxUrl: actorJSON.outbox, | 442 | outboxUrl: actorJSON.outbox, |
440 | sharedInboxUrl: actorJSON.endpoints.sharedInbox, | ||
441 | followersUrl: actorJSON.followers, | 443 | followersUrl: actorJSON.followers, |
442 | followingUrl: actorJSON.following | 444 | followingUrl: actorJSON.following, |
445 | |||
446 | sharedInboxUrl: actorJSON.endpoints && actorJSON.endpoints.sharedInbox | ||
447 | ? actorJSON.endpoints.sharedInbox | ||
448 | : null, | ||
443 | }) | 449 | }) |
444 | 450 | ||
445 | const avatarInfo = await getAvatarInfoIfExists(actorJSON) | 451 | const avatarInfo = await getAvatarInfoIfExists(actorJSON) |
diff --git a/server/lib/activitypub/send/send-create.ts b/server/lib/activitypub/send/send-create.ts index 26ec3e948..edbc14a73 100644 --- a/server/lib/activitypub/send/send-create.ts +++ b/server/lib/activitypub/send/send-create.ts | |||
@@ -100,7 +100,7 @@ async function sendCreateVideoComment (comment: MCommentOwnerVideo, t: Transacti | |||
100 | if (isOrigin) return broadcastToFollowers(createActivity, byActor, actorsInvolvedInComment, t, actorsException) | 100 | if (isOrigin) return broadcastToFollowers(createActivity, byActor, actorsInvolvedInComment, t, actorsException) |
101 | 101 | ||
102 | // Send to origin | 102 | // Send to origin |
103 | t.afterCommit(() => unicastTo(createActivity, byActor, comment.Video.VideoChannel.Account.Actor.sharedInboxUrl)) | 103 | t.afterCommit(() => unicastTo(createActivity, byActor, comment.Video.VideoChannel.Account.Actor.getSharedInbox())) |
104 | } | 104 | } |
105 | 105 | ||
106 | function buildCreateActivity (url: string, byActor: MActorLight, object: any, audience?: ActivityAudience): ActivityCreate { | 106 | function buildCreateActivity (url: string, byActor: MActorLight, object: any, audience?: ActivityAudience): ActivityCreate { |
diff --git a/server/lib/activitypub/send/send-delete.ts b/server/lib/activitypub/send/send-delete.ts index 4b1ff8dc5..a91756ff4 100644 --- a/server/lib/activitypub/send/send-delete.ts +++ b/server/lib/activitypub/send/send-delete.ts | |||
@@ -71,7 +71,7 @@ async function sendDeleteVideoComment (videoComment: MCommentOwnerVideoReply, t: | |||
71 | if (isVideoOrigin) return broadcastToFollowers(activity, byActor, actorsInvolvedInComment, t, actorsException) | 71 | if (isVideoOrigin) return broadcastToFollowers(activity, byActor, actorsInvolvedInComment, t, actorsException) |
72 | 72 | ||
73 | // Send to origin | 73 | // Send to origin |
74 | t.afterCommit(() => unicastTo(activity, byActor, videoComment.Video.VideoChannel.Account.Actor.sharedInboxUrl)) | 74 | t.afterCommit(() => unicastTo(activity, byActor, videoComment.Video.VideoChannel.Account.Actor.getSharedInbox())) |
75 | } | 75 | } |
76 | 76 | ||
77 | async function sendDeleteVideoPlaylist (videoPlaylist: MVideoPlaylistFullSummary, t: Transaction) { | 77 | async function sendDeleteVideoPlaylist (videoPlaylist: MVideoPlaylistFullSummary, t: Transaction) { |
diff --git a/server/lib/activitypub/send/send-flag.ts b/server/lib/activitypub/send/send-flag.ts index 5ae1614ab..da7638a7b 100644 --- a/server/lib/activitypub/send/send-flag.ts +++ b/server/lib/activitypub/send/send-flag.ts | |||
@@ -18,7 +18,7 @@ async function sendVideoAbuse (byActor: MActor, videoAbuse: MVideoAbuseVideo, vi | |||
18 | const audience = { to: [ video.VideoChannel.Account.Actor.url ], cc: [] } | 18 | const audience = { to: [ video.VideoChannel.Account.Actor.url ], cc: [] } |
19 | const flagActivity = buildFlagActivity(url, byActor, videoAbuse, audience) | 19 | const flagActivity = buildFlagActivity(url, byActor, videoAbuse, audience) |
20 | 20 | ||
21 | t.afterCommit(() => unicastTo(flagActivity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl)) | 21 | t.afterCommit(() => unicastTo(flagActivity, byActor, video.VideoChannel.Account.Actor.getSharedInbox())) |
22 | } | 22 | } |
23 | 23 | ||
24 | function buildFlagActivity (url: string, byActor: MActor, videoAbuse: MVideoAbuseVideo, audience: ActivityAudience): ActivityFlag { | 24 | function buildFlagActivity (url: string, byActor: MActor, videoAbuse: MVideoAbuseVideo, audience: ActivityAudience): ActivityFlag { |
diff --git a/server/lib/activitypub/send/utils.ts b/server/lib/activitypub/send/utils.ts index 8129ab32a..77b723479 100644 --- a/server/lib/activitypub/send/utils.ts +++ b/server/lib/activitypub/send/utils.ts | |||
@@ -7,7 +7,7 @@ import { JobQueue } from '../../job-queue' | |||
7 | import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getRemoteVideoAudience } from '../audience' | 7 | import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getRemoteVideoAudience } from '../audience' |
8 | import { getServerActor } from '../../../helpers/utils' | 8 | import { getServerActor } from '../../../helpers/utils' |
9 | import { afterCommitIfTransaction } from '../../../helpers/database-utils' | 9 | import { afterCommitIfTransaction } from '../../../helpers/database-utils' |
10 | import { MActorFollowerException, MActor, MActorId, MActorLight, MVideo, MVideoAccountLight } from '../../../typings/models' | 10 | import { MActorWithInboxes, MActor, MActorId, MActorLight, MVideo, MVideoAccountLight } from '../../../typings/models' |
11 | 11 | ||
12 | async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: { | 12 | async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: { |
13 | byActor: MActorLight, | 13 | byActor: MActorLight, |
@@ -24,7 +24,7 @@ async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAud | |||
24 | const activity = activityBuilder(audience) | 24 | const activity = activityBuilder(audience) |
25 | 25 | ||
26 | return afterCommitIfTransaction(transaction, () => { | 26 | return afterCommitIfTransaction(transaction, () => { |
27 | return unicastTo(activity, byActor, video.VideoChannel.Account.Actor.sharedInboxUrl) | 27 | return unicastTo(activity, byActor, video.VideoChannel.Account.Actor.getSharedInbox()) |
28 | }) | 28 | }) |
29 | } | 29 | } |
30 | 30 | ||
@@ -40,7 +40,7 @@ async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAud | |||
40 | async function forwardVideoRelatedActivity ( | 40 | async function forwardVideoRelatedActivity ( |
41 | activity: Activity, | 41 | activity: Activity, |
42 | t: Transaction, | 42 | t: Transaction, |
43 | followersException: MActorFollowerException[] = [], | 43 | followersException: MActorWithInboxes[] = [], |
44 | video: MVideo | 44 | video: MVideo |
45 | ) { | 45 | ) { |
46 | // Mastodon does not add our announces in audience, so we forward to them manually | 46 | // Mastodon does not add our announces in audience, so we forward to them manually |
@@ -53,7 +53,7 @@ async function forwardVideoRelatedActivity ( | |||
53 | async function forwardActivity ( | 53 | async function forwardActivity ( |
54 | activity: Activity, | 54 | activity: Activity, |
55 | t: Transaction, | 55 | t: Transaction, |
56 | followersException: MActorFollowerException[] = [], | 56 | followersException: MActorWithInboxes[] = [], |
57 | additionalFollowerUrls: string[] = [] | 57 | additionalFollowerUrls: string[] = [] |
58 | ) { | 58 | ) { |
59 | logger.info('Forwarding activity %s.', activity.id) | 59 | logger.info('Forwarding activity %s.', activity.id) |
@@ -90,7 +90,7 @@ async function broadcastToFollowers ( | |||
90 | byActor: MActorId, | 90 | byActor: MActorId, |
91 | toFollowersOf: MActorId[], | 91 | toFollowersOf: MActorId[], |
92 | t: Transaction, | 92 | t: Transaction, |
93 | actorsException: MActorFollowerException[] = [] | 93 | actorsException: MActorWithInboxes[] = [] |
94 | ) { | 94 | ) { |
95 | const uris = await computeFollowerUris(toFollowersOf, actorsException, t) | 95 | const uris = await computeFollowerUris(toFollowersOf, actorsException, t) |
96 | 96 | ||
@@ -102,7 +102,7 @@ async function broadcastToActors ( | |||
102 | byActor: MActorId, | 102 | byActor: MActorId, |
103 | toActors: MActor[], | 103 | toActors: MActor[], |
104 | t?: Transaction, | 104 | t?: Transaction, |
105 | actorsException: MActorFollowerException[] = [] | 105 | actorsException: MActorWithInboxes[] = [] |
106 | ) { | 106 | ) { |
107 | const uris = await computeUris(toActors, actorsException) | 107 | const uris = await computeUris(toActors, actorsException) |
108 | return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor)) | 108 | return afterCommitIfTransaction(t, () => broadcastTo(uris, data, byActor)) |
@@ -147,7 +147,7 @@ export { | |||
147 | 147 | ||
148 | // --------------------------------------------------------------------------- | 148 | // --------------------------------------------------------------------------- |
149 | 149 | ||
150 | async function computeFollowerUris (toFollowersOf: MActorId[], actorsException: MActorFollowerException[], t: Transaction) { | 150 | async function computeFollowerUris (toFollowersOf: MActorId[], actorsException: MActorWithInboxes[], t: Transaction) { |
151 | const toActorFollowerIds = toFollowersOf.map(a => a.id) | 151 | const toActorFollowerIds = toFollowersOf.map(a => a.id) |
152 | 152 | ||
153 | const result = await ActorFollowModel.listAcceptedFollowerSharedInboxUrls(toActorFollowerIds, t) | 153 | const result = await ActorFollowModel.listAcceptedFollowerSharedInboxUrls(toActorFollowerIds, t) |
@@ -156,11 +156,11 @@ async function computeFollowerUris (toFollowersOf: MActorId[], actorsException: | |||
156 | return result.data.filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1) | 156 | return result.data.filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1) |
157 | } | 157 | } |
158 | 158 | ||
159 | async function computeUris (toActors: MActor[], actorsException: MActorFollowerException[] = []) { | 159 | async function computeUris (toActors: MActor[], actorsException: MActorWithInboxes[] = []) { |
160 | const serverActor = await getServerActor() | 160 | const serverActor = await getServerActor() |
161 | const targetUrls = toActors | 161 | const targetUrls = toActors |
162 | .filter(a => a.id !== serverActor.id) // Don't send to ourselves | 162 | .filter(a => a.id !== serverActor.id) // Don't send to ourselves |
163 | .map(a => a.sharedInboxUrl || a.inboxUrl) | 163 | .map(a => a.getSharedInbox()) |
164 | 164 | ||
165 | const toActorSharedInboxesSet = new Set(targetUrls) | 165 | const toActorSharedInboxesSet = new Set(targetUrls) |
166 | 166 | ||
@@ -169,10 +169,10 @@ async function computeUris (toActors: MActor[], actorsException: MActorFollowerE | |||
169 | .filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1) | 169 | .filter(sharedInbox => sharedInboxesException.indexOf(sharedInbox) === -1) |
170 | } | 170 | } |
171 | 171 | ||
172 | async function buildSharedInboxesException (actorsException: MActorFollowerException[]) { | 172 | async function buildSharedInboxesException (actorsException: MActorWithInboxes[]) { |
173 | const serverActor = await getServerActor() | 173 | const serverActor = await getServerActor() |
174 | 174 | ||
175 | return actorsException | 175 | return actorsException |
176 | .map(f => f.sharedInboxUrl || f.inboxUrl) | 176 | .map(f => f.getSharedInbox()) |
177 | .concat([ serverActor.sharedInboxUrl ]) | 177 | .concat([ serverActor.sharedInboxUrl ]) |
178 | } | 178 | } |
diff --git a/server/models/activitypub/actor-follow.ts b/server/models/activitypub/actor-follow.ts index 8498692f0..fb3c4ef9d 100644 --- a/server/models/activitypub/actor-follow.ts +++ b/server/models/activitypub/actor-follow.ts | |||
@@ -574,8 +574,8 @@ export class ActorFollowModel extends Model<ActorFollowModel> { | |||
574 | } | 574 | } |
575 | 575 | ||
576 | const selections: string[] = [] | 576 | const selections: string[] = [] |
577 | if (distinct === true) selections.push('DISTINCT("Follows"."' + columnUrl + '") AS "url"') | 577 | if (distinct === true) selections.push('DISTINCT("Follows"."' + columnUrl + '") AS "selectionUrl"') |
578 | else selections.push('"Follows"."' + columnUrl + '" AS "url"') | 578 | else selections.push('"Follows"."' + columnUrl + '" AS "selectionUrl"') |
579 | 579 | ||
580 | selections.push('COUNT(*) AS "total"') | 580 | selections.push('COUNT(*) AS "total"') |
581 | 581 | ||
@@ -585,7 +585,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> { | |||
585 | let query = 'SELECT ' + selection + ' FROM "actor" ' + | 585 | let query = 'SELECT ' + selection + ' FROM "actor" ' + |
586 | 'INNER JOIN "actorFollow" ON "actorFollow"."' + firstJoin + '" = "actor"."id" ' + | 586 | 'INNER JOIN "actorFollow" ON "actorFollow"."' + firstJoin + '" = "actor"."id" ' + |
587 | 'INNER JOIN "actor" AS "Follows" ON "actorFollow"."' + secondJoin + '" = "Follows"."id" ' + | 587 | 'INNER JOIN "actor" AS "Follows" ON "actorFollow"."' + secondJoin + '" = "Follows"."id" ' + |
588 | 'WHERE "actor"."id" = ANY ($actorIds) AND "actorFollow"."state" = \'accepted\' ' | 588 | 'WHERE "actor"."id" = ANY ($actorIds) AND "actorFollow"."state" = \'accepted\' AND "selectionUrl" IS NOT NULL ' |
589 | 589 | ||
590 | if (count !== undefined) query += 'LIMIT ' + count | 590 | if (count !== undefined) query += 'LIMIT ' + count |
591 | if (start !== undefined) query += ' OFFSET ' + start | 591 | if (start !== undefined) query += ' OFFSET ' + start |
@@ -599,7 +599,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> { | |||
599 | } | 599 | } |
600 | 600 | ||
601 | const [ followers, [ dataTotal ] ] = await Promise.all(tasks) | 601 | const [ followers, [ dataTotal ] ] = await Promise.all(tasks) |
602 | const urls: string[] = followers.map(f => f.url) | 602 | const urls: string[] = followers.map(f => f.selectionUrl) |
603 | 603 | ||
604 | return { | 604 | return { |
605 | data: urls, | 605 | data: urls, |
diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts index 535ebd792..42a24b583 100644 --- a/server/models/activitypub/actor.ts +++ b/server/models/activitypub/actor.ts | |||
@@ -44,7 +44,8 @@ import { | |||
44 | MActorFull, | 44 | MActorFull, |
45 | MActorHost, | 45 | MActorHost, |
46 | MActorServer, | 46 | MActorServer, |
47 | MActorSummaryFormattable | 47 | MActorSummaryFormattable, |
48 | MActorWithInboxes | ||
48 | } from '../../typings/models' | 49 | } from '../../typings/models' |
49 | import * as Bluebird from 'bluebird' | 50 | import * as Bluebird from 'bluebird' |
50 | 51 | ||
@@ -179,8 +180,8 @@ export class ActorModel extends Model<ActorModel> { | |||
179 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) | 180 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) |
180 | outboxUrl: string | 181 | outboxUrl: string |
181 | 182 | ||
182 | @AllowNull(false) | 183 | @AllowNull(true) |
183 | @Is('ActorSharedInboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'shared inbox url')) | 184 | @Is('ActorSharedInboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'shared inbox url', true)) |
184 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) | 185 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) |
185 | sharedInboxUrl: string | 186 | sharedInboxUrl: string |
186 | 187 | ||
@@ -402,6 +403,10 @@ export class ActorModel extends Model<ActorModel> { | |||
402 | }) | 403 | }) |
403 | } | 404 | } |
404 | 405 | ||
406 | getSharedInbox (this: MActorWithInboxes) { | ||
407 | return this.sharedInboxUrl || this.inboxUrl | ||
408 | } | ||
409 | |||
405 | toFormattedSummaryJSON (this: MActorSummaryFormattable) { | 410 | toFormattedSummaryJSON (this: MActorSummaryFormattable) { |
406 | let avatar: Avatar = null | 411 | let avatar: Avatar = null |
407 | if (this.Avatar) { | 412 | if (this.Avatar) { |
diff --git a/server/typings/models/account/actor.ts b/server/typings/models/account/actor.ts index bcacb8351..ee4ece755 100644 --- a/server/typings/models/account/actor.ts +++ b/server/typings/models/account/actor.ts | |||
@@ -19,7 +19,7 @@ export type MActorUsername = Pick<MActor, 'preferredUsername'> | |||
19 | 19 | ||
20 | export type MActorFollowersUrl = Pick<MActor, 'followersUrl'> | 20 | export type MActorFollowersUrl = Pick<MActor, 'followersUrl'> |
21 | export type MActorAudience = MActorUrl & MActorFollowersUrl | 21 | export type MActorAudience = MActorUrl & MActorFollowersUrl |
22 | export type MActorFollowerException = Pick<ActorModel, 'sharedInboxUrl' | 'inboxUrl'> | 22 | export type MActorWithInboxes = Pick<ActorModel, 'sharedInboxUrl' | 'inboxUrl' | 'getSharedInbox'> |
23 | export type MActorSignature = MActorAccountChannelId | 23 | export type MActorSignature = MActorAccountChannelId |
24 | 24 | ||
25 | export type MActorLight = Omit<MActor, 'privateKey' | 'privateKey'> | 25 | export type MActorLight = Omit<MActor, 'privateKey' | 'privateKey'> |
diff --git a/shared/models/activitypub/activitypub-actor.ts b/shared/models/activitypub/activitypub-actor.ts index 53ec579bc..b8a2dc925 100644 --- a/shared/models/activitypub/activitypub-actor.ts +++ b/shared/models/activitypub/activitypub-actor.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { ActivityPubAttributedTo } from './objects/common-objects' | 1 | import { ActivityPubAttributedTo } from './objects/common-objects' |
2 | 2 | ||
3 | export type ActivityPubActorType = 'Person' | 'Application' | 'Group' | 3 | export type ActivityPubActorType = 'Person' | 'Application' | 'Group' | 'Service' | 'Organization' |
4 | 4 | ||
5 | export interface ActivityPubActor { | 5 | export interface ActivityPubActor { |
6 | '@context': any[] | 6 | '@context': any[] |