]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/helpers/custom-validators/misc.ts
Fix pending subscription deletion
[github/Chocobozzz/PeerTube.git] / server / helpers / custom-validators / misc.ts
CommitLineData
ac81d1a0 1import 'multer'
f6d6e7f8 2import { UploadFilesForCheck } from 'express'
345da516 3import { sep } from 'path'
f6d6e7f8 4import validator from 'validator'
0628157f 5import { isShortUUID, shortToUUID } from '@shared/extra-utils'
fdbda9e3 6
69818c93 7function exists (value: any) {
e4c55619
C
8 return value !== undefined && value !== null
9}
10
345da516
C
11function isSafePath (p: string) {
12 return exists(p) &&
13 (p + '').split(sep).every(part => {
f023a19c 14 return [ '..' ].includes(part) === false
345da516
C
15 })
16}
17
5e47f6ab
C
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)
0c9668f7
C
24}
25
d7ce9dca
C
26function isSafePeerTubeFilenameWithoutExtension (filename: string) {
27 return filename.match(/^[a-z0-9-]+$/)
28}
29
c158a5fa 30function isArray (value: any): value is any[] {
e4c55619
C
31 return Array.isArray(value)
32}
33
2f1548fd
C
34function isNotEmptyIntArray (value: any) {
35 return Array.isArray(value) && value.every(v => validator.isInt('' + v)) && value.length !== 0
cef534ed
C
36}
37
b033851f
C
38function isNotEmptyStringArray (value: any) {
39 return Array.isArray(value) && value.every(v => typeof v === 'string' && v.length !== 0) && value.length !== 0
40}
41
09209296
C
42function isArrayOf (value: any, validator: (value: any) => boolean) {
43 return isArray(value) && value.every(v => validator(v))
44}
45
72c7248b
C
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
fbd67e7f
C
58function areUUIDsValid (values: string[]) {
59 return isArray(values) && values.every(v => isUUIDValid(v))
60}
61
72c7248b
C
62function isIdOrUUIDValid (value: string) {
63 return isIdValid(value) || isUUIDValid(value)
64}
65
360329cc 66function isBooleanValid (value: any) {
47564bbe
C
67 return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value))
68}
69
fb719404
C
70function isIntOrNull (value: any) {
71 return value === null || validator.isInt('' + value)
72}
73
d4a8e7a6 74// ---------------------------------------------------------------------------
f0a39880 75
c729caf6
C
76function isFileValid (options: {
77 files: UploadFilesForCheck
f2eb23cd 78
c729caf6
C
79 maxSize: number | null
80 mimeTypeRegex: string | null
f2eb23cd 81
c729caf6 82 field?: string
f2eb23cd 83
c729caf6
C
84 optional?: boolean // Default false
85}) {
86 const { files, mimeTypeRegex, field, maxSize, optional = false } = options
f2eb23cd 87
ac81d1a0
C
88 // Should have files
89 if (!files) return optional
ac81d1a0 90
c729caf6
C
91 const fileArray = isArray(files)
92 ? files
93 : files[field]
94
95 if (!fileArray || !isArray(fileArray) || fileArray.length === 0) {
ac81d1a0
C
96 return optional
97 }
98
c729caf6 99 // The file exists
a1587156 100 const file = fileArray[0]
99b75748 101 if (!file?.originalname) return false
ac81d1a0 102
0c237b19 103 // Check size
c1e791ba 104 if ((maxSize !== null) && file.size > maxSize) return false
0c237b19 105
c729caf6
C
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)
ac81d1a0
C
113}
114
e4c55619
C
115// ---------------------------------------------------------------------------
116
d4a8e7a6 117function toCompleteUUID (value: string) {
ded68a97
C
118 if (isShortUUID(value)) {
119 try {
120 return shortToUUID(value)
121 } catch {
122 return null
123 }
124 }
d4a8e7a6
C
125
126 return value
127}
128
fbd67e7f
C
129function toCompleteUUIDs (values: string[]) {
130 return values.map(v => toCompleteUUID(v))
131}
132
d4a8e7a6
C
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
d4a8e7a6
C
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
65fcc311
C
166export {
167 exists,
09209296 168 isArrayOf,
2f1548fd 169 isNotEmptyIntArray,
72c7248b 170 isArray,
fb719404 171 isIntOrNull,
72c7248b 172 isIdValid,
345da516 173 isSafePath,
b033851f 174 isNotEmptyStringArray,
72c7248b 175 isUUIDValid,
fbd67e7f 176 toCompleteUUIDs,
d4a8e7a6 177 toCompleteUUID,
72c7248b 178 isIdOrUUIDValid,
47564bbe 179 isDateValid,
2efd32f6 180 toValueOrNull,
c8861d5d 181 toBooleanOrNull,
ac81d1a0 182 isBooleanValid,
360329cc 183 toIntOrNull,
fbd67e7f 184 areUUIDsValid,
f0a39880 185 toIntArray,
c729caf6 186 isFileValid,
d7ce9dca 187 isSafePeerTubeFilenameWithoutExtension,
0c9668f7 188 isSafeFilename,
c729caf6 189 checkMimetypeRegex
65fcc311 190}