1 import * as Bluebird from 'bluebird'
2 import { Response } from 'express'
3 import * as validator from 'validator'
4 import { CONSTRAINTS_FIELDS } from '../../../initializers'
5 import { ActorModel } from '../../../models/activitypub/actor'
6 import { isAccountNameValid } from '../accounts'
7 import { exists, isUUIDValid } from '../misc'
8 import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels'
9 import { isActivityPubUrlValid, isBaseActivityValid, setValidAttributedTo } from './misc'
11 function isActorEndpointsObjectValid (endpointObject: any) {
12 return isActivityPubUrlValid(endpointObject.sharedInbox)
15 function isActorPublicKeyObjectValid (publicKeyObject: any) {
16 return isActivityPubUrlValid(publicKeyObject.id) &&
17 isActivityPubUrlValid(publicKeyObject.owner) &&
18 isActorPublicKeyValid(publicKeyObject.publicKeyPem)
21 function isActorTypeValid (type: string) {
22 return type === 'Person' || type === 'Application' || type === 'Group'
25 function isActorPublicKeyValid (publicKey: string) {
26 return exists(publicKey) &&
27 typeof publicKey === 'string' &&
28 publicKey.startsWith('-----BEGIN PUBLIC KEY-----') &&
29 publicKey.endsWith('-----END PUBLIC KEY-----') &&
30 validator.isLength(publicKey, CONSTRAINTS_FIELDS.ACTOR.PUBLIC_KEY)
33 function isActorPreferredUsernameValid (preferredUsername: string) {
34 return isAccountNameValid(preferredUsername) || isVideoChannelNameValid(preferredUsername)
37 const actorNameRegExp = new RegExp('[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_]+')
38 function isActorNameValid (name: string) {
39 return exists(name) && validator.matches(name, actorNameRegExp)
42 function isActorPrivateKeyValid (privateKey: string) {
43 return exists(privateKey) &&
44 typeof privateKey === 'string' &&
45 privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') &&
46 privateKey.endsWith('-----END RSA PRIVATE KEY-----') &&
47 validator.isLength(privateKey, CONSTRAINTS_FIELDS.ACTOR.PRIVATE_KEY)
50 function isRemoteActorValid (remoteActor: any) {
51 return isActivityPubUrlValid(remoteActor.id) &&
52 isUUIDValid(remoteActor.uuid) &&
53 isActorTypeValid(remoteActor.type) &&
54 isActivityPubUrlValid(remoteActor.following) &&
55 isActivityPubUrlValid(remoteActor.followers) &&
56 isActivityPubUrlValid(remoteActor.inbox) &&
57 isActivityPubUrlValid(remoteActor.outbox) &&
58 isActorNameValid(remoteActor.name) &&
59 isActorPreferredUsernameValid(remoteActor.preferredUsername) &&
60 isActivityPubUrlValid(remoteActor.url) &&
61 isActorPublicKeyObjectValid(remoteActor.publicKey) &&
62 isActorEndpointsObjectValid(remoteActor.endpoints) &&
63 (!remoteActor.summary || isVideoChannelDescriptionValid(remoteActor.summary)) &&
64 setValidAttributedTo(remoteActor) &&
65 // If this is not an account, it should be attributed to an account
66 // In PeerTube we use this to attach a video channel to a specific account
67 (remoteActor.type === 'Person' || remoteActor.attributedTo.length !== 0)
70 function isActorFollowingCountValid (value: string) {
71 return exists(value) && validator.isInt('' + value, { min: 0 })
74 function isActorFollowersCountValid (value: string) {
75 return exists(value) && validator.isInt('' + value, { min: 0 })
78 function isActorDeleteActivityValid (activity: any) {
79 return isBaseActivityValid(activity, 'Delete')
82 function isActorFollowActivityValid (activity: any) {
83 return isBaseActivityValid(activity, 'Follow') &&
84 isActivityPubUrlValid(activity.object)
87 function isActorAcceptActivityValid (activity: any) {
88 return isBaseActivityValid(activity, 'Accept')
91 function isActorIdExist (id: number | string, res: Response) {
92 let promise: Bluebird<ActorModel>
94 if (validator.isInt('' + id)) {
95 promise = ActorModel.load(+id)
97 promise = ActorModel.loadByUUID('' + id)
100 return isActorExist(promise, res)
103 function isLocalActorNameExist (name: string, res: Response) {
104 const promise = ActorModel.loadLocalByName(name)
106 return isActorExist(promise, res)
109 async function isActorExist (p: Bluebird<ActorModel>, res: Response) {
110 const actor = await p
114 .send({ error: 'Actor not found' })
120 res.locals.actor = actor
125 // ---------------------------------------------------------------------------
128 isActorEndpointsObjectValid,
129 isActorPublicKeyObjectValid,
131 isActorPublicKeyValid,
132 isActorPreferredUsernameValid,
133 isActorPrivateKeyValid,
135 isActorFollowingCountValid,
136 isActorFollowersCountValid,
137 isActorFollowActivityValid,
138 isActorAcceptActivityValid,
139 isActorDeleteActivityValid,
141 isLocalActorNameExist,