aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/helpers/custom-validators/activitypub/actor.ts
blob: e1a4b5b8f8a40d880b281ebaa1757e2708aeea72 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import * as validator from 'validator'
import { CONSTRAINTS_FIELDS } from '../../../initializers'
import { exists } from '../misc'
import { isActivityPubUrlValid, isBaseActivityValid, setValidAttributedTo } from './misc'

function isActorEndpointsObjectValid (endpointObject: any) {
  return isActivityPubUrlValid(endpointObject.sharedInbox)
}

function isActorPublicKeyObjectValid (publicKeyObject: any) {
  return isActivityPubUrlValid(publicKeyObject.id) &&
    isActivityPubUrlValid(publicKeyObject.owner) &&
    isActorPublicKeyValid(publicKeyObject.publicKeyPem)
}

function isActorTypeValid (type: string) {
  return type === 'Person' || type === 'Application' || type === 'Group'
}

function isActorPublicKeyValid (publicKey: string) {
  return exists(publicKey) &&
    typeof publicKey === 'string' &&
    publicKey.startsWith('-----BEGIN 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 exists(preferredUsername) && validator.matches(preferredUsername, actorNameRegExp)
}

function isActorPrivateKeyValid (privateKey: string) {
  return exists(privateKey) &&
    typeof privateKey === 'string' &&
    privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') &&
    // 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
    (actor.type === 'Person' || actor.attributedTo.length !== 0)
}

function isActorFollowingCountValid (value: string) {
  return exists(value) && validator.isInt('' + value, { min: 0 })
}

function isActorFollowersCountValid (value: string) {
  return exists(value) && validator.isInt('' + value, { min: 0 })
}

function isActorDeleteActivityValid (activity: any) {
  return isBaseActivityValid(activity, 'Delete')
}

function isActorFollowActivityValid (activity: any) {
  return isBaseActivityValid(activity, 'Follow') &&
    isActivityPubUrlValid(activity.object)
}

function isActorAcceptActivityValid (activity: any) {
  return isBaseActivityValid(activity, 'Accept')
}

function isActorUpdateActivityValid (activity: any) {
  return isBaseActivityValid(activity, 'Update') &&
    isActorObjectValid(activity.object)
}

// ---------------------------------------------------------------------------

export {
  isActorEndpointsObjectValid,
  isActorPublicKeyObjectValid,
  isActorTypeValid,
  isActorPublicKeyValid,
  isActorPreferredUsernameValid,
  isActorPrivateKeyValid,
  isActorObjectValid,
  isActorFollowingCountValid,
  isActorFollowersCountValid,
  isActorFollowActivityValid,
  isActorAcceptActivityValid,
  isActorDeleteActivityValid,
  isActorUpdateActivityValid
}