diff options
9 files changed, 100 insertions, 61 deletions
diff --git a/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts b/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts index 2b7ba353c..468be022c 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts | |||
@@ -47,7 +47,7 @@ export class MyAccountProfileComponent extends FormReactive implements OnInit { | |||
47 | 47 | ||
48 | updateMyProfile () { | 48 | updateMyProfile () { |
49 | const displayName = this.form.value['display-name'] | 49 | const displayName = this.form.value['display-name'] |
50 | const description = this.form.value['description'] | 50 | const description = this.form.value['description'] || null |
51 | 51 | ||
52 | this.error = null | 52 | this.error = null |
53 | 53 | ||
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts index 0f03548ad..fab9cacd8 100644 --- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts +++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts | |||
@@ -64,8 +64,8 @@ export class MyAccountVideoChannelCreateComponent extends MyAccountVideoChannelE | |||
64 | const body = this.form.value | 64 | const body = this.form.value |
65 | const videoChannelCreate: VideoChannelCreate = { | 65 | const videoChannelCreate: VideoChannelCreate = { |
66 | displayName: body['display-name'], | 66 | displayName: body['display-name'], |
67 | description: body.description || undefined, | 67 | description: body.description || null, |
68 | support: body.support || undefined | 68 | support: body.support || null |
69 | } | 69 | } |
70 | 70 | ||
71 | this.videoChannelService.createVideoChannel(videoChannelCreate).subscribe( | 71 | this.videoChannelService.createVideoChannel(videoChannelCreate).subscribe( |
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts index c0dc6a939..9adc38691 100644 --- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts +++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts | |||
@@ -92,8 +92,8 @@ export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelE | |||
92 | const body = this.form.value | 92 | const body = this.form.value |
93 | const videoChannelUpdate: VideoChannelUpdate = { | 93 | const videoChannelUpdate: VideoChannelUpdate = { |
94 | displayName: body['display-name'], | 94 | displayName: body['display-name'], |
95 | description: body.description || undefined, | 95 | description: body.description || null, |
96 | support: body.support || undefined | 96 | support: body.support || null |
97 | } | 97 | } |
98 | 98 | ||
99 | this.videoChannelService.updateVideoChannel(this.videoChannelToUpdate.uuid, videoChannelUpdate).subscribe( | 99 | this.videoChannelService.updateVideoChannel(this.videoChannelToUpdate.uuid, videoChannelUpdate).subscribe( |
diff --git a/client/src/app/shared/forms/form-validators/user.ts b/client/src/app/shared/forms/form-validators/user.ts index c6b65e0df..0973f1b00 100644 --- a/client/src/app/shared/forms/form-validators/user.ts +++ b/client/src/app/shared/forms/form-validators/user.ts | |||
@@ -60,12 +60,10 @@ export const USER_DISPLAY_NAME = { | |||
60 | } | 60 | } |
61 | export const USER_DESCRIPTION = { | 61 | export const USER_DESCRIPTION = { |
62 | VALIDATORS: [ | 62 | VALIDATORS: [ |
63 | Validators.required, | ||
64 | Validators.minLength(3), | 63 | Validators.minLength(3), |
65 | Validators.maxLength(250) | 64 | Validators.maxLength(250) |
66 | ], | 65 | ], |
67 | MESSAGES: { | 66 | MESSAGES: { |
68 | 'required': 'Description is required.', | ||
69 | 'minlength': 'Description must be at least 3 characters long.', | 67 | 'minlength': 'Description must be at least 3 characters long.', |
70 | 'maxlength': 'Description cannot be more than 250 characters long.' | 68 | 'maxlength': 'Description cannot be more than 250 characters long.' |
71 | } | 69 | } |
diff --git a/client/src/app/shared/misc/utils.ts b/client/src/app/shared/misc/utils.ts index 99f6b3cf0..b5bf99be2 100644 --- a/client/src/app/shared/misc/utils.ts +++ b/client/src/app/shared/misc/utils.ts | |||
@@ -66,7 +66,7 @@ function objectToFormData (obj: any, form?: FormData, namespace?: string) { | |||
66 | 66 | ||
67 | if (obj[key] === undefined) continue | 67 | if (obj[key] === undefined) continue |
68 | 68 | ||
69 | if (typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) { | 69 | if (obj[key] !== null && typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) { |
70 | objectToFormData(obj[ key ], fd, key) | 70 | objectToFormData(obj[ key ], fd, key) |
71 | } else { | 71 | } else { |
72 | fd.append(formKey, obj[ key ]) | 72 | fd.append(formKey, obj[ key ]) |
diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts index 8870cbee4..b45777c55 100644 --- a/client/src/app/shared/video/video.service.ts +++ b/client/src/app/shared/video/video.service.ts | |||
@@ -54,11 +54,11 @@ export class VideoService { | |||
54 | } | 54 | } |
55 | 55 | ||
56 | updateVideo (video: VideoEdit) { | 56 | updateVideo (video: VideoEdit) { |
57 | const language = video.language || undefined | 57 | const language = video.language || null |
58 | const licence = video.licence || undefined | 58 | const licence = video.licence || null |
59 | const category = video.category || undefined | 59 | const category = video.category || null |
60 | const description = video.description || undefined | 60 | const description = video.description || null |
61 | const support = video.support || undefined | 61 | const support = video.support || null |
62 | 62 | ||
63 | const body: VideoUpdate = { | 63 | const body: VideoUpdate = { |
64 | name: video.name, | 64 | name: video.name, |
diff --git a/server/helpers/custom-validators/misc.ts b/server/helpers/custom-validators/misc.ts index 8a270b777..275482fa1 100644 --- a/server/helpers/custom-validators/misc.ts +++ b/server/helpers/custom-validators/misc.ts | |||
@@ -25,10 +25,22 @@ function isIdOrUUIDValid (value: string) { | |||
25 | return isIdValid(value) || isUUIDValid(value) | 25 | return isIdValid(value) || isUUIDValid(value) |
26 | } | 26 | } |
27 | 27 | ||
28 | function isBooleanValid (value: string) { | 28 | function isBooleanValid (value: any) { |
29 | return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value)) | 29 | return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value)) |
30 | } | 30 | } |
31 | 31 | ||
32 | function toIntOrNull (value: string) { | ||
33 | if (value === 'null') return null | ||
34 | |||
35 | return validator.toInt(value) | ||
36 | } | ||
37 | |||
38 | function toStringOrNull (value: string) { | ||
39 | if (value === 'null') return null | ||
40 | |||
41 | return value | ||
42 | } | ||
43 | |||
32 | function isFileValid ( | 44 | function isFileValid ( |
33 | files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], | 45 | files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], |
34 | mimeTypeRegex: string, | 46 | mimeTypeRegex: string, |
@@ -61,6 +73,8 @@ export { | |||
61 | isUUIDValid, | 73 | isUUIDValid, |
62 | isIdOrUUIDValid, | 74 | isIdOrUUIDValid, |
63 | isDateValid, | 75 | isDateValid, |
76 | toStringOrNull, | ||
64 | isBooleanValid, | 77 | isBooleanValid, |
78 | toIntOrNull, | ||
65 | isFileValid | 79 | isFileValid |
66 | } | 80 | } |
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts index e3543ef93..b93dccc50 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos.ts | |||
@@ -2,7 +2,7 @@ import * as express from 'express' | |||
2 | import 'express-validator' | 2 | import 'express-validator' |
3 | import { body, param, query } from 'express-validator/check' | 3 | import { body, param, query } from 'express-validator/check' |
4 | import { UserRight, VideoPrivacy } from '../../../shared' | 4 | import { UserRight, VideoPrivacy } from '../../../shared' |
5 | import { isBooleanValid, isIdOrUUIDValid, isIdValid, isUUIDValid } from '../../helpers/custom-validators/misc' | 5 | import { isBooleanValid, isIdOrUUIDValid, isIdValid, isUUIDValid, toIntOrNull, toStringOrNull } from '../../helpers/custom-validators/misc' |
6 | import { | 6 | import { |
7 | isVideoAbuseReasonValid, | 7 | isVideoAbuseReasonValid, |
8 | isVideoCategoryValid, | 8 | isVideoCategoryValid, |
@@ -14,7 +14,8 @@ import { | |||
14 | isVideoLicenceValid, | 14 | isVideoLicenceValid, |
15 | isVideoNameValid, | 15 | isVideoNameValid, |
16 | isVideoPrivacyValid, | 16 | isVideoPrivacyValid, |
17 | isVideoRatingTypeValid, isVideoSupportValid, | 17 | isVideoRatingTypeValid, |
18 | isVideoSupportValid, | ||
18 | isVideoTagsValid | 19 | isVideoTagsValid |
19 | } from '../../helpers/custom-validators/videos' | 20 | } from '../../helpers/custom-validators/videos' |
20 | import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils' | 21 | import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils' |
@@ -41,16 +42,40 @@ const videosAddValidator = [ | |||
41 | + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ') | 42 | + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ') |
42 | ), | 43 | ), |
43 | body('name').custom(isVideoNameValid).withMessage('Should have a valid name'), | 44 | body('name').custom(isVideoNameValid).withMessage('Should have a valid name'), |
44 | body('category').optional().custom(isVideoCategoryValid).withMessage('Should have a valid category'), | 45 | body('category') |
45 | body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'), | 46 | .optional() |
46 | body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), | 47 | .customSanitizer(toIntOrNull) |
47 | body('nsfw').custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), | 48 | .custom(isVideoCategoryValid).withMessage('Should have a valid category'), |
48 | body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), | 49 | body('licence') |
49 | body('support').optional().custom(isVideoSupportValid).withMessage('Should have a valid support text'), | 50 | .optional() |
51 | .customSanitizer(toIntOrNull) | ||
52 | .custom(isVideoLicenceValid).withMessage('Should have a valid licence'), | ||
53 | body('language') | ||
54 | .optional() | ||
55 | .customSanitizer(toStringOrNull) | ||
56 | .custom(isVideoLanguageValid).withMessage('Should have a valid language'), | ||
57 | body('nsfw') | ||
58 | .toBoolean() | ||
59 | .custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), | ||
60 | body('description') | ||
61 | .optional() | ||
62 | .customSanitizer(toStringOrNull) | ||
63 | .custom(isVideoDescriptionValid).withMessage('Should have a valid description'), | ||
64 | body('support') | ||
65 | .optional() | ||
66 | .customSanitizer(toStringOrNull) | ||
67 | .custom(isVideoSupportValid).withMessage('Should have a valid support text'), | ||
68 | body('tags') | ||
69 | .optional() | ||
70 | .custom(isVideoTagsValid).withMessage('Should have correct tags'), | ||
71 | body('commentsEnabled') | ||
72 | .toBoolean() | ||
73 | .custom(isBooleanValid).withMessage('Should have comments enabled boolean'), | ||
74 | body('privacy') | ||
75 | .optional() | ||
76 | .toInt() | ||
77 | .custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), | ||
50 | body('channelId').custom(isIdValid).withMessage('Should have correct video channel id'), | 78 | body('channelId').custom(isIdValid).withMessage('Should have correct video channel id'), |
51 | body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), | ||
52 | body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), | ||
53 | body('commentsEnabled').custom(isBooleanValid).withMessage('Should have comments enabled boolean'), | ||
54 | 79 | ||
55 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 80 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
56 | logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files }) | 81 | logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files }) |
@@ -110,16 +135,44 @@ const videosUpdateValidator = [ | |||
110 | 'This preview file is not supported. Please, make sure it is of the following type : ' | 135 | 'This preview file is not supported. Please, make sure it is of the following type : ' |
111 | + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ') | 136 | + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ') |
112 | ), | 137 | ), |
113 | body('name').optional().custom(isVideoNameValid).withMessage('Should have a valid name'), | 138 | body('name') |
114 | body('category').optional().custom(isVideoCategoryValid).withMessage('Should have a valid category'), | 139 | .optional() |
115 | body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'), | 140 | .custom(isVideoNameValid).withMessage('Should have a valid name'), |
116 | body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), | 141 | body('category') |
117 | body('nsfw').optional().custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), | 142 | .optional() |
118 | body('privacy').optional().custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), | 143 | .customSanitizer(toIntOrNull) |
119 | body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), | 144 | .custom(isVideoCategoryValid).withMessage('Should have a valid category'), |
120 | body('support').optional().custom(isVideoSupportValid).withMessage('Should have a valid support text'), | 145 | body('licence') |
121 | body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), | 146 | .optional() |
122 | body('commentsEnabled').optional().custom(isBooleanValid).withMessage('Should have comments enabled boolean'), | 147 | .customSanitizer(toIntOrNull) |
148 | .custom(isVideoLicenceValid).withMessage('Should have a valid licence'), | ||
149 | body('language') | ||
150 | .optional() | ||
151 | .customSanitizer(toStringOrNull) | ||
152 | .custom(isVideoLanguageValid).withMessage('Should have a valid language'), | ||
153 | body('nsfw') | ||
154 | .optional() | ||
155 | .toBoolean() | ||
156 | .custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), | ||
157 | body('privacy') | ||
158 | .optional() | ||
159 | .toInt() | ||
160 | .custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), | ||
161 | body('description') | ||
162 | .optional() | ||
163 | .customSanitizer(toStringOrNull) | ||
164 | .custom(isVideoDescriptionValid).withMessage('Should have a valid description'), | ||
165 | body('support') | ||
166 | .optional() | ||
167 | .customSanitizer(toStringOrNull) | ||
168 | .custom(isVideoSupportValid).withMessage('Should have a valid support text'), | ||
169 | body('tags') | ||
170 | .optional() | ||
171 | .custom(isVideoTagsValid).withMessage('Should have correct tags'), | ||
172 | body('commentsEnabled') | ||
173 | .optional() | ||
174 | .toBoolean() | ||
175 | .custom(isBooleanValid).withMessage('Should have comments enabled boolean'), | ||
123 | 176 | ||
124 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 177 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
125 | logger.debug('Checking videosUpdate parameters', { parameters: req.body }) | 178 | logger.debug('Checking videosUpdate parameters', { parameters: req.body }) |
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts index 499a4fc94..2b341a5b3 100644 --- a/server/tests/api/check-params/videos.ts +++ b/server/tests/api/check-params/videos.ts | |||
@@ -231,13 +231,6 @@ describe('Test videos API validator', function () { | |||
231 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | 231 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) |
232 | }) | 232 | }) |
233 | 233 | ||
234 | it('Should fail with a bad nsfw attribute', async function () { | ||
235 | const fields = immutableAssign(baseCorrectParams, { nsfw: 2 }) | ||
236 | const attaches = baseCorrectAttaches | ||
237 | |||
238 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | ||
239 | }) | ||
240 | |||
241 | it('Should fail without commentsEnabled attribute', async function () { | 234 | it('Should fail without commentsEnabled attribute', async function () { |
242 | const fields = omit(baseCorrectParams, 'commentsEnabled') | 235 | const fields = omit(baseCorrectParams, 'commentsEnabled') |
243 | const attaches = baseCorrectAttaches | 236 | const attaches = baseCorrectAttaches |
@@ -245,13 +238,6 @@ describe('Test videos API validator', function () { | |||
245 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | 238 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) |
246 | }) | 239 | }) |
247 | 240 | ||
248 | it('Should fail with a bad commentsEnabled attribute', async function () { | ||
249 | const fields = immutableAssign(baseCorrectParams, { commentsEnabled: 2 }) | ||
250 | const attaches = baseCorrectAttaches | ||
251 | |||
252 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | ||
253 | }) | ||
254 | |||
255 | it('Should fail with a long description', async function () { | 241 | it('Should fail with a long description', async function () { |
256 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(2500) }) | 242 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(2500) }) |
257 | const attaches = baseCorrectAttaches | 243 | const attaches = baseCorrectAttaches |
@@ -485,18 +471,6 @@ describe('Test videos API validator', function () { | |||
485 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) | 471 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) |
486 | }) | 472 | }) |
487 | 473 | ||
488 | it('Should fail with a bad nsfw attribute', async function () { | ||
489 | const fields = immutableAssign(baseCorrectParams, { nsfw: 2 }) | ||
490 | |||
491 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) | ||
492 | }) | ||
493 | |||
494 | it('Should fail with a bad commentsEnabled attribute', async function () { | ||
495 | const fields = immutableAssign(baseCorrectParams, { commentsEnabled: 2 }) | ||
496 | |||
497 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) | ||
498 | }) | ||
499 | |||
500 | it('Should fail with a long description', async function () { | 474 | it('Should fail with a long description', async function () { |
501 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(2500) }) | 475 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(2500) }) |
502 | 476 | ||