ghost 4.23.0 → 4.26.0

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 (175) hide show
  1. package/.eslintrc.js +39 -0
  2. package/content/themes/casper/assets/built/casper.js +1 -1
  3. package/content/themes/casper/assets/built/casper.js.map +1 -1
  4. package/content/themes/casper/assets/built/global.css +1 -1
  5. package/content/themes/casper/assets/built/global.css.map +1 -1
  6. package/content/themes/casper/assets/built/screen.css +1 -1
  7. package/content/themes/casper/assets/built/screen.css.map +1 -1
  8. package/content/themes/casper/assets/css/global.css +6 -1
  9. package/content/themes/casper/assets/css/screen.css +50 -215
  10. package/content/themes/casper/default.hbs +2 -2
  11. package/content/themes/casper/package.json +3 -2
  12. package/content/themes/casper/post.hbs +1 -1
  13. package/content/themes/casper/yarn.lock +173 -123
  14. package/core/app.js +20 -5
  15. package/core/boot.js +77 -36
  16. package/core/bridge.js +10 -10
  17. package/core/built/assets/ghost-dark-ef86e3bc7f0fb83d39d3d6a49bff8dd5.css +1 -0
  18. package/core/built/assets/ghost.min-57c1e677f42d596942d317ce93e8a62c.css +1 -0
  19. package/core/built/assets/{ghost.min-cccc107e881b74c7aaf1a73e1e5e0dee.js → ghost.min-f3c6886e191d34450e9ffca0c8fa056e.js} +543 -618
  20. package/core/built/assets/icons/audio-upload.svg +8 -0
  21. package/core/built/assets/{vendor.min-c9002845b6c30ac978abdadde9f33d7c.js → vendor.min-b6b8d2a31d61830c2d8f65c5ba54236a.js} +2656 -2118
  22. package/core/frontend/apps/amp/lib/helpers/amp_content.js +2 -2
  23. package/core/frontend/apps/amp/lib/views/amp.hbs +75 -0
  24. package/core/frontend/apps/private-blogging/index.js +1 -1
  25. package/core/frontend/helpers/url.js +18 -1
  26. package/core/frontend/services/apps/index.js +1 -1
  27. package/core/frontend/services/apps/loader.js +3 -3
  28. package/core/frontend/services/card-assets/index.js +0 -12
  29. package/core/frontend/services/card-assets/service.js +22 -21
  30. package/core/frontend/services/helpers/handlebars.js +1 -1
  31. package/core/frontend/services/theme-engine/middleware/ensure-active-theme.js +34 -0
  32. package/core/frontend/services/theme-engine/middleware/index.js +6 -0
  33. package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +116 -0
  34. package/core/frontend/services/theme-engine/middleware/update-local-template-data.js +9 -0
  35. package/core/frontend/services/theme-engine/middleware/update-local-template-options.js +57 -0
  36. package/core/frontend/src/cards/css/audio.css +186 -0
  37. package/core/frontend/src/cards/css/blockquote.css +27 -0
  38. package/core/frontend/src/cards/css/bookmark.css +7 -0
  39. package/core/frontend/src/cards/css/button.css +4 -0
  40. package/core/frontend/src/cards/css/callout.css +23 -15
  41. package/core/frontend/src/cards/css/gallery.css +13 -3
  42. package/core/frontend/src/cards/css/toggle.css +48 -15
  43. package/core/frontend/src/cards/js/audio.js +137 -0
  44. package/core/frontend/web/middleware/error-handler.js +93 -0
  45. package/core/frontend/web/middleware/handle-image-sizes.js +3 -6
  46. package/core/frontend/web/middleware/index.js +1 -0
  47. package/core/frontend/web/middleware/serve-public-file.js +25 -8
  48. package/core/frontend/web/site.js +2 -5
  49. package/core/server/adapters/scheduling/SchedulingDefault.js +2 -2
  50. package/core/server/adapters/storage/LocalStorageBase.js +2 -2
  51. package/core/server/api/canary/db.js +2 -2
  52. package/core/server/api/canary/media.js +3 -2
  53. package/core/server/api/canary/oembed.js +16 -1
  54. package/core/server/api/canary/session.js +1 -1
  55. package/core/server/api/canary/slugs.js +1 -1
  56. package/core/server/api/canary/utils/permissions.js +2 -2
  57. package/core/server/api/canary/utils/serializers/output/config.js +2 -6
  58. package/core/server/api/v2/db.js +2 -2
  59. package/core/server/api/v2/session.js +1 -1
  60. package/core/server/api/v2/slugs.js +1 -1
  61. package/core/server/api/v2/utils/permissions.js +2 -2
  62. package/core/server/api/v3/db.js +2 -2
  63. package/core/server/api/v3/session.js +1 -1
  64. package/core/server/api/v3/slugs.js +1 -1
  65. package/core/server/api/v3/utils/permissions.js +2 -2
  66. package/core/server/data/db/state-manager.js +4 -4
  67. package/core/server/data/exporter/export-filename.js +1 -1
  68. package/core/server/data/importer/handlers/json.js +1 -1
  69. package/core/server/data/importer/import-manager.js +1 -1
  70. package/core/server/data/importer/importers/data/base.js +1 -1
  71. package/core/server/data/migrations/utils.js +2 -2
  72. package/core/server/data/migrations/versions/1.25/1-update-koenig-beta-html.js +1 -0
  73. package/core/server/data/migrations/versions/3.1/08-add-uuid-values-to-members.js +1 -0
  74. package/core/server/data/migrations/versions/3.22/02-settings-key-renames.js +2 -0
  75. package/core/server/data/migrations/versions/3.22/05-migrate-members-subscription-settings.js +3 -0
  76. package/core/server/data/migrations/versions/3.22/06-migrate-stripe-connect-settings.js +2 -0
  77. package/core/server/data/migrations/versions/3.23/01-migrate-bulk-email-settings.js +1 -0
  78. package/core/server/data/migrations/versions/3.29/01-remove-duplicate-subscriptions.js +2 -0
  79. package/core/server/data/migrations/versions/3.29/02-remove-duplicate-customers.js +2 -0
  80. package/core/server/data/migrations/versions/3.38/04-populate-recipient-filter-column.js +2 -0
  81. package/core/server/data/migrations/versions/4.0/01-update-mobiledoc.js +2 -0
  82. package/core/server/data/migrations/versions/4.0/03-populate-status-column-for-members.js +4 -0
  83. package/core/server/data/migrations/versions/4.0/06-populate-members-subscribe-events-table.js +1 -0
  84. package/core/server/data/migrations/versions/4.0/17-populate-members-status-events-table.js +1 -0
  85. package/core/server/data/migrations/versions/4.0/18-transform-urls-absolute-to-transform-ready.js +5 -0
  86. package/core/server/data/migrations/versions/4.0/22-solve-orphaned-webhooks.js +1 -0
  87. package/core/server/data/migrations/versions/4.0/23-regenerate-posts-html.js +1 -0
  88. package/core/server/data/migrations/versions/4.0/25-populate-members-paid-subscription-events-table.js +2 -1
  89. package/core/server/data/migrations/versions/4.12/02-fix-member-statuses.js +1 -0
  90. package/core/server/data/migrations/versions/4.14/01-fix-comped-member-statuses.js +3 -0
  91. package/core/server/data/migrations/versions/4.14/02-fix-free-members-status-events.js +1 -0
  92. package/core/server/data/migrations/versions/4.20/05-remove-not-null-constraint-from-portal-title.js +2 -0
  93. package/core/server/data/migrations/versions/4.23/01-truncate-offer-names.js +1 -0
  94. package/core/server/data/migrations/versions/4.3/04-attach-members-to-product.js +1 -0
  95. package/core/server/data/migrations/versions/4.4/01-restore-free-members-signup-setting-from-backup.js +1 -0
  96. package/core/server/data/migrations/versions/4.6/01-remove-comped-status.js +1 -0
  97. package/core/server/data/migrations/versions/4.8/04-migrate-show-newsletter-header-setting.js +1 -0
  98. package/core/server/data/migrations/versions/4.9/05-fix-missed-mobiledoc-url-transforms.js +1 -0
  99. package/core/server/data/migrations/versions/4.9/06-add-comped-status.js +1 -0
  100. package/core/server/data/migrations/versions/4.9/07-update-comped-members-status-events.js +1 -0
  101. package/core/server/data/schema/commands.js +2 -2
  102. package/core/server/ghost-server.js +2 -2
  103. package/core/server/lib/image/image-size.js +2 -2
  104. package/core/server/models/base/listeners.js +2 -2
  105. package/core/server/models/member-email-change-event.js +2 -2
  106. package/core/server/models/member-login-event.js +2 -2
  107. package/core/server/models/member-paid-subscription-event.js +3 -3
  108. package/core/server/models/member-payment-event.js +3 -3
  109. package/core/server/models/member-product-event.js +6 -6
  110. package/core/server/models/member-status-event.js +5 -3
  111. package/core/server/models/member-subscribe-event.js +9 -3
  112. package/core/server/models/relations/authors.js +1 -1
  113. package/core/server/models/settings.js +1 -1
  114. package/core/server/notify.js +1 -2
  115. package/core/server/services/auth/passwordreset.js +1 -1
  116. package/core/server/services/auth/setup.js +1 -1
  117. package/core/server/services/email-analytics/jobs/index.js +1 -1
  118. package/core/server/services/mega/mega.js +6 -4
  119. package/core/server/services/mega/template.js +47 -17
  120. package/core/server/services/members/api.js +22 -0
  121. package/core/server/services/members/config.js +1 -1
  122. package/core/server/services/members/emails/signup-paid.js +168 -0
  123. package/core/server/services/members/service.js +6 -2
  124. package/core/server/services/members/stripe-connect.js +4 -2
  125. package/core/server/services/nft-oembed.js +7 -2
  126. package/core/server/services/oembed.js +15 -3
  127. package/core/server/services/permissions/can-this.js +1 -1
  128. package/core/server/services/redirects/api.js +20 -25
  129. package/core/server/services/redirects/index.js +18 -10
  130. package/core/server/services/redirects/utils.js +14 -0
  131. package/core/server/services/redirects/validation.js +10 -0
  132. package/core/server/services/route-settings/default-settings-manager.js +1 -1
  133. package/core/server/services/route-settings/index.js +40 -17
  134. package/core/server/services/route-settings/route-settings.js +120 -115
  135. package/core/server/services/route-settings/settings-loader.js +18 -36
  136. package/core/server/services/route-settings/yaml-parser.js +1 -1
  137. package/core/server/services/slack.js +1 -1
  138. package/core/server/services/themes/activation-bridge.js +3 -3
  139. package/core/server/services/themes/storage.js +2 -2
  140. package/core/server/services/twitter-embed.js +81 -0
  141. package/core/server/services/url/LocalFileCache.js +75 -0
  142. package/core/server/services/url/UrlService.js +15 -47
  143. package/core/server/services/url/index.js +17 -4
  144. package/core/server/services/xmlrpc.js +2 -2
  145. package/core/server/web/admin/app.js +2 -5
  146. package/core/server/web/admin/controller.js +35 -12
  147. package/core/server/web/admin/middleware/redirect-admin-urls.js +15 -0
  148. package/core/server/web/admin/views/default-prod.html +4 -4
  149. package/core/server/web/admin/views/default.html +4 -4
  150. package/core/server/web/api/canary/admin/app.js +0 -3
  151. package/core/server/web/api/canary/admin/middleware.js +1 -1
  152. package/core/server/web/api/canary/content/app.js +0 -3
  153. package/core/server/web/api/v2/admin/app.js +0 -3
  154. package/core/server/web/api/v2/admin/middleware.js +1 -1
  155. package/core/server/web/api/v2/content/app.js +0 -3
  156. package/core/server/web/api/v3/admin/app.js +0 -3
  157. package/core/server/web/api/v3/admin/middleware.js +1 -1
  158. package/core/server/web/api/v3/content/app.js +0 -3
  159. package/core/server/web/members/app.js +0 -3
  160. package/core/server/web/oauth/app.js +0 -4
  161. package/core/server/web/parent/app.js +2 -13
  162. package/core/server/web/parent/backend.js +2 -0
  163. package/core/server/web/shared/middleware/error-handler.js +57 -162
  164. package/core/server/web/shared/middleware/index.js +0 -4
  165. package/core/shared/config/defaults.json +7 -1
  166. package/core/shared/express.js +1 -1
  167. package/core/shared/labs.js +12 -7
  168. package/core/shared/sentry.js +1 -1
  169. package/package.json +41 -40
  170. package/yarn.lock +799 -948
  171. package/content/themes/casper/assets/js/gallery-card.js +0 -24
  172. package/core/built/assets/ghost-dark-42cf6e0c730578940ec069bda45aea41.css +0 -1
  173. package/core/built/assets/ghost.min-fcf6a0738421f86c47c55f20d00c5ba9.css +0 -1
  174. package/core/frontend/services/theme-engine/middleware.js +0 -209
  175. package/core/server/web/shared/middleware/maintenance.js +0 -25
@@ -5,6 +5,7 @@ const logging = require('@tryghost/logging');
5
5
  module.exports = createTransactionalMigration(
6
6
  async function up(knex) {
7
7
  logging.info('Updating members.status based on members_stripe_customers_subscriptions.status');
8
+ // eslint-disable-next-line no-restricted-syntax
8
9
  const paidMemberIds = (await knex('members')
9
10
  .select('members.id')
10
11
  .innerJoin(
@@ -24,6 +25,7 @@ module.exports = createTransactionalMigration(
24
25
  }
25
26
  )).map(({id}) => id);
26
27
 
28
+ // eslint-disable-next-line no-restricted-syntax
27
29
  const compedMemberIds = (await knex('members')
28
30
  .select('members.id')
29
31
  .innerJoin(
@@ -54,6 +56,7 @@ module.exports = createTransactionalMigration(
54
56
 
55
57
  const paidMemberIdChunks = chunk(paidMemberIds, chunkSize);
56
58
 
59
+ // eslint-disable-next-line no-restricted-syntax
57
60
  for (const paidMemberIdsChunk of paidMemberIdChunks) {
58
61
  await knex('members')
59
62
  .update('status', 'paid')
@@ -62,6 +65,7 @@ module.exports = createTransactionalMigration(
62
65
 
63
66
  const compedMemberIdChunks = chunk(compedMemberIds, chunkSize);
64
67
 
68
+ // eslint-disable-next-line no-restricted-syntax
65
69
  for (const compedMemberIdsChunk of compedMemberIdChunks) {
66
70
  await knex('members')
67
71
  .update('status', 'comped')
@@ -42,6 +42,7 @@ module.exports = createTransactionalMigration(
42
42
 
43
43
  const eventChunks = chunk(allEvents, chunkSize);
44
44
 
45
+ // eslint-disable-next-line no-restricted-syntax
45
46
  for (const events of eventChunks) {
46
47
  await knex.insert(events).into('members_subscribe_events');
47
48
  }
@@ -28,6 +28,7 @@ module.exports = createTransactionalMigration(
28
28
 
29
29
  const eventChunks = chunk(membersStatusEvents, chunkSize);
30
30
 
31
+ // eslint-disable-next-line no-restricted-syntax
31
32
  for (const events of eventChunks) {
32
33
  await knex.insert(events).into('members_status_events');
33
34
  }
@@ -18,6 +18,7 @@ module.exports = createIrreversibleMigration(async (knex) => {
18
18
  // pushing all queries into the query builder buffer in parallel
19
19
  // https://stackoverflow.com/questions/54105280/how-to-loop-through-multi-line-sql-query-and-use-them-in-knex-transactions
20
20
 
21
+ // eslint-disable-next-line no-restricted-syntax
21
22
  for (const postIdRow of postIdRows) {
22
23
  const {id} = postIdRow;
23
24
  const [post] = await knex('posts')
@@ -80,6 +81,7 @@ module.exports = createIrreversibleMigration(async (knex) => {
80
81
  .forUpdate()
81
82
  .select('id');
82
83
 
84
+ // eslint-disable-next-line no-restricted-syntax
83
85
  for (const userIdRow of userIdRows) {
84
86
  const {id} = userIdRow;
85
87
  const [user] = await knex('users')
@@ -108,6 +110,7 @@ module.exports = createIrreversibleMigration(async (knex) => {
108
110
  .forUpdate()
109
111
  .select('id');
110
112
 
113
+ // eslint-disable-next-line no-restricted-syntax
111
114
  for (const tagIdRow of tagIdRows) {
112
115
  const {id} = tagIdRow;
113
116
  const [tag] = await knex('tags')
@@ -148,6 +151,7 @@ module.exports = createIrreversibleMigration(async (knex) => {
148
151
  .forUpdate()
149
152
  .select('id');
150
153
 
154
+ // eslint-disable-next-line no-restricted-syntax
151
155
  for (const snippetIdRow of snippetIdRows) {
152
156
  const {id} = snippetIdRow;
153
157
  const [snippet] = await knex('snippets')
@@ -180,6 +184,7 @@ module.exports = createIrreversibleMigration(async (knex) => {
180
184
  'twitter_image'
181
185
  ]);
182
186
 
187
+ // eslint-disable-next-line no-restricted-syntax
183
188
  for (const settingRow of settingsRows) {
184
189
  let {key, value} = settingRow;
185
190
 
@@ -77,6 +77,7 @@ module.exports = createIrreversibleMigration(
77
77
  };
78
78
  await knex('api_keys').insert(adminKey);
79
79
 
80
+ // eslint-disable-next-line no-restricted-syntax
80
81
  for (let i = 0; i < orphanedWebhooks.length; i++) {
81
82
  const webhook = orphanedWebhooks[i];
82
83
 
@@ -17,6 +17,7 @@ module.exports = createIrreversibleMigration(async (knex) => {
17
17
  // pushing all queries into the query builder buffer in parallel
18
18
  // https://stackoverflow.com/questions/54105280/how-to-loop-through-multi-line-sql-query-and-use-them-in-knex-transactions
19
19
 
20
+ // eslint-disable-next-line no-restricted-syntax
20
21
  for (const postIdRow of postIdRows) {
21
22
  const {id} = postIdRow;
22
23
  const [post] = await knex('posts')
@@ -44,7 +44,7 @@ module.exports = createTransactionalMigration(
44
44
  return amount * 30;
45
45
  }
46
46
 
47
- throw new errors.GhostError({
47
+ throw new errors.InternalServerError({
48
48
  message: tpl(messages.unknownSubscriptionIntervalError , {
49
49
  interval
50
50
  })
@@ -116,6 +116,7 @@ module.exports = createTransactionalMigration(
116
116
 
117
117
  const eventChunks = chunk(allEvents, chunkSize);
118
118
 
119
+ // eslint-disable-next-line no-restricted-syntax
119
120
  for (const events of eventChunks) {
120
121
  await knex.insert(events).into('members_paid_subscription_events');
121
122
  }
@@ -26,6 +26,7 @@ module.exports = createTransactionalMigration(
26
26
 
27
27
  const chunks = chunkArray(freeMembersIds, chunkSize);
28
28
 
29
+ // eslint-disable-next-line no-restricted-syntax
29
30
  for (const chunk of chunks) {
30
31
  await knex('members')
31
32
  .update('status', 'free')
@@ -3,6 +3,7 @@ const {createTransactionalMigration} = require('../../utils');
3
3
  const logging = require('@tryghost/logging');
4
4
 
5
5
  module.exports = createTransactionalMigration(async function up(knex) {
6
+ // eslint-disable-next-line no-restricted-syntax
6
7
  const compedMemberIds = (await knex('members')
7
8
  .select('members.id')
8
9
  .innerJoin(
@@ -44,12 +45,14 @@ module.exports = createTransactionalMigration(async function up(knex) {
44
45
 
45
46
  const compedMemberIdChunks = chunk(compedMemberIds, chunkSize);
46
47
 
48
+ // eslint-disable-next-line no-restricted-syntax
47
49
  for (const compedMemberIdsChunk of compedMemberIdChunks) {
48
50
  await knex('members')
49
51
  .update('status', 'comped')
50
52
  .whereIn('id', compedMemberIdsChunk);
51
53
  }
52
54
 
55
+ // eslint-disable-next-line no-restricted-syntax
53
56
  for (const memberId of compedMemberIds) {
54
57
  const mostRecentStatusEvent = await knex('members_status_events')
55
58
  .select('*')
@@ -49,6 +49,7 @@ module.exports = createTransactionalMigration(
49
49
  // and so we're left with 998 for our WHERE IN clause values
50
50
  const chunkedEventsToUpdate = _.chunk(eventsToUpdate, 998);
51
51
 
52
+ // eslint-disable-next-line no-restricted-syntax
52
53
  for (const chunk of chunkedEventsToUpdate) {
53
54
  logging.info(`Updating a chunk of ${chunk.length} member status events`);
54
55
  await knex('members_status_events')
@@ -15,6 +15,7 @@ module.exports = createNonTransactionalMigration(
15
15
  });
16
16
 
17
17
  if (knex.client.config.client === 'sqlite3') {
18
+ // eslint-disable-next-line no-restricted-syntax
18
19
  for (const column of ['name', 'code', 'stripe_coupon_id']) {
19
20
  await addUnique('offers', column, knex);
20
21
  }
@@ -32,6 +33,7 @@ module.exports = createNonTransactionalMigration(
32
33
  });
33
34
 
34
35
  if (knex.client.config.client === 'sqlite3') {
36
+ // eslint-disable-next-line no-restricted-syntax
35
37
  for (const column of ['name', 'code', 'stripe_coupon_id']) {
36
38
  await addUnique('offers', column, knex);
37
39
  }
@@ -47,6 +47,7 @@ module.exports = createTransactionalMigration(
47
47
  return offers.concat(updatedRow);
48
48
  }, []);
49
49
 
50
+ // eslint-disable-next-line no-restricted-syntax
50
51
  for (const truncatedOffer of truncatedOffers) {
51
52
  await knex('offers')
52
53
  .update('name', truncatedOffer.name)
@@ -38,6 +38,7 @@ module.exports = createTransactionalMigration(
38
38
  const chunkSize = 333;
39
39
  const memberProductRelationsChunks = chunk(memberProductRelations, chunkSize);
40
40
 
41
+ // eslint-disable-next-line no-restricted-syntax
41
42
  for (const relations of memberProductRelationsChunks) {
42
43
  await knex.insert(relations).into('members_products');
43
44
  }
@@ -63,6 +63,7 @@ module.exports = createTransactionalMigration(
63
63
 
64
64
  let hasRestored = false;
65
65
 
66
+ // eslint-disable-next-line no-restricted-syntax
66
67
  for (const backupFile of backupFiles) {
67
68
  try {
68
69
  const backup = require(path.join(dataPath, backupFile));
@@ -9,6 +9,7 @@ module.exports = createTransactionalMigration(
9
9
  .where('status', 'comped');
10
10
  },
11
11
  async function down(knex) {
12
+ // eslint-disable-next-line no-restricted-syntax
12
13
  const compedMemberIds = (await knex('members')
13
14
  .select('members.id')
14
15
  .innerJoin(
@@ -27,6 +27,7 @@ module.exports = createTransactionalMigration(
27
27
  const newSettingKeys = ['newsletter_show_header_title', 'newsletter_show_header_icon'];
28
28
  const now = connection.raw('CURRENT_TIMESTAMP');
29
29
 
30
+ // eslint-disable-next-line no-restricted-syntax
30
31
  for (const settingKey of newSettingKeys) {
31
32
  const existingSetting = await connection('settings').where('key', settingKey).first();
32
33
 
@@ -33,6 +33,7 @@ module.exports = createTransactionalMigration(
33
33
  .forUpdate()
34
34
  .select('id');
35
35
 
36
+ // eslint-disable-next-line no-restricted-syntax
36
37
  for (const postIdRow of postIdRows) {
37
38
  const {id} = postIdRow;
38
39
  const [post] = await knex('posts')
@@ -3,6 +3,7 @@ const {createTransactionalMigration} = require('../../utils.js');
3
3
 
4
4
  module.exports = createTransactionalMigration(
5
5
  async function up(knex) {
6
+ // eslint-disable-next-line no-restricted-syntax
6
7
  const compedMemberIds = (await knex('members')
7
8
  .select('members.id')
8
9
  .innerJoin(
@@ -15,6 +15,7 @@ module.exports = createTransactionalMigration(
15
15
  logging.info(`Found ${compedMembers.length} comped members - checking members_status_events`);
16
16
  }
17
17
 
18
+ // eslint-disable-next-line no-restricted-syntax
18
19
  for (const member of compedMembers) {
19
20
  const mostRecentStatusEvent = await knex('members_status_events')
20
21
  .select('*')
@@ -139,7 +139,7 @@ async function hasForeignSQLite({fromTable, fromColumn, toTable, toColumn, trans
139
139
  const client = knex.client.config.client;
140
140
 
141
141
  if (client !== 'sqlite3') {
142
- throw new errors.GhostError({
142
+ throw new errors.InternalServerError({
143
143
  message: tpl(messages.hasForeignSQLite3)
144
144
  });
145
145
  }
@@ -265,7 +265,7 @@ async function hasPrimaryKeySQLite(tableName, transaction) {
265
265
  const client = knex.client.config.client;
266
266
 
267
267
  if (client !== 'sqlite3') {
268
- throw new errors.GhostError({
268
+ throw new errors.InternalServerError({
269
269
  message: tpl(messages.hasPrimaryKeySQLiteError)
270
270
  });
271
271
  }
@@ -107,13 +107,13 @@ class GhostServer {
107
107
  let ghostError;
108
108
 
109
109
  if (error.code === 'EADDRINUSE') {
110
- ghostError = new errors.GhostError({
110
+ ghostError = new errors.InternalServerError({
111
111
  message: tpl(messages.addressInUse.error),
112
112
  context: tpl(messages.addressInUse.context, {port: config.get('server').port}),
113
113
  help: tpl(messages.addressInUse.help)
114
114
  });
115
115
  } else {
116
- ghostError = new errors.GhostError({
116
+ ghostError = new errors.InternalServerError({
117
117
  message: tpl(messages.otherError.error, {errorNumber: error.errno}),
118
118
  context: tpl(messages.otherError.context),
119
119
  help: tpl(messages.otherError.help)
@@ -177,7 +177,7 @@ class ImageSize {
177
177
  context: err.url || imagePath
178
178
  }));
179
179
  }).catch(function (err) {
180
- if (errors.utils.isIgnitionError(err)) {
180
+ if (errors.utils.isGhostError(err)) {
181
181
  return Promise.reject(err);
182
182
  }
183
183
 
@@ -241,7 +241,7 @@ class ImageSize {
241
241
  }
242
242
  }));
243
243
  }).catch((err) => {
244
- if (errors.utils.isIgnitionError(err)) {
244
+ if (errors.utils.isGhostError(err)) {
245
245
  return Promise.reject(err);
246
246
  }
247
247
 
@@ -69,13 +69,13 @@ events.on('settings.timezone.edited', function (settingModel, options) {
69
69
  try {
70
70
  await models.Post.edit(post.toJSON(), _.merge({id: post.id}, options));
71
71
  } catch (err) {
72
- logging.error(new errors.GhostError({
72
+ logging.error(new errors.InternalServerError({
73
73
  err
74
74
  }));
75
75
  }
76
76
  });
77
77
  } catch (err) {
78
- logging.error(new errors.GhostError({
78
+ logging.error(new errors.InternalServerError({
79
79
  err: err,
80
80
  level: 'critical'
81
81
  }));
@@ -9,11 +9,11 @@ const MemberEmailChangeEvent = ghostBookshelf.Model.extend({
9
9
  }
10
10
  }, {
11
11
  async edit() {
12
- throw new errors.IncorrectUsageError('Cannot edit MemberEmailChangeEvent');
12
+ throw new errors.IncorrectUsageError({message: 'Cannot edit MemberEmailChangeEvent'});
13
13
  },
14
14
 
15
15
  async destroy() {
16
- throw new errors.IncorrectUsageError('Cannot destroy MemberEmailChangeEvent');
16
+ throw new errors.IncorrectUsageError({message: 'Cannot destroy MemberEmailChangeEvent'});
17
17
  }
18
18
  });
19
19
 
@@ -9,11 +9,11 @@ const MemberLoginEvent = ghostBookshelf.Model.extend({
9
9
  }
10
10
  }, {
11
11
  async edit() {
12
- throw new errors.IncorrectUsageError('Cannot edit MemberLoginEvent');
12
+ throw new errors.IncorrectUsageError({message: 'Cannot edit MemberLoginEvent'});
13
13
  },
14
14
 
15
15
  async destroy() {
16
- throw new errors.IncorrectUsageError('Cannot destroy MemberLoginEvent');
16
+ throw new errors.IncorrectUsageError({message: 'Cannot destroy MemberLoginEvent'});
17
17
  }
18
18
  });
19
19
 
@@ -11,7 +11,7 @@ const MemberPaidSubscriptionEvent = ghostBookshelf.Model.extend({
11
11
  customQuery(qb, options) {
12
12
  if (options.aggregateMRRDeltas) {
13
13
  if (options.limit || options.filter) {
14
- throw new errors.IncorrectUsageError('aggregateMRRDeltas does not work when passed a filter or limit');
14
+ throw new errors.IncorrectUsageError({message: 'aggregateMRRDeltas does not work when passed a filter or limit'});
15
15
  }
16
16
  const knex = ghostBookshelf.knex;
17
17
  return qb.clear('select')
@@ -33,11 +33,11 @@ const MemberPaidSubscriptionEvent = ghostBookshelf.Model.extend({
33
33
  return options;
34
34
  },
35
35
  async edit() {
36
- throw new errors.IncorrectUsageError('Cannot edit MemberPaidSubscriptionEvent');
36
+ throw new errors.IncorrectUsageError({message: 'Cannot edit MemberPaidSubscriptionEvent'});
37
37
  },
38
38
 
39
39
  async destroy() {
40
- throw new errors.IncorrectUsageError('Cannot destroy MemberPaidSubscriptionEvent');
40
+ throw new errors.IncorrectUsageError({message: 'Cannot destroy MemberPaidSubscriptionEvent'});
41
41
  }
42
42
  });
43
43
 
@@ -11,7 +11,7 @@ const MemberPaymentEvent = ghostBookshelf.Model.extend({
11
11
  customQuery(qb, options) {
12
12
  if (options.aggregatePaymentVolume) {
13
13
  if (options.limit || options.filter) {
14
- throw new errors.IncorrectUsageError('aggregatePaymentVolume does not work when passed a filter or limit');
14
+ throw new errors.IncorrectUsageError({message: 'aggregatePaymentVolume does not work when passed a filter or limit'});
15
15
  }
16
16
  const knex = ghostBookshelf.knex;
17
17
  return qb.clear('select')
@@ -33,11 +33,11 @@ const MemberPaymentEvent = ghostBookshelf.Model.extend({
33
33
  return options;
34
34
  },
35
35
  async edit() {
36
- throw new errors.IncorrectUsageError('Cannot edit MemberPaymentEvent');
36
+ throw new errors.IncorrectUsageError({message: 'Cannot edit MemberPaymentEvent'});
37
37
  },
38
38
 
39
39
  async destroy() {
40
- throw new errors.IncorrectUsageError('Cannot destroy MemberPaymentEvent');
40
+ throw new errors.IncorrectUsageError({message: 'Cannot destroy MemberPaymentEvent'});
41
41
  }
42
42
  });
43
43
 
@@ -19,15 +19,15 @@ const MemberProductEvent = ghostBookshelf.Model.extend({
19
19
 
20
20
  }, {
21
21
  async edit() {
22
- throw new errors.IncorrectUsageError(
23
- tpl(messages.cannotPerformAction, 'edit')
24
- );
22
+ throw new errors.IncorrectUsageError({
23
+ message: tpl(messages.cannotPerformAction, 'edit')
24
+ });
25
25
  },
26
26
 
27
27
  async destroy() {
28
- throw new errors.IncorrectUsageError(
29
- tpl(messages.cannotPerformAction, 'destroy')
30
- );
28
+ throw new errors.IncorrectUsageError({
29
+ message: tpl(messages.cannotPerformAction, 'destroy')
30
+ });
31
31
  }
32
32
  });
33
33
 
@@ -11,7 +11,9 @@ const MemberStatusEvent = ghostBookshelf.Model.extend({
11
11
  customQuery(qb, options) {
12
12
  if (options.aggregateStatusCounts) {
13
13
  if (options.limit || options.filter) {
14
- throw new errors.IncorrectUsageError('aggregateStatusCounts does not work when passed a filter or limit');
14
+ throw new errors.IncorrectUsageError({
15
+ message: 'aggregateStatusCounts does not work when passed a filter or limit'
16
+ });
15
17
  }
16
18
  const knex = ghostBookshelf.knex;
17
19
  return qb.clear('select')
@@ -46,11 +48,11 @@ const MemberStatusEvent = ghostBookshelf.Model.extend({
46
48
  return options;
47
49
  },
48
50
  async edit() {
49
- throw new errors.IncorrectUsageError('Cannot edit MemberStatusEvent');
51
+ throw new errors.IncorrectUsageError({message: 'Cannot edit MemberStatusEvent'});
50
52
  },
51
53
 
52
54
  async destroy() {
53
- throw new errors.IncorrectUsageError('Cannot destroy MemberStatusEvent');
55
+ throw new errors.IncorrectUsageError({message: 'Cannot destroy MemberStatusEvent'});
54
56
  }
55
57
  });
56
58
 
@@ -11,7 +11,9 @@ const MemberSubscribeEvent = ghostBookshelf.Model.extend({
11
11
  customQuery(qb, options) {
12
12
  if (options.aggregateSubscriptionDeltas) {
13
13
  if (options.limit || options.filter) {
14
- throw new errors.IncorrectUsageError('aggregateSubscriptionDeltas does not work when passed a filter or limit');
14
+ throw new errors.IncorrectUsageError({
15
+ message: 'aggregateSubscriptionDeltas does not work when passed a filter or limit'
16
+ });
15
17
  }
16
18
  const knex = ghostBookshelf.knex;
17
19
  return qb.clear('select')
@@ -32,11 +34,15 @@ const MemberSubscribeEvent = ghostBookshelf.Model.extend({
32
34
  return options;
33
35
  },
34
36
  async edit() {
35
- throw new errors.IncorrectUsageError('Cannot edit MemberSubscribeEvent');
37
+ throw new errors.IncorrectUsageError({
38
+ message: 'Cannot edit MemberSubscribeEvent'
39
+ });
36
40
  },
37
41
 
38
42
  async destroy() {
39
- throw new errors.IncorrectUsageError('Cannot destroy MemberSubscribeEvent');
43
+ throw new errors.IncorrectUsageError({
44
+ message: 'Cannot destroy MemberSubscribeEvent'
45
+ });
40
46
  }
41
47
  });
42
48
 
@@ -324,7 +324,7 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
324
324
  .then(() => response);
325
325
  })
326
326
  .catch((err) => {
327
- throw new errors.GhostError({err: err});
327
+ throw new errors.InternalServerError({err: err});
328
328
  });
329
329
  });
330
330
 
@@ -346,7 +346,7 @@ Settings = ghostBookshelf.Model.extend({
346
346
  );
347
347
 
348
348
  if (validationErrors.length) {
349
- throw new errors.ValidationError(validationErrors.join('\n'));
349
+ throw new errors.ValidationError({message: validationErrors.join('\n')});
350
350
  }
351
351
  },
352
352
  async labs(model) {
@@ -8,7 +8,6 @@
8
8
 
9
9
  // Required Ghost internals
10
10
  const config = require('../shared/config');
11
- const logging = require('@tryghost/logging');
12
11
 
13
12
  let notified = {
14
13
  started: false,
@@ -53,7 +52,7 @@ async function notify(type, error = null) {
53
52
  let socketAddress = config.get('bootstrap-socket');
54
53
  if (socketAddress) {
55
54
  const bootstrapSocket = require('@tryghost/bootstrap-socket');
56
- return bootstrapSocket.connectAndSend(socketAddress, logging, message);
55
+ return bootstrapSocket.connectAndSend(socketAddress, message);
57
56
  }
58
57
 
59
58
  return Promise.resolve();
@@ -148,7 +148,7 @@ function doReset(options, tokenParts, settingsAPI) {
148
148
  return Promise.reject(err);
149
149
  })
150
150
  .catch((err) => {
151
- if (errors.utils.isIgnitionError(err)) {
151
+ if (errors.utils.isGhostError(err)) {
152
152
  return Promise.reject(err);
153
153
  }
154
154
  return Promise.reject(new errors.UnauthorizedError({err: err}));
@@ -59,7 +59,7 @@ async function setupUser(userData) {
59
59
  const owner = await models.User.findOne({role: 'Owner', status: 'all'});
60
60
 
61
61
  if (!owner) {
62
- throw new errors.GhostError({
62
+ throw new errors.InternalServerError({
63
63
  message: tpl(messages.setupUnableToRun)
64
64
  });
65
65
  }
@@ -12,7 +12,7 @@ module.exports = {
12
12
  !hasScheduled &&
13
13
  config.get('emailAnalytics') &&
14
14
  config.get('backgroundJobs:emailAnalytics') &&
15
- !process.env.NODE_ENV.match(/^testing/)
15
+ !process.env.NODE_ENV.startsWith('test')
16
16
  ) {
17
17
  // Don't register email analytics job if we have no emails,
18
18
  // processor usage from many sites spinning up threads can be high.
@@ -131,7 +131,7 @@ const transformEmailRecipientFilter = (emailRecipientFilter, {errorProperty = 'e
131
131
  // `paid` and `free` were swapped out for NQL filters in 4.5.0, we shouldn't see them here now
132
132
  case 'paid':
133
133
  case 'free':
134
- throw new errors.GhostError({
134
+ throw new errors.InternalServerError({
135
135
  message: tpl(messages.unexpectedFilterError, {
136
136
  property: errorProperty,
137
137
  value: emailRecipientFilter
@@ -140,7 +140,7 @@ const transformEmailRecipientFilter = (emailRecipientFilter, {errorProperty = 'e
140
140
  case 'all':
141
141
  return 'subscribed:true';
142
142
  case 'none':
143
- throw new errors.GhostError({
143
+ throw new errors.InternalServerError({
144
144
  message: tpl(messages.noneFilterError, {
145
145
  property: errorProperty
146
146
  })
@@ -352,7 +352,7 @@ async function sendEmailJob({emailModel, options}) {
352
352
  error: errorMessage
353
353
  }, {patch: true});
354
354
 
355
- throw new errors.GhostError({
355
+ throw new errors.InternalServerError({
356
356
  err: error,
357
357
  context: tpl(messages.sendEmailRequestFailed)
358
358
  });
@@ -416,7 +416,9 @@ function partitionMembersBySegment(memberRows, segments) {
416
416
  segmentedMemberRows = memberRows.filter(member => member.status !== 'free');
417
417
  memberRows = memberRows.filter(member => member.status === 'free');
418
418
  } else {
419
- throw new errors.ValidationError(tpl(messages.invalidSegment));
419
+ throw new errors.ValidationError({
420
+ message: tpl(messages.invalidSegment)
421
+ });
420
422
  }
421
423
 
422
424
  partitions[memberSegment] = segmentedMemberRows;