diff options
Diffstat (limited to 'server/helpers')
-rw-r--r-- | server/helpers/custom-validators/index.js | 2 | ||||
-rw-r--r-- | server/helpers/custom-validators/pods.js | 9 | ||||
-rw-r--r-- | server/helpers/custom-validators/remote/index.js | 11 | ||||
-rw-r--r-- | server/helpers/custom-validators/remote/videos.js | 73 | ||||
-rw-r--r-- | server/helpers/custom-validators/videos.js | 71 | ||||
-rw-r--r-- | server/helpers/logger.js | 6 | ||||
-rw-r--r-- | server/helpers/peertube-crypto.js | 65 | ||||
-rw-r--r-- | server/helpers/requests.js | 46 | ||||
-rw-r--r-- | server/helpers/utils.js | 35 |
9 files changed, 223 insertions, 95 deletions
diff --git a/server/helpers/custom-validators/index.js b/server/helpers/custom-validators/index.js index 96b5b20b9..9383e0304 100644 --- a/server/helpers/custom-validators/index.js +++ b/server/helpers/custom-validators/index.js | |||
@@ -2,12 +2,14 @@ | |||
2 | 2 | ||
3 | const miscValidators = require('./misc') | 3 | const miscValidators = require('./misc') |
4 | const podsValidators = require('./pods') | 4 | const podsValidators = require('./pods') |
5 | const remoteValidators = require('./remote') | ||
5 | const usersValidators = require('./users') | 6 | const usersValidators = require('./users') |
6 | const videosValidators = require('./videos') | 7 | const videosValidators = require('./videos') |
7 | 8 | ||
8 | const validators = { | 9 | const validators = { |
9 | misc: miscValidators, | 10 | misc: miscValidators, |
10 | pods: podsValidators, | 11 | pods: podsValidators, |
12 | remote: remoteValidators, | ||
11 | users: usersValidators, | 13 | users: usersValidators, |
12 | videos: videosValidators | 14 | videos: videosValidators |
13 | } | 15 | } |
diff --git a/server/helpers/custom-validators/pods.js b/server/helpers/custom-validators/pods.js index 0154a2424..8bb3733ff 100644 --- a/server/helpers/custom-validators/pods.js +++ b/server/helpers/custom-validators/pods.js | |||
@@ -5,14 +5,19 @@ const validator = require('express-validator').validator | |||
5 | const miscValidators = require('./misc') | 5 | const miscValidators = require('./misc') |
6 | 6 | ||
7 | const podsValidators = { | 7 | const podsValidators = { |
8 | isEachUniqueHostValid | 8 | isEachUniqueHostValid, |
9 | isHostValid | ||
10 | } | ||
11 | |||
12 | function isHostValid (host) { | ||
13 | return validator.isURL(host) && host.split('://').length === 1 | ||
9 | } | 14 | } |
10 | 15 | ||
11 | function isEachUniqueHostValid (hosts) { | 16 | function isEachUniqueHostValid (hosts) { |
12 | return miscValidators.isArray(hosts) && | 17 | return miscValidators.isArray(hosts) && |
13 | hosts.length !== 0 && | 18 | hosts.length !== 0 && |
14 | hosts.every(function (host) { | 19 | hosts.every(function (host) { |
15 | return validator.isURL(host) && host.split('://').length === 1 && hosts.indexOf(host) === hosts.lastIndexOf(host) | 20 | return isHostValid(host) && hosts.indexOf(host) === hosts.lastIndexOf(host) |
16 | }) | 21 | }) |
17 | } | 22 | } |
18 | 23 | ||
diff --git a/server/helpers/custom-validators/remote/index.js b/server/helpers/custom-validators/remote/index.js new file mode 100644 index 000000000..1939a95f4 --- /dev/null +++ b/server/helpers/custom-validators/remote/index.js | |||
@@ -0,0 +1,11 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const remoteVideosValidators = require('./videos') | ||
4 | |||
5 | const validators = { | ||
6 | videos: remoteVideosValidators | ||
7 | } | ||
8 | |||
9 | // --------------------------------------------------------------------------- | ||
10 | |||
11 | module.exports = validators | ||
diff --git a/server/helpers/custom-validators/remote/videos.js b/server/helpers/custom-validators/remote/videos.js new file mode 100644 index 000000000..7c27b9dbb --- /dev/null +++ b/server/helpers/custom-validators/remote/videos.js | |||
@@ -0,0 +1,73 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const videosValidators = require('../videos') | ||
4 | const miscValidators = require('../misc') | ||
5 | |||
6 | const remoteVideosValidators = { | ||
7 | isEachRemoteRequestVideosValid | ||
8 | } | ||
9 | |||
10 | function isEachRemoteRequestVideosValid (requests) { | ||
11 | return miscValidators.isArray(requests) && | ||
12 | requests.every(function (request) { | ||
13 | const video = request.data | ||
14 | return ( | ||
15 | isRequestTypeAddValid(request.type) && | ||
16 | videosValidators.isVideoAuthorValid(video.author) && | ||
17 | videosValidators.isVideoDateValid(video.createdAt) && | ||
18 | videosValidators.isVideoDateValid(video.updatedAt) && | ||
19 | videosValidators.isVideoDescriptionValid(video.description) && | ||
20 | videosValidators.isVideoDurationValid(video.duration) && | ||
21 | videosValidators.isVideoInfoHashValid(video.infoHash) && | ||
22 | videosValidators.isVideoNameValid(video.name) && | ||
23 | videosValidators.isVideoTagsValid(video.tags) && | ||
24 | videosValidators.isVideoThumbnailDataValid(video.thumbnailData) && | ||
25 | videosValidators.isVideoRemoteIdValid(video.remoteId) && | ||
26 | videosValidators.isVideoExtnameValid(video.extname) | ||
27 | ) || | ||
28 | ( | ||
29 | isRequestTypeUpdateValid(request.type) && | ||
30 | videosValidators.isVideoDateValid(video.createdAt) && | ||
31 | videosValidators.isVideoDateValid(video.updatedAt) && | ||
32 | videosValidators.isVideoDescriptionValid(video.description) && | ||
33 | videosValidators.isVideoDurationValid(video.duration) && | ||
34 | videosValidators.isVideoInfoHashValid(video.infoHash) && | ||
35 | videosValidators.isVideoNameValid(video.name) && | ||
36 | videosValidators.isVideoTagsValid(video.tags) && | ||
37 | videosValidators.isVideoRemoteIdValid(video.remoteId) && | ||
38 | videosValidators.isVideoExtnameValid(video.extname) | ||
39 | ) || | ||
40 | ( | ||
41 | isRequestTypeRemoveValid(request.type) && | ||
42 | videosValidators.isVideoRemoteIdValid(video.remoteId) | ||
43 | ) || | ||
44 | ( | ||
45 | isRequestTypeReportAbuseValid(request.type) && | ||
46 | videosValidators.isVideoRemoteIdValid(request.data.videoRemoteId) && | ||
47 | videosValidators.isVideoAbuseReasonValid(request.data.reportReason) && | ||
48 | videosValidators.isVideoAbuseReporterUsernameValid(request.data.reporterUsername) | ||
49 | ) | ||
50 | }) | ||
51 | } | ||
52 | |||
53 | // --------------------------------------------------------------------------- | ||
54 | |||
55 | module.exports = remoteVideosValidators | ||
56 | |||
57 | // --------------------------------------------------------------------------- | ||
58 | |||
59 | function isRequestTypeAddValid (value) { | ||
60 | return value === 'add' | ||
61 | } | ||
62 | |||
63 | function isRequestTypeUpdateValid (value) { | ||
64 | return value === 'update' | ||
65 | } | ||
66 | |||
67 | function isRequestTypeRemoveValid (value) { | ||
68 | return value === 'remove' | ||
69 | } | ||
70 | |||
71 | function isRequestTypeReportAbuseValid (value) { | ||
72 | return value === 'report-abuse' | ||
73 | } | ||
diff --git a/server/helpers/custom-validators/videos.js b/server/helpers/custom-validators/videos.js index 1a7753265..7f727854d 100644 --- a/server/helpers/custom-validators/videos.js +++ b/server/helpers/custom-validators/videos.js | |||
@@ -6,43 +6,22 @@ const constants = require('../../initializers/constants') | |||
6 | const usersValidators = require('./users') | 6 | const usersValidators = require('./users') |
7 | const miscValidators = require('./misc') | 7 | const miscValidators = require('./misc') |
8 | const VIDEOS_CONSTRAINTS_FIELDS = constants.CONSTRAINTS_FIELDS.VIDEOS | 8 | const VIDEOS_CONSTRAINTS_FIELDS = constants.CONSTRAINTS_FIELDS.VIDEOS |
9 | const VIDEO_ABUSES_CONSTRAINTS_FIELDS = constants.CONSTRAINTS_FIELDS.VIDEO_ABUSES | ||
9 | 10 | ||
10 | const videosValidators = { | 11 | const videosValidators = { |
11 | isEachRemoteVideosValid, | ||
12 | isVideoAuthorValid, | 12 | isVideoAuthorValid, |
13 | isVideoDateValid, | 13 | isVideoDateValid, |
14 | isVideoDescriptionValid, | 14 | isVideoDescriptionValid, |
15 | isVideoDurationValid, | 15 | isVideoDurationValid, |
16 | isVideoMagnetValid, | 16 | isVideoInfoHashValid, |
17 | isVideoNameValid, | 17 | isVideoNameValid, |
18 | isVideoPodHostValid, | ||
19 | isVideoTagsValid, | 18 | isVideoTagsValid, |
20 | isVideoThumbnailValid, | 19 | isVideoThumbnailValid, |
21 | isVideoThumbnail64Valid | 20 | isVideoThumbnailDataValid, |
22 | } | 21 | isVideoExtnameValid, |
23 | 22 | isVideoRemoteIdValid, | |
24 | function isEachRemoteVideosValid (requests) { | 23 | isVideoAbuseReasonValid, |
25 | return miscValidators.isArray(requests) && | 24 | isVideoAbuseReporterUsernameValid |
26 | requests.every(function (request) { | ||
27 | const video = request.data | ||
28 | return ( | ||
29 | isRequestTypeAddValid(request.type) && | ||
30 | isVideoAuthorValid(video.author) && | ||
31 | isVideoDateValid(video.createdDate) && | ||
32 | isVideoDescriptionValid(video.description) && | ||
33 | isVideoDurationValid(video.duration) && | ||
34 | isVideoMagnetValid(video.magnet) && | ||
35 | isVideoNameValid(video.name) && | ||
36 | isVideoTagsValid(video.tags) && | ||
37 | isVideoThumbnail64Valid(video.thumbnailBase64) && | ||
38 | isVideoRemoteIdValid(video.remoteId) | ||
39 | ) || | ||
40 | ( | ||
41 | isRequestTypeRemoveValid(request.type) && | ||
42 | isVideoNameValid(video.name) && | ||
43 | isVideoRemoteIdValid(video.remoteId) | ||
44 | ) | ||
45 | }) | ||
46 | } | 25 | } |
47 | 26 | ||
48 | function isVideoAuthorValid (value) { | 27 | function isVideoAuthorValid (value) { |
@@ -61,17 +40,16 @@ function isVideoDurationValid (value) { | |||
61 | return validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION) | 40 | return validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION) |
62 | } | 41 | } |
63 | 42 | ||
64 | function isVideoMagnetValid (value) { | 43 | function isVideoExtnameValid (value) { |
65 | return validator.isLength(value.infoHash, VIDEOS_CONSTRAINTS_FIELDS.MAGNET.INFO_HASH) | 44 | return VIDEOS_CONSTRAINTS_FIELDS.EXTNAME.indexOf(value) !== -1 |
66 | } | 45 | } |
67 | 46 | ||
68 | function isVideoNameValid (value) { | 47 | function isVideoInfoHashValid (value) { |
69 | return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME) | 48 | return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH) |
70 | } | 49 | } |
71 | 50 | ||
72 | function isVideoPodHostValid (value) { | 51 | function isVideoNameValid (value) { |
73 | // TODO: set options (TLD...) | 52 | return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME) |
74 | return validator.isURL(value) | ||
75 | } | 53 | } |
76 | 54 | ||
77 | function isVideoTagsValid (tags) { | 55 | function isVideoTagsValid (tags) { |
@@ -87,25 +65,22 @@ function isVideoThumbnailValid (value) { | |||
87 | return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL) | 65 | return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL) |
88 | } | 66 | } |
89 | 67 | ||
90 | function isVideoThumbnail64Valid (value) { | 68 | function isVideoThumbnailDataValid (value) { |
91 | return validator.isBase64(value) && | 69 | return validator.isByteLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL_DATA) |
92 | validator.isByteLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL64) | ||
93 | } | 70 | } |
94 | 71 | ||
95 | function isVideoRemoteIdValid (value) { | 72 | function isVideoRemoteIdValid (value) { |
96 | return validator.isMongoId(value) | 73 | return validator.isUUID(value, 4) |
97 | } | 74 | } |
98 | 75 | ||
99 | // --------------------------------------------------------------------------- | 76 | function isVideoAbuseReasonValid (value) { |
77 | return validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON) | ||
78 | } | ||
100 | 79 | ||
101 | module.exports = videosValidators | 80 | function isVideoAbuseReporterUsernameValid (value) { |
81 | return usersValidators.isUserUsernameValid(value) | ||
82 | } | ||
102 | 83 | ||
103 | // --------------------------------------------------------------------------- | 84 | // --------------------------------------------------------------------------- |
104 | 85 | ||
105 | function isRequestTypeAddValid (value) { | 86 | module.exports = videosValidators |
106 | return value === 'add' | ||
107 | } | ||
108 | |||
109 | function isRequestTypeRemoveValid (value) { | ||
110 | return value === 'remove' | ||
111 | } | ||
diff --git a/server/helpers/logger.js b/server/helpers/logger.js index fcc1789fd..281acedb8 100644 --- a/server/helpers/logger.js +++ b/server/helpers/logger.js | |||
@@ -22,7 +22,8 @@ const logger = new winston.Logger({ | |||
22 | json: true, | 22 | json: true, |
23 | maxsize: 5242880, | 23 | maxsize: 5242880, |
24 | maxFiles: 5, | 24 | maxFiles: 5, |
25 | colorize: false | 25 | colorize: false, |
26 | prettyPrint: true | ||
26 | }), | 27 | }), |
27 | new winston.transports.Console({ | 28 | new winston.transports.Console({ |
28 | level: 'debug', | 29 | level: 'debug', |
@@ -30,7 +31,8 @@ const logger = new winston.Logger({ | |||
30 | handleExceptions: true, | 31 | handleExceptions: true, |
31 | humanReadableUnhandledException: true, | 32 | humanReadableUnhandledException: true, |
32 | json: false, | 33 | json: false, |
33 | colorize: true | 34 | colorize: true, |
35 | prettyPrint: true | ||
34 | }) | 36 | }) |
35 | ], | 37 | ], |
36 | exitOnError: true | 38 | exitOnError: true |
diff --git a/server/helpers/peertube-crypto.js b/server/helpers/peertube-crypto.js index 2e07df00e..0f1e02ad6 100644 --- a/server/helpers/peertube-crypto.js +++ b/server/helpers/peertube-crypto.js | |||
@@ -1,16 +1,13 @@ | |||
1 | 'use strict' | 1 | 'use strict' |
2 | 2 | ||
3 | const bcrypt = require('bcrypt') | ||
4 | const crypto = require('crypto') | 3 | const crypto = require('crypto') |
4 | const bcrypt = require('bcrypt') | ||
5 | const fs = require('fs') | 5 | const fs = require('fs') |
6 | const openssl = require('openssl-wrapper') | 6 | const openssl = require('openssl-wrapper') |
7 | const ursa = require('ursa') | ||
8 | 7 | ||
9 | const constants = require('../initializers/constants') | 8 | const constants = require('../initializers/constants') |
10 | const logger = require('./logger') | 9 | const logger = require('./logger') |
11 | 10 | ||
12 | const algorithm = 'aes-256-ctr' | ||
13 | |||
14 | const peertubeCrypto = { | 11 | const peertubeCrypto = { |
15 | checkSignature, | 12 | checkSignature, |
16 | comparePassword, | 13 | comparePassword, |
@@ -19,12 +16,51 @@ const peertubeCrypto = { | |||
19 | sign | 16 | sign |
20 | } | 17 | } |
21 | 18 | ||
22 | function checkSignature (publicKey, rawData, hexSignature) { | 19 | function checkSignature (publicKey, data, hexSignature) { |
23 | const crt = ursa.createPublicKey(publicKey) | 20 | const verify = crypto.createVerify(constants.SIGNATURE_ALGORITHM) |
24 | const isValid = crt.hashAndVerify('sha256', new Buffer(rawData).toString('hex'), hexSignature, 'hex') | 21 | |
22 | let dataString | ||
23 | if (typeof data === 'string') { | ||
24 | dataString = data | ||
25 | } else { | ||
26 | try { | ||
27 | dataString = JSON.stringify(data) | ||
28 | } catch (err) { | ||
29 | logger.error('Cannot check signature.', { error: err }) | ||
30 | return false | ||
31 | } | ||
32 | } | ||
33 | |||
34 | verify.update(dataString, 'utf8') | ||
35 | |||
36 | const isValid = verify.verify(publicKey, hexSignature, constants.SIGNATURE_ENCODING) | ||
25 | return isValid | 37 | return isValid |
26 | } | 38 | } |
27 | 39 | ||
40 | function sign (data) { | ||
41 | const sign = crypto.createSign(constants.SIGNATURE_ALGORITHM) | ||
42 | |||
43 | let dataString | ||
44 | if (typeof data === 'string') { | ||
45 | dataString = data | ||
46 | } else { | ||
47 | try { | ||
48 | dataString = JSON.stringify(data) | ||
49 | } catch (err) { | ||
50 | logger.error('Cannot sign data.', { error: err }) | ||
51 | return '' | ||
52 | } | ||
53 | } | ||
54 | |||
55 | sign.update(dataString, 'utf8') | ||
56 | |||
57 | // TODO: make async | ||
58 | const myKey = fs.readFileSync(constants.CONFIG.STORAGE.CERT_DIR + 'peertube.key.pem') | ||
59 | const signature = sign.sign(myKey, constants.SIGNATURE_ENCODING) | ||
60 | |||
61 | return signature | ||
62 | } | ||
63 | |||
28 | function comparePassword (plainPassword, hashPassword, callback) { | 64 | function comparePassword (plainPassword, hashPassword, callback) { |
29 | bcrypt.compare(plainPassword, hashPassword, function (err, isPasswordMatch) { | 65 | bcrypt.compare(plainPassword, hashPassword, function (err, isPasswordMatch) { |
30 | if (err) return callback(err) | 66 | if (err) return callback(err) |
@@ -55,13 +91,6 @@ function cryptPassword (password, callback) { | |||
55 | }) | 91 | }) |
56 | } | 92 | } |
57 | 93 | ||
58 | function sign (data) { | ||
59 | const myKey = ursa.createPrivateKey(fs.readFileSync(constants.CONFIG.STORAGE.CERT_DIR + 'peertube.key.pem')) | ||
60 | const signature = myKey.hashAndSign('sha256', data, 'utf8', 'hex') | ||
61 | |||
62 | return signature | ||
63 | } | ||
64 | |||
65 | // --------------------------------------------------------------------------- | 94 | // --------------------------------------------------------------------------- |
66 | 95 | ||
67 | module.exports = peertubeCrypto | 96 | module.exports = peertubeCrypto |
@@ -113,11 +142,3 @@ function createCerts (callback) { | |||
113 | }) | 142 | }) |
114 | }) | 143 | }) |
115 | } | 144 | } |
116 | |||
117 | function generatePassword (callback) { | ||
118 | crypto.randomBytes(32, function (err, buf) { | ||
119 | if (err) return callback(err) | ||
120 | |||
121 | callback(null, buf.toString('utf8')) | ||
122 | }) | ||
123 | } | ||
diff --git a/server/helpers/requests.js b/server/helpers/requests.js index b0cda09fe..095b95e1c 100644 --- a/server/helpers/requests.js +++ b/server/helpers/requests.js | |||
@@ -28,31 +28,37 @@ function makeSecureRequest (params, callback) { | |||
28 | url: constants.REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path | 28 | url: constants.REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path |
29 | } | 29 | } |
30 | 30 | ||
31 | // Add data with POST requst ? | 31 | if (params.method !== 'POST') { |
32 | if (params.method === 'POST') { | 32 | return callback(new Error('Cannot make a secure request with a non POST method.')) |
33 | requestParams.json = {} | 33 | } |
34 | 34 | ||
35 | // Add signature if it is specified in the params | 35 | requestParams.json = {} |
36 | if (params.sign === true) { | ||
37 | const host = constants.CONFIG.WEBSERVER.HOST | ||
38 | |||
39 | requestParams.json.signature = { | ||
40 | host, | ||
41 | signature: peertubeCrypto.sign(host) | ||
42 | } | ||
43 | } | ||
44 | 36 | ||
45 | // If there are data informations | 37 | // Add signature if it is specified in the params |
38 | if (params.sign === true) { | ||
39 | const host = constants.CONFIG.WEBSERVER.HOST | ||
40 | |||
41 | let dataToSign | ||
46 | if (params.data) { | 42 | if (params.data) { |
47 | requestParams.json.data = params.data | 43 | dataToSign = dataToSign = params.data |
48 | request.post(requestParams, callback) | ||
49 | } else { | 44 | } else { |
50 | // No data | 45 | // We do not have data to sign so we just take our host |
51 | request.post(requestParams, callback) | 46 | // It is not ideal but the connection should be in HTTPS |
47 | dataToSign = host | ||
52 | } | 48 | } |
53 | } else { | 49 | |
54 | request.get(requestParams, callback) | 50 | requestParams.json.signature = { |
51 | host, // Which host we pretend to be | ||
52 | signature: peertubeCrypto.sign(dataToSign) | ||
53 | } | ||
54 | } | ||
55 | |||
56 | // If there are data informations | ||
57 | if (params.data) { | ||
58 | requestParams.json.data = params.data | ||
55 | } | 59 | } |
60 | |||
61 | request.post(requestParams, callback) | ||
56 | } | 62 | } |
57 | 63 | ||
58 | // --------------------------------------------------------------------------- | 64 | // --------------------------------------------------------------------------- |
diff --git a/server/helpers/utils.js b/server/helpers/utils.js index 9f27671b6..a902850cd 100644 --- a/server/helpers/utils.js +++ b/server/helpers/utils.js | |||
@@ -1,13 +1,21 @@ | |||
1 | 'use strict' | 1 | 'use strict' |
2 | 2 | ||
3 | const crypto = require('crypto') | 3 | const crypto = require('crypto') |
4 | const retry = require('async/retry') | ||
4 | 5 | ||
5 | const logger = require('./logger') | 6 | const logger = require('./logger') |
6 | 7 | ||
7 | const utils = { | 8 | const utils = { |
9 | badRequest, | ||
8 | cleanForExit, | 10 | cleanForExit, |
9 | generateRandomString, | 11 | generateRandomString, |
10 | isTestInstance | 12 | isTestInstance, |
13 | getFormatedObjects, | ||
14 | transactionRetryer | ||
15 | } | ||
16 | |||
17 | function badRequest (req, res, next) { | ||
18 | res.type('json').status(400).end() | ||
11 | } | 19 | } |
12 | 20 | ||
13 | function generateRandomString (size, callback) { | 21 | function generateRandomString (size, callback) { |
@@ -27,6 +35,31 @@ function isTestInstance () { | |||
27 | return (process.env.NODE_ENV === 'test') | 35 | return (process.env.NODE_ENV === 'test') |
28 | } | 36 | } |
29 | 37 | ||
38 | function getFormatedObjects (objects, objectsTotal) { | ||
39 | const formatedObjects = [] | ||
40 | |||
41 | objects.forEach(function (object) { | ||
42 | formatedObjects.push(object.toFormatedJSON()) | ||
43 | }) | ||
44 | |||
45 | return { | ||
46 | total: objectsTotal, | ||
47 | data: formatedObjects | ||
48 | } | ||
49 | } | ||
50 | |||
51 | function transactionRetryer (func, callback) { | ||
52 | retry({ | ||
53 | times: 5, | ||
54 | |||
55 | errorFilter: function (err) { | ||
56 | const willRetry = (err.name === 'SequelizeDatabaseError') | ||
57 | logger.debug('Maybe retrying the transaction function.', { willRetry }) | ||
58 | return willRetry | ||
59 | } | ||
60 | }, func, callback) | ||
61 | } | ||
62 | |||
30 | // --------------------------------------------------------------------------- | 63 | // --------------------------------------------------------------------------- |
31 | 64 | ||
32 | module.exports = utils | 65 | module.exports = utils |