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