@jsreport/jsreport-core 3.1.2-test.2 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/LICENSE +166 -166
  2. package/README.md +310 -298
  3. package/index.js +29 -29
  4. package/lib/main/blobStorage/blobStorage.js +53 -52
  5. package/lib/main/blobStorage/inMemoryProvider.js +27 -27
  6. package/lib/main/blobStorage/mainActions.js +24 -24
  7. package/lib/main/createDefaultLoggerFormat.js +17 -17
  8. package/lib/main/defaults.js +14 -14
  9. package/lib/main/extensions/discover.js +20 -20
  10. package/lib/main/extensions/extensionsManager.js +264 -264
  11. package/lib/main/extensions/fileUtils.js +56 -56
  12. package/lib/main/extensions/findVersion.js +49 -49
  13. package/lib/main/extensions/locationCache.js +103 -103
  14. package/lib/main/extensions/sorter.js +10 -10
  15. package/lib/main/extensions/validateMinimalVersion.js +50 -50
  16. package/lib/main/folders/cascadeFolderRemove.js +25 -25
  17. package/lib/main/folders/getEntitiesInFolder.js +53 -53
  18. package/lib/main/folders/index.js +42 -42
  19. package/lib/main/folders/moveBetweenFolders.js +354 -354
  20. package/lib/main/folders/validateDuplicatedName.js +107 -107
  21. package/lib/main/folders/validateReservedName.js +53 -53
  22. package/lib/main/logger.js +254 -244
  23. package/lib/main/migration/resourcesToAssets.js +230 -230
  24. package/lib/main/migration/xlsxTemplatesToAssets.js +128 -128
  25. package/lib/main/monitoring.js +92 -91
  26. package/lib/main/optionsLoad.js +231 -237
  27. package/lib/main/optionsSchema.js +237 -237
  28. package/lib/main/profiler.js +13 -1
  29. package/lib/main/reporter.js +589 -579
  30. package/lib/main/request.js +21 -0
  31. package/lib/main/schemaValidator.js +252 -252
  32. package/lib/main/settings.js +154 -154
  33. package/lib/main/store/checkDuplicatedId.js +27 -27
  34. package/lib/main/store/collection.js +329 -329
  35. package/lib/main/store/documentStore.js +469 -469
  36. package/lib/main/store/mainActions.js +28 -28
  37. package/lib/main/store/memoryStoreProvider.js +99 -99
  38. package/lib/main/store/queue.js +48 -48
  39. package/lib/main/store/referenceUtils.js +251 -251
  40. package/lib/main/store/setupValidateId.js +43 -43
  41. package/lib/main/store/setupValidateShortid.js +71 -71
  42. package/lib/main/store/transaction.js +69 -69
  43. package/lib/main/store/typeUtils.js +180 -180
  44. package/lib/main/templates.js +34 -34
  45. package/lib/main/validateEntityName.js +62 -62
  46. package/lib/shared/createError.js +36 -36
  47. package/lib/shared/encryption.js +114 -114
  48. package/lib/shared/folders/index.js +11 -11
  49. package/lib/shared/folders/normalizeEntityPath.js +15 -15
  50. package/lib/shared/folders/resolveEntityFromPath.js +88 -88
  51. package/lib/shared/folders/resolveEntityPath.js +46 -46
  52. package/lib/shared/folders/resolveFolderFromPath.js +38 -38
  53. package/lib/shared/generateRequestId.js +4 -4
  54. package/lib/shared/listenerCollection.js +169 -169
  55. package/lib/shared/normalizeMetaFromLogs.js +30 -30
  56. package/lib/shared/reporter.js +128 -123
  57. package/lib/shared/request.js +64 -64
  58. package/lib/shared/tempFilesHandler.js +81 -81
  59. package/lib/shared/templates.js +82 -82
  60. package/lib/static/helpers.js +33 -33
  61. package/lib/worker/blobStorage.js +34 -34
  62. package/lib/worker/defaultProxyExtend.js +46 -46
  63. package/lib/worker/documentStore.js +49 -49
  64. package/lib/worker/extensionsManager.js +17 -17
  65. package/lib/worker/logger.js +48 -48
  66. package/lib/worker/render/diff.js +138 -138
  67. package/lib/worker/render/executeEngine.js +232 -207
  68. package/lib/worker/render/htmlRecipe.js +10 -10
  69. package/lib/worker/render/moduleHelper.js +45 -43
  70. package/lib/worker/render/noneEngine.js +12 -12
  71. package/lib/worker/render/profiler.js +162 -158
  72. package/lib/worker/render/render.js +202 -205
  73. package/lib/worker/render/resolveReferences.js +60 -60
  74. package/lib/worker/reporter.js +197 -191
  75. package/lib/worker/sandbox/runInSandbox.js +64 -12
  76. package/lib/worker/sandbox/safeSandbox.js +829 -828
  77. package/lib/worker/templates.js +80 -78
  78. package/lib/worker/workerHandler.js +55 -54
  79. package/package.json +91 -92
  80. package/test/blobStorage/common.js +25 -21
  81. package/test/store/common.js +1449 -1449
@@ -1,34 +1,34 @@
1
-
2
- module.exports = (reporter) => {
3
- reporter.documentStore.registerEntityType('TemplateType', {
4
- name: { type: 'Edm.String' },
5
- content: { type: 'Edm.String', document: { extension: 'html', engine: true } },
6
- recipe: { type: 'Edm.String' },
7
- helpers: { type: 'Edm.String', document: { extension: 'js' }, schema: { type: 'object' } },
8
- engine: { type: 'Edm.String' }
9
- }, true)
10
-
11
- reporter.documentStore.registerEntitySet('templates', {
12
- entityType: 'jsreport.TemplateType',
13
- splitIntoDirectories: true
14
- })
15
-
16
- reporter.initializeListeners.add('templates', () => {
17
- const templatesCol = reporter.documentStore.collection('templates')
18
-
19
- templatesCol.beforeInsertListeners.add('templates', (doc) => {
20
- if (!doc.engine) {
21
- throw reporter.createError('Template must contain engine', {
22
- weak: true,
23
- statusCode: 400
24
- })
25
- }
26
- if (!doc.recipe) {
27
- throw reporter.createError('Template must contain recipe', {
28
- weak: true,
29
- statusCode: 400
30
- })
31
- }
32
- })
33
- })
34
- }
1
+
2
+ module.exports = (reporter) => {
3
+ reporter.documentStore.registerEntityType('TemplateType', {
4
+ name: { type: 'Edm.String' },
5
+ content: { type: 'Edm.String', document: { extension: 'html', engine: true } },
6
+ recipe: { type: 'Edm.String' },
7
+ helpers: { type: 'Edm.String', document: { extension: 'js' }, schema: { type: 'object' } },
8
+ engine: { type: 'Edm.String' }
9
+ }, true)
10
+
11
+ reporter.documentStore.registerEntitySet('templates', {
12
+ entityType: 'jsreport.TemplateType',
13
+ splitIntoDirectories: true
14
+ })
15
+
16
+ reporter.initializeListeners.add('templates', () => {
17
+ const templatesCol = reporter.documentStore.collection('templates')
18
+
19
+ templatesCol.beforeInsertListeners.add('templates', (doc) => {
20
+ if (!doc.engine) {
21
+ throw reporter.createError('Template must contain engine', {
22
+ weak: true,
23
+ statusCode: 400
24
+ })
25
+ }
26
+ if (!doc.recipe) {
27
+ throw reporter.createError('Template must contain recipe', {
28
+ weak: true,
29
+ statusCode: 400
30
+ })
31
+ }
32
+ })
33
+ })
34
+ }
@@ -1,62 +1,62 @@
1
- /* eslint-disable no-control-regex, no-useless-escape */
2
-
3
- const createError = require('../shared/createError')
4
-
5
- const invalidFileNameCharacters = [
6
- '<',
7
- '>',
8
- ':',
9
- '"',
10
- { character: '/', escaped: '\\/' },
11
- { character: '\\', escaped: '\\\\' },
12
- '|',
13
- '?',
14
- '*'
15
- ]
16
-
17
- function getInvalidFileNameCharactersRegExp () {
18
- // original regexp taken from https://github.com/sindresorhus/filename-reserved-regex
19
- return new RegExp(`[${
20
- invalidFileNameCharacters.map(c => typeof c === 'string' ? c : c.escaped).join('')
21
- }\\x00-\\x1F]`, 'g')
22
- }
23
-
24
- module.exports = (name) => {
25
- if (name == null || (typeof name === 'string' && name.trim() === '')) {
26
- throw createError('Entity name can not be empty', {
27
- statusCode: 400
28
- })
29
- }
30
-
31
- if (typeof name !== 'string') {
32
- throw createError('Entity name must be a string', {
33
- statusCode: 400
34
- })
35
- }
36
-
37
- if (name.trim() === '.') {
38
- throw createError('Entity name can not be "."', {
39
- statusCode: 400
40
- })
41
- }
42
-
43
- if (name.trim() === '..') {
44
- throw createError('Entity name can not be ".."', {
45
- statusCode: 400
46
- })
47
- }
48
-
49
- const containsInvalid = getInvalidFileNameCharactersRegExp().test(name)
50
-
51
- if (containsInvalid) {
52
- const msg = `Entity name can not contain characters ${
53
- invalidFileNameCharacters.map(c => typeof c === 'string' ? c : c.character).join(', ')
54
- } and non-printable characters. name used: ${name}`
55
-
56
- throw createError(msg, {
57
- statusCode: 400
58
- })
59
- }
60
-
61
- return true
62
- }
1
+ /* eslint-disable no-control-regex, no-useless-escape */
2
+
3
+ const createError = require('../shared/createError')
4
+
5
+ const invalidFileNameCharacters = [
6
+ '<',
7
+ '>',
8
+ ':',
9
+ '"',
10
+ { character: '/', escaped: '\\/' },
11
+ { character: '\\', escaped: '\\\\' },
12
+ '|',
13
+ '?',
14
+ '*'
15
+ ]
16
+
17
+ function getInvalidFileNameCharactersRegExp () {
18
+ // original regexp taken from https://github.com/sindresorhus/filename-reserved-regex
19
+ return new RegExp(`[${
20
+ invalidFileNameCharacters.map(c => typeof c === 'string' ? c : c.escaped).join('')
21
+ }\\x00-\\x1F]`, 'g')
22
+ }
23
+
24
+ module.exports = (name) => {
25
+ if (name == null || (typeof name === 'string' && name.trim() === '')) {
26
+ throw createError('Entity name can not be empty', {
27
+ statusCode: 400
28
+ })
29
+ }
30
+
31
+ if (typeof name !== 'string') {
32
+ throw createError('Entity name must be a string', {
33
+ statusCode: 400
34
+ })
35
+ }
36
+
37
+ if (name.trim() === '.') {
38
+ throw createError('Entity name can not be "."', {
39
+ statusCode: 400
40
+ })
41
+ }
42
+
43
+ if (name.trim() === '..') {
44
+ throw createError('Entity name can not be ".."', {
45
+ statusCode: 400
46
+ })
47
+ }
48
+
49
+ const containsInvalid = getInvalidFileNameCharactersRegExp().test(name)
50
+
51
+ if (containsInvalid) {
52
+ const msg = `Entity name can not contain characters ${
53
+ invalidFileNameCharacters.map(c => typeof c === 'string' ? c : c.character).join(', ')
54
+ } and non-printable characters. name used: ${name}`
55
+
56
+ throw createError(msg, {
57
+ statusCode: 400
58
+ })
59
+ }
60
+
61
+ return true
62
+ }
@@ -1,36 +1,36 @@
1
- const _omit = require('lodash.omit')
2
-
3
- module.exports = function (message, options = {}) {
4
- const { original } = options
5
- let error
6
-
7
- if (message == null && original != null) {
8
- error = original
9
- } else {
10
- error = new Error(message)
11
-
12
- if (original != null) {
13
- error.entity = original.entity
14
- error.lineNumber = original.lineNumber
15
- error.property = original.property
16
-
17
- if (error.message == null || error.message === '') {
18
- error.message = `${original.message}`
19
- } else {
20
- error.message += `. ${original.message}`
21
- }
22
-
23
- if (error.stack != null && original.stack != null) {
24
- error.stack += `\ncaused by: ${original.stack}`
25
- }
26
- }
27
- }
28
-
29
- Object.assign(error, _omit(options, 'original'))
30
-
31
- if ((error.statusCode === 400 || error.statusCode === 404) && error.weak == null) {
32
- error.weak = true
33
- }
34
-
35
- return error
36
- }
1
+ const _omit = require('lodash.omit')
2
+
3
+ module.exports = function (message, options = {}) {
4
+ const { original } = options
5
+ let error
6
+
7
+ if (message == null && original != null) {
8
+ error = original
9
+ } else {
10
+ error = new Error(message)
11
+
12
+ if (original != null) {
13
+ error.entity = original.entity
14
+ error.lineNumber = original.lineNumber
15
+ error.property = original.property
16
+
17
+ if (error.message == null || error.message === '') {
18
+ error.message = `${original.message}`
19
+ } else {
20
+ error.message += `. ${original.message}`
21
+ }
22
+
23
+ if (error.stack != null && original.stack != null) {
24
+ error.stack += `\ncaused by: ${original.stack}`
25
+ }
26
+ }
27
+ }
28
+
29
+ Object.assign(error, _omit(options, 'original'))
30
+
31
+ if ((error.statusCode === 400 || error.statusCode === 404) && error.weak == null) {
32
+ error.weak = true
33
+ }
34
+
35
+ return error
36
+ }
@@ -1,114 +1,114 @@
1
- const crypto = require('crypto')
2
-
3
- module.exports = (reporter) => {
4
- const DEFAULT_ENCRYPTION = 'aes-128-gcm'
5
- const DEFAULT_IV_LENGTH = 16 // For AES, this is always 16
6
- const prefix = 'jrEncrypt'
7
-
8
- function getEncryptionOpts (opts) {
9
- let secret = opts.secret
10
- let encryption = opts.encryption
11
- let ivLength = opts.ivLength
12
-
13
- if (!secret && reporter.options.encryption) {
14
- secret = reporter.options.encryption.secretKey
15
- }
16
-
17
- if (!encryption) {
18
- encryption = DEFAULT_ENCRYPTION
19
- }
20
-
21
- if (!ivLength) {
22
- ivLength = DEFAULT_IV_LENGTH
23
- }
24
-
25
- return {
26
- secret,
27
- encryption,
28
- ivLength
29
- }
30
- }
31
-
32
- async function encrypt (text, opts = {}) {
33
- if (reporter.options.encryption && reporter.options.encryption.enabled === false) {
34
- return text
35
- }
36
-
37
- const { secret, encryption, ivLength } = getEncryptionOpts(opts)
38
-
39
- if (!secret) {
40
- throw reporter.createError('using reporter.encryption.encrypt requires to specify a secret, make sure to pass one or to define the "options.encryption.secretKey" option in config', {
41
- statusCode: 400,
42
- encryptionNoSecret: true
43
- })
44
- }
45
-
46
- const iv = crypto.randomBytes(ivLength)
47
- const cipher = crypto.createCipheriv(encryption, Buffer.from(secret), iv)
48
- let encrypted = cipher.update(text)
49
-
50
- encrypted = Buffer.concat([encrypted, cipher.final()])
51
-
52
- const authTag = cipher.getAuthTag()
53
-
54
- return `${prefix}$${authTag.toString('hex')}:${iv.toString('hex')}:${encrypted.toString('hex')}`
55
- }
56
-
57
- async function decrypt (rawText, opts = {}) {
58
- const isTextEncrypted = isEncrypted(rawText)
59
-
60
- if (isTextEncrypted && reporter.options.encryption.enabled === false) {
61
- throw reporter.createError('using reporter.encryption.decrypt to restore encrypted value requires to enable encryption, make sure to enable it using "options.encryption.enabled" option in config', {
62
- statusCode: 400,
63
- encryptionDisabled: true
64
- })
65
- }
66
-
67
- if (!isTextEncrypted) {
68
- return rawText
69
- }
70
-
71
- const { secret, encryption } = getEncryptionOpts(opts)
72
-
73
- if (!secret) {
74
- throw reporter.createError('using reporter.encryption.decrypt requires to specify a secret, make sure to pass one or to define the "options.encryption.secretKey" option in config', {
75
- statusCode: 400,
76
- encryptionNoSecret: true
77
- })
78
- }
79
-
80
- try {
81
- const text = rawText.replace(new RegExp('^' + prefix + '\\$'), '')
82
- const textParts = text.split(':')
83
- const authTag = Buffer.from(textParts.shift(), 'hex')
84
- const iv = Buffer.from(textParts.shift(), 'hex')
85
- const encryptedText = Buffer.from(textParts.join(':'), 'hex')
86
- const decipher = crypto.createDecipheriv(encryption, Buffer.from(secret), iv)
87
-
88
- decipher.setAuthTag(authTag)
89
-
90
- let decrypted = decipher.update(encryptedText)
91
-
92
- decrypted = Buffer.concat([decrypted, decipher.final()])
93
-
94
- return decrypted.toString()
95
- } catch (e) {
96
- throw reporter.createError(`reporter.encryption.decrypt failed, make sure "options.encryption.secretKey" was not changed and you are using the same key which was used to encrypt content. ${e.message}`, {
97
- statusCode: 400,
98
- encryptionDecryptFail: true
99
- })
100
- }
101
- }
102
-
103
- function isEncrypted (text) {
104
- if (text == null) {
105
- return false
106
- }
107
-
108
- const regExp = new RegExp('^' + prefix + '\\$[^:\\s]+:[^:\\s]+')
109
-
110
- return regExp.test(text)
111
- }
112
-
113
- return { encrypt, decrypt, isEncrypted }
114
- }
1
+ const crypto = require('crypto')
2
+
3
+ module.exports = (reporter) => {
4
+ const DEFAULT_ENCRYPTION = 'aes-128-gcm'
5
+ const DEFAULT_IV_LENGTH = 16 // For AES, this is always 16
6
+ const prefix = 'jrEncrypt'
7
+
8
+ function getEncryptionOpts (opts) {
9
+ let secret = opts.secret
10
+ let encryption = opts.encryption
11
+ let ivLength = opts.ivLength
12
+
13
+ if (!secret && reporter.options.encryption) {
14
+ secret = reporter.options.encryption.secretKey
15
+ }
16
+
17
+ if (!encryption) {
18
+ encryption = DEFAULT_ENCRYPTION
19
+ }
20
+
21
+ if (!ivLength) {
22
+ ivLength = DEFAULT_IV_LENGTH
23
+ }
24
+
25
+ return {
26
+ secret,
27
+ encryption,
28
+ ivLength
29
+ }
30
+ }
31
+
32
+ async function encrypt (text, opts = {}) {
33
+ if (reporter.options.encryption && reporter.options.encryption.enabled === false) {
34
+ return text
35
+ }
36
+
37
+ const { secret, encryption, ivLength } = getEncryptionOpts(opts)
38
+
39
+ if (!secret) {
40
+ throw reporter.createError('using reporter.encryption.encrypt requires to specify a secret, make sure to pass one or to define the "options.encryption.secretKey" option in config', {
41
+ statusCode: 400,
42
+ encryptionNoSecret: true
43
+ })
44
+ }
45
+
46
+ const iv = crypto.randomBytes(ivLength)
47
+ const cipher = crypto.createCipheriv(encryption, Buffer.from(secret), iv)
48
+ let encrypted = cipher.update(text)
49
+
50
+ encrypted = Buffer.concat([encrypted, cipher.final()])
51
+
52
+ const authTag = cipher.getAuthTag()
53
+
54
+ return `${prefix}$${authTag.toString('hex')}:${iv.toString('hex')}:${encrypted.toString('hex')}`
55
+ }
56
+
57
+ async function decrypt (rawText, opts = {}) {
58
+ const isTextEncrypted = isEncrypted(rawText)
59
+
60
+ if (isTextEncrypted && reporter.options.encryption.enabled === false) {
61
+ throw reporter.createError('using reporter.encryption.decrypt to restore encrypted value requires to enable encryption, make sure to enable it using "options.encryption.enabled" option in config', {
62
+ statusCode: 400,
63
+ encryptionDisabled: true
64
+ })
65
+ }
66
+
67
+ if (!isTextEncrypted) {
68
+ return rawText
69
+ }
70
+
71
+ const { secret, encryption } = getEncryptionOpts(opts)
72
+
73
+ if (!secret) {
74
+ throw reporter.createError('using reporter.encryption.decrypt requires to specify a secret, make sure to pass one or to define the "options.encryption.secretKey" option in config', {
75
+ statusCode: 400,
76
+ encryptionNoSecret: true
77
+ })
78
+ }
79
+
80
+ try {
81
+ const text = rawText.replace(new RegExp('^' + prefix + '\\$'), '')
82
+ const textParts = text.split(':')
83
+ const authTag = Buffer.from(textParts.shift(), 'hex')
84
+ const iv = Buffer.from(textParts.shift(), 'hex')
85
+ const encryptedText = Buffer.from(textParts.join(':'), 'hex')
86
+ const decipher = crypto.createDecipheriv(encryption, Buffer.from(secret), iv)
87
+
88
+ decipher.setAuthTag(authTag)
89
+
90
+ let decrypted = decipher.update(encryptedText)
91
+
92
+ decrypted = Buffer.concat([decrypted, decipher.final()])
93
+
94
+ return decrypted.toString()
95
+ } catch (e) {
96
+ throw reporter.createError(`reporter.encryption.decrypt failed, make sure "options.encryption.secretKey" was not changed and you are using the same key which was used to encrypt content. ${e.message}`, {
97
+ statusCode: 400,
98
+ encryptionDecryptFail: true
99
+ })
100
+ }
101
+ }
102
+
103
+ function isEncrypted (text) {
104
+ if (text == null) {
105
+ return false
106
+ }
107
+
108
+ const regExp = new RegExp('^' + prefix + '\\$[^:\\s]+:[^:\\s]+')
109
+
110
+ return regExp.test(text)
111
+ }
112
+
113
+ return { encrypt, decrypt, isEncrypted }
114
+ }
@@ -1,11 +1,11 @@
1
- const resolveFolderFromPath = require('./resolveFolderFromPath')
2
- const resolveEntityFromPath = require('./resolveEntityFromPath')
3
- const resolveEntityPath = require('./resolveEntityPath')
4
-
5
- module.exports = (reporter) => {
6
- return {
7
- resolveEntityPath: resolveEntityPath(reporter),
8
- resolveFolderFromPath: resolveFolderFromPath(reporter),
9
- resolveEntityFromPath: resolveEntityFromPath(reporter)
10
- }
11
- }
1
+ const resolveFolderFromPath = require('./resolveFolderFromPath')
2
+ const resolveEntityFromPath = require('./resolveEntityFromPath')
3
+ const resolveEntityPath = require('./resolveEntityPath')
4
+
5
+ module.exports = (reporter) => {
6
+ return {
7
+ resolveEntityPath: resolveEntityPath(reporter),
8
+ resolveFolderFromPath: resolveFolderFromPath(reporter),
9
+ resolveEntityFromPath: resolveEntityFromPath(reporter)
10
+ }
11
+ }
@@ -1,15 +1,15 @@
1
- const path = require('path')
2
-
3
- module.exports = function normalizeEntityPath (entityPath, { currentPath }, req) {
4
- let parentPath = '/'
5
-
6
- if (req && req.context.currentFolderPath) {
7
- parentPath = req.context.currentFolderPath
8
- }
9
-
10
- if (currentPath) {
11
- parentPath = currentPath
12
- }
13
-
14
- return path.posix.resolve(parentPath, entityPath).replace(/\\/g, '/')
15
- }
1
+ const path = require('path')
2
+
3
+ module.exports = function normalizeEntityPath (entityPath, { currentPath }, req) {
4
+ let parentPath = '/'
5
+
6
+ if (req && req.context.currentFolderPath) {
7
+ parentPath = req.context.currentFolderPath
8
+ }
9
+
10
+ if (currentPath) {
11
+ parentPath = currentPath
12
+ }
13
+
14
+ return path.posix.resolve(parentPath, entityPath).replace(/\\/g, '/')
15
+ }