]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/helpers/custom-validators/misc.ts
Don't inject untrusted input
[github/Chocobozzz/PeerTube.git] / server / helpers / custom-validators / misc.ts
1 import 'multer'
2 import { UploadFilesForCheck } from 'express'
3 import { sep } from 'path'
4 import validator from 'validator'
5 import { isShortUUID, shortToUUID } from '@shared/extra-utils'
6
7 function exists (value: any) {
8 return value !== undefined && value !== null
9 }
10
11 function isSafePath (p: string) {
12 return exists(p) &&
13 (p + '').split(sep).every(part => {
14 return [ '..' ].includes(part) === false
15 })
16 }
17
18 function isArray (value: any): value is any[] {
19 return Array.isArray(value)
20 }
21
22 function isNotEmptyIntArray (value: any) {
23 return Array.isArray(value) && value.every(v => validator.isInt('' + v)) && value.length !== 0
24 }
25
26 function isNotEmptyStringArray (value: any) {
27 return Array.isArray(value) && value.every(v => typeof v === 'string' && v.length !== 0) && value.length !== 0
28 }
29
30 function isArrayOf (value: any, validator: (value: any) => boolean) {
31 return isArray(value) && value.every(v => validator(v))
32 }
33
34 function isDateValid (value: string) {
35 return exists(value) && validator.isISO8601(value)
36 }
37
38 function isIdValid (value: string) {
39 return exists(value) && validator.isInt('' + value)
40 }
41
42 function isUUIDValid (value: string) {
43 return exists(value) && validator.isUUID('' + value, 4)
44 }
45
46 function areUUIDsValid (values: string[]) {
47 return isArray(values) && values.every(v => isUUIDValid(v))
48 }
49
50 function isIdOrUUIDValid (value: string) {
51 return isIdValid(value) || isUUIDValid(value)
52 }
53
54 function isBooleanValid (value: any) {
55 return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value))
56 }
57
58 function isIntOrNull (value: any) {
59 return value === null || validator.isInt('' + value)
60 }
61
62 // ---------------------------------------------------------------------------
63
64 function isFileValid (options: {
65 files: UploadFilesForCheck
66
67 maxSize: number | null
68 mimeTypeRegex: string | null
69
70 field?: string
71
72 optional?: boolean // Default false
73 }) {
74 const { files, mimeTypeRegex, field, maxSize, optional = false } = options
75
76 // Should have files
77 if (!files) return optional
78
79 const fileArray = isArray(files)
80 ? files
81 : files[field]
82
83 if (!fileArray || !isArray(fileArray) || fileArray.length === 0) {
84 return optional
85 }
86
87 // The file exists
88 const file = fileArray[0]
89 if (!file || !file.originalname) return false
90
91 // Check size
92 if ((maxSize !== null) && file.size > maxSize) return false
93
94 if (mimeTypeRegex === null) return true
95
96 return checkMimetypeRegex(file.mimetype, mimeTypeRegex)
97 }
98
99 function checkMimetypeRegex (fileMimeType: string, mimeTypeRegex: string) {
100 return new RegExp(`^${mimeTypeRegex}$`, 'i').test(fileMimeType)
101 }
102
103 // ---------------------------------------------------------------------------
104
105 function toCompleteUUID (value: string) {
106 if (isShortUUID(value)) return shortToUUID(value)
107
108 return value
109 }
110
111 function toCompleteUUIDs (values: string[]) {
112 return values.map(v => toCompleteUUID(v))
113 }
114
115 function toIntOrNull (value: string) {
116 const v = toValueOrNull(value)
117
118 if (v === null || v === undefined) return v
119 if (typeof v === 'number') return v
120
121 return validator.toInt('' + v)
122 }
123
124 function toBooleanOrNull (value: any) {
125 const v = toValueOrNull(value)
126
127 if (v === null || v === undefined) return v
128 if (typeof v === 'boolean') return v
129
130 return validator.toBoolean('' + v)
131 }
132
133 function toValueOrNull (value: string) {
134 if (value === 'null') return null
135
136 return value
137 }
138
139 function toIntArray (value: any) {
140 if (!value) return []
141 if (isArray(value) === false) return [ validator.toInt(value) ]
142
143 return value.map(v => validator.toInt(v))
144 }
145
146 // ---------------------------------------------------------------------------
147
148 export {
149 exists,
150 isArrayOf,
151 isNotEmptyIntArray,
152 isArray,
153 isIntOrNull,
154 isIdValid,
155 isSafePath,
156 isNotEmptyStringArray,
157 isUUIDValid,
158 toCompleteUUIDs,
159 toCompleteUUID,
160 isIdOrUUIDValid,
161 isDateValid,
162 toValueOrNull,
163 toBooleanOrNull,
164 isBooleanValid,
165 toIntOrNull,
166 areUUIDsValid,
167 toIntArray,
168 isFileValid,
169 checkMimetypeRegex
170 }