mirror of https://github.com/Chocobozzz/PeerTube
Add ability for plugins to alter video jsonld
parent
4899138ec5
commit
3b504f6ed4
|
@ -22,11 +22,11 @@ export class VideoAttributesComponent implements OnInit {
|
||||||
constructor (private hooks: HooksService) { }
|
constructor (private hooks: HooksService) { }
|
||||||
|
|
||||||
async ngOnInit () {
|
async ngOnInit () {
|
||||||
this.pluginMetadata = await this.hooks.wrapFunResult(
|
this.pluginMetadata = await this.hooks.wrapObject(
|
||||||
this.buildPluginMetadata.bind(this),
|
this.pluginMetadata,
|
||||||
{ video: this.video },
|
|
||||||
'video-watch',
|
'video-watch',
|
||||||
'filter:video-watch.video-plugin-metadata.result'
|
'filter:video-watch.video-plugin-metadata.result',
|
||||||
|
{ video: this.video }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,11 +39,4 @@ export class VideoAttributesComponent implements OnInit {
|
||||||
|
|
||||||
return this.video.tags
|
return this.video.tags
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for plugin hooks
|
|
||||||
private buildPluginMetadata (_options: {
|
|
||||||
video: VideoDetails
|
|
||||||
}): PluginMetadata[] {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,15 +48,6 @@ export class HooksService {
|
||||||
return this.pluginService.runHook(hookResultName, result, params)
|
return this.pluginService.runHook(hookResultName, result, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
async wrapFunResult <P, R, H extends ClientFilterHookName>
|
|
||||||
(fun: RawFunction<P, R>, params: P, scope: PluginClientScope, hookResultName: H) {
|
|
||||||
await this.pluginService.ensurePluginsAreLoaded(scope)
|
|
||||||
|
|
||||||
const result = fun(params)
|
|
||||||
|
|
||||||
return this.pluginService.runHook(hookResultName, result, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
runAction<T, U extends ClientActionHookName> (hookName: U, scope: PluginClientScope, params?: T) {
|
runAction<T, U extends ClientActionHookName> (hookName: U, scope: PluginClientScope, params?: T) {
|
||||||
// Use setTimeout to give priority to Angular change detector
|
// Use setTimeout to give priority to Angular change detector
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -66,13 +57,13 @@ export class HooksService {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async wrapObject<T, U extends ClientFilterHookName> (result: T, scope: PluginClientScope, hookName: U) {
|
async wrapObject<T, U extends ClientFilterHookName> (result: T, scope: PluginClientScope, hookName: U, context?: any) {
|
||||||
await this.pluginService.ensurePluginsAreLoaded(scope)
|
await this.pluginService.ensurePluginsAreLoaded(scope)
|
||||||
|
|
||||||
return this.wrapObjectWithoutScopeLoad(result, hookName)
|
return this.wrapObjectWithoutScopeLoad(result, hookName, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private wrapObjectWithoutScopeLoad<T, U extends ClientFilterHookName> (result: T, hookName: U) {
|
private wrapObjectWithoutScopeLoad<T, U extends ClientFilterHookName> (result: T, hookName: U, context?: any) {
|
||||||
return this.pluginService.runHook(hookName, result)
|
return this.pluginService.runHook(hookName, result, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ activityPubClientRouter.get(
|
||||||
[ '/accounts?/:name', '/accounts?/:name/video-channels', '/a/:name', '/a/:name/video-channels' ],
|
[ '/accounts?/:name', '/accounts?/:name/video-channels', '/a/:name', '/a/:name/video-channels' ],
|
||||||
executeIfActivityPub,
|
executeIfActivityPub,
|
||||||
asyncMiddleware(localAccountValidator),
|
asyncMiddleware(localAccountValidator),
|
||||||
accountController
|
asyncMiddleware(accountController)
|
||||||
)
|
)
|
||||||
activityPubClientRouter.get('/accounts?/:name/followers',
|
activityPubClientRouter.get('/accounts?/:name/followers',
|
||||||
executeIfActivityPub,
|
executeIfActivityPub,
|
||||||
|
@ -69,13 +69,13 @@ activityPubClientRouter.get('/accounts?/:name/likes/:videoId',
|
||||||
executeIfActivityPub,
|
executeIfActivityPub,
|
||||||
cacheRoute(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS),
|
cacheRoute(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS),
|
||||||
asyncMiddleware(getAccountVideoRateValidatorFactory('like')),
|
asyncMiddleware(getAccountVideoRateValidatorFactory('like')),
|
||||||
getAccountVideoRateFactory('like')
|
asyncMiddleware(getAccountVideoRateFactory('like'))
|
||||||
)
|
)
|
||||||
activityPubClientRouter.get('/accounts?/:name/dislikes/:videoId',
|
activityPubClientRouter.get('/accounts?/:name/dislikes/:videoId',
|
||||||
executeIfActivityPub,
|
executeIfActivityPub,
|
||||||
cacheRoute(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS),
|
cacheRoute(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS),
|
||||||
asyncMiddleware(getAccountVideoRateValidatorFactory('dislike')),
|
asyncMiddleware(getAccountVideoRateValidatorFactory('dislike')),
|
||||||
getAccountVideoRateFactory('dislike')
|
asyncMiddleware(getAccountVideoRateFactory('dislike'))
|
||||||
)
|
)
|
||||||
|
|
||||||
activityPubClientRouter.get(
|
activityPubClientRouter.get(
|
||||||
|
@ -131,7 +131,7 @@ activityPubClientRouter.get(
|
||||||
executeIfActivityPub,
|
executeIfActivityPub,
|
||||||
asyncMiddleware(videoChannelsNameWithHostValidator),
|
asyncMiddleware(videoChannelsNameWithHostValidator),
|
||||||
ensureIsLocalChannel,
|
ensureIsLocalChannel,
|
||||||
videoChannelController
|
asyncMiddleware(videoChannelController)
|
||||||
)
|
)
|
||||||
activityPubClientRouter.get('/video-channels/:nameWithHost/followers',
|
activityPubClientRouter.get('/video-channels/:nameWithHost/followers',
|
||||||
executeIfActivityPub,
|
executeIfActivityPub,
|
||||||
|
@ -172,13 +172,13 @@ activityPubClientRouter.get(
|
||||||
activityPubClientRouter.get('/video-playlists/:playlistId/videos/:playlistElementId',
|
activityPubClientRouter.get('/video-playlists/:playlistId/videos/:playlistElementId',
|
||||||
executeIfActivityPub,
|
executeIfActivityPub,
|
||||||
asyncMiddleware(videoPlaylistElementAPGetValidator),
|
asyncMiddleware(videoPlaylistElementAPGetValidator),
|
||||||
videoPlaylistElementController
|
asyncMiddleware(videoPlaylistElementController)
|
||||||
)
|
)
|
||||||
|
|
||||||
activityPubClientRouter.get('/videos/local-viewer/:localViewerId',
|
activityPubClientRouter.get('/videos/local-viewer/:localViewerId',
|
||||||
executeIfActivityPub,
|
executeIfActivityPub,
|
||||||
asyncMiddleware(getVideoLocalViewerValidator),
|
asyncMiddleware(getVideoLocalViewerValidator),
|
||||||
getVideoLocalViewerController
|
asyncMiddleware(getVideoLocalViewerController)
|
||||||
)
|
)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -189,10 +189,10 @@ export {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
function accountController (req: express.Request, res: express.Response) {
|
async function accountController (req: express.Request, res: express.Response) {
|
||||||
const account = res.locals.account
|
const account = res.locals.account
|
||||||
|
|
||||||
return activityPubResponse(activityPubContextify(account.toActivityPubObject(), 'Actor'), res)
|
return activityPubResponse(activityPubContextify(await account.toActivityPubObject(), 'Actor'), res)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function accountFollowersController (req: express.Request, res: express.Response) {
|
async function accountFollowersController (req: express.Request, res: express.Response) {
|
||||||
|
@ -246,7 +246,7 @@ async function videoController (req: express.Request, res: express.Response) {
|
||||||
const videoWithCaptions = Object.assign(video, { VideoCaptions: captions })
|
const videoWithCaptions = Object.assign(video, { VideoCaptions: captions })
|
||||||
|
|
||||||
const audience = getAudience(videoWithCaptions.VideoChannel.Account.Actor, videoWithCaptions.privacy === VideoPrivacy.PUBLIC)
|
const audience = getAudience(videoWithCaptions.VideoChannel.Account.Actor, videoWithCaptions.privacy === VideoPrivacy.PUBLIC)
|
||||||
const videoObject = audiencify(videoWithCaptions.toActivityPubObject(), audience)
|
const videoObject = audiencify(await videoWithCaptions.toActivityPubObject(), audience)
|
||||||
|
|
||||||
if (req.path.endsWith('/activity')) {
|
if (req.path.endsWith('/activity')) {
|
||||||
const data = buildCreateActivity(videoWithCaptions.url, video.VideoChannel.Account.Actor, videoObject, audience)
|
const data = buildCreateActivity(videoWithCaptions.url, video.VideoChannel.Account.Actor, videoObject, audience)
|
||||||
|
@ -321,10 +321,10 @@ async function videoCommentsController (req: express.Request, res: express.Respo
|
||||||
return activityPubResponse(activityPubContextify(json, 'Collection'), res)
|
return activityPubResponse(activityPubContextify(json, 'Collection'), res)
|
||||||
}
|
}
|
||||||
|
|
||||||
function videoChannelController (req: express.Request, res: express.Response) {
|
async function videoChannelController (req: express.Request, res: express.Response) {
|
||||||
const videoChannel = res.locals.videoChannel
|
const videoChannel = res.locals.videoChannel
|
||||||
|
|
||||||
return activityPubResponse(activityPubContextify(videoChannel.toActivityPubObject(), 'Actor'), res)
|
return activityPubResponse(activityPubContextify(await videoChannel.toActivityPubObject(), 'Actor'), res)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function videoChannelFollowersController (req: express.Request, res: express.Response) {
|
async function videoChannelFollowersController (req: express.Request, res: express.Response) {
|
||||||
|
|
|
@ -63,7 +63,7 @@ async function buildActivities (actor: MActorLight, start: number, count: number
|
||||||
|
|
||||||
activities.push(announceActivity)
|
activities.push(announceActivity)
|
||||||
} else {
|
} else {
|
||||||
const videoObject = video.toActivityPubObject()
|
const videoObject = await video.toActivityPubObject()
|
||||||
const createActivity = buildCreateActivity(video.url, byActor, videoObject, createActivityAudience)
|
const createActivity = buildCreateActivity(video.url, byActor, videoObject, createActivityAudience)
|
||||||
|
|
||||||
activities.push(createActivity)
|
activities.push(createActivity)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import express from 'express'
|
import express from 'express'
|
||||||
|
|
||||||
function activityPubResponse (data: any, res: express.Response) {
|
async function activityPubResponse (promise: Promise<any>, res: express.Response) {
|
||||||
|
const data = await promise
|
||||||
|
|
||||||
return res.type('application/activity+json; charset=utf-8')
|
return res.type('application/activity+json; charset=utf-8')
|
||||||
.json(data)
|
.json(data)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { ContextType } from '@shared/models'
|
import { ContextType } from '@shared/models'
|
||||||
|
import { Hooks } from '../plugins/hooks'
|
||||||
|
|
||||||
function activityPubContextify <T> (data: T, type: ContextType) {
|
async function activityPubContextify <T> (data: T, type: ContextType) {
|
||||||
return { ...getContextData(type), ...data }
|
return { ...await getContextData(type), ...data }
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -165,10 +166,13 @@ const contextStore: { [ id in ContextType ]: (string | { [ id: string ]: string
|
||||||
Rate: buildContext()
|
Rate: buildContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
function getContextData (type: ContextType) {
|
async function getContextData (type: ContextType) {
|
||||||
return {
|
const contextData = await Hooks.wrapObject(
|
||||||
'@context': contextStore[type]
|
contextStore[type],
|
||||||
}
|
'filter:activity-pub.activity.context.build.result'
|
||||||
|
)
|
||||||
|
|
||||||
|
return { '@context': contextData }
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildContext (contextValue?: ContextValue) {
|
function buildContext (contextValue?: ContextValue) {
|
||||||
|
|
|
@ -52,9 +52,9 @@ function buildGlobalHeaders (body: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function signAndContextify <T> (byActor: MActor, data: T, contextType: ContextType | null) {
|
async function signAndContextify <T> (byActor: MActor, data: T, contextType: ContextType | null) {
|
||||||
const activity = contextType
|
const activity = contextType
|
||||||
? activityPubContextify(data, contextType)
|
? await activityPubContextify(data, contextType)
|
||||||
: data
|
: data
|
||||||
|
|
||||||
return signJsonLDObject(byActor, activity)
|
return signJsonLDObject(byActor, activity)
|
||||||
|
|
|
@ -33,7 +33,7 @@ async function sendCreateVideo (video: MVideoAP, transaction: Transaction) {
|
||||||
logger.info('Creating job to send video creation of %s.', video.url, lTags(video.uuid))
|
logger.info('Creating job to send video creation of %s.', video.url, lTags(video.uuid))
|
||||||
|
|
||||||
const byActor = video.VideoChannel.Account.Actor
|
const byActor = video.VideoChannel.Account.Actor
|
||||||
const videoObject = video.toActivityPubObject()
|
const videoObject = await video.toActivityPubObject()
|
||||||
|
|
||||||
const audience = getAudience(byActor, video.privacy === VideoPrivacy.PUBLIC)
|
const audience = getAudience(byActor, video.privacy === VideoPrivacy.PUBLIC)
|
||||||
const createActivity = buildCreateActivity(video.url, byActor, videoObject, audience)
|
const createActivity = buildCreateActivity(video.url, byActor, videoObject, audience)
|
||||||
|
|
|
@ -36,7 +36,7 @@ async function sendUpdateVideo (videoArg: MVideoAPWithoutCaption, transaction: T
|
||||||
video.VideoCaptions = await video.$get('VideoCaptions', { transaction })
|
video.VideoCaptions = await video.$get('VideoCaptions', { transaction })
|
||||||
}
|
}
|
||||||
|
|
||||||
const videoObject = video.toActivityPubObject()
|
const videoObject = await video.toActivityPubObject()
|
||||||
const audience = getAudience(byActor, video.privacy === VideoPrivacy.PUBLIC)
|
const audience = getAudience(byActor, video.privacy === VideoPrivacy.PUBLIC)
|
||||||
|
|
||||||
const updateActivity = buildUpdateActivity(url, byActor, videoObject, audience)
|
const updateActivity = buildUpdateActivity(url, byActor, videoObject, audience)
|
||||||
|
|
|
@ -447,8 +447,8 @@ export class AccountModel extends Model<Partial<AttributesOnly<AccountModel>>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toActivityPubObject (this: MAccountAP) {
|
async toActivityPubObject (this: MAccountAP) {
|
||||||
const obj = this.Actor.toActivityPubObject(this.name)
|
const obj = await this.Actor.toActivityPubObject(this.name)
|
||||||
|
|
||||||
return Object.assign(obj, {
|
return Object.assign(obj, {
|
||||||
summary: this.description
|
summary: this.description
|
||||||
|
|
|
@ -809,8 +809,8 @@ export class VideoChannelModel extends Model<Partial<AttributesOnly<VideoChannel
|
||||||
return Object.assign(actor, videoChannel)
|
return Object.assign(actor, videoChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
toActivityPubObject (this: MChannelAP): ActivityPubActor {
|
async toActivityPubObject (this: MChannelAP): Promise<ActivityPubActor> {
|
||||||
const obj = this.Actor.toActivityPubObject(this.name)
|
const obj = await this.Actor.toActivityPubObject(this.name)
|
||||||
|
|
||||||
return Object.assign(obj, {
|
return Object.assign(obj, {
|
||||||
summary: this.description,
|
summary: this.description,
|
||||||
|
|
|
@ -137,6 +137,7 @@ import { VideoShareModel } from './video-share'
|
||||||
import { VideoSourceModel } from './video-source'
|
import { VideoSourceModel } from './video-source'
|
||||||
import { VideoStreamingPlaylistModel } from './video-streaming-playlist'
|
import { VideoStreamingPlaylistModel } from './video-streaming-playlist'
|
||||||
import { VideoTagModel } from './video-tag'
|
import { VideoTagModel } from './video-tag'
|
||||||
|
import { Hooks } from '@server/lib/plugins/hooks'
|
||||||
|
|
||||||
export enum ScopeNames {
|
export enum ScopeNames {
|
||||||
FOR_API = 'FOR_API',
|
FOR_API = 'FOR_API',
|
||||||
|
@ -1713,8 +1714,12 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
||||||
return files
|
return files
|
||||||
}
|
}
|
||||||
|
|
||||||
toActivityPubObject (this: MVideoAP): VideoObject {
|
toActivityPubObject (this: MVideoAP): Promise<VideoObject> {
|
||||||
return videoModelToActivityPubObject(this)
|
return Hooks.wrapObject(
|
||||||
|
videoModelToActivityPubObject(this),
|
||||||
|
'filter:activity-pub.video.jsonld.build.result',
|
||||||
|
{ video: this }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
getTruncatedDescription () {
|
getTruncatedDescription () {
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { buildDigest } from '@server/helpers/peertube-crypto'
|
import { buildDigest } from '@server/helpers/peertube-crypto'
|
||||||
import { HTTP_SIGNATURE } from '@server/initializers/constants'
|
import { ACTIVITY_PUB, HTTP_SIGNATURE } from '@server/initializers/constants'
|
||||||
import { activityPubContextify } from '@server/lib/activitypub/context'
|
import { activityPubContextify } from '@server/lib/activitypub/context'
|
||||||
import { buildGlobalHeaders, signAndContextify } from '@server/lib/activitypub/send'
|
import { buildGlobalHeaders, signAndContextify } from '@server/lib/activitypub/send'
|
||||||
import { makeFollowRequest, makePOSTAPRequest } from '@server/tests/shared'
|
import { makePOSTAPRequest } from '@server/tests/shared'
|
||||||
import { buildAbsoluteFixturePath, wait } from '@shared/core-utils'
|
import { buildAbsoluteFixturePath, wait } from '@shared/core-utils'
|
||||||
import { HttpStatusCode } from '@shared/models'
|
import { HttpStatusCode } from '@shared/models'
|
||||||
import { cleanupTests, createMultipleServers, killallServers, PeerTubeServer } from '@shared/server-commands'
|
import { cleanupTests, createMultipleServers, killallServers, PeerTubeServer } from '@shared/server-commands'
|
||||||
|
@ -43,6 +43,32 @@ function getAnnounceWithoutContext (server: PeerTubeServer) {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function makeFollowRequest (to: { url: string }, by: { url: string, privateKey }) {
|
||||||
|
const follow = {
|
||||||
|
type: 'Follow',
|
||||||
|
id: by.url + '/' + new Date().getTime(),
|
||||||
|
actor: by.url,
|
||||||
|
object: to.url
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = await activityPubContextify(follow, 'Follow')
|
||||||
|
|
||||||
|
const httpSignature = {
|
||||||
|
algorithm: HTTP_SIGNATURE.ALGORITHM,
|
||||||
|
authorizationHeaderName: HTTP_SIGNATURE.HEADER_NAME,
|
||||||
|
keyId: by.url,
|
||||||
|
key: by.privateKey,
|
||||||
|
headers: HTTP_SIGNATURE.HEADERS_TO_SIGN
|
||||||
|
}
|
||||||
|
const headers = {
|
||||||
|
'digest': buildDigest(body),
|
||||||
|
'content-type': 'application/activity+json',
|
||||||
|
'accept': ACTIVITY_PUB.ACCEPT_HEADER
|
||||||
|
}
|
||||||
|
|
||||||
|
return makePOSTAPRequest(to.url + '/inbox', body, httpSignature, headers)
|
||||||
|
}
|
||||||
|
|
||||||
describe('Test ActivityPub security', function () {
|
describe('Test ActivityPub security', function () {
|
||||||
let servers: PeerTubeServer[]
|
let servers: PeerTubeServer[]
|
||||||
let url: string
|
let url: string
|
||||||
|
@ -77,7 +103,7 @@ describe('Test ActivityPub security', function () {
|
||||||
describe('When checking HTTP signature', function () {
|
describe('When checking HTTP signature', function () {
|
||||||
|
|
||||||
it('Should fail with an invalid digest', async function () {
|
it('Should fail with an invalid digest', async function () {
|
||||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
||||||
const headers = {
|
const headers = {
|
||||||
Digest: buildDigest({ hello: 'coucou' })
|
Digest: buildDigest({ hello: 'coucou' })
|
||||||
}
|
}
|
||||||
|
@ -91,7 +117,7 @@ describe('Test ActivityPub security', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with an invalid date', async function () {
|
it('Should fail with an invalid date', async function () {
|
||||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
||||||
const headers = buildGlobalHeaders(body)
|
const headers = buildGlobalHeaders(body)
|
||||||
headers['date'] = 'Wed, 21 Oct 2015 07:28:00 GMT'
|
headers['date'] = 'Wed, 21 Oct 2015 07:28:00 GMT'
|
||||||
|
|
||||||
|
@ -107,7 +133,7 @@ describe('Test ActivityPub security', function () {
|
||||||
await setKeysOfServer(servers[0], servers[1], invalidKeys.publicKey, invalidKeys.privateKey)
|
await setKeysOfServer(servers[0], servers[1], invalidKeys.publicKey, invalidKeys.privateKey)
|
||||||
await setKeysOfServer(servers[1], servers[1], invalidKeys.publicKey, invalidKeys.privateKey)
|
await setKeysOfServer(servers[1], servers[1], invalidKeys.publicKey, invalidKeys.privateKey)
|
||||||
|
|
||||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
||||||
const headers = buildGlobalHeaders(body)
|
const headers = buildGlobalHeaders(body)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -122,7 +148,7 @@ describe('Test ActivityPub security', function () {
|
||||||
await setKeysOfServer(servers[0], servers[1], keys.publicKey, keys.privateKey)
|
await setKeysOfServer(servers[0], servers[1], keys.publicKey, keys.privateKey)
|
||||||
await setKeysOfServer(servers[1], servers[1], keys.publicKey, keys.privateKey)
|
await setKeysOfServer(servers[1], servers[1], keys.publicKey, keys.privateKey)
|
||||||
|
|
||||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
||||||
const headers = buildGlobalHeaders(body)
|
const headers = buildGlobalHeaders(body)
|
||||||
|
|
||||||
const signatureOptions = baseHttpSignature()
|
const signatureOptions = baseHttpSignature()
|
||||||
|
@ -145,7 +171,7 @@ describe('Test ActivityPub security', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should succeed with a valid HTTP signature draft 11 (without date but with (created))', async function () {
|
it('Should succeed with a valid HTTP signature draft 11 (without date but with (created))', async function () {
|
||||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
||||||
const headers = buildGlobalHeaders(body)
|
const headers = buildGlobalHeaders(body)
|
||||||
|
|
||||||
const signatureOptions = baseHttpSignature()
|
const signatureOptions = baseHttpSignature()
|
||||||
|
@ -156,7 +182,7 @@ describe('Test ActivityPub security', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should succeed with a valid HTTP signature', async function () {
|
it('Should succeed with a valid HTTP signature', async function () {
|
||||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
||||||
const headers = buildGlobalHeaders(body)
|
const headers = buildGlobalHeaders(body)
|
||||||
|
|
||||||
const { statusCode } = await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
|
const { statusCode } = await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
|
||||||
|
@ -175,7 +201,7 @@ describe('Test ActivityPub security', function () {
|
||||||
await killallServers([ servers[1] ])
|
await killallServers([ servers[1] ])
|
||||||
await servers[1].run()
|
await servers[1].run()
|
||||||
|
|
||||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
|
||||||
const headers = buildGlobalHeaders(body)
|
const headers = buildGlobalHeaders(body)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
import { buildDigest } from '@server/helpers/peertube-crypto'
|
|
||||||
import { doRequest } from '@server/helpers/requests'
|
import { doRequest } from '@server/helpers/requests'
|
||||||
import { ACTIVITY_PUB, HTTP_SIGNATURE } from '@server/initializers/constants'
|
|
||||||
import { activityPubContextify } from '@server/lib/activitypub/context'
|
|
||||||
|
|
||||||
export function makePOSTAPRequest (url: string, body: any, httpSignature: any, headers: any) {
|
export function makePOSTAPRequest (url: string, body: any, httpSignature: any, headers: any) {
|
||||||
const options = {
|
const options = {
|
||||||
|
@ -13,29 +10,3 @@ export function makePOSTAPRequest (url: string, body: any, httpSignature: any, h
|
||||||
|
|
||||||
return doRequest(url, options)
|
return doRequest(url, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function makeFollowRequest (to: { url: string }, by: { url: string, privateKey }) {
|
|
||||||
const follow = {
|
|
||||||
type: 'Follow',
|
|
||||||
id: by.url + '/' + new Date().getTime(),
|
|
||||||
actor: by.url,
|
|
||||||
object: to.url
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = activityPubContextify(follow, 'Follow')
|
|
||||||
|
|
||||||
const httpSignature = {
|
|
||||||
algorithm: HTTP_SIGNATURE.ALGORITHM,
|
|
||||||
authorizationHeaderName: HTTP_SIGNATURE.HEADER_NAME,
|
|
||||||
keyId: by.url,
|
|
||||||
key: by.privateKey,
|
|
||||||
headers: HTTP_SIGNATURE.HEADERS_TO_SIGN
|
|
||||||
}
|
|
||||||
const headers = {
|
|
||||||
'digest': buildDigest(body),
|
|
||||||
'content-type': 'application/activity+json',
|
|
||||||
'accept': ACTIVITY_PUB.ACCEPT_HEADER
|
|
||||||
}
|
|
||||||
|
|
||||||
return makePOSTAPRequest(to.url + '/inbox', body, httpSignature, headers)
|
|
||||||
}
|
|
||||||
|
|
|
@ -75,8 +75,7 @@ const I18N_LOCALE_ALIAS = {
|
||||||
'zh': 'zh-Hans-CN'
|
'zh': 'zh-Hans-CN'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const POSSIBLE_LOCALES = Object.keys(I18N_LOCALES)
|
export const POSSIBLE_LOCALES = (Object.keys(I18N_LOCALES) as string[]).concat(Object.keys(I18N_LOCALE_ALIAS))
|
||||||
.concat(Object.keys(I18N_LOCALE_ALIAS))
|
|
||||||
|
|
||||||
export function getDefaultLocale () {
|
export function getDefaultLocale () {
|
||||||
return 'en-US'
|
return 'en-US'
|
||||||
|
|
|
@ -113,7 +113,13 @@ export const serverFilterHookObject = {
|
||||||
'filter:transcoding.manual.resolutions-to-transcode.result': true,
|
'filter:transcoding.manual.resolutions-to-transcode.result': true,
|
||||||
'filter:transcoding.auto.resolutions-to-transcode.result': true,
|
'filter:transcoding.auto.resolutions-to-transcode.result': true,
|
||||||
|
|
||||||
'filter:activity-pub.remote-video-comment.create.accept.result': true
|
'filter:activity-pub.remote-video-comment.create.accept.result': true,
|
||||||
|
|
||||||
|
'filter:activity-pub.activity.context.build.result': true,
|
||||||
|
|
||||||
|
// Filter the result of video JSON LD builder
|
||||||
|
// You may also need to use filter:activity-pub.activity.context.build.result to also update JSON LD context
|
||||||
|
'filter:activity-pub.video.jsonld.build.result': true
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ServerFilterHookName = keyof typeof serverFilterHookObject
|
export type ServerFilterHookName = keyof typeof serverFilterHookObject
|
||||||
|
|
Loading…
Reference in New Issue