diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2016-12-28 15:49:23 +0100 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2016-12-28 15:49:23 +0100 |
commit | 67bf9b96bbcd92b069fe86d9223fe0f8b9c6e677 (patch) | |
tree | bae6a9b0c3133c9cc38a2972222b5991f0cf614e /server/models | |
parent | 552cc9d646e78edae8b0fe61564d4e49db0b6206 (diff) | |
download | PeerTube-67bf9b96bbcd92b069fe86d9223fe0f8b9c6e677.tar.gz PeerTube-67bf9b96bbcd92b069fe86d9223fe0f8b9c6e677.tar.zst PeerTube-67bf9b96bbcd92b069fe86d9223fe0f8b9c6e677.zip |
Server: add database field validations
Diffstat (limited to 'server/models')
-rw-r--r-- | server/models/application.js | 8 | ||||
-rw-r--r-- | server/models/author.js | 13 | ||||
-rw-r--r-- | server/models/oauth-client.js | 11 | ||||
-rw-r--r-- | server/models/oauth-token.js | 19 | ||||
-rw-r--r-- | server/models/pod.js | 34 | ||||
-rw-r--r-- | server/models/request.js | 14 | ||||
-rw-r--r-- | server/models/tag.js | 3 | ||||
-rw-r--r-- | server/models/user.js | 32 | ||||
-rw-r--r-- | server/models/video.js | 74 |
9 files changed, 147 insertions, 61 deletions
diff --git a/server/models/application.js b/server/models/application.js index 4114ed76d..46dcfde33 100644 --- a/server/models/application.js +++ b/server/models/application.js | |||
@@ -1,9 +1,15 @@ | |||
1 | 'use strict' | ||
2 | |||
1 | module.exports = function (sequelize, DataTypes) { | 3 | module.exports = function (sequelize, DataTypes) { |
2 | const Application = sequelize.define('Application', | 4 | const Application = sequelize.define('Application', |
3 | { | 5 | { |
4 | migrationVersion: { | 6 | migrationVersion: { |
5 | type: DataTypes.INTEGER, | 7 | type: DataTypes.INTEGER, |
6 | defaultValue: 0 | 8 | defaultValue: 0, |
9 | allowNull: false, | ||
10 | validate: { | ||
11 | isInt: true | ||
12 | } | ||
7 | } | 13 | } |
8 | }, | 14 | }, |
9 | { | 15 | { |
diff --git a/server/models/author.js b/server/models/author.js index 493c2ca11..e0ac868ea 100644 --- a/server/models/author.js +++ b/server/models/author.js | |||
@@ -1,8 +1,19 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const customUsersValidators = require('../helpers/custom-validators').users | ||
4 | |||
1 | module.exports = function (sequelize, DataTypes) { | 5 | module.exports = function (sequelize, DataTypes) { |
2 | const Author = sequelize.define('Author', | 6 | const Author = sequelize.define('Author', |
3 | { | 7 | { |
4 | name: { | 8 | name: { |
5 | type: DataTypes.STRING | 9 | type: DataTypes.STRING, |
10 | allowNull: false, | ||
11 | validate: { | ||
12 | usernameValid: function (value) { | ||
13 | const res = customUsersValidators.isUserUsernameValid(value) | ||
14 | if (res === false) throw new Error('Username is not valid.') | ||
15 | } | ||
16 | } | ||
6 | } | 17 | } |
7 | }, | 18 | }, |
8 | { | 19 | { |
diff --git a/server/models/oauth-client.js b/server/models/oauth-client.js index 15118591a..b56838d4c 100644 --- a/server/models/oauth-client.js +++ b/server/models/oauth-client.js | |||
@@ -1,11 +1,15 @@ | |||
1 | 'use strict' | ||
2 | |||
1 | module.exports = function (sequelize, DataTypes) { | 3 | module.exports = function (sequelize, DataTypes) { |
2 | const OAuthClient = sequelize.define('OAuthClient', | 4 | const OAuthClient = sequelize.define('OAuthClient', |
3 | { | 5 | { |
4 | clientId: { | 6 | clientId: { |
5 | type: DataTypes.STRING | 7 | type: DataTypes.STRING, |
8 | allowNull: false | ||
6 | }, | 9 | }, |
7 | clientSecret: { | 10 | clientSecret: { |
8 | type: DataTypes.STRING | 11 | type: DataTypes.STRING, |
12 | allowNull: false | ||
9 | }, | 13 | }, |
10 | grants: { | 14 | grants: { |
11 | type: DataTypes.ARRAY(DataTypes.STRING) | 15 | type: DataTypes.ARRAY(DataTypes.STRING) |
@@ -28,9 +32,6 @@ module.exports = function (sequelize, DataTypes) { | |||
28 | return OAuthClient | 32 | return OAuthClient |
29 | } | 33 | } |
30 | 34 | ||
31 | // TODO: validation | ||
32 | // OAuthClientSchema.path('clientSecret').required(true) | ||
33 | |||
34 | // --------------------------------------------------------------------------- | 35 | // --------------------------------------------------------------------------- |
35 | 36 | ||
36 | function associate (models) { | 37 | function associate (models) { |
diff --git a/server/models/oauth-token.js b/server/models/oauth-token.js index c9108bf95..f8de4e916 100644 --- a/server/models/oauth-token.js +++ b/server/models/oauth-token.js | |||
@@ -1,3 +1,5 @@ | |||
1 | 'use strict' | ||
2 | |||
1 | const logger = require('../helpers/logger') | 3 | const logger = require('../helpers/logger') |
2 | 4 | ||
3 | // --------------------------------------------------------------------------- | 5 | // --------------------------------------------------------------------------- |
@@ -6,16 +8,20 @@ module.exports = function (sequelize, DataTypes) { | |||
6 | const OAuthToken = sequelize.define('OAuthToken', | 8 | const OAuthToken = sequelize.define('OAuthToken', |
7 | { | 9 | { |
8 | accessToken: { | 10 | accessToken: { |
9 | type: DataTypes.STRING | 11 | type: DataTypes.STRING, |
12 | allowNull: false | ||
10 | }, | 13 | }, |
11 | accessTokenExpiresAt: { | 14 | accessTokenExpiresAt: { |
12 | type: DataTypes.DATE | 15 | type: DataTypes.DATE, |
16 | allowNull: false | ||
13 | }, | 17 | }, |
14 | refreshToken: { | 18 | refreshToken: { |
15 | type: DataTypes.STRING | 19 | type: DataTypes.STRING, |
20 | allowNull: false | ||
16 | }, | 21 | }, |
17 | refreshTokenExpiresAt: { | 22 | refreshTokenExpiresAt: { |
18 | type: DataTypes.DATE | 23 | type: DataTypes.DATE, |
24 | allowNull: false | ||
19 | } | 25 | } |
20 | }, | 26 | }, |
21 | { | 27 | { |
@@ -33,11 +39,6 @@ module.exports = function (sequelize, DataTypes) { | |||
33 | return OAuthToken | 39 | return OAuthToken |
34 | } | 40 | } |
35 | 41 | ||
36 | // TODO: validation | ||
37 | // OAuthTokenSchema.path('accessToken').required(true) | ||
38 | // OAuthTokenSchema.path('client').required(true) | ||
39 | // OAuthTokenSchema.path('user').required(true) | ||
40 | |||
41 | // --------------------------------------------------------------------------- | 42 | // --------------------------------------------------------------------------- |
42 | 43 | ||
43 | function associate (models) { | 44 | function associate (models) { |
diff --git a/server/models/pod.js b/server/models/pod.js index fff6970a7..84f78f200 100644 --- a/server/models/pod.js +++ b/server/models/pod.js | |||
@@ -3,6 +3,7 @@ | |||
3 | const map = require('lodash/map') | 3 | const map = require('lodash/map') |
4 | 4 | ||
5 | const constants = require('../initializers/constants') | 5 | const constants = require('../initializers/constants') |
6 | const customPodsValidators = require('../helpers/custom-validators').pods | ||
6 | 7 | ||
7 | // --------------------------------------------------------------------------- | 8 | // --------------------------------------------------------------------------- |
8 | 9 | ||
@@ -10,14 +11,27 @@ module.exports = function (sequelize, DataTypes) { | |||
10 | const Pod = sequelize.define('Pod', | 11 | const Pod = sequelize.define('Pod', |
11 | { | 12 | { |
12 | host: { | 13 | host: { |
13 | type: DataTypes.STRING | 14 | type: DataTypes.STRING, |
15 | allowNull: false, | ||
16 | validate: { | ||
17 | isHost: function (value) { | ||
18 | const res = customPodsValidators.isHostValid(value) | ||
19 | if (res === false) throw new Error('Host not valid.') | ||
20 | } | ||
21 | } | ||
14 | }, | 22 | }, |
15 | publicKey: { | 23 | publicKey: { |
16 | type: DataTypes.STRING(5000) | 24 | type: DataTypes.STRING(5000), |
25 | allowNull: false | ||
17 | }, | 26 | }, |
18 | score: { | 27 | score: { |
19 | type: DataTypes.INTEGER, | 28 | type: DataTypes.INTEGER, |
20 | defaultValue: constants.FRIEND_SCORE.BASE | 29 | defaultValue: constants.FRIEND_SCORE.BASE, |
30 | allowNull: false, | ||
31 | validate: { | ||
32 | isInt: true, | ||
33 | max: constants.FRIEND_SCORE.MAX | ||
34 | } | ||
21 | } | 35 | } |
22 | }, | 36 | }, |
23 | { | 37 | { |
@@ -42,12 +56,6 @@ module.exports = function (sequelize, DataTypes) { | |||
42 | return Pod | 56 | return Pod |
43 | } | 57 | } |
44 | 58 | ||
45 | // TODO: max score -> constants.FRIENDS_SCORE.MAX | ||
46 | // TODO: validation | ||
47 | // PodSchema.path('host').validate(validator.isURL) | ||
48 | // PodSchema.path('publicKey').required(true) | ||
49 | // PodSchema.path('score').validate(function (value) { return !isNaN(value) }) | ||
50 | |||
51 | // ------------------------------ METHODS ------------------------------ | 59 | // ------------------------------ METHODS ------------------------------ |
52 | 60 | ||
53 | function toFormatedJSON () { | 61 | function toFormatedJSON () { |
@@ -82,15 +90,17 @@ function incrementScores (ids, value, callback) { | |||
82 | score: this.sequelize.literal('score +' + value) | 90 | score: this.sequelize.literal('score +' + value) |
83 | } | 91 | } |
84 | 92 | ||
85 | const query = { | 93 | const options = { |
86 | where: { | 94 | where: { |
87 | id: { | 95 | id: { |
88 | $in: ids | 96 | $in: ids |
89 | } | 97 | } |
90 | } | 98 | }, |
99 | // In this case score is a literal and not an integer so we do not validate it | ||
100 | validate: false | ||
91 | } | 101 | } |
92 | 102 | ||
93 | return this.update(update, query).asCallback(callback) | 103 | return this.update(update, options).asCallback(callback) |
94 | } | 104 | } |
95 | 105 | ||
96 | function list (callback) { | 106 | function list (callback) { |
diff --git a/server/models/request.js b/server/models/request.js index 70aa32610..e18f8fe3d 100644 --- a/server/models/request.js +++ b/server/models/request.js | |||
@@ -3,6 +3,7 @@ | |||
3 | const each = require('async/each') | 3 | const each = require('async/each') |
4 | const eachLimit = require('async/eachLimit') | 4 | const eachLimit = require('async/eachLimit') |
5 | const waterfall = require('async/waterfall') | 5 | const waterfall = require('async/waterfall') |
6 | const values = require('lodash/values') | ||
6 | 7 | ||
7 | const constants = require('../initializers/constants') | 8 | const constants = require('../initializers/constants') |
8 | const logger = require('../helpers/logger') | 9 | const logger = require('../helpers/logger') |
@@ -17,11 +18,12 @@ module.exports = function (sequelize, DataTypes) { | |||
17 | const Request = sequelize.define('Request', | 18 | const Request = sequelize.define('Request', |
18 | { | 19 | { |
19 | request: { | 20 | request: { |
20 | type: DataTypes.JSON | 21 | type: DataTypes.JSON, |
22 | allowNull: false | ||
21 | }, | 23 | }, |
22 | endpoint: { | 24 | endpoint: { |
23 | // TODO: enum? | 25 | type: DataTypes.ENUM(values(constants.REQUEST_ENDPOINTS)), |
24 | type: DataTypes.STRING | 26 | allowNull: false |
25 | } | 27 | } |
26 | }, | 28 | }, |
27 | { | 29 | { |
@@ -196,7 +198,7 @@ function makeRequests () { | |||
196 | 198 | ||
197 | makeRequest(toPod, requestToMake.endpoint, requestToMake.datas, function (success) { | 199 | makeRequest(toPod, requestToMake.endpoint, requestToMake.datas, function (success) { |
198 | if (success === true) { | 200 | if (success === true) { |
199 | logger.debug('Removing requests for %s pod.', requestToMake.toPodId, { requestsIds: requestToMake.ids }) | 201 | logger.debug('Removing requests for pod %s.', requestToMake.toPodId, { requestsIds: requestToMake.ids }) |
200 | 202 | ||
201 | goodPods.push(requestToMake.toPodId) | 203 | goodPods.push(requestToMake.toPodId) |
202 | 204 | ||
@@ -261,13 +263,13 @@ function updatePodsScore (goodPods, badPods) { | |||
261 | 263 | ||
262 | if (goodPods.length !== 0) { | 264 | if (goodPods.length !== 0) { |
263 | Pod.incrementScores(goodPods, constants.PODS_SCORE.BONUS, function (err) { | 265 | Pod.incrementScores(goodPods, constants.PODS_SCORE.BONUS, function (err) { |
264 | if (err) logger.error('Cannot increment scores of good pods.') | 266 | if (err) logger.error('Cannot increment scores of good pods.', { error: err }) |
265 | }) | 267 | }) |
266 | } | 268 | } |
267 | 269 | ||
268 | if (badPods.length !== 0) { | 270 | if (badPods.length !== 0) { |
269 | Pod.incrementScores(badPods, constants.PODS_SCORE.MALUS, function (err) { | 271 | Pod.incrementScores(badPods, constants.PODS_SCORE.MALUS, function (err) { |
270 | if (err) logger.error('Cannot decrement scores of bad pods.') | 272 | if (err) logger.error('Cannot decrement scores of bad pods.', { error: err }) |
271 | removeBadPods.call(self) | 273 | removeBadPods.call(self) |
272 | }) | 274 | }) |
273 | } | 275 | } |
diff --git a/server/models/tag.js b/server/models/tag.js index 874e88842..d6c2d3bb1 100644 --- a/server/models/tag.js +++ b/server/models/tag.js | |||
@@ -6,7 +6,8 @@ module.exports = function (sequelize, DataTypes) { | |||
6 | const Tag = sequelize.define('Tag', | 6 | const Tag = sequelize.define('Tag', |
7 | { | 7 | { |
8 | name: { | 8 | name: { |
9 | type: DataTypes.STRING | 9 | type: DataTypes.STRING, |
10 | allowNull: false | ||
10 | } | 11 | } |
11 | }, | 12 | }, |
12 | { | 13 | { |
diff --git a/server/models/user.js b/server/models/user.js index e50eb96ea..944986a44 100644 --- a/server/models/user.js +++ b/server/models/user.js | |||
@@ -1,5 +1,11 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const values = require('lodash/values') | ||
4 | |||
1 | const modelUtils = require('./utils') | 5 | const modelUtils = require('./utils') |
6 | const constants = require('../initializers/constants') | ||
2 | const peertubeCrypto = require('../helpers/peertube-crypto') | 7 | const peertubeCrypto = require('../helpers/peertube-crypto') |
8 | const customUsersValidators = require('../helpers/custom-validators').users | ||
3 | 9 | ||
4 | // --------------------------------------------------------------------------- | 10 | // --------------------------------------------------------------------------- |
5 | 11 | ||
@@ -7,13 +13,28 @@ module.exports = function (sequelize, DataTypes) { | |||
7 | const User = sequelize.define('User', | 13 | const User = sequelize.define('User', |
8 | { | 14 | { |
9 | password: { | 15 | password: { |
10 | type: DataTypes.STRING | 16 | type: DataTypes.STRING, |
17 | allowNull: false, | ||
18 | validate: { | ||
19 | passwordValid: function (value) { | ||
20 | const res = customUsersValidators.isUserPasswordValid(value) | ||
21 | if (res === false) throw new Error('Password not valid.') | ||
22 | } | ||
23 | } | ||
11 | }, | 24 | }, |
12 | username: { | 25 | username: { |
13 | type: DataTypes.STRING | 26 | type: DataTypes.STRING, |
27 | allowNull: false, | ||
28 | validate: { | ||
29 | usernameValid: function (value) { | ||
30 | const res = customUsersValidators.isUserUsernameValid(value) | ||
31 | if (res === false) throw new Error('Username not valid.') | ||
32 | } | ||
33 | } | ||
14 | }, | 34 | }, |
15 | role: { | 35 | role: { |
16 | type: DataTypes.STRING | 36 | type: DataTypes.ENUM(values(constants.USER_ROLES)), |
37 | allowNull: false | ||
17 | } | 38 | } |
18 | }, | 39 | }, |
19 | { | 40 | { |
@@ -41,11 +62,6 @@ module.exports = function (sequelize, DataTypes) { | |||
41 | return User | 62 | return User |
42 | } | 63 | } |
43 | 64 | ||
44 | // TODO: Validation | ||
45 | // UserSchema.path('password').required(customUsersValidators.isUserPasswordValid) | ||
46 | // UserSchema.path('username').required(customUsersValidators.isUserUsernameValid) | ||
47 | // UserSchema.path('role').validate(customUsersValidators.isUserRoleValid) | ||
48 | |||
49 | function beforeCreateOrUpdate (user, options, next) { | 65 | function beforeCreateOrUpdate (user, options, next) { |
50 | peertubeCrypto.cryptPassword(user.password, function (err, hash) { | 66 | peertubeCrypto.cryptPassword(user.password, function (err, hash) { |
51 | if (err) return next(err) | 67 | if (err) return next(err) |
diff --git a/server/models/video.js b/server/models/video.js index 04478c8d7..3ebc48ad4 100644 --- a/server/models/video.js +++ b/server/models/video.js | |||
@@ -8,10 +8,12 @@ const map = require('lodash/map') | |||
8 | const parallel = require('async/parallel') | 8 | const parallel = require('async/parallel') |
9 | const parseTorrent = require('parse-torrent') | 9 | const parseTorrent = require('parse-torrent') |
10 | const pathUtils = require('path') | 10 | const pathUtils = require('path') |
11 | const values = require('lodash/values') | ||
11 | 12 | ||
12 | const constants = require('../initializers/constants') | 13 | const constants = require('../initializers/constants') |
13 | const logger = require('../helpers/logger') | 14 | const logger = require('../helpers/logger') |
14 | const modelUtils = require('./utils') | 15 | const modelUtils = require('./utils') |
16 | const customVideosValidators = require('../helpers/custom-validators').videos | ||
15 | 17 | ||
16 | // --------------------------------------------------------------------------- | 18 | // --------------------------------------------------------------------------- |
17 | 19 | ||
@@ -22,26 +24,61 @@ module.exports = function (sequelize, DataTypes) { | |||
22 | id: { | 24 | id: { |
23 | type: DataTypes.UUID, | 25 | type: DataTypes.UUID, |
24 | defaultValue: DataTypes.UUIDV4, | 26 | defaultValue: DataTypes.UUIDV4, |
25 | primaryKey: true | 27 | primaryKey: true, |
28 | validate: { | ||
29 | isUUID: 4 | ||
30 | } | ||
26 | }, | 31 | }, |
27 | name: { | 32 | name: { |
28 | type: DataTypes.STRING | 33 | type: DataTypes.STRING, |
34 | allowNull: false, | ||
35 | validate: { | ||
36 | nameValid: function (value) { | ||
37 | const res = customVideosValidators.isVideoNameValid(value) | ||
38 | if (res === false) throw new Error('Video name is not valid.') | ||
39 | } | ||
40 | } | ||
29 | }, | 41 | }, |
30 | extname: { | 42 | extname: { |
31 | // TODO: enum? | 43 | type: DataTypes.ENUM(values(constants.CONSTRAINTS_FIELDS.VIDEOS.EXTNAME)), |
32 | type: DataTypes.STRING | 44 | allowNull: false |
33 | }, | 45 | }, |
34 | remoteId: { | 46 | remoteId: { |
35 | type: DataTypes.UUID | 47 | type: DataTypes.UUID, |
48 | allowNull: true, | ||
49 | validate: { | ||
50 | isUUID: 4 | ||
51 | } | ||
36 | }, | 52 | }, |
37 | description: { | 53 | description: { |
38 | type: DataTypes.STRING | 54 | type: DataTypes.STRING, |
55 | allowNull: false, | ||
56 | validate: { | ||
57 | descriptionValid: function (value) { | ||
58 | const res = customVideosValidators.isVideoDescriptionValid(value) | ||
59 | if (res === false) throw new Error('Video description is not valid.') | ||
60 | } | ||
61 | } | ||
39 | }, | 62 | }, |
40 | infoHash: { | 63 | infoHash: { |
41 | type: DataTypes.STRING | 64 | type: DataTypes.STRING, |
65 | allowNull: false, | ||
66 | validate: { | ||
67 | infoHashValid: function (value) { | ||
68 | const res = customVideosValidators.isVideoInfoHashValid(value) | ||
69 | if (res === false) throw new Error('Video info hash is not valid.') | ||
70 | } | ||
71 | } | ||
42 | }, | 72 | }, |
43 | duration: { | 73 | duration: { |
44 | type: DataTypes.INTEGER | 74 | type: DataTypes.INTEGER, |
75 | allowNull: false, | ||
76 | validate: { | ||
77 | durationValid: function (value) { | ||
78 | const res = customVideosValidators.isVideoDurationValid(value) | ||
79 | if (res === false) throw new Error('Video duration is not valid.') | ||
80 | } | ||
81 | } | ||
45 | } | 82 | } |
46 | }, | 83 | }, |
47 | { | 84 | { |
@@ -71,6 +108,7 @@ module.exports = function (sequelize, DataTypes) { | |||
71 | toRemoteJSON | 108 | toRemoteJSON |
72 | }, | 109 | }, |
73 | hooks: { | 110 | hooks: { |
111 | beforeValidate, | ||
74 | beforeCreate, | 112 | beforeCreate, |
75 | afterDestroy | 113 | afterDestroy |
76 | } | 114 | } |
@@ -80,13 +118,14 @@ module.exports = function (sequelize, DataTypes) { | |||
80 | return Video | 118 | return Video |
81 | } | 119 | } |
82 | 120 | ||
83 | // TODO: Validation | 121 | function beforeValidate (video, options, next) { |
84 | // VideoSchema.path('name').validate(customVideosValidators.isVideoNameValid) | 122 | if (video.isOwned()) { |
85 | // VideoSchema.path('description').validate(customVideosValidators.isVideoDescriptionValid) | 123 | // 40 hexa length |
86 | // VideoSchema.path('podHost').validate(customVideosValidators.isVideoPodHostValid) | 124 | video.infoHash = '0123456789abcdef0123456789abcdef01234567' |
87 | // VideoSchema.path('author').validate(customVideosValidators.isVideoAuthorValid) | 125 | } |
88 | // VideoSchema.path('duration').validate(customVideosValidators.isVideoDurationValid) | 126 | |
89 | // VideoSchema.path('tags').validate(customVideosValidators.isVideoTagsValid) | 127 | return next(null) |
128 | } | ||
90 | 129 | ||
91 | function beforeCreate (video, options, next) { | 130 | function beforeCreate (video, options, next) { |
92 | const tasks = [] | 131 | const tasks = [] |
@@ -113,9 +152,8 @@ function beforeCreate (video, options, next) { | |||
113 | if (err) return callback(err) | 152 | if (err) return callback(err) |
114 | 153 | ||
115 | const parsedTorrent = parseTorrent(torrent) | 154 | const parsedTorrent = parseTorrent(torrent) |
116 | video.infoHash = parsedTorrent.infoHash | 155 | video.set('infoHash', parsedTorrent.infoHash) |
117 | 156 | video.validate().asCallback(callback) | |
118 | callback(null) | ||
119 | }) | 157 | }) |
120 | }) | 158 | }) |
121 | }, | 159 | }, |