X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fhelpers%2Fcustom-validators%2Factivitypub%2Factor.ts;h=6958b2b00568b6094f9b7dd042a54ea2bf14e1e7;hb=f37dc0dd14d9ce0b59c454c2c1b935fcbe9727e9;hp=bf42757c59005d95bce30a7934f2d1e8bdd30c06;hpb=50d6de9c286abcb34ff4234d56d9cbb803db7665;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/helpers/custom-validators/activitypub/actor.ts b/server/helpers/custom-validators/activitypub/actor.ts index bf42757c5..6958b2b00 100644 --- a/server/helpers/custom-validators/activitypub/actor.ts +++ b/server/helpers/custom-validators/activitypub/actor.ts @@ -1,12 +1,9 @@ -import * as Bluebird from 'bluebird' -import { Response } from 'express' import * as validator from 'validator' import { CONSTRAINTS_FIELDS } from '../../../initializers' -import { ActorModel } from '../../../models/activitypub/actor' -import { isAccountNameValid } from '../accounts' -import { exists, isUUIDValid } from '../misc' -import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels' +import { exists, isArray } from '../misc' +import { truncate } from 'lodash' import { isActivityPubUrlValid, isBaseActivityValid, setValidAttributedTo } from './misc' +import { isHostValid } from '../servers' function isActorEndpointsObjectValid (endpointObject: any) { return isActivityPubUrlValid(endpointObject.sharedInbox) @@ -26,45 +23,41 @@ function isActorPublicKeyValid (publicKey: string) { return exists(publicKey) && typeof publicKey === 'string' && publicKey.startsWith('-----BEGIN PUBLIC KEY-----') && - publicKey.endsWith('-----END PUBLIC KEY-----') && - validator.isLength(publicKey, CONSTRAINTS_FIELDS.ACTOR.PUBLIC_KEY) + publicKey.indexOf('-----END PUBLIC KEY-----') !== -1 && + validator.isLength(publicKey, CONSTRAINTS_FIELDS.ACTORS.PUBLIC_KEY) } +const actorNameRegExp = new RegExp('^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\\-_]+$') function isActorPreferredUsernameValid (preferredUsername: string) { - return isAccountNameValid(preferredUsername) || isVideoChannelNameValid(preferredUsername) -} - -const actorNameRegExp = new RegExp('[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_]+') -function isActorNameValid (name: string) { - return exists(name) && validator.matches(name, actorNameRegExp) + return exists(preferredUsername) && validator.matches(preferredUsername, actorNameRegExp) } function isActorPrivateKeyValid (privateKey: string) { return exists(privateKey) && typeof privateKey === 'string' && privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') && - privateKey.endsWith('-----END RSA PRIVATE KEY-----') && - validator.isLength(privateKey, CONSTRAINTS_FIELDS.ACTOR.PRIVATE_KEY) -} - -function isRemoteActorValid (remoteActor: any) { - return isActivityPubUrlValid(remoteActor.id) && - isUUIDValid(remoteActor.uuid) && - isActorTypeValid(remoteActor.type) && - isActivityPubUrlValid(remoteActor.following) && - isActivityPubUrlValid(remoteActor.followers) && - isActivityPubUrlValid(remoteActor.inbox) && - isActivityPubUrlValid(remoteActor.outbox) && - isActorNameValid(remoteActor.name) && - isActorPreferredUsernameValid(remoteActor.preferredUsername) && - isActivityPubUrlValid(remoteActor.url) && - isActorPublicKeyObjectValid(remoteActor.publicKey) && - isActorEndpointsObjectValid(remoteActor.endpoints) && - (!remoteActor.summary || isVideoChannelDescriptionValid(remoteActor.summary)) && - setValidAttributedTo(remoteActor) && + // Sometimes there is a \n at the end, so just assert the string contains the end mark + privateKey.indexOf('-----END RSA PRIVATE KEY-----') !== -1 && + validator.isLength(privateKey, CONSTRAINTS_FIELDS.ACTORS.PRIVATE_KEY) +} + +function isActorObjectValid (actor: any) { + return exists(actor) && + isActivityPubUrlValid(actor.id) && + isActorTypeValid(actor.type) && + isActivityPubUrlValid(actor.following) && + isActivityPubUrlValid(actor.followers) && + isActivityPubUrlValid(actor.inbox) && + isActivityPubUrlValid(actor.outbox) && + isActorPreferredUsernameValid(actor.preferredUsername) && + isActivityPubUrlValid(actor.url) && + isActorPublicKeyObjectValid(actor.publicKey) && + isActorEndpointsObjectValid(actor.endpoints) && + setValidAttributedTo(actor) && + // If this is not an account, it should be attributed to an account // In PeerTube we use this to attach a video channel to a specific account - (remoteActor.type === 'Person' || remoteActor.attributedTo.length !== 0) + (actor.type === 'Person' || actor.attributedTo.length !== 0) } function isActorFollowingCountValid (value: string) { @@ -88,57 +81,66 @@ function isActorAcceptActivityValid (activity: any) { return isBaseActivityValid(activity, 'Accept') } -function isActorIdExist (id: number | string, res: Response) { - let promise: Bluebird - - if (validator.isInt('' + id)) { - promise = ActorModel.load(+id) - } else { // UUID - promise = ActorModel.loadByUUID('' + id) - } - - return isActorExist(promise, res) +function isActorRejectActivityValid (activity: any) { + return isBaseActivityValid(activity, 'Reject') } -function isLocalActorNameExist (name: string, res: Response) { - const promise = ActorModel.loadLocalByName(name) +function isActorUpdateActivityValid (activity: any) { + normalizeActor(activity.object) - return isActorExist(promise, res) + return isBaseActivityValid(activity, 'Update') && + isActorObjectValid(activity.object) } -async function isActorExist (p: Bluebird, res: Response) { - const actor = await p +function normalizeActor (actor: any) { + if (!actor || !actor.url) return - if (!actor) { - res.status(404) - .send({ error: 'Actor not found' }) - .end() + if (typeof actor.url !== 'string') { + actor.url = actor.url.href || actor.url.url + } - return false + if (actor.summary && typeof actor.summary === 'string') { + actor.summary = truncate(actor.summary, { length: CONSTRAINTS_FIELDS.USERS.DESCRIPTION.max }) + + if (actor.summary.length < CONSTRAINTS_FIELDS.USERS.DESCRIPTION.min) { + actor.summary = null + } } - res.locals.actor = actor + return +} + +function isValidActorHandle (handle: string) { + if (!exists(handle)) return false + + const parts = handle.split('@') + if (parts.length !== 2) return false + + return isHostValid(parts[1]) +} - return true +function areValidActorHandles (handles: string[]) { + return isArray(handles) && handles.every(h => isValidActorHandle(h)) } // --------------------------------------------------------------------------- export { + normalizeActor, + areValidActorHandles, isActorEndpointsObjectValid, isActorPublicKeyObjectValid, isActorTypeValid, isActorPublicKeyValid, isActorPreferredUsernameValid, isActorPrivateKeyValid, - isRemoteActorValid, + isActorObjectValid, isActorFollowingCountValid, isActorFollowersCountValid, isActorFollowActivityValid, isActorAcceptActivityValid, + isActorRejectActivityValid, isActorDeleteActivityValid, - isActorIdExist, - isLocalActorNameExist, - isActorNameValid, - isActorExist + isActorUpdateActivityValid, + isValidActorHandle }