mirror of https://github.com/Chocobozzz/PeerTube
Handle correctly formatted AP attributedTo
parent
cefe22cf7c
commit
7f7e9d4e90
|
@ -51,7 +51,8 @@ function setValidAttributedTo (obj: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.attributedTo = obj.attributedTo.filter(a => {
|
obj.attributedTo = obj.attributedTo.filter(a => {
|
||||||
return (a.type === 'Group' || a.type === 'Person') && isActivityPubUrlValid(a.id)
|
return isActivityPubUrlValid(a) ||
|
||||||
|
((a.type === 'Group' || a.type === 'Person') && isActivityPubUrlValid(a.id))
|
||||||
})
|
})
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -3,8 +3,9 @@ import { logger } from '@server/helpers/logger'
|
||||||
import { JobQueue } from '@server/lib/job-queue'
|
import { JobQueue } from '@server/lib/job-queue'
|
||||||
import { ActorLoadByUrlType, loadActorByUrl } from '@server/lib/model-loaders'
|
import { ActorLoadByUrlType, loadActorByUrl } from '@server/lib/model-loaders'
|
||||||
import { MActor, MActorAccountChannelId, MActorAccountChannelIdActor, MActorAccountId, MActorFullActor } from '@server/types/models'
|
import { MActor, MActorAccountChannelId, MActorAccountChannelIdActor, MActorAccountId, MActorFullActor } from '@server/types/models'
|
||||||
import { ActivityPubActor } from '@shared/models'
|
import { arrayify } from '@shared/core-utils'
|
||||||
import { getAPId } from '../activity'
|
import { ActivityPubActor, APObjectId } from '@shared/models'
|
||||||
|
import { fetchAPObject, getAPId } from '../activity'
|
||||||
import { checkUrlsSameHost } from '../url'
|
import { checkUrlsSameHost } from '../url'
|
||||||
import { refreshActorIfNeeded } from './refresh'
|
import { refreshActorIfNeeded } from './refresh'
|
||||||
import { APActorCreator, fetchRemoteActor } from './shared'
|
import { APActorCreator, fetchRemoteActor } from './shared'
|
||||||
|
@ -40,7 +41,7 @@ async function getOrCreateAPActor (
|
||||||
const { actorObject } = await fetchRemoteActor(actorUrl)
|
const { actorObject } = await fetchRemoteActor(actorUrl)
|
||||||
if (actorObject === undefined) throw new Error('Cannot fetch remote actor ' + actorUrl)
|
if (actorObject === undefined) throw new Error('Cannot fetch remote actor ' + actorUrl)
|
||||||
|
|
||||||
// actorUrl is just an alias/rediraction, so process object id instead
|
// actorUrl is just an alias/redirection, so process object id instead
|
||||||
if (actorObject.id !== actorUrl) return getOrCreateAPActor(actorObject, 'all', recurseIfNeeded, updateCollections)
|
if (actorObject.id !== actorUrl) return getOrCreateAPActor(actorObject, 'all', recurseIfNeeded, updateCollections)
|
||||||
|
|
||||||
// Create the attributed to actor
|
// Create the attributed to actor
|
||||||
|
@ -68,29 +69,48 @@ async function getOrCreateAPActor (
|
||||||
return actorRefreshed
|
return actorRefreshed
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOrCreateAPOwner (actorObject: ActivityPubActor, actorUrl: string) {
|
async function getOrCreateAPOwner (actorObject: ActivityPubActor, actorUrl: string) {
|
||||||
const accountAttributedTo = actorObject.attributedTo.find(a => a.type === 'Person')
|
const accountAttributedTo = await findOwner(actorUrl, actorObject.attributedTo, 'Person')
|
||||||
if (!accountAttributedTo) throw new Error('Cannot find account attributed to video channel ' + actorUrl)
|
if (!accountAttributedTo) {
|
||||||
|
throw new Error(`Cannot find account attributed to video channel ${actorUrl}`)
|
||||||
if (checkUrlsSameHost(accountAttributedTo.id, actorUrl) !== true) {
|
|
||||||
throw new Error(`Account attributed to ${accountAttributedTo.id} does not have the same host than actor url ${actorUrl}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Don't recurse another time
|
// Don't recurse another time
|
||||||
const recurseIfNeeded = false
|
const recurseIfNeeded = false
|
||||||
return getOrCreateAPActor(accountAttributedTo.id, 'all', recurseIfNeeded)
|
return getOrCreateAPActor(accountAttributedTo, 'all', recurseIfNeeded)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Cannot get or create account attributed to video channel ' + actorUrl)
|
logger.error('Cannot get or create account attributed to video channel ' + actorUrl)
|
||||||
throw new Error(err)
|
throw new Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function findOwner (rootUrl: string, attributedTo: APObjectId[] | APObjectId, type: 'Person' | 'Group') {
|
||||||
|
for (const actorToCheck of arrayify(attributedTo)) {
|
||||||
|
const actorObject = await fetchAPObject<ActivityPubActor>(getAPId(actorToCheck))
|
||||||
|
|
||||||
|
if (!actorObject) {
|
||||||
|
logger.warn('Unknown attributed to actor %s for owner %s', actorToCheck, rootUrl)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkUrlsSameHost(actorObject.id, rootUrl) !== true) {
|
||||||
|
logger.warn(`Account attributed to ${actorObject.id} does not have the same host than owner actor url ${rootUrl}`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actorObject.type === type) return actorObject
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getOrCreateAPOwner,
|
getOrCreateAPOwner,
|
||||||
getOrCreateAPActor
|
getOrCreateAPActor,
|
||||||
|
findOwner
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -77,7 +77,7 @@ async function setVideoChannel (playlistObject: PlaylistObject, playlistAttribut
|
||||||
throw new Error('Not attributed to for playlist object ' + getAPId(playlistObject))
|
throw new Error('Not attributed to for playlist object ' + getAPId(playlistObject))
|
||||||
}
|
}
|
||||||
|
|
||||||
const actor = await getOrCreateAPActor(playlistObject.attributedTo[0], 'all')
|
const actor = await getOrCreateAPActor(getAPId(playlistObject.attributedTo[0]), 'all')
|
||||||
|
|
||||||
if (!actor.VideoChannel) {
|
if (!actor.VideoChannel) {
|
||||||
logger.warn('Playlist "attributedTo" %s is not a video channel.', playlistObject.id, { playlistObject, ...lTags(playlistObject.id) })
|
logger.warn('Playlist "attributedTo" %s is not a video channel.', playlistObject.id, { playlistObject, ...lTags(playlistObject.id) })
|
||||||
|
|
|
@ -18,8 +18,7 @@ import {
|
||||||
MVideoThumbnail
|
MVideoThumbnail
|
||||||
} from '@server/types/models'
|
} from '@server/types/models'
|
||||||
import { ActivityTagObject, ThumbnailType, VideoObject, VideoStreamingPlaylistType } from '@shared/models'
|
import { ActivityTagObject, ThumbnailType, VideoObject, VideoStreamingPlaylistType } from '@shared/models'
|
||||||
import { getOrCreateAPActor } from '../../actors'
|
import { findOwner, getOrCreateAPActor } from '../../actors'
|
||||||
import { checkUrlsSameHost } from '../../url'
|
|
||||||
import {
|
import {
|
||||||
getCaptionAttributesFromObject,
|
getCaptionAttributesFromObject,
|
||||||
getFileAttributesFromUrl,
|
getFileAttributesFromUrl,
|
||||||
|
@ -37,13 +36,9 @@ export abstract class APVideoAbstractBuilder {
|
||||||
protected abstract lTags: LoggerTagsFn
|
protected abstract lTags: LoggerTagsFn
|
||||||
|
|
||||||
protected async getOrCreateVideoChannelFromVideoObject () {
|
protected async getOrCreateVideoChannelFromVideoObject () {
|
||||||
const channel = this.videoObject.attributedTo.find(a => a.type === 'Group')
|
const channel = await findOwner(this.videoObject.id, this.videoObject.attributedTo, 'Group')
|
||||||
if (!channel) throw new Error('Cannot find associated video channel to video ' + this.videoObject.url)
|
if (!channel) throw new Error('Cannot find associated video channel to video ' + this.videoObject.url)
|
||||||
|
|
||||||
if (checkUrlsSameHost(channel.id, this.videoObject.id) !== true) {
|
|
||||||
throw new Error(`Video channel url ${channel.id} does not have the same host than video object id ${this.videoObject.id}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
return getOrCreateAPActor(channel.id, 'all')
|
return getOrCreateAPActor(channel.id, 'all')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,10 +114,7 @@ export type ActivityUrlObject =
|
||||||
| ActivityVideoFileMetadataUrlObject
|
| ActivityVideoFileMetadataUrlObject
|
||||||
| ActivityTrackerUrlObject
|
| ActivityTrackerUrlObject
|
||||||
|
|
||||||
export interface ActivityPubAttributedTo {
|
export type ActivityPubAttributedTo = { type: 'Group' | 'Person', id: string } | string
|
||||||
type: 'Group' | 'Person'
|
|
||||||
id: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ActivityTombstoneObject {
|
export interface ActivityTombstoneObject {
|
||||||
'@context'?: any
|
'@context'?: any
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ActivityIconObject } from './common-objects'
|
import { ActivityIconObject, ActivityPubAttributedTo } from './common-objects'
|
||||||
|
|
||||||
export interface PlaylistObject {
|
export interface PlaylistObject {
|
||||||
id: string
|
id: string
|
||||||
|
@ -12,7 +12,7 @@ export interface PlaylistObject {
|
||||||
uuid: string
|
uuid: string
|
||||||
|
|
||||||
totalItems: number
|
totalItems: number
|
||||||
attributedTo: string[]
|
attributedTo: ActivityPubAttributedTo[]
|
||||||
|
|
||||||
icon?: ActivityIconObject
|
icon?: ActivityIconObject
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ActivityTagObject } from './common-objects'
|
import { ActivityPubAttributedTo, ActivityTagObject } from './common-objects'
|
||||||
|
|
||||||
export interface VideoCommentObject {
|
export interface VideoCommentObject {
|
||||||
type: 'Note'
|
type: 'Note'
|
||||||
|
@ -11,6 +11,6 @@ export interface VideoCommentObject {
|
||||||
published: string
|
published: string
|
||||||
updated: string
|
updated: string
|
||||||
url: string
|
url: string
|
||||||
attributedTo: string
|
attributedTo: ActivityPubAttributedTo
|
||||||
tag: ActivityTagObject[]
|
tag: ActivityTagObject[]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue