mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-05 19:42:24 +02:00
Begin activitypub
This commit is contained in:
parent
343ad675f2
commit
e4f97babf7
92 changed files with 2507 additions and 920 deletions
123
server/helpers/custom-validators/activitypub/account.ts
Normal file
123
server/helpers/custom-validators/activitypub/account.ts
Normal file
|
@ -0,0 +1,123 @@
|
|||
import * as validator from 'validator'
|
||||
|
||||
import { exists, isUUIDValid } from '../misc'
|
||||
import { isActivityPubUrlValid } from './misc'
|
||||
import { isUserUsernameValid } from '../users'
|
||||
|
||||
function isAccountEndpointsObjectValid (endpointObject: any) {
|
||||
return isAccountSharedInboxValid(endpointObject.sharedInbox)
|
||||
}
|
||||
|
||||
function isAccountSharedInboxValid (sharedInbox: string) {
|
||||
return isActivityPubUrlValid(sharedInbox)
|
||||
}
|
||||
|
||||
function isAccountPublicKeyObjectValid (publicKeyObject: any) {
|
||||
return isAccountPublicKeyIdValid(publicKeyObject.id) &&
|
||||
isAccountPublicKeyOwnerValid(publicKeyObject.owner) &&
|
||||
isAccountPublicKeyValid(publicKeyObject.publicKeyPem)
|
||||
}
|
||||
|
||||
function isAccountPublicKeyIdValid (id: string) {
|
||||
return isActivityPubUrlValid(id)
|
||||
}
|
||||
|
||||
function isAccountTypeValid (type: string) {
|
||||
return type === 'Person' || type === 'Application'
|
||||
}
|
||||
|
||||
function isAccountPublicKeyOwnerValid (owner: string) {
|
||||
return isActivityPubUrlValid(owner)
|
||||
}
|
||||
|
||||
function isAccountPublicKeyValid (publicKey: string) {
|
||||
return exists(publicKey) &&
|
||||
typeof publicKey === 'string' &&
|
||||
publicKey.startsWith('-----BEGIN PUBLIC KEY-----') &&
|
||||
publicKey.endsWith('-----END PUBLIC KEY-----')
|
||||
}
|
||||
|
||||
function isAccountIdValid (id: string) {
|
||||
return isActivityPubUrlValid(id)
|
||||
}
|
||||
|
||||
function isAccountFollowingValid (id: string) {
|
||||
return isActivityPubUrlValid(id)
|
||||
}
|
||||
|
||||
function isAccountFollowersValid (id: string) {
|
||||
return isActivityPubUrlValid(id)
|
||||
}
|
||||
|
||||
function isAccountInboxValid (inbox: string) {
|
||||
return isActivityPubUrlValid(inbox)
|
||||
}
|
||||
|
||||
function isAccountOutboxValid (outbox: string) {
|
||||
return isActivityPubUrlValid(outbox)
|
||||
}
|
||||
|
||||
function isAccountNameValid (name: string) {
|
||||
return isUserUsernameValid(name)
|
||||
}
|
||||
|
||||
function isAccountPreferredUsernameValid (preferredUsername: string) {
|
||||
return isAccountNameValid(preferredUsername)
|
||||
}
|
||||
|
||||
function isAccountUrlValid (url: string) {
|
||||
return isActivityPubUrlValid(url)
|
||||
}
|
||||
|
||||
function isAccountPrivateKeyValid (privateKey: string) {
|
||||
return exists(privateKey) &&
|
||||
typeof privateKey === 'string' &&
|
||||
privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') &&
|
||||
privateKey.endsWith('-----END RSA PRIVATE KEY-----')
|
||||
}
|
||||
|
||||
function isRemoteAccountValid (remoteAccount: any) {
|
||||
return isAccountIdValid(remoteAccount.id) &&
|
||||
isUUIDValid(remoteAccount.uuid) &&
|
||||
isAccountTypeValid(remoteAccount.type) &&
|
||||
isAccountFollowingValid(remoteAccount.following) &&
|
||||
isAccountFollowersValid(remoteAccount.followers) &&
|
||||
isAccountInboxValid(remoteAccount.inbox) &&
|
||||
isAccountOutboxValid(remoteAccount.outbox) &&
|
||||
isAccountPreferredUsernameValid(remoteAccount.preferredUsername) &&
|
||||
isAccountUrlValid(remoteAccount.url) &&
|
||||
isAccountPublicKeyObjectValid(remoteAccount.publicKey) &&
|
||||
isAccountEndpointsObjectValid(remoteAccount.endpoint)
|
||||
}
|
||||
|
||||
function isAccountFollowingCountValid (value: string) {
|
||||
return exists(value) && validator.isInt('' + value, { min: 0 })
|
||||
}
|
||||
|
||||
function isAccountFollowersCountValid (value: string) {
|
||||
return exists(value) && validator.isInt('' + value, { min: 0 })
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
isAccountEndpointsObjectValid,
|
||||
isAccountSharedInboxValid,
|
||||
isAccountPublicKeyObjectValid,
|
||||
isAccountPublicKeyIdValid,
|
||||
isAccountTypeValid,
|
||||
isAccountPublicKeyOwnerValid,
|
||||
isAccountPublicKeyValid,
|
||||
isAccountIdValid,
|
||||
isAccountFollowingValid,
|
||||
isAccountFollowersValid,
|
||||
isAccountInboxValid,
|
||||
isAccountOutboxValid,
|
||||
isAccountPreferredUsernameValid,
|
||||
isAccountUrlValid,
|
||||
isAccountPrivateKeyValid,
|
||||
isRemoteAccountValid,
|
||||
isAccountFollowingCountValid,
|
||||
isAccountFollowersCountValid,
|
||||
isAccountNameValid
|
||||
}
|
4
server/helpers/custom-validators/activitypub/index.ts
Normal file
4
server/helpers/custom-validators/activitypub/index.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
export * from './account'
|
||||
export * from './signature'
|
||||
export * from './misc'
|
||||
export * from './videos'
|
17
server/helpers/custom-validators/activitypub/misc.ts
Normal file
17
server/helpers/custom-validators/activitypub/misc.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { exists } from '../misc'
|
||||
|
||||
function isActivityPubUrlValid (url: string) {
|
||||
const isURLOptions = {
|
||||
require_host: true,
|
||||
require_tld: true,
|
||||
require_protocol: true,
|
||||
require_valid_protocol: true,
|
||||
protocols: [ 'http', 'https' ]
|
||||
}
|
||||
|
||||
return exists(url) && validator.isURL(url, isURLOptions)
|
||||
}
|
||||
|
||||
export {
|
||||
isActivityPubUrlValid
|
||||
}
|
22
server/helpers/custom-validators/activitypub/signature.ts
Normal file
22
server/helpers/custom-validators/activitypub/signature.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { exists } from '../misc'
|
||||
import { isActivityPubUrlValid } from './misc'
|
||||
|
||||
function isSignatureTypeValid (signatureType: string) {
|
||||
return exists(signatureType) && signatureType === 'GraphSignature2012'
|
||||
}
|
||||
|
||||
function isSignatureCreatorValid (signatureCreator: string) {
|
||||
return exists(signatureCreator) && isActivityPubUrlValid(signatureCreator)
|
||||
}
|
||||
|
||||
function isSignatureValueValid (signatureValue: string) {
|
||||
return exists(signatureValue) && signatureValue.length > 0
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
isSignatureTypeValid,
|
||||
isSignatureCreatorValid,
|
||||
isSignatureValueValid
|
||||
}
|
184
server/helpers/custom-validators/activitypub/videos.ts
Normal file
184
server/helpers/custom-validators/activitypub/videos.ts
Normal file
|
@ -0,0 +1,184 @@
|
|||
import 'express-validator'
|
||||
import { has, values } from 'lodash'
|
||||
|
||||
import {
|
||||
REQUEST_ENDPOINTS,
|
||||
REQUEST_ENDPOINT_ACTIONS,
|
||||
REQUEST_VIDEO_EVENT_TYPES
|
||||
} from '../../../initializers'
|
||||
import { isArray, isDateValid, isUUIDValid } from '../misc'
|
||||
import {
|
||||
isVideoThumbnailDataValid,
|
||||
isVideoAbuseReasonValid,
|
||||
isVideoAbuseReporterUsernameValid,
|
||||
isVideoViewsValid,
|
||||
isVideoLikesValid,
|
||||
isVideoDislikesValid,
|
||||
isVideoEventCountValid,
|
||||
isRemoteVideoCategoryValid,
|
||||
isRemoteVideoLicenceValid,
|
||||
isRemoteVideoLanguageValid,
|
||||
isVideoNSFWValid,
|
||||
isVideoTruncatedDescriptionValid,
|
||||
isVideoDurationValid,
|
||||
isVideoFileInfoHashValid,
|
||||
isVideoNameValid,
|
||||
isVideoTagsValid,
|
||||
isVideoFileExtnameValid,
|
||||
isVideoFileResolutionValid
|
||||
} from '../videos'
|
||||
import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels'
|
||||
import { isVideoAuthorNameValid } from '../video-authors'
|
||||
|
||||
const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
|
||||
|
||||
const checkers: { [ id: string ]: (obj: any) => boolean } = {}
|
||||
checkers[ENDPOINT_ACTIONS.ADD_VIDEO] = checkAddVideo
|
||||
checkers[ENDPOINT_ACTIONS.UPDATE_VIDEO] = checkUpdateVideo
|
||||
checkers[ENDPOINT_ACTIONS.REMOVE_VIDEO] = checkRemoveVideo
|
||||
checkers[ENDPOINT_ACTIONS.REPORT_ABUSE] = checkReportVideo
|
||||
checkers[ENDPOINT_ACTIONS.ADD_CHANNEL] = checkAddVideoChannel
|
||||
checkers[ENDPOINT_ACTIONS.UPDATE_CHANNEL] = checkUpdateVideoChannel
|
||||
checkers[ENDPOINT_ACTIONS.REMOVE_CHANNEL] = checkRemoveVideoChannel
|
||||
checkers[ENDPOINT_ACTIONS.ADD_AUTHOR] = checkAddAuthor
|
||||
checkers[ENDPOINT_ACTIONS.REMOVE_AUTHOR] = checkRemoveAuthor
|
||||
|
||||
function removeBadRequestVideos (requests: any[]) {
|
||||
for (let i = requests.length - 1; i >= 0 ; i--) {
|
||||
const request = requests[i]
|
||||
const video = request.data
|
||||
|
||||
if (
|
||||
!video ||
|
||||
checkers[request.type] === undefined ||
|
||||
checkers[request.type](video) === false
|
||||
) {
|
||||
requests.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeBadRequestVideosQadu (requests: any[]) {
|
||||
for (let i = requests.length - 1; i >= 0 ; i--) {
|
||||
const request = requests[i]
|
||||
const video = request.data
|
||||
|
||||
if (
|
||||
!video ||
|
||||
(
|
||||
isUUIDValid(video.uuid) &&
|
||||
(has(video, 'views') === false || isVideoViewsValid(video.views)) &&
|
||||
(has(video, 'likes') === false || isVideoLikesValid(video.likes)) &&
|
||||
(has(video, 'dislikes') === false || isVideoDislikesValid(video.dislikes))
|
||||
) === false
|
||||
) {
|
||||
requests.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeBadRequestVideosEvents (requests: any[]) {
|
||||
for (let i = requests.length - 1; i >= 0 ; i--) {
|
||||
const request = requests[i]
|
||||
const eventData = request.data
|
||||
|
||||
if (
|
||||
!eventData ||
|
||||
(
|
||||
isUUIDValid(eventData.uuid) &&
|
||||
values(REQUEST_VIDEO_EVENT_TYPES).indexOf(eventData.eventType) !== -1 &&
|
||||
isVideoEventCountValid(eventData.count)
|
||||
) === false
|
||||
) {
|
||||
requests.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
removeBadRequestVideos,
|
||||
removeBadRequestVideosQadu,
|
||||
removeBadRequestVideosEvents
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function isCommonVideoAttributesValid (video: any) {
|
||||
return isDateValid(video.createdAt) &&
|
||||
isDateValid(video.updatedAt) &&
|
||||
isRemoteVideoCategoryValid(video.category) &&
|
||||
isRemoteVideoLicenceValid(video.licence) &&
|
||||
isRemoteVideoLanguageValid(video.language) &&
|
||||
isVideoNSFWValid(video.nsfw) &&
|
||||
isVideoTruncatedDescriptionValid(video.truncatedDescription) &&
|
||||
isVideoDurationValid(video.duration) &&
|
||||
isVideoNameValid(video.name) &&
|
||||
isVideoTagsValid(video.tags) &&
|
||||
isUUIDValid(video.uuid) &&
|
||||
isVideoViewsValid(video.views) &&
|
||||
isVideoLikesValid(video.likes) &&
|
||||
isVideoDislikesValid(video.dislikes) &&
|
||||
isArray(video.files) &&
|
||||
video.files.every(videoFile => {
|
||||
if (!videoFile) return false
|
||||
|
||||
return (
|
||||
isVideoFileInfoHashValid(videoFile.infoHash) &&
|
||||
isVideoFileExtnameValid(videoFile.extname) &&
|
||||
isVideoFileResolutionValid(videoFile.resolution)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
function checkAddVideo (video: any) {
|
||||
return isCommonVideoAttributesValid(video) &&
|
||||
isUUIDValid(video.channelUUID) &&
|
||||
isVideoThumbnailDataValid(video.thumbnailData)
|
||||
}
|
||||
|
||||
function checkUpdateVideo (video: any) {
|
||||
return isCommonVideoAttributesValid(video)
|
||||
}
|
||||
|
||||
function checkRemoveVideo (video: any) {
|
||||
return isUUIDValid(video.uuid)
|
||||
}
|
||||
|
||||
function checkReportVideo (abuse: any) {
|
||||
return isUUIDValid(abuse.videoUUID) &&
|
||||
isVideoAbuseReasonValid(abuse.reportReason) &&
|
||||
isVideoAbuseReporterUsernameValid(abuse.reporterUsername)
|
||||
}
|
||||
|
||||
function checkAddVideoChannel (videoChannel: any) {
|
||||
return isUUIDValid(videoChannel.uuid) &&
|
||||
isVideoChannelNameValid(videoChannel.name) &&
|
||||
isVideoChannelDescriptionValid(videoChannel.description) &&
|
||||
isDateValid(videoChannel.createdAt) &&
|
||||
isDateValid(videoChannel.updatedAt) &&
|
||||
isUUIDValid(videoChannel.ownerUUID)
|
||||
}
|
||||
|
||||
function checkUpdateVideoChannel (videoChannel: any) {
|
||||
return isUUIDValid(videoChannel.uuid) &&
|
||||
isVideoChannelNameValid(videoChannel.name) &&
|
||||
isVideoChannelDescriptionValid(videoChannel.description) &&
|
||||
isDateValid(videoChannel.createdAt) &&
|
||||
isDateValid(videoChannel.updatedAt) &&
|
||||
isUUIDValid(videoChannel.ownerUUID)
|
||||
}
|
||||
|
||||
function checkRemoveVideoChannel (videoChannel: any) {
|
||||
return isUUIDValid(videoChannel.uuid)
|
||||
}
|
||||
|
||||
function checkAddAuthor (author: any) {
|
||||
return isUUIDValid(author.uuid) &&
|
||||
isVideoAuthorNameValid(author.name)
|
||||
}
|
||||
|
||||
function checkRemoveAuthor (author: any) {
|
||||
return isUUIDValid(author.uuid)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue