aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/helpers/custom-validators/activitypub
diff options
context:
space:
mode:
authorChocobozzz <florian.bigard@gmail.com>2017-11-09 17:51:58 +0100
committerChocobozzz <florian.bigard@gmail.com>2017-11-27 19:40:51 +0100
commite4f97babf701481b55cc10fb3448feab5f97c867 (patch)
treeaf37402a594dc5ff09f71ecb0687e8cfe4cdb471 /server/helpers/custom-validators/activitypub
parent343ad675f2a26c15b86150a9a3552e619d5d44f4 (diff)
downloadPeerTube-e4f97babf701481b55cc10fb3448feab5f97c867.tar.gz
PeerTube-e4f97babf701481b55cc10fb3448feab5f97c867.tar.zst
PeerTube-e4f97babf701481b55cc10fb3448feab5f97c867.zip
Begin activitypub
Diffstat (limited to 'server/helpers/custom-validators/activitypub')
-rw-r--r--server/helpers/custom-validators/activitypub/account.ts123
-rw-r--r--server/helpers/custom-validators/activitypub/index.ts4
-rw-r--r--server/helpers/custom-validators/activitypub/misc.ts17
-rw-r--r--server/helpers/custom-validators/activitypub/signature.ts22
-rw-r--r--server/helpers/custom-validators/activitypub/videos.ts184
5 files changed, 350 insertions, 0 deletions
diff --git a/server/helpers/custom-validators/activitypub/account.ts b/server/helpers/custom-validators/activitypub/account.ts
new file mode 100644
index 000000000..8a7d1b7fe
--- /dev/null
+++ b/server/helpers/custom-validators/activitypub/account.ts
@@ -0,0 +1,123 @@
1import * as validator from 'validator'
2
3import { exists, isUUIDValid } from '../misc'
4import { isActivityPubUrlValid } from './misc'
5import { isUserUsernameValid } from '../users'
6
7function isAccountEndpointsObjectValid (endpointObject: any) {
8 return isAccountSharedInboxValid(endpointObject.sharedInbox)
9}
10
11function isAccountSharedInboxValid (sharedInbox: string) {
12 return isActivityPubUrlValid(sharedInbox)
13}
14
15function isAccountPublicKeyObjectValid (publicKeyObject: any) {
16 return isAccountPublicKeyIdValid(publicKeyObject.id) &&
17 isAccountPublicKeyOwnerValid(publicKeyObject.owner) &&
18 isAccountPublicKeyValid(publicKeyObject.publicKeyPem)
19}
20
21function isAccountPublicKeyIdValid (id: string) {
22 return isActivityPubUrlValid(id)
23}
24
25function isAccountTypeValid (type: string) {
26 return type === 'Person' || type === 'Application'
27}
28
29function isAccountPublicKeyOwnerValid (owner: string) {
30 return isActivityPubUrlValid(owner)
31}
32
33function isAccountPublicKeyValid (publicKey: string) {
34 return exists(publicKey) &&
35 typeof publicKey === 'string' &&
36 publicKey.startsWith('-----BEGIN PUBLIC KEY-----') &&
37 publicKey.endsWith('-----END PUBLIC KEY-----')
38}
39
40function isAccountIdValid (id: string) {
41 return isActivityPubUrlValid(id)
42}
43
44function isAccountFollowingValid (id: string) {
45 return isActivityPubUrlValid(id)
46}
47
48function isAccountFollowersValid (id: string) {
49 return isActivityPubUrlValid(id)
50}
51
52function isAccountInboxValid (inbox: string) {
53 return isActivityPubUrlValid(inbox)
54}
55
56function isAccountOutboxValid (outbox: string) {
57 return isActivityPubUrlValid(outbox)
58}
59
60function isAccountNameValid (name: string) {
61 return isUserUsernameValid(name)
62}
63
64function isAccountPreferredUsernameValid (preferredUsername: string) {
65 return isAccountNameValid(preferredUsername)
66}
67
68function isAccountUrlValid (url: string) {
69 return isActivityPubUrlValid(url)
70}
71
72function isAccountPrivateKeyValid (privateKey: string) {
73 return exists(privateKey) &&
74 typeof privateKey === 'string' &&
75 privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') &&
76 privateKey.endsWith('-----END RSA PRIVATE KEY-----')
77}
78
79function isRemoteAccountValid (remoteAccount: any) {
80 return isAccountIdValid(remoteAccount.id) &&
81 isUUIDValid(remoteAccount.uuid) &&
82 isAccountTypeValid(remoteAccount.type) &&
83 isAccountFollowingValid(remoteAccount.following) &&
84 isAccountFollowersValid(remoteAccount.followers) &&
85 isAccountInboxValid(remoteAccount.inbox) &&
86 isAccountOutboxValid(remoteAccount.outbox) &&
87 isAccountPreferredUsernameValid(remoteAccount.preferredUsername) &&
88 isAccountUrlValid(remoteAccount.url) &&
89 isAccountPublicKeyObjectValid(remoteAccount.publicKey) &&
90 isAccountEndpointsObjectValid(remoteAccount.endpoint)
91}
92
93function isAccountFollowingCountValid (value: string) {
94 return exists(value) && validator.isInt('' + value, { min: 0 })
95}
96
97function isAccountFollowersCountValid (value: string) {
98 return exists(value) && validator.isInt('' + value, { min: 0 })
99}
100
101// ---------------------------------------------------------------------------
102
103export {
104 isAccountEndpointsObjectValid,
105 isAccountSharedInboxValid,
106 isAccountPublicKeyObjectValid,
107 isAccountPublicKeyIdValid,
108 isAccountTypeValid,
109 isAccountPublicKeyOwnerValid,
110 isAccountPublicKeyValid,
111 isAccountIdValid,
112 isAccountFollowingValid,
113 isAccountFollowersValid,
114 isAccountInboxValid,
115 isAccountOutboxValid,
116 isAccountPreferredUsernameValid,
117 isAccountUrlValid,
118 isAccountPrivateKeyValid,
119 isRemoteAccountValid,
120 isAccountFollowingCountValid,
121 isAccountFollowersCountValid,
122 isAccountNameValid
123}
diff --git a/server/helpers/custom-validators/activitypub/index.ts b/server/helpers/custom-validators/activitypub/index.ts
new file mode 100644
index 000000000..800f0ddf3
--- /dev/null
+++ b/server/helpers/custom-validators/activitypub/index.ts
@@ -0,0 +1,4 @@
1export * from './account'
2export * from './signature'
3export * from './misc'
4export * from './videos'
diff --git a/server/helpers/custom-validators/activitypub/misc.ts b/server/helpers/custom-validators/activitypub/misc.ts
new file mode 100644
index 000000000..806d33483
--- /dev/null
+++ b/server/helpers/custom-validators/activitypub/misc.ts
@@ -0,0 +1,17 @@
1import { exists } from '../misc'
2
3function isActivityPubUrlValid (url: string) {
4 const isURLOptions = {
5 require_host: true,
6 require_tld: true,
7 require_protocol: true,
8 require_valid_protocol: true,
9 protocols: [ 'http', 'https' ]
10 }
11
12 return exists(url) && validator.isURL(url, isURLOptions)
13}
14
15export {
16 isActivityPubUrlValid
17}
diff --git a/server/helpers/custom-validators/activitypub/signature.ts b/server/helpers/custom-validators/activitypub/signature.ts
new file mode 100644
index 000000000..683ed2b1c
--- /dev/null
+++ b/server/helpers/custom-validators/activitypub/signature.ts
@@ -0,0 +1,22 @@
1import { exists } from '../misc'
2import { isActivityPubUrlValid } from './misc'
3
4function isSignatureTypeValid (signatureType: string) {
5 return exists(signatureType) && signatureType === 'GraphSignature2012'
6}
7
8function isSignatureCreatorValid (signatureCreator: string) {
9 return exists(signatureCreator) && isActivityPubUrlValid(signatureCreator)
10}
11
12function isSignatureValueValid (signatureValue: string) {
13 return exists(signatureValue) && signatureValue.length > 0
14}
15
16// ---------------------------------------------------------------------------
17
18export {
19 isSignatureTypeValid,
20 isSignatureCreatorValid,
21 isSignatureValueValid
22}
diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts
new file mode 100644
index 000000000..e0ffba679
--- /dev/null
+++ b/server/helpers/custom-validators/activitypub/videos.ts
@@ -0,0 +1,184 @@
1import 'express-validator'
2import { has, values } from 'lodash'
3
4import {
5 REQUEST_ENDPOINTS,
6 REQUEST_ENDPOINT_ACTIONS,
7 REQUEST_VIDEO_EVENT_TYPES
8} from '../../../initializers'
9import { isArray, isDateValid, isUUIDValid } from '../misc'
10import {
11 isVideoThumbnailDataValid,
12 isVideoAbuseReasonValid,
13 isVideoAbuseReporterUsernameValid,
14 isVideoViewsValid,
15 isVideoLikesValid,
16 isVideoDislikesValid,
17 isVideoEventCountValid,
18 isRemoteVideoCategoryValid,
19 isRemoteVideoLicenceValid,
20 isRemoteVideoLanguageValid,
21 isVideoNSFWValid,
22 isVideoTruncatedDescriptionValid,
23 isVideoDurationValid,
24 isVideoFileInfoHashValid,
25 isVideoNameValid,
26 isVideoTagsValid,
27 isVideoFileExtnameValid,
28 isVideoFileResolutionValid
29} from '../videos'
30import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels'
31import { isVideoAuthorNameValid } from '../video-authors'
32
33const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
34
35const checkers: { [ id: string ]: (obj: any) => boolean } = {}
36checkers[ENDPOINT_ACTIONS.ADD_VIDEO] = checkAddVideo
37checkers[ENDPOINT_ACTIONS.UPDATE_VIDEO] = checkUpdateVideo
38checkers[ENDPOINT_ACTIONS.REMOVE_VIDEO] = checkRemoveVideo
39checkers[ENDPOINT_ACTIONS.REPORT_ABUSE] = checkReportVideo
40checkers[ENDPOINT_ACTIONS.ADD_CHANNEL] = checkAddVideoChannel
41checkers[ENDPOINT_ACTIONS.UPDATE_CHANNEL] = checkUpdateVideoChannel
42checkers[ENDPOINT_ACTIONS.REMOVE_CHANNEL] = checkRemoveVideoChannel
43checkers[ENDPOINT_ACTIONS.ADD_AUTHOR] = checkAddAuthor
44checkers[ENDPOINT_ACTIONS.REMOVE_AUTHOR] = checkRemoveAuthor
45
46function removeBadRequestVideos (requests: any[]) {
47 for (let i = requests.length - 1; i >= 0 ; i--) {
48 const request = requests[i]
49 const video = request.data
50
51 if (
52 !video ||
53 checkers[request.type] === undefined ||
54 checkers[request.type](video) === false
55 ) {
56 requests.splice(i, 1)
57 }
58 }
59}
60
61function removeBadRequestVideosQadu (requests: any[]) {
62 for (let i = requests.length - 1; i >= 0 ; i--) {
63 const request = requests[i]
64 const video = request.data
65
66 if (
67 !video ||
68 (
69 isUUIDValid(video.uuid) &&
70 (has(video, 'views') === false || isVideoViewsValid(video.views)) &&
71 (has(video, 'likes') === false || isVideoLikesValid(video.likes)) &&
72 (has(video, 'dislikes') === false || isVideoDislikesValid(video.dislikes))
73 ) === false
74 ) {
75 requests.splice(i, 1)
76 }
77 }
78}
79
80function removeBadRequestVideosEvents (requests: any[]) {
81 for (let i = requests.length - 1; i >= 0 ; i--) {
82 const request = requests[i]
83 const eventData = request.data
84
85 if (
86 !eventData ||
87 (
88 isUUIDValid(eventData.uuid) &&
89 values(REQUEST_VIDEO_EVENT_TYPES).indexOf(eventData.eventType) !== -1 &&
90 isVideoEventCountValid(eventData.count)
91 ) === false
92 ) {
93 requests.splice(i, 1)
94 }
95 }
96}
97
98// ---------------------------------------------------------------------------
99
100export {
101 removeBadRequestVideos,
102 removeBadRequestVideosQadu,
103 removeBadRequestVideosEvents
104}
105
106// ---------------------------------------------------------------------------
107
108function isCommonVideoAttributesValid (video: any) {
109 return isDateValid(video.createdAt) &&
110 isDateValid(video.updatedAt) &&
111 isRemoteVideoCategoryValid(video.category) &&
112 isRemoteVideoLicenceValid(video.licence) &&
113 isRemoteVideoLanguageValid(video.language) &&
114 isVideoNSFWValid(video.nsfw) &&
115 isVideoTruncatedDescriptionValid(video.truncatedDescription) &&
116 isVideoDurationValid(video.duration) &&
117 isVideoNameValid(video.name) &&
118 isVideoTagsValid(video.tags) &&
119 isUUIDValid(video.uuid) &&
120 isVideoViewsValid(video.views) &&
121 isVideoLikesValid(video.likes) &&
122 isVideoDislikesValid(video.dislikes) &&
123 isArray(video.files) &&
124 video.files.every(videoFile => {
125 if (!videoFile) return false
126
127 return (
128 isVideoFileInfoHashValid(videoFile.infoHash) &&
129 isVideoFileExtnameValid(videoFile.extname) &&
130 isVideoFileResolutionValid(videoFile.resolution)
131 )
132 })
133}
134
135function checkAddVideo (video: any) {
136 return isCommonVideoAttributesValid(video) &&
137 isUUIDValid(video.channelUUID) &&
138 isVideoThumbnailDataValid(video.thumbnailData)
139}
140
141function checkUpdateVideo (video: any) {
142 return isCommonVideoAttributesValid(video)
143}
144
145function checkRemoveVideo (video: any) {
146 return isUUIDValid(video.uuid)
147}
148
149function checkReportVideo (abuse: any) {
150 return isUUIDValid(abuse.videoUUID) &&
151 isVideoAbuseReasonValid(abuse.reportReason) &&
152 isVideoAbuseReporterUsernameValid(abuse.reporterUsername)
153}
154
155function checkAddVideoChannel (videoChannel: any) {
156 return isUUIDValid(videoChannel.uuid) &&
157 isVideoChannelNameValid(videoChannel.name) &&
158 isVideoChannelDescriptionValid(videoChannel.description) &&
159 isDateValid(videoChannel.createdAt) &&
160 isDateValid(videoChannel.updatedAt) &&
161 isUUIDValid(videoChannel.ownerUUID)
162}
163
164function checkUpdateVideoChannel (videoChannel: any) {
165 return isUUIDValid(videoChannel.uuid) &&
166 isVideoChannelNameValid(videoChannel.name) &&
167 isVideoChannelDescriptionValid(videoChannel.description) &&
168 isDateValid(videoChannel.createdAt) &&
169 isDateValid(videoChannel.updatedAt) &&
170 isUUIDValid(videoChannel.ownerUUID)
171}
172
173function checkRemoveVideoChannel (videoChannel: any) {
174 return isUUIDValid(videoChannel.uuid)
175}
176
177function checkAddAuthor (author: any) {
178 return isUUIDValid(author.uuid) &&
179 isVideoAuthorNameValid(author.name)
180}
181
182function checkRemoveAuthor (author: any) {
183 return isUUIDValid(author.uuid)
184}