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