const miscValidators = require('./misc')
const podsValidators = {
- isEachUniqueHostValid
+ isEachUniqueHostValid,
+ isHostValid
+}
+
+function isHostValid (host) {
+ return validator.isURL(host) && host.split('://').length === 1
}
function isEachUniqueHostValid (hosts) {
return miscValidators.isArray(hosts) &&
hosts.length !== 0 &&
hosts.every(function (host) {
- return validator.isURL(host) && host.split('://').length === 1 && hosts.indexOf(host) === hosts.lastIndexOf(host)
+ return isHostValid(host) && hosts.indexOf(host) === hosts.lastIndexOf(host)
})
}
isVideoDurationValid,
isVideoInfoHashValid,
isVideoNameValid,
- isVideoPodHostValid,
isVideoTagsValid,
isVideoThumbnailValid,
isVideoThumbnail64Valid
return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
}
-function isVideoPodHostValid (value) {
- // TODO: set options (TLD...)
- return validator.isURL(value)
-}
-
function isVideoTagsValid (tags) {
return miscValidators.isArray(tags) &&
validator.isInt(tags.length, VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
NAME: { min: 3, max: 50 }, // Length
DESCRIPTION: { min: 3, max: 250 }, // Length
EXTNAME: [ '.mp4', '.ogv', '.webm' ],
- INFO_HASH: { min: 10, max: 50 }, // Length
+ INFO_HASH: { min: 40, max: 40 }, // Length, infohash is 20 bytes length but we represent it in hexa so 20 * 2
DURATION: { min: 1, max: 7200 }, // Number
TAGS: { min: 1, max: 3 }, // Number of total tags
TAG: { min: 2, max: 10 }, // Length
const username = 'root'
const role = constants.USER_ROLES.ADMIN
+ const createOptions = {}
let password = ''
// Do not generate a random password for tests
if (process.env.NODE_APP_INSTANCE) {
password += process.env.NODE_APP_INSTANCE
}
+
+ // Our password is weak so do not validate it
+ createOptions.validate = false
} else {
password = passwordGenerator(8, true)
}
- const user = db.User.build({
+ const userData = {
username,
password,
role
- })
+ }
- user.save().asCallback(function (err, createdUser) {
+ db.User.create(userData, createOptions).asCallback(function (err, createdUser) {
if (err) return callback(err)
logger.info('Username: ' + username)
+'use strict'
+
module.exports = function (sequelize, DataTypes) {
const Application = sequelize.define('Application',
{
migrationVersion: {
type: DataTypes.INTEGER,
- defaultValue: 0
+ defaultValue: 0,
+ allowNull: false,
+ validate: {
+ isInt: true
+ }
}
},
{
+'use strict'
+
+const customUsersValidators = require('../helpers/custom-validators').users
+
module.exports = function (sequelize, DataTypes) {
const Author = sequelize.define('Author',
{
name: {
- type: DataTypes.STRING
+ type: DataTypes.STRING,
+ allowNull: false,
+ validate: {
+ usernameValid: function (value) {
+ const res = customUsersValidators.isUserUsernameValid(value)
+ if (res === false) throw new Error('Username is not valid.')
+ }
+ }
}
},
{
+'use strict'
+
module.exports = function (sequelize, DataTypes) {
const OAuthClient = sequelize.define('OAuthClient',
{
clientId: {
- type: DataTypes.STRING
+ type: DataTypes.STRING,
+ allowNull: false
},
clientSecret: {
- type: DataTypes.STRING
+ type: DataTypes.STRING,
+ allowNull: false
},
grants: {
type: DataTypes.ARRAY(DataTypes.STRING)
return OAuthClient
}
-// TODO: validation
-// OAuthClientSchema.path('clientSecret').required(true)
-
// ---------------------------------------------------------------------------
function associate (models) {
+'use strict'
+
const logger = require('../helpers/logger')
// ---------------------------------------------------------------------------
const OAuthToken = sequelize.define('OAuthToken',
{
accessToken: {
- type: DataTypes.STRING
+ type: DataTypes.STRING,
+ allowNull: false
},
accessTokenExpiresAt: {
- type: DataTypes.DATE
+ type: DataTypes.DATE,
+ allowNull: false
},
refreshToken: {
- type: DataTypes.STRING
+ type: DataTypes.STRING,
+ allowNull: false
},
refreshTokenExpiresAt: {
- type: DataTypes.DATE
+ type: DataTypes.DATE,
+ allowNull: false
}
},
{
return OAuthToken
}
-// TODO: validation
-// OAuthTokenSchema.path('accessToken').required(true)
-// OAuthTokenSchema.path('client').required(true)
-// OAuthTokenSchema.path('user').required(true)
-
// ---------------------------------------------------------------------------
function associate (models) {
const map = require('lodash/map')
const constants = require('../initializers/constants')
+const customPodsValidators = require('../helpers/custom-validators').pods
// ---------------------------------------------------------------------------
const Pod = sequelize.define('Pod',
{
host: {
- type: DataTypes.STRING
+ type: DataTypes.STRING,
+ allowNull: false,
+ validate: {
+ isHost: function (value) {
+ const res = customPodsValidators.isHostValid(value)
+ if (res === false) throw new Error('Host not valid.')
+ }
+ }
},
publicKey: {
- type: DataTypes.STRING(5000)
+ type: DataTypes.STRING(5000),
+ allowNull: false
},
score: {
type: DataTypes.INTEGER,
- defaultValue: constants.FRIEND_SCORE.BASE
+ defaultValue: constants.FRIEND_SCORE.BASE,
+ allowNull: false,
+ validate: {
+ isInt: true,
+ max: constants.FRIEND_SCORE.MAX
+ }
}
},
{
return Pod
}
-// TODO: max score -> constants.FRIENDS_SCORE.MAX
-// TODO: validation
-// PodSchema.path('host').validate(validator.isURL)
-// PodSchema.path('publicKey').required(true)
-// PodSchema.path('score').validate(function (value) { return !isNaN(value) })
-
// ------------------------------ METHODS ------------------------------
function toFormatedJSON () {
score: this.sequelize.literal('score +' + value)
}
- const query = {
+ const options = {
where: {
id: {
$in: ids
}
- }
+ },
+ // In this case score is a literal and not an integer so we do not validate it
+ validate: false
}
- return this.update(update, query).asCallback(callback)
+ return this.update(update, options).asCallback(callback)
}
function list (callback) {
const each = require('async/each')
const eachLimit = require('async/eachLimit')
const waterfall = require('async/waterfall')
+const values = require('lodash/values')
const constants = require('../initializers/constants')
const logger = require('../helpers/logger')
const Request = sequelize.define('Request',
{
request: {
- type: DataTypes.JSON
+ type: DataTypes.JSON,
+ allowNull: false
},
endpoint: {
- // TODO: enum?
- type: DataTypes.STRING
+ type: DataTypes.ENUM(values(constants.REQUEST_ENDPOINTS)),
+ allowNull: false
}
},
{
makeRequest(toPod, requestToMake.endpoint, requestToMake.datas, function (success) {
if (success === true) {
- logger.debug('Removing requests for %s pod.', requestToMake.toPodId, { requestsIds: requestToMake.ids })
+ logger.debug('Removing requests for pod %s.', requestToMake.toPodId, { requestsIds: requestToMake.ids })
goodPods.push(requestToMake.toPodId)
if (goodPods.length !== 0) {
Pod.incrementScores(goodPods, constants.PODS_SCORE.BONUS, function (err) {
- if (err) logger.error('Cannot increment scores of good pods.')
+ if (err) logger.error('Cannot increment scores of good pods.', { error: err })
})
}
if (badPods.length !== 0) {
Pod.incrementScores(badPods, constants.PODS_SCORE.MALUS, function (err) {
- if (err) logger.error('Cannot decrement scores of bad pods.')
+ if (err) logger.error('Cannot decrement scores of bad pods.', { error: err })
removeBadPods.call(self)
})
}
const Tag = sequelize.define('Tag',
{
name: {
- type: DataTypes.STRING
+ type: DataTypes.STRING,
+ allowNull: false
}
},
{
+'use strict'
+
+const values = require('lodash/values')
+
const modelUtils = require('./utils')
+const constants = require('../initializers/constants')
const peertubeCrypto = require('../helpers/peertube-crypto')
+const customUsersValidators = require('../helpers/custom-validators').users
// ---------------------------------------------------------------------------
const User = sequelize.define('User',
{
password: {
- type: DataTypes.STRING
+ type: DataTypes.STRING,
+ allowNull: false,
+ validate: {
+ passwordValid: function (value) {
+ const res = customUsersValidators.isUserPasswordValid(value)
+ if (res === false) throw new Error('Password not valid.')
+ }
+ }
},
username: {
- type: DataTypes.STRING
+ type: DataTypes.STRING,
+ allowNull: false,
+ validate: {
+ usernameValid: function (value) {
+ const res = customUsersValidators.isUserUsernameValid(value)
+ if (res === false) throw new Error('Username not valid.')
+ }
+ }
},
role: {
- type: DataTypes.STRING
+ type: DataTypes.ENUM(values(constants.USER_ROLES)),
+ allowNull: false
}
},
{
return User
}
-// TODO: Validation
-// UserSchema.path('password').required(customUsersValidators.isUserPasswordValid)
-// UserSchema.path('username').required(customUsersValidators.isUserUsernameValid)
-// UserSchema.path('role').validate(customUsersValidators.isUserRoleValid)
-
function beforeCreateOrUpdate (user, options, next) {
peertubeCrypto.cryptPassword(user.password, function (err, hash) {
if (err) return next(err)
const parallel = require('async/parallel')
const parseTorrent = require('parse-torrent')
const pathUtils = require('path')
+const values = require('lodash/values')
const constants = require('../initializers/constants')
const logger = require('../helpers/logger')
const modelUtils = require('./utils')
+const customVideosValidators = require('../helpers/custom-validators').videos
// ---------------------------------------------------------------------------
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
- primaryKey: true
+ primaryKey: true,
+ validate: {
+ isUUID: 4
+ }
},
name: {
- type: DataTypes.STRING
+ type: DataTypes.STRING,
+ allowNull: false,
+ validate: {
+ nameValid: function (value) {
+ const res = customVideosValidators.isVideoNameValid(value)
+ if (res === false) throw new Error('Video name is not valid.')
+ }
+ }
},
extname: {
- // TODO: enum?
- type: DataTypes.STRING
+ type: DataTypes.ENUM(values(constants.CONSTRAINTS_FIELDS.VIDEOS.EXTNAME)),
+ allowNull: false
},
remoteId: {
- type: DataTypes.UUID
+ type: DataTypes.UUID,
+ allowNull: true,
+ validate: {
+ isUUID: 4
+ }
},
description: {
- type: DataTypes.STRING
+ type: DataTypes.STRING,
+ allowNull: false,
+ validate: {
+ descriptionValid: function (value) {
+ const res = customVideosValidators.isVideoDescriptionValid(value)
+ if (res === false) throw new Error('Video description is not valid.')
+ }
+ }
},
infoHash: {
- type: DataTypes.STRING
+ type: DataTypes.STRING,
+ allowNull: false,
+ validate: {
+ infoHashValid: function (value) {
+ const res = customVideosValidators.isVideoInfoHashValid(value)
+ if (res === false) throw new Error('Video info hash is not valid.')
+ }
+ }
},
duration: {
- type: DataTypes.INTEGER
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ validate: {
+ durationValid: function (value) {
+ const res = customVideosValidators.isVideoDurationValid(value)
+ if (res === false) throw new Error('Video duration is not valid.')
+ }
+ }
}
},
{
toRemoteJSON
},
hooks: {
+ beforeValidate,
beforeCreate,
afterDestroy
}
return Video
}
-// TODO: Validation
-// VideoSchema.path('name').validate(customVideosValidators.isVideoNameValid)
-// VideoSchema.path('description').validate(customVideosValidators.isVideoDescriptionValid)
-// VideoSchema.path('podHost').validate(customVideosValidators.isVideoPodHostValid)
-// VideoSchema.path('author').validate(customVideosValidators.isVideoAuthorValid)
-// VideoSchema.path('duration').validate(customVideosValidators.isVideoDurationValid)
-// VideoSchema.path('tags').validate(customVideosValidators.isVideoTagsValid)
+function beforeValidate (video, options, next) {
+ if (video.isOwned()) {
+ // 40 hexa length
+ video.infoHash = '0123456789abcdef0123456789abcdef01234567'
+ }
+
+ return next(null)
+}
function beforeCreate (video, options, next) {
const tasks = []
if (err) return callback(err)
const parsedTorrent = parseTorrent(torrent)
- video.infoHash = parsedTorrent.infoHash
-
- callback(null)
+ video.set('infoHash', parsedTorrent.infoHash)
+ video.validate().asCallback(callback)
})
})
},