Merge branch 'feature/correctly-send-activities' into develop
[oweals/peertube.git] / server / helpers / custom-validators / activitypub / activity.ts
1 import * as validator from 'validator'
2 import { Activity, ActivityType } from '../../../../shared/models/activitypub'
3 import { sanitizeAndCheckActorObject } from './actor'
4 import { isActivityPubUrlValid, isBaseActivityValid, isObjectValid } from './misc'
5 import { isDislikeActivityValid } from './rate'
6 import { sanitizeAndCheckVideoCommentObject } from './video-comments'
7 import { sanitizeAndCheckVideoTorrentObject } from './videos'
8 import { isViewActivityValid } from './view'
9 import { exists } from '../misc'
10 import { isCacheFileObjectValid } from './cache-file'
11 import { isFlagActivityValid } from './flag'
12
13 function isRootActivityValid (activity: any) {
14   return Array.isArray(activity['@context']) && (
15     (
16       (activity.type === 'Collection' || activity.type === 'OrderedCollection') &&
17       validator.isInt(activity.totalItems, { min: 0 }) &&
18       Array.isArray(activity.items)
19     ) ||
20     (
21       isActivityPubUrlValid(activity.id) &&
22       exists(activity.actor) &&
23       (isActivityPubUrlValid(activity.actor) || isActivityPubUrlValid(activity.actor.id))
24     )
25   )
26 }
27
28 const activityCheckers: { [ P in ActivityType ]: (activity: Activity) => boolean } = {
29   Create: checkCreateActivity,
30   Update: checkUpdateActivity,
31   Delete: checkDeleteActivity,
32   Follow: checkFollowActivity,
33   Accept: checkAcceptActivity,
34   Reject: checkRejectActivity,
35   Announce: checkAnnounceActivity,
36   Undo: checkUndoActivity,
37   Like: checkLikeActivity,
38   View: checkViewActivity,
39   Flag: checkFlagActivity,
40   Dislike: checkDislikeActivity
41 }
42
43 function isActivityValid (activity: any) {
44   const checker = activityCheckers[activity.type]
45   // Unknown activity type
46   if (!checker) return false
47
48   return checker(activity)
49 }
50
51 // ---------------------------------------------------------------------------
52
53 export {
54   isRootActivityValid,
55   isActivityValid
56 }
57
58 // ---------------------------------------------------------------------------
59
60 function checkViewActivity (activity: any) {
61   return isBaseActivityValid(activity, 'View') &&
62     isViewActivityValid(activity)
63 }
64
65 function checkFlagActivity (activity: any) {
66   return isBaseActivityValid(activity, 'Flag') &&
67     isFlagActivityValid(activity)
68 }
69
70 function checkDislikeActivity (activity: any) {
71   return isBaseActivityValid(activity, 'Dislike') &&
72     isDislikeActivityValid(activity)
73 }
74
75 function checkCreateActivity (activity: any) {
76   return isBaseActivityValid(activity, 'Create') &&
77     (
78       isViewActivityValid(activity.object) ||
79       isDislikeActivityValid(activity.object) ||
80       isFlagActivityValid(activity.object) ||
81
82       isCacheFileObjectValid(activity.object) ||
83       sanitizeAndCheckVideoCommentObject(activity.object) ||
84       sanitizeAndCheckVideoTorrentObject(activity.object)
85     )
86 }
87
88 function checkUpdateActivity (activity: any) {
89   return isBaseActivityValid(activity, 'Update') &&
90     (
91       isCacheFileObjectValid(activity.object) ||
92       sanitizeAndCheckVideoTorrentObject(activity.object) ||
93       sanitizeAndCheckActorObject(activity.object)
94     )
95 }
96
97 function checkDeleteActivity (activity: any) {
98   // We don't really check objects
99   return isBaseActivityValid(activity, 'Delete') &&
100     isObjectValid(activity.object)
101 }
102
103 function checkFollowActivity (activity: any) {
104   return isBaseActivityValid(activity, 'Follow') &&
105     isObjectValid(activity.object)
106 }
107
108 function checkAcceptActivity (activity: any) {
109   return isBaseActivityValid(activity, 'Accept')
110 }
111
112 function checkRejectActivity (activity: any) {
113   return isBaseActivityValid(activity, 'Reject')
114 }
115
116 function checkAnnounceActivity (activity: any) {
117   return isBaseActivityValid(activity, 'Announce') &&
118     isObjectValid(activity.object)
119 }
120
121 function checkUndoActivity (activity: any) {
122   return isBaseActivityValid(activity, 'Undo') &&
123     (
124       checkFollowActivity(activity.object) ||
125       checkLikeActivity(activity.object) ||
126       checkDislikeActivity(activity.object) ||
127       checkAnnounceActivity(activity.object) ||
128       checkCreateActivity(activity.object)
129     )
130 }
131
132 function checkLikeActivity (activity: any) {
133   return isBaseActivityValid(activity, 'Like') &&
134     isObjectValid(activity.object)
135 }