diff options
7 files changed, 41 insertions, 28 deletions
diff --git a/server/helpers/custom-validators/activitypub/misc.ts b/server/helpers/custom-validators/activitypub/misc.ts index 279ad83dc..7df47cf15 100644 --- a/server/helpers/custom-validators/activitypub/misc.ts +++ b/server/helpers/custom-validators/activitypub/misc.ts | |||
@@ -51,7 +51,8 @@ function setValidAttributedTo (obj: any) { | |||
51 | } | 51 | } |
52 | 52 | ||
53 | obj.attributedTo = obj.attributedTo.filter(a => { | 53 | obj.attributedTo = obj.attributedTo.filter(a => { |
54 | return (a.type === 'Group' || a.type === 'Person') && isActivityPubUrlValid(a.id) | 54 | return isActivityPubUrlValid(a) || |
55 | ((a.type === 'Group' || a.type === 'Person') && isActivityPubUrlValid(a.id)) | ||
55 | }) | 56 | }) |
56 | 57 | ||
57 | return true | 58 | return true |
diff --git a/server/lib/activitypub/actors/get.ts b/server/lib/activitypub/actors/get.ts index e73b7d707..b2be3f5fb 100644 --- a/server/lib/activitypub/actors/get.ts +++ b/server/lib/activitypub/actors/get.ts | |||
@@ -3,8 +3,9 @@ import { logger } from '@server/helpers/logger' | |||
3 | import { JobQueue } from '@server/lib/job-queue' | 3 | import { JobQueue } from '@server/lib/job-queue' |
4 | import { ActorLoadByUrlType, loadActorByUrl } from '@server/lib/model-loaders' | 4 | import { ActorLoadByUrlType, loadActorByUrl } from '@server/lib/model-loaders' |
5 | import { MActor, MActorAccountChannelId, MActorAccountChannelIdActor, MActorAccountId, MActorFullActor } from '@server/types/models' | 5 | import { MActor, MActorAccountChannelId, MActorAccountChannelIdActor, MActorAccountId, MActorFullActor } from '@server/types/models' |
6 | import { ActivityPubActor } from '@shared/models' | 6 | import { arrayify } from '@shared/core-utils' |
7 | import { getAPId } from '../activity' | 7 | import { ActivityPubActor, APObjectId } from '@shared/models' |
8 | import { fetchAPObject, getAPId } from '../activity' | ||
8 | import { checkUrlsSameHost } from '../url' | 9 | import { checkUrlsSameHost } from '../url' |
9 | import { refreshActorIfNeeded } from './refresh' | 10 | import { refreshActorIfNeeded } from './refresh' |
10 | import { APActorCreator, fetchRemoteActor } from './shared' | 11 | import { APActorCreator, fetchRemoteActor } from './shared' |
@@ -40,7 +41,7 @@ async function getOrCreateAPActor ( | |||
40 | const { actorObject } = await fetchRemoteActor(actorUrl) | 41 | const { actorObject } = await fetchRemoteActor(actorUrl) |
41 | if (actorObject === undefined) throw new Error('Cannot fetch remote actor ' + actorUrl) | 42 | if (actorObject === undefined) throw new Error('Cannot fetch remote actor ' + actorUrl) |
42 | 43 | ||
43 | // actorUrl is just an alias/rediraction, so process object id instead | 44 | // actorUrl is just an alias/redirection, so process object id instead |
44 | if (actorObject.id !== actorUrl) return getOrCreateAPActor(actorObject, 'all', recurseIfNeeded, updateCollections) | 45 | if (actorObject.id !== actorUrl) return getOrCreateAPActor(actorObject, 'all', recurseIfNeeded, updateCollections) |
45 | 46 | ||
46 | // Create the attributed to actor | 47 | // Create the attributed to actor |
@@ -68,29 +69,48 @@ async function getOrCreateAPActor ( | |||
68 | return actorRefreshed | 69 | return actorRefreshed |
69 | } | 70 | } |
70 | 71 | ||
71 | function getOrCreateAPOwner (actorObject: ActivityPubActor, actorUrl: string) { | 72 | async function getOrCreateAPOwner (actorObject: ActivityPubActor, actorUrl: string) { |
72 | const accountAttributedTo = actorObject.attributedTo.find(a => a.type === 'Person') | 73 | const accountAttributedTo = await findOwner(actorUrl, actorObject.attributedTo, 'Person') |
73 | if (!accountAttributedTo) throw new Error('Cannot find account attributed to video channel ' + actorUrl) | 74 | if (!accountAttributedTo) { |
74 | 75 | throw new Error(`Cannot find account attributed to video channel ${actorUrl}`) | |
75 | if (checkUrlsSameHost(accountAttributedTo.id, actorUrl) !== true) { | ||
76 | throw new Error(`Account attributed to ${accountAttributedTo.id} does not have the same host than actor url ${actorUrl}`) | ||
77 | } | 76 | } |
78 | 77 | ||
79 | try { | 78 | try { |
80 | // Don't recurse another time | 79 | // Don't recurse another time |
81 | const recurseIfNeeded = false | 80 | const recurseIfNeeded = false |
82 | return getOrCreateAPActor(accountAttributedTo.id, 'all', recurseIfNeeded) | 81 | return getOrCreateAPActor(accountAttributedTo, 'all', recurseIfNeeded) |
83 | } catch (err) { | 82 | } catch (err) { |
84 | logger.error('Cannot get or create account attributed to video channel ' + actorUrl) | 83 | logger.error('Cannot get or create account attributed to video channel ' + actorUrl) |
85 | throw new Error(err) | 84 | throw new Error(err) |
86 | } | 85 | } |
87 | } | 86 | } |
88 | 87 | ||
88 | async function findOwner (rootUrl: string, attributedTo: APObjectId[] | APObjectId, type: 'Person' | 'Group') { | ||
89 | for (const actorToCheck of arrayify(attributedTo)) { | ||
90 | const actorObject = await fetchAPObject<ActivityPubActor>(getAPId(actorToCheck)) | ||
91 | |||
92 | if (!actorObject) { | ||
93 | logger.warn('Unknown attributed to actor %s for owner %s', actorToCheck, rootUrl) | ||
94 | continue | ||
95 | } | ||
96 | |||
97 | if (checkUrlsSameHost(actorObject.id, rootUrl) !== true) { | ||
98 | logger.warn(`Account attributed to ${actorObject.id} does not have the same host than owner actor url ${rootUrl}`) | ||
99 | continue | ||
100 | } | ||
101 | |||
102 | if (actorObject.type === type) return actorObject | ||
103 | } | ||
104 | |||
105 | return undefined | ||
106 | } | ||
107 | |||
89 | // --------------------------------------------------------------------------- | 108 | // --------------------------------------------------------------------------- |
90 | 109 | ||
91 | export { | 110 | export { |
92 | getOrCreateAPOwner, | 111 | getOrCreateAPOwner, |
93 | getOrCreateAPActor | 112 | getOrCreateAPActor, |
113 | findOwner | ||
94 | } | 114 | } |
95 | 115 | ||
96 | // --------------------------------------------------------------------------- | 116 | // --------------------------------------------------------------------------- |
diff --git a/server/lib/activitypub/playlists/create-update.ts b/server/lib/activitypub/playlists/create-update.ts index 9339e8ea4..920d3943a 100644 --- a/server/lib/activitypub/playlists/create-update.ts +++ b/server/lib/activitypub/playlists/create-update.ts | |||
@@ -77,7 +77,7 @@ async function setVideoChannel (playlistObject: PlaylistObject, playlistAttribut | |||
77 | throw new Error('Not attributed to for playlist object ' + getAPId(playlistObject)) | 77 | throw new Error('Not attributed to for playlist object ' + getAPId(playlistObject)) |
78 | } | 78 | } |
79 | 79 | ||
80 | const actor = await getOrCreateAPActor(playlistObject.attributedTo[0], 'all') | 80 | const actor = await getOrCreateAPActor(getAPId(playlistObject.attributedTo[0]), 'all') |
81 | 81 | ||
82 | if (!actor.VideoChannel) { | 82 | if (!actor.VideoChannel) { |
83 | logger.warn('Playlist "attributedTo" %s is not a video channel.', playlistObject.id, { playlistObject, ...lTags(playlistObject.id) }) | 83 | logger.warn('Playlist "attributedTo" %s is not a video channel.', playlistObject.id, { playlistObject, ...lTags(playlistObject.id) }) |
diff --git a/server/lib/activitypub/videos/shared/abstract-builder.ts b/server/lib/activitypub/videos/shared/abstract-builder.ts index 7c5c73139..8af67ecac 100644 --- a/server/lib/activitypub/videos/shared/abstract-builder.ts +++ b/server/lib/activitypub/videos/shared/abstract-builder.ts | |||
@@ -18,8 +18,7 @@ import { | |||
18 | MVideoThumbnail | 18 | MVideoThumbnail |
19 | } from '@server/types/models' | 19 | } from '@server/types/models' |
20 | import { ActivityTagObject, ThumbnailType, VideoObject, VideoStreamingPlaylistType } from '@shared/models' | 20 | import { ActivityTagObject, ThumbnailType, VideoObject, VideoStreamingPlaylistType } from '@shared/models' |
21 | import { getOrCreateAPActor } from '../../actors' | 21 | import { findOwner, getOrCreateAPActor } from '../../actors' |
22 | import { checkUrlsSameHost } from '../../url' | ||
23 | import { | 22 | import { |
24 | getCaptionAttributesFromObject, | 23 | getCaptionAttributesFromObject, |
25 | getFileAttributesFromUrl, | 24 | getFileAttributesFromUrl, |
@@ -37,13 +36,9 @@ export abstract class APVideoAbstractBuilder { | |||
37 | protected abstract lTags: LoggerTagsFn | 36 | protected abstract lTags: LoggerTagsFn |
38 | 37 | ||
39 | protected async getOrCreateVideoChannelFromVideoObject () { | 38 | protected async getOrCreateVideoChannelFromVideoObject () { |
40 | const channel = this.videoObject.attributedTo.find(a => a.type === 'Group') | 39 | const channel = await findOwner(this.videoObject.id, this.videoObject.attributedTo, 'Group') |
41 | if (!channel) throw new Error('Cannot find associated video channel to video ' + this.videoObject.url) | 40 | if (!channel) throw new Error('Cannot find associated video channel to video ' + this.videoObject.url) |
42 | 41 | ||
43 | if (checkUrlsSameHost(channel.id, this.videoObject.id) !== true) { | ||
44 | throw new Error(`Video channel url ${channel.id} does not have the same host than video object id ${this.videoObject.id}`) | ||
45 | } | ||
46 | |||
47 | return getOrCreateAPActor(channel.id, 'all') | 42 | return getOrCreateAPActor(channel.id, 'all') |
48 | } | 43 | } |
49 | 44 | ||
diff --git a/shared/models/activitypub/objects/common-objects.ts b/shared/models/activitypub/objects/common-objects.ts index 9bf994379..db9c73658 100644 --- a/shared/models/activitypub/objects/common-objects.ts +++ b/shared/models/activitypub/objects/common-objects.ts | |||
@@ -114,10 +114,7 @@ export type ActivityUrlObject = | |||
114 | | ActivityVideoFileMetadataUrlObject | 114 | | ActivityVideoFileMetadataUrlObject |
115 | | ActivityTrackerUrlObject | 115 | | ActivityTrackerUrlObject |
116 | 116 | ||
117 | export interface ActivityPubAttributedTo { | 117 | export type ActivityPubAttributedTo = { type: 'Group' | 'Person', id: string } | string |
118 | type: 'Group' | 'Person' | ||
119 | id: string | ||
120 | } | ||
121 | 118 | ||
122 | export interface ActivityTombstoneObject { | 119 | export interface ActivityTombstoneObject { |
123 | '@context'?: any | 120 | '@context'?: any |
diff --git a/shared/models/activitypub/objects/playlist-object.ts b/shared/models/activitypub/objects/playlist-object.ts index 842c03790..0ccb71828 100644 --- a/shared/models/activitypub/objects/playlist-object.ts +++ b/shared/models/activitypub/objects/playlist-object.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { ActivityIconObject } from './common-objects' | 1 | import { ActivityIconObject, ActivityPubAttributedTo } from './common-objects' |
2 | 2 | ||
3 | export interface PlaylistObject { | 3 | export interface PlaylistObject { |
4 | id: string | 4 | id: string |
@@ -12,7 +12,7 @@ export interface PlaylistObject { | |||
12 | uuid: string | 12 | uuid: string |
13 | 13 | ||
14 | totalItems: number | 14 | totalItems: number |
15 | attributedTo: string[] | 15 | attributedTo: ActivityPubAttributedTo[] |
16 | 16 | ||
17 | icon?: ActivityIconObject | 17 | icon?: ActivityIconObject |
18 | 18 | ||
diff --git a/shared/models/activitypub/objects/video-comment-object.ts b/shared/models/activitypub/objects/video-comment-object.ts index ba9001730..fb1e6f8db 100644 --- a/shared/models/activitypub/objects/video-comment-object.ts +++ b/shared/models/activitypub/objects/video-comment-object.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { ActivityTagObject } from './common-objects' | 1 | import { ActivityPubAttributedTo, ActivityTagObject } from './common-objects' |
2 | 2 | ||
3 | export interface VideoCommentObject { | 3 | export interface VideoCommentObject { |
4 | type: 'Note' | 4 | type: 'Note' |
@@ -11,6 +11,6 @@ export interface VideoCommentObject { | |||
11 | published: string | 11 | published: string |
12 | updated: string | 12 | updated: string |
13 | url: string | 13 | url: string |
14 | attributedTo: string | 14 | attributedTo: ActivityPubAttributedTo |
15 | tag: ActivityTagObject[] | 15 | tag: ActivityTagObject[] |
16 | } | 16 | } |