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