aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2018-01-03 11:10:40 +0100
committerChocobozzz <me@florianbigard.com>2018-01-03 11:10:40 +0100
commit01de67b9a4fcdf01102ccc3cb7dc24beebf6c7ea (patch)
tree9e01809f09adbcd512a8dedf73093a123f88e02c /server
parent47564bbe2eeb2baae9b7e3f9b2b8d16522bc7e04 (diff)
downloadPeerTube-01de67b9a4fcdf01102ccc3cb7dc24beebf6c7ea.tar.gz
PeerTube-01de67b9a4fcdf01102ccc3cb7dc24beebf6c7ea.tar.zst
PeerTube-01de67b9a4fcdf01102ccc3cb7dc24beebf6c7ea.zip
Add avatar max size limit
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/config.ts15
-rw-r--r--server/helpers/custom-validators/activitypub/actor.ts4
-rw-r--r--server/helpers/custom-validators/activitypub/misc.ts2
-rw-r--r--server/initializers/constants.ts12
-rw-r--r--server/middlewares/validators/users.ts11
-rw-r--r--server/models/activitypub/actor.ts16
-rw-r--r--server/models/server/server.ts2
-rw-r--r--server/tests/api/check-params/users.ts8
-rw-r--r--server/tests/api/fixtures/avatar-big.pngbin0 -> 146585 bytes
9 files changed, 50 insertions, 20 deletions
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
index 2f1132904..35c89835b 100644
--- a/server/controllers/api/config.ts
+++ b/server/controllers/api/config.ts
@@ -1,7 +1,7 @@
1import * as express from 'express' 1import * as express from 'express'
2import { isSignupAllowed } from '../../helpers/utils' 2import { isSignupAllowed } from '../../helpers/utils'
3 3
4import { CONFIG } from '../../initializers' 4import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers'
5import { asyncMiddleware } from '../../middlewares' 5import { asyncMiddleware } from '../../middlewares'
6import { ServerConfig } from '../../../shared' 6import { ServerConfig } from '../../../shared'
7 7
@@ -24,6 +24,19 @@ async function getConfig (req: express.Request, res: express.Response, next: exp
24 }, 24 },
25 transcoding: { 25 transcoding: {
26 enabledResolutions 26 enabledResolutions
27 },
28 avatar: {
29 file: {
30 size: {
31 max: CONSTRAINTS_FIELDS.ACTORS.AVATAR.FILE_SIZE.max
32 },
33 extensions: CONSTRAINTS_FIELDS.ACTORS.AVATAR.EXTNAME
34 }
35 },
36 video: {
37 file: {
38 extensions: CONSTRAINTS_FIELDS.VIDEOS.EXTNAME
39 }
27 } 40 }
28 } 41 }
29 42
diff --git a/server/helpers/custom-validators/activitypub/actor.ts b/server/helpers/custom-validators/activitypub/actor.ts
index 630bace30..700e06007 100644
--- a/server/helpers/custom-validators/activitypub/actor.ts
+++ b/server/helpers/custom-validators/activitypub/actor.ts
@@ -24,7 +24,7 @@ function isActorPublicKeyValid (publicKey: string) {
24 typeof publicKey === 'string' && 24 typeof publicKey === 'string' &&
25 publicKey.startsWith('-----BEGIN PUBLIC KEY-----') && 25 publicKey.startsWith('-----BEGIN PUBLIC KEY-----') &&
26 publicKey.indexOf('-----END PUBLIC KEY-----') !== -1 && 26 publicKey.indexOf('-----END PUBLIC KEY-----') !== -1 &&
27 validator.isLength(publicKey, CONSTRAINTS_FIELDS.ACTOR.PUBLIC_KEY) 27 validator.isLength(publicKey, CONSTRAINTS_FIELDS.ACTORS.PUBLIC_KEY)
28} 28}
29 29
30const actorNameRegExp = new RegExp('[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_]+') 30const actorNameRegExp = new RegExp('[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_]+')
@@ -42,7 +42,7 @@ function isActorPrivateKeyValid (privateKey: string) {
42 privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') && 42 privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') &&
43 // Sometimes there is a \n at the end, so just assert the string contains the end mark 43 // Sometimes there is a \n at the end, so just assert the string contains the end mark
44 privateKey.indexOf('-----END RSA PRIVATE KEY-----') !== -1 && 44 privateKey.indexOf('-----END RSA PRIVATE KEY-----') !== -1 &&
45 validator.isLength(privateKey, CONSTRAINTS_FIELDS.ACTOR.PRIVATE_KEY) 45 validator.isLength(privateKey, CONSTRAINTS_FIELDS.ACTORS.PRIVATE_KEY)
46} 46}
47 47
48function isRemoteActorValid (remoteActor: any) { 48function isRemoteActorValid (remoteActor: any) {
diff --git a/server/helpers/custom-validators/activitypub/misc.ts b/server/helpers/custom-validators/activitypub/misc.ts
index aa6ffc9bd..75d308e9d 100644
--- a/server/helpers/custom-validators/activitypub/misc.ts
+++ b/server/helpers/custom-validators/activitypub/misc.ts
@@ -17,7 +17,7 @@ function isActivityPubUrlValid (url: string) {
17 isURLOptions.require_tld = false 17 isURLOptions.require_tld = false
18 } 18 }
19 19
20 return exists(url) && validator.isURL('' + url, isURLOptions) && validator.isLength('' + url, CONSTRAINTS_FIELDS.ACTOR.URL) 20 return exists(url) && validator.isURL('' + url, isURLOptions) && validator.isLength('' + url, CONSTRAINTS_FIELDS.ACTORS.URL)
21} 21}
22 22
23function isBaseActivityValid (activity: any, type: string) { 23function isBaseActivityValid (activity: any, type: string) {
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 31bb6c981..aefb91537 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -133,9 +133,6 @@ const CONFIG = {
133 } 133 }
134} 134}
135 135
136const AVATARS_DIR = {
137 ACCOUNT: join(CONFIG.STORAGE.AVATARS_DIR, 'account')
138}
139// --------------------------------------------------------------------------- 136// ---------------------------------------------------------------------------
140 137
141const CONSTRAINTS_FIELDS = { 138const CONSTRAINTS_FIELDS = {
@@ -169,12 +166,15 @@ const CONSTRAINTS_FIELDS = {
169 FILE_SIZE: { min: 10 }, 166 FILE_SIZE: { min: 10 },
170 URL: { min: 3, max: 2000 } // Length 167 URL: { min: 3, max: 2000 } // Length
171 }, 168 },
172 ACTOR: { 169 ACTORS: {
173 PUBLIC_KEY: { min: 10, max: 5000 }, // Length 170 PUBLIC_KEY: { min: 10, max: 5000 }, // Length
174 PRIVATE_KEY: { min: 10, max: 5000 }, // Length 171 PRIVATE_KEY: { min: 10, max: 5000 }, // Length
175 URL: { min: 3, max: 2000 }, // Length 172 URL: { min: 3, max: 2000 }, // Length
176 AVATAR: { 173 AVATAR: {
177 EXTNAME: [ '.png', '.jpeg', '.jpg' ] 174 EXTNAME: [ '.png', '.jpeg', '.jpg' ],
175 FILE_SIZE: {
176 max: 2 * 1024 * 1024 // 2MB
177 }
178 } 178 }
179 }, 179 },
180 VIDEO_EVENTS: { 180 VIDEO_EVENTS: {
@@ -345,6 +345,7 @@ if (isTestInstance() === true) {
345 REMOTE_SCHEME.WS = 'ws' 345 REMOTE_SCHEME.WS = 'ws'
346 STATIC_MAX_AGE = '0' 346 STATIC_MAX_AGE = '0'
347 ACTIVITY_PUB.COLLECTION_ITEMS_PER_PAGE = 2 347 ACTIVITY_PUB.COLLECTION_ITEMS_PER_PAGE = 2
348 CONSTRAINTS_FIELDS.ACTORS.AVATAR.FILE_SIZE.max = 100 * 1024 // 100KB
348} 349}
349 350
350CONFIG.WEBSERVER.URL = sanitizeUrl(CONFIG.WEBSERVER.SCHEME + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT) 351CONFIG.WEBSERVER.URL = sanitizeUrl(CONFIG.WEBSERVER.SCHEME + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT)
@@ -372,7 +373,6 @@ export {
372 PREVIEWS_SIZE, 373 PREVIEWS_SIZE,
373 REMOTE_SCHEME, 374 REMOTE_SCHEME,
374 FOLLOW_STATES, 375 FOLLOW_STATES,
375 AVATARS_DIR,
376 SERVER_ACTOR_NAME, 376 SERVER_ACTOR_NAME,
377 PRIVATE_RSA_KEY_SIZE, 377 PRIVATE_RSA_KEY_SIZE,
378 SORTABLE_COLUMNS, 378 SORTABLE_COLUMNS,
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts
index 7c77e9a39..7de3e442c 100644
--- a/server/middlewares/validators/users.ts
+++ b/server/middlewares/validators/users.ts
@@ -12,6 +12,7 @@ import { isSignupAllowed } from '../../helpers/utils'
12import { CONSTRAINTS_FIELDS } from '../../initializers' 12import { CONSTRAINTS_FIELDS } from '../../initializers'
13import { UserModel } from '../../models/account/user' 13import { UserModel } from '../../models/account/user'
14import { areValidationErrors } from './utils' 14import { areValidationErrors } from './utils'
15import Multer = require('multer')
15 16
16const usersAddValidator = [ 17const usersAddValidator = [
17 body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'), 18 body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'),
@@ -100,7 +101,7 @@ const usersUpdateMeValidator = [
100const usersUpdateMyAvatarValidator = [ 101const usersUpdateMyAvatarValidator = [
101 body('avatarfile').custom((value, { req }) => isAvatarFile(req.files)).withMessage( 102 body('avatarfile').custom((value, { req }) => isAvatarFile(req.files)).withMessage(
102 'This file is not supported. Please, make sure it is of the following type : ' 103 'This file is not supported. Please, make sure it is of the following type : '
103 + CONSTRAINTS_FIELDS.ACTOR.AVATAR.EXTNAME.join(', ') 104 + CONSTRAINTS_FIELDS.ACTORS.AVATAR.EXTNAME.join(', ')
104 ), 105 ),
105 106
106 (req: express.Request, res: express.Response, next: express.NextFunction) => { 107 (req: express.Request, res: express.Response, next: express.NextFunction) => {
@@ -108,6 +109,14 @@ const usersUpdateMyAvatarValidator = [
108 109
109 if (areValidationErrors(req, res)) return 110 if (areValidationErrors(req, res)) return
110 111
112 const imageFile = req.files['avatarfile'][0] as Express.Multer.File
113 if (imageFile.size > CONSTRAINTS_FIELDS.ACTORS.AVATAR.FILE_SIZE.max) {
114 res.status(400)
115 .send({ error: `The size of the avatar is too big (>${CONSTRAINTS_FIELDS.ACTORS.AVATAR.FILE_SIZE.max}).` })
116 .end()
117 return
118 }
119
111 return next() 120 return next()
112 } 121 }
113] 122]
diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts
index a12f3ec9e..ff5ab2e32 100644
--- a/server/models/activitypub/actor.ts
+++ b/server/models/activitypub/actor.ts
@@ -87,17 +87,17 @@ export class ActorModel extends Model<ActorModel> {
87 87
88 @AllowNull(false) 88 @AllowNull(false)
89 @Is('ActorUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url')) 89 @Is('ActorUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url'))
90 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTOR.URL.max)) 90 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max))
91 url: string 91 url: string
92 92
93 @AllowNull(true) 93 @AllowNull(true)
94 @Is('ActorPublicKey', value => throwIfNotValid(value, isActorPublicKeyValid, 'public key')) 94 @Is('ActorPublicKey', value => throwIfNotValid(value, isActorPublicKeyValid, 'public key'))
95 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTOR.PUBLIC_KEY.max)) 95 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.PUBLIC_KEY.max))
96 publicKey: string 96 publicKey: string
97 97
98 @AllowNull(true) 98 @AllowNull(true)
99 @Is('ActorPublicKey', value => throwIfNotValid(value, isActorPrivateKeyValid, 'private key')) 99 @Is('ActorPublicKey', value => throwIfNotValid(value, isActorPrivateKeyValid, 'private key'))
100 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTOR.PRIVATE_KEY.max)) 100 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.PRIVATE_KEY.max))
101 privateKey: string 101 privateKey: string
102 102
103 @AllowNull(false) 103 @AllowNull(false)
@@ -112,27 +112,27 @@ export class ActorModel extends Model<ActorModel> {
112 112
113 @AllowNull(false) 113 @AllowNull(false)
114 @Is('ActorInboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'inbox url')) 114 @Is('ActorInboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'inbox url'))
115 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTOR.URL.max)) 115 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max))
116 inboxUrl: string 116 inboxUrl: string
117 117
118 @AllowNull(false) 118 @AllowNull(false)
119 @Is('ActorOutboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'outbox url')) 119 @Is('ActorOutboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'outbox url'))
120 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTOR.URL.max)) 120 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max))
121 outboxUrl: string 121 outboxUrl: string
122 122
123 @AllowNull(false) 123 @AllowNull(false)
124 @Is('ActorSharedInboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'shared inbox url')) 124 @Is('ActorSharedInboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'shared inbox url'))
125 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTOR.URL.max)) 125 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max))
126 sharedInboxUrl: string 126 sharedInboxUrl: string
127 127
128 @AllowNull(false) 128 @AllowNull(false)
129 @Is('ActorFollowersUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'followers url')) 129 @Is('ActorFollowersUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'followers url'))
130 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTOR.URL.max)) 130 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max))
131 followersUrl: string 131 followersUrl: string
132 132
133 @AllowNull(false) 133 @AllowNull(false)
134 @Is('ActorFollowingUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'following url')) 134 @Is('ActorFollowingUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'following url'))
135 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTOR.URL.max)) 135 @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max))
136 followingUrl: string 136 followingUrl: string
137 137
138 @CreatedAt 138 @CreatedAt
diff --git a/server/models/server/server.ts b/server/models/server/server.ts
index d35aa0ca4..122e5f74f 100644
--- a/server/models/server/server.ts
+++ b/server/models/server/server.ts
@@ -27,7 +27,7 @@ export class ServerModel extends Model<ServerModel> {
27 @AllowNull(false) 27 @AllowNull(false)
28 @Default(SERVERS_SCORE.BASE) 28 @Default(SERVERS_SCORE.BASE)
29 @IsInt 29 @IsInt
30 @Max(SERVERS_SCORE.MAX) 30 @Max(SERVERS_SCORE.max)
31 @Column 31 @Column
32 score: number 32 score: number
33 33
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts
index 33d92ac24..14fcf8703 100644
--- a/server/tests/api/check-params/users.ts
+++ b/server/tests/api/check-params/users.ts
@@ -276,6 +276,14 @@ describe('Test users API validators', function () {
276 await makePostUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches }) 276 await makePostUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
277 }) 277 })
278 278
279 it('Should fail with a big file', async function () {
280 const fields = {}
281 const attaches = {
282 'avatarfile': join(__dirname, '..', 'fixtures', 'avatar-big.png')
283 }
284 await makePostUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
285 })
286
279 it('Should succeed with the correct params', async function () { 287 it('Should succeed with the correct params', async function () {
280 const fields = {} 288 const fields = {}
281 const attaches = { 289 const attaches = {
diff --git a/server/tests/api/fixtures/avatar-big.png b/server/tests/api/fixtures/avatar-big.png
new file mode 100644
index 000000000..e593e40da
--- /dev/null
+++ b/server/tests/api/fixtures/avatar-big.png
Binary files differ