aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2018-06-22 15:42:55 +0200
committerChocobozzz <me@florianbigard.com>2018-06-22 15:42:55 +0200
commit0c237b19fdf9c614293c1442f0ab95a81ce05735 (patch)
tree81f7ae4262630da5e8041bd70e2cb856e48253a3
parentc4082b8b4e3684baae0172e97297c936d7419f2c (diff)
downloadPeerTube-0c237b19fdf9c614293c1442f0ab95a81ce05735.tar.gz
PeerTube-0c237b19fdf9c614293c1442f0ab95a81ce05735.tar.zst
PeerTube-0c237b19fdf9c614293c1442f0ab95a81ce05735.zip
Fix images size limit
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-settings.component.ts6
-rw-r--r--client/src/app/shared/users/user.model.ts7
-rw-r--r--client/src/app/videos/+video-edit/shared/video-image.component.ts11
-rw-r--r--server/helpers/custom-validators/misc.ts4
-rw-r--r--server/helpers/custom-validators/users.ts3
-rw-r--r--server/helpers/custom-validators/videos.ts4
-rw-r--r--server/middlewares/validators/users.ts10
-rw-r--r--server/middlewares/validators/videos.ts45
-rw-r--r--server/tests/api/check-params/videos.ts8
9 files changed, 59 insertions, 39 deletions
diff --git a/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts b/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
index 15f977e58..14293f14c 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
+++ b/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
@@ -50,6 +50,10 @@ export class MyAccountSettingsComponent implements OnInit {
50 50
51 changeAvatar () { 51 changeAvatar () {
52 const avatarfile = this.avatarfileInput.nativeElement.files[ 0 ] 52 const avatarfile = this.avatarfileInput.nativeElement.files[ 0 ]
53 if (avatarfile.size > this.maxAvatarSize) {
54 this.notificationsService.error('Error', 'This image is too large.')
55 return
56 }
53 57
54 const formData = new FormData() 58 const formData = new FormData()
55 formData.append('avatarfile', avatarfile) 59 formData.append('avatarfile', avatarfile)
@@ -59,7 +63,7 @@ export class MyAccountSettingsComponent implements OnInit {
59 data => { 63 data => {
60 this.notificationsService.success(this.i18n('Success'), this.i18n('Avatar changed.')) 64 this.notificationsService.success(this.i18n('Success'), this.i18n('Avatar changed.'))
61 65
62 this.user.account.avatar = data.avatar 66 this.user.updateAccountAvatar(data.avatar)
63 }, 67 },
64 68
65 err => this.notificationsService.error(this.i18n('Error'), err.message) 69 err => this.notificationsService.error(this.i18n('Error'), err.message)
diff --git a/client/src/app/shared/users/user.model.ts b/client/src/app/shared/users/user.model.ts
index b4be2270f..60a0f26df 100644
--- a/client/src/app/shared/users/user.model.ts
+++ b/client/src/app/shared/users/user.model.ts
@@ -9,6 +9,7 @@ import {
9import { NSFWPolicyType } from '../../../../../shared/models/videos/nsfw-policy.type' 9import { NSFWPolicyType } from '../../../../../shared/models/videos/nsfw-policy.type'
10import { Actor } from '@app/shared/actor/actor.model' 10import { Actor } from '@app/shared/actor/actor.model'
11import { Account } from '@app/shared/account/account.model' 11import { Account } from '@app/shared/account/account.model'
12import { Avatar } from '../../../../../shared/models/avatars/avatar.model'
12 13
13export type UserConstructorHash = { 14export type UserConstructorHash = {
14 id: number, 15 id: number,
@@ -84,6 +85,12 @@ export class User implements UserServerModel {
84 this.updateComputedAttributes() 85 this.updateComputedAttributes()
85 } 86 }
86 87
88 updateAccountAvatar (newAccountAvatar: Avatar) {
89 this.account.avatar = newAccountAvatar
90
91 this.updateComputedAttributes()
92 }
93
87 private updateComputedAttributes () { 94 private updateComputedAttributes () {
88 this.accountAvatarUrl = Actor.GET_ACTOR_AVATAR_URL(this.account) 95 this.accountAvatarUrl = Actor.GET_ACTOR_AVATAR_URL(this.account)
89 } 96 }
diff --git a/client/src/app/videos/+video-edit/shared/video-image.component.ts b/client/src/app/videos/+video-edit/shared/video-image.component.ts
index df6565857..25955baaa 100644
--- a/client/src/app/videos/+video-edit/shared/video-image.component.ts
+++ b/client/src/app/videos/+video-edit/shared/video-image.component.ts
@@ -2,6 +2,8 @@ import { Component, forwardRef, Input } from '@angular/core'
2import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' 2import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
3import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser' 3import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'
4import { ServerService } from '@app/core' 4import { ServerService } from '@app/core'
5import { NotificationsService } from 'angular2-notifications'
6import { I18n } from '@ngx-translate/i18n-polyfill'
5 7
6@Component({ 8@Component({
7 selector: 'my-video-image', 9 selector: 'my-video-image',
@@ -27,7 +29,9 @@ export class VideoImageComponent implements ControlValueAccessor {
27 29
28 constructor ( 30 constructor (
29 private sanitizer: DomSanitizer, 31 private sanitizer: DomSanitizer,
30 private serverService: ServerService 32 private serverService: ServerService,
33 private notificationsService: NotificationsService,
34 private i18n: I18n
31 ) {} 35 ) {}
32 36
33 get videoImageExtensions () { 37 get videoImageExtensions () {
@@ -42,6 +46,11 @@ export class VideoImageComponent implements ControlValueAccessor {
42 if (event.target.files && event.target.files.length) { 46 if (event.target.files && event.target.files.length) {
43 const [ file ] = event.target.files 47 const [ file ] = event.target.files
44 48
49 if (file.size > this.maxVideoImageSize) {
50 this.notificationsService.error(this.i18n('Error'), this.i18n('This image is too large.'))
51 return
52 }
53
45 this.file = file 54 this.file = file
46 this.propagateChange(this.file) 55 this.propagateChange(this.file)
47 this.updatePreview() 56 this.updatePreview()
diff --git a/server/helpers/custom-validators/misc.ts b/server/helpers/custom-validators/misc.ts
index 254b4db6c..455aae367 100644
--- a/server/helpers/custom-validators/misc.ts
+++ b/server/helpers/custom-validators/misc.ts
@@ -45,6 +45,7 @@ function isFileValid (
45 files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], 45 files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
46 mimeTypeRegex: string, 46 mimeTypeRegex: string,
47 field: string, 47 field: string,
48 maxSize: number,
48 optional = false 49 optional = false
49) { 50) {
50 // Should have files 51 // Should have files
@@ -61,6 +62,9 @@ function isFileValid (
61 const file = fileArray[ 0 ] 62 const file = fileArray[ 0 ]
62 if (!file || !file.originalname) return false 63 if (!file || !file.originalname) return false
63 64
65 // Check size
66 if (maxSize && file.size > maxSize) return false
67
64 return new RegExp(`^${mimeTypeRegex}$`, 'i').test(file.mimetype) 68 return new RegExp(`^${mimeTypeRegex}$`, 'i').test(file.mimetype)
65} 69}
66 70
diff --git a/server/helpers/custom-validators/users.ts b/server/helpers/custom-validators/users.ts
index b59b766de..ce1323e94 100644
--- a/server/helpers/custom-validators/users.ts
+++ b/server/helpers/custom-validators/users.ts
@@ -2,7 +2,6 @@ import 'express-validator'
2import * as validator from 'validator' 2import * as validator from 'validator'
3import { UserRole } from '../../../shared' 3import { UserRole } from '../../../shared'
4import { CONSTRAINTS_FIELDS, NSFW_POLICY_TYPES } from '../../initializers' 4import { CONSTRAINTS_FIELDS, NSFW_POLICY_TYPES } from '../../initializers'
5
6import { exists, isFileValid } from './misc' 5import { exists, isFileValid } from './misc'
7import { values } from 'lodash' 6import { values } from 'lodash'
8 7
@@ -52,7 +51,7 @@ const avatarMimeTypes = CONSTRAINTS_FIELDS.ACTORS.AVATAR.EXTNAME
52 .join('|') 51 .join('|')
53const avatarMimeTypesRegex = `image/(${avatarMimeTypes})` 52const avatarMimeTypesRegex = `image/(${avatarMimeTypes})`
54function isAvatarFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) { 53function isAvatarFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
55 return isFileValid(files, avatarMimeTypesRegex, 'avatarfile') 54 return isFileValid(files, avatarMimeTypesRegex, 'avatarfile', CONSTRAINTS_FIELDS.ACTORS.AVATAR.FILE_SIZE.max)
56} 55}
57 56
58// --------------------------------------------------------------------------- 57// ---------------------------------------------------------------------------
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts
index a227136ac..ae392f8c2 100644
--- a/server/helpers/custom-validators/videos.ts
+++ b/server/helpers/custom-validators/videos.ts
@@ -86,7 +86,7 @@ const videoFileTypes = Object.keys(VIDEO_MIMETYPE_EXT).map(m => `(${m})`)
86const videoFileTypesRegex = videoFileTypes.join('|') 86const videoFileTypesRegex = videoFileTypes.join('|')
87 87
88function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) { 88function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
89 return isFileValid(files, videoFileTypesRegex, 'videofile') 89 return isFileValid(files, videoFileTypesRegex, 'videofile', null)
90} 90}
91 91
92const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME 92const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
@@ -95,7 +95,7 @@ const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
95const videoImageTypesRegex = `image/(${videoImageTypes})` 95const videoImageTypesRegex = `image/(${videoImageTypes})`
96 96
97function isVideoImage (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], field: string) { 97function isVideoImage (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], field: string) {
98 return isFileValid(files, videoImageTypesRegex, field, true) 98 return isFileValid(files, videoImageTypesRegex, field, CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max, true)
99} 99}
100 100
101function isVideoPrivacyValid (value: number) { 101function isVideoPrivacyValid (value: number) {
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts
index 8fbab4dd0..55a08a648 100644
--- a/server/middlewares/validators/users.ts
+++ b/server/middlewares/validators/users.ts
@@ -118,7 +118,7 @@ const usersUpdateMeValidator = [
118 118
119const usersUpdateMyAvatarValidator = [ 119const usersUpdateMyAvatarValidator = [
120 body('avatarfile').custom((value, { req }) => isAvatarFile(req.files)).withMessage( 120 body('avatarfile').custom((value, { req }) => isAvatarFile(req.files)).withMessage(
121 'This file is not supported. Please, make sure it is of the following type : ' 121 'This file is not supported or too large. Please, make sure it is of the following type : '
122 + CONSTRAINTS_FIELDS.ACTORS.AVATAR.EXTNAME.join(', ') 122 + CONSTRAINTS_FIELDS.ACTORS.AVATAR.EXTNAME.join(', ')
123 ), 123 ),
124 124
@@ -127,14 +127,6 @@ const usersUpdateMyAvatarValidator = [
127 127
128 if (areValidationErrors(req, res)) return 128 if (areValidationErrors(req, res)) return
129 129
130 const imageFile = req.files['avatarfile'][0] as Express.Multer.File
131 if (imageFile.size > CONSTRAINTS_FIELDS.ACTORS.AVATAR.FILE_SIZE.max) {
132 res.status(400)
133 .send({ error: `The size of the avatar is too big (>${CONSTRAINTS_FIELDS.ACTORS.AVATAR.FILE_SIZE.max}).` })
134 .end()
135 return
136 }
137
138 return next() 130 return next()
139 } 131 }
140] 132]
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts
index 5595edf17..59d65d5a4 100644
--- a/server/middlewares/validators/videos.ts
+++ b/server/middlewares/validators/videos.ts
@@ -38,18 +38,21 @@ import { authenticate } from '../oauth'
38import { areValidationErrors } from './utils' 38import { areValidationErrors } from './utils'
39 39
40const videosAddValidator = [ 40const videosAddValidator = [
41 body('videofile').custom((value, { req }) => isVideoFile(req.files)).withMessage( 41 body('videofile')
42 'This file is not supported. Please, make sure it is of the following type : ' 42 .custom((value, { req }) => isVideoFile(req.files)).withMessage(
43 + CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ') 43 'This file is not supported or too large. Please, make sure it is of the following type : '
44 ), 44 + CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ')
45 body('thumbnailfile').custom((value, { req }) => isVideoImage(req.files, 'thumbnailfile')).withMessage( 45 ),
46 'This thumbnail file is not supported. Please, make sure it is of the following type : ' 46 body('thumbnailfile')
47 + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ') 47 .custom((value, { req }) => isVideoImage(req.files, 'thumbnailfile')).withMessage(
48 ), 48 'This thumbnail file is not supported or too large. Please, make sure it is of the following type : '
49 body('previewfile').custom((value, { req }) => isVideoImage(req.files, 'previewfile')).withMessage( 49 + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ')
50 'This preview file is not supported. Please, make sure it is of the following type : ' 50 ),
51 + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ') 51 body('previewfile')
52 ), 52 .custom((value, { req }) => isVideoImage(req.files, 'previewfile')).withMessage(
53 'This preview file is not supported or too large. Please, make sure it is of the following type : '
54 + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ')
55 ),
53 body('name').custom(isVideoNameValid).withMessage('Should have a valid name'), 56 body('name').custom(isVideoNameValid).withMessage('Should have a valid name'),
54 body('category') 57 body('category')
55 .optional() 58 .optional()
@@ -147,14 +150,16 @@ const videosAddValidator = [
147 150
148const videosUpdateValidator = [ 151const videosUpdateValidator = [
149 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 152 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
150 body('thumbnailfile').custom((value, { req }) => isVideoImage(req.files, 'thumbnailfile')).withMessage( 153 body('thumbnailfile')
151 'This thumbnail file is not supported. Please, make sure it is of the following type : ' 154 .custom((value, { req }) => isVideoImage(req.files, 'thumbnailfile')).withMessage(
152 + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ') 155 'This thumbnail file is not supported or too large. Please, make sure it is of the following type : '
153 ), 156 + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ')
154 body('previewfile').custom((value, { req }) => isVideoImage(req.files, 'previewfile')).withMessage( 157 ),
155 'This preview file is not supported. Please, make sure it is of the following type : ' 158 body('previewfile')
156 + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ') 159 .custom((value, { req }) => isVideoImage(req.files, 'previewfile')).withMessage(
157 ), 160 'This preview file is not supported or too large. Please, make sure it is of the following type : '
161 + CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME.join(', ')
162 ),
158 body('name') 163 body('name')
159 .optional() 164 .optional()
160 .custom(isVideoNameValid).withMessage('Should have a valid name'), 165 .custom(isVideoNameValid).withMessage('Should have a valid name'),
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts
index abbea6ba3..7fce8ba7c 100644
--- a/server/tests/api/check-params/videos.ts
+++ b/server/tests/api/check-params/videos.ts
@@ -326,7 +326,7 @@ describe('Test videos API validator', function () {
326 const fields = baseCorrectParams 326 const fields = baseCorrectParams
327 const attaches = { 327 const attaches = {
328 'thumbnailfile': join(__dirname, '..', '..', 'fixtures', 'avatar.png'), 328 'thumbnailfile': join(__dirname, '..', '..', 'fixtures', 'avatar.png'),
329 'videofile': join(__dirname, '..', '..', 'fixtures', 'video_short_fake.webm') 329 'videofile': join(__dirname, '..', '..', 'fixtures', 'video_short.mp4')
330 } 330 }
331 331
332 await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 332 await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
@@ -336,7 +336,7 @@ describe('Test videos API validator', function () {
336 const fields = baseCorrectParams 336 const fields = baseCorrectParams
337 const attaches = { 337 const attaches = {
338 'thumbnailfile': join(__dirname, '..', '..', 'fixtures', 'avatar-big.png'), 338 'thumbnailfile': join(__dirname, '..', '..', 'fixtures', 'avatar-big.png'),
339 'videofile': join(__dirname, '..', '..', 'fixtures', 'video_short_fake.webm') 339 'videofile': join(__dirname, '..', '..', 'fixtures', 'video_short.mp4')
340 } 340 }
341 341
342 await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 342 await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
@@ -346,7 +346,7 @@ describe('Test videos API validator', function () {
346 const fields = baseCorrectParams 346 const fields = baseCorrectParams
347 const attaches = { 347 const attaches = {
348 'previewfile': join(__dirname, '..', '..', 'fixtures', 'avatar.png'), 348 'previewfile': join(__dirname, '..', '..', 'fixtures', 'avatar.png'),
349 'videofile': join(__dirname, '..', '..', 'fixtures', 'video_short_fake.webm') 349 'videofile': join(__dirname, '..', '..', 'fixtures', 'video_short.mp4')
350 } 350 }
351 351
352 await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 352 await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
@@ -356,7 +356,7 @@ describe('Test videos API validator', function () {
356 const fields = baseCorrectParams 356 const fields = baseCorrectParams
357 const attaches = { 357 const attaches = {
358 'previewfile': join(__dirname, '..', '..', 'fixtures', 'avatar-big.png'), 358 'previewfile': join(__dirname, '..', '..', 'fixtures', 'avatar-big.png'),
359 'videofile': join(__dirname, '..', '..', 'fixtures', 'video_short_fake.webm') 359 'videofile': join(__dirname, '..', '..', 'fixtures', 'video_short.mp4')
360 } 360 }
361 361
362 await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 362 await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })