ghost 4.18.0 → 4.20.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.
- package/.eslintrc.js +9 -8
- package/Gruntfile.js +1 -1
- package/PRIVACY.md +3 -0
- package/content/adapters/README.md +2 -2
- package/core/boot.js +17 -12
- package/core/bridge.js +9 -1
- package/core/built/assets/{chunk.3.b80d3e1e6b8556aaff3c.js → chunk.3.777d43e2ce954ba8b2f5.js} +25 -25
- package/core/built/assets/codemirror/{codemirror-21a09582262987037db73b152fb35f7c.js → codemirror-d25c379b87ec8b33d54ac7149bc0b6ae.js} +14 -14
- package/core/built/assets/ghost-dark-20e2892d4f30d0d1183c9ac725ea37d0.css +1 -0
- package/core/built/assets/{ghost.min-88d647a008a5b1dd678a89ae1e55c038.js → ghost.min-26e427944e719b616b8dc7fbb3bbd2f9.js} +709 -422
- package/core/built/assets/ghost.min-57e46fd3b1145ecf2cbd185a13611f3b.css +1 -0
- package/core/built/assets/icons/arrow-left-small.svg +0 -4
- package/core/built/assets/icons/paintbrush.svg +10 -1
- package/core/built/assets/icons/post.svg +3 -1
- package/core/built/assets/img/footer-marketplace-bg-572b6c6486a7e26316954d599eaa9f30.png +0 -0
- package/core/built/assets/img/marketing/offers-1-f2e1b653c4d5bb90eea9d7a2862530f9.jpg +0 -0
- package/core/built/assets/img/marketing/offers-2-28a225d34cc39d133748431536961d00.jpg +0 -0
- package/core/built/assets/img/marketing/offers-3-2094c91ab21a16c37fbe6ec16c140160.jpg +0 -0
- package/core/built/assets/img/themes/Alto-f4db5af43ca9771c7ac1f754de3ddf2f.png +0 -0
- package/core/built/assets/img/themes/Bulletin-57d45b992ff0e26e0acdce7ed4cccd67.png +0 -0
- package/core/built/assets/img/themes/Casper-c7e784d7188cc5d7f097d9b6c97b0263.jpg +0 -0
- package/core/built/assets/img/themes/Dawn-be81aa8c8caae8fcfb5d5fbec823fdcc.png +0 -0
- package/core/built/assets/img/themes/Digest-d3467ac22a290e1ad3a543014758286e.png +0 -0
- package/core/built/assets/img/themes/Dope-6f8e0bbc199ce4af9a60859e9e6a74ad.png +0 -0
- package/core/built/assets/img/themes/Ease-9c279ea6cec3c0f1823f81c9dd24b116.png +0 -0
- package/core/built/assets/img/themes/Edge-0258906309e11fd075a1d9880aa09b20.png +0 -0
- package/core/built/assets/img/themes/Edition-d8f508e93bc24bdf2716ae6f8b3d44f8.png +0 -0
- package/core/built/assets/img/themes/Editorial-a25a4a34c04dedd858bd5e05ef388b1c.jpg +0 -0
- package/core/built/assets/img/themes/Journal-accf0031bbae0919900a049061e65a04.png +0 -0
- package/core/built/assets/img/themes/London-3f07efcee9e5bfb9a33827064eb77e70.jpg +0 -0
- package/core/built/assets/img/themes/Massively-06edf00108429f7fb8e65f190fba34fe.jpg +0 -0
- package/core/built/assets/img/themes/Ruby-11a53c62015612f4b3aca8f503121225.png +0 -0
- package/core/built/assets/img/themes/Wave-86e8044c2d76cb57a9030e4c24ac9520.png +0 -0
- package/core/built/assets/simplemde/{simplemde-232f69d126310434489071a1891e6d8b.js → simplemde-3ffc0ec9e9fecf29b9a499db678c9e65.js} +14 -14
- package/core/built/assets/{vendor.min-7dc7cf9c92175ebfb9cea95c120ee8a7.js → vendor.min-af502ac4142871500fc424f6a5a254ec.js} +2206 -1859
- package/core/frontend/apps/amp/lib/router.js +1 -1
- package/core/frontend/helpers/match.js +17 -23
- package/core/frontend/meta/author-url.js +1 -1
- package/core/frontend/meta/url.js +1 -1
- package/core/{server → frontend}/public/favicon.ico +0 -0
- package/core/{server → frontend}/public/ghost.css +0 -0
- package/core/{server → frontend}/public/ghost.min.css +0 -0
- package/core/{server → frontend}/public/robots.txt +0 -0
- package/core/{server → frontend}/public/sitemap.xsl +0 -0
- package/core/frontend/services/proxy.js +1 -1
- package/core/frontend/services/rendering.js +1 -1
- package/core/frontend/services/routing/CollectionRouter.js +3 -49
- package/core/frontend/services/routing/ParentRouter.js +1 -4
- package/core/frontend/services/routing/StaticPagesRouter.js +3 -5
- package/core/frontend/services/routing/StaticRoutesRouter.js +4 -6
- package/core/frontend/services/routing/TaxonomyRouter.js +4 -5
- package/core/frontend/services/routing/controllers/collection.js +2 -2
- package/core/frontend/services/routing/controllers/email-post.js +2 -2
- package/core/frontend/services/routing/controllers/entry.js +2 -2
- package/core/frontend/services/routing/controllers/preview.js +2 -2
- package/core/frontend/services/routing/index.js +6 -12
- package/core/frontend/services/routing/registry.js +13 -0
- package/core/frontend/services/routing/router-manager.js +185 -0
- package/core/frontend/services/rss/generate-feed.js +2 -2
- package/core/frontend/services/theme-engine/i18n/i18n.js +267 -28
- package/core/frontend/services/theme-engine/i18n/index.js +1 -1
- package/core/frontend/services/theme-engine/i18n/theme-i18n.js +73 -0
- package/core/frontend/web/index.js +1 -0
- package/core/{server/web/site → frontend/web}/middleware/handle-image-sizes.js +4 -4
- package/core/{server/web/site → frontend/web}/middleware/index.js +0 -0
- package/core/{server/web/site → frontend/web}/middleware/redirect-ghost-to-admin.js +3 -3
- package/core/{server/web/site → frontend/web}/middleware/serve-favicon.js +6 -6
- package/core/{server/web/site → frontend/web}/middleware/serve-public-file.js +2 -2
- package/core/{server/web/site → frontend/web}/middleware/static-theme.js +3 -3
- package/core/frontend/web/routes.js +13 -0
- package/core/{server/web/site/app.js → frontend/web/site.js} +12 -16
- package/core/server/adapters/storage/LocalFileStorage.js +35 -39
- package/core/server/adapters/storage/index.js +12 -2
- package/core/server/api/canary/custom-theme-settings.js +2 -2
- package/core/server/api/canary/images.js +1 -1
- package/core/server/api/canary/oembed.js +2 -2
- package/core/server/api/canary/offers.js +29 -1
- package/core/server/api/canary/posts-public.js +6 -2
- package/core/server/api/canary/products.js +6 -2
- package/core/server/api/canary/tags-public.js +6 -2
- package/core/server/api/canary/users.js +9 -4
- package/core/server/api/canary/utils/serializers/output/custom-theme-settings.js +2 -2
- package/core/server/api/canary/utils/serializers/output/notifications.js +1 -0
- package/core/server/api/canary/utils/serializers/output/settings.js +2 -3
- package/core/server/api/canary/utils/serializers/output/utils/url.js +1 -1
- package/core/server/api/canary/utils/validators/input/oembed.js +4 -1
- package/core/server/api/canary/utils/validators/input/passwordreset.js +8 -3
- package/core/server/api/canary/utils/validators/input/settings.js +5 -4
- package/core/server/api/canary/utils/validators/input/setup.js +6 -2
- package/core/server/api/canary/utils/validators/input/users.js +6 -2
- package/core/server/api/canary/utils/validators/input/webhooks.js +8 -3
- package/core/server/api/v2/images.js +1 -1
- package/core/server/api/v2/utils/serializers/output/authentication.js +9 -4
- package/core/server/api/v2/utils/serializers/output/notifications.js +1 -0
- package/core/server/api/v2/utils/serializers/output/users.js +5 -3
- package/core/server/api/v2/utils/serializers/output/utils/url.js +1 -1
- package/core/server/api/v2/utils/validators/input/images.js +11 -6
- package/core/server/api/v2/utils/validators/input/invitations.js +14 -6
- package/core/server/api/v2/utils/validators/input/invites.js +6 -2
- package/core/server/api/v2/utils/validators/input/oembed.js +6 -2
- package/core/server/api/v2/utils/validators/input/passwordreset.js +8 -3
- package/core/server/api/v2/utils/validators/input/settings.js +10 -4
- package/core/server/api/v2/utils/validators/input/setup.js +6 -2
- package/core/server/api/v2/utils/validators/input/users.js +5 -2
- package/core/server/api/v3/authentication.js +6 -2
- package/core/server/api/v3/authors-public.js +6 -2
- package/core/server/api/v3/email.js +9 -4
- package/core/server/api/v3/images.js +1 -1
- package/core/server/api/v3/integrations.js +7 -3
- package/core/server/api/v3/invites.js +6 -3
- package/core/server/api/v3/labels.js +10 -5
- package/core/server/api/v3/memberSigninUrls.js +5 -2
- package/core/server/api/v3/oembed.js +2 -2
- package/core/server/api/v3/pages-public.js +5 -2
- package/core/server/api/v3/pages.js +6 -3
- package/core/server/api/v3/posts-public.js +5 -3
- package/core/server/api/v3/posts.js +7 -3
- package/core/server/api/v3/preview.js +5 -3
- package/core/server/api/v3/session.js +7 -3
- package/core/server/api/v3/settings.js +8 -3
- package/core/server/api/v3/slugs.js +5 -4
- package/core/server/api/v3/utils/serializers/output/authentication.js +10 -4
- package/core/server/api/v3/utils/serializers/output/notifications.js +1 -0
- package/core/server/api/v3/utils/serializers/output/settings.js +2 -3
- package/core/server/api/v3/utils/serializers/output/users.js +6 -2
- package/core/server/api/v3/utils/serializers/output/utils/url.js +1 -1
- package/core/server/api/v3/utils/validators/input/images.js +12 -7
- package/core/server/api/v3/utils/validators/input/invitations.js +14 -6
- package/core/server/api/v3/utils/validators/input/invites.js +6 -2
- package/core/server/api/v3/utils/validators/input/oembed.js +6 -2
- package/core/server/api/v3/utils/validators/input/passwordreset.js +8 -3
- package/core/server/api/v3/utils/validators/input/settings.js +5 -4
- package/core/server/api/v3/utils/validators/input/setup.js +6 -2
- package/core/server/api/v3/utils/validators/input/users.js +6 -2
- package/core/server/api/v3/utils/validators/input/webhooks.js +8 -3
- package/core/server/data/exporter/table-lists.js +2 -1
- package/core/server/data/importer/handlers/image.js +1 -1
- package/core/server/data/importer/importers/image.js +1 -1
- package/core/server/data/migrations/init/1-create-tables.js +7 -8
- package/core/server/data/migrations/init/2-create-fixtures.js +8 -8
- package/core/server/data/migrations/versions/4.19/01-add-active-column-to-offers.js +7 -0
- package/core/server/data/migrations/versions/4.19/02-add-offer-redemptions-table.js +8 -0
- package/core/server/data/migrations/versions/4.20/01-remove-offer-redemptions-table.js +19 -0
- package/core/server/data/migrations/versions/4.20/02-remove-offers-table.js +30 -0
- package/core/server/data/migrations/versions/4.20/03-add-offers-table.js +21 -0
- package/core/server/data/migrations/versions/4.20/04-add-offer-redemptions-table.js +9 -0
- package/core/server/data/migrations/versions/4.20/05-remove-not-null-constraint-from-portal-title.js +41 -0
- package/core/server/data/schema/fixtures/utils.js +150 -143
- package/core/server/data/schema/schema.js +15 -3
- package/core/server/frontend/ghost.min.css +1 -0
- package/core/server/lib/image/blog-icon.js +10 -10
- package/core/server/lib/image/image-size.js +5 -5
- package/core/server/lib/image/image-utils.js +4 -4
- package/core/server/lib/image/index.js +1 -2
- package/core/server/lib/mobiledoc.js +3 -2
- package/core/server/models/action.js +7 -4
- package/core/server/models/base/plugins/overrides.js +19 -6
- package/core/server/models/custom-theme-setting.js +56 -1
- package/core/server/models/index.js +4 -45
- package/core/server/models/member.js +5 -0
- package/core/server/models/offer-redemption.js +10 -0
- package/core/server/models/user.js +2 -1
- package/core/server/overrides.js +6 -2
- package/core/server/run-update-check.js +0 -3
- package/core/server/services/adapter-manager/config.js +1 -0
- package/core/server/services/adapter-manager/index.js +9 -5
- package/core/server/services/adapter-manager/options-resolver.js +18 -0
- package/core/server/services/bulk-email/bulk-email-processor.js +6 -2
- package/core/server/services/bulk-email/mailgun.js +1 -1
- package/core/server/services/custom-theme-settings.js +10 -4
- package/core/server/services/invites/index.js +0 -2
- package/core/server/services/invites/invites.js +5 -5
- package/core/server/services/mail/GhostMailer.js +18 -10
- package/core/server/services/mega/mega.js +3 -3
- package/core/server/services/mega/post-email-serializer.js +2 -2
- package/core/server/services/members/api.js +3 -4
- package/core/server/services/members/emails/signin.js +1 -1
- package/core/server/services/members/emails/signup.js +1 -1
- package/core/server/services/members/emails/subscribe.js +1 -1
- package/core/server/services/members/middleware.js +10 -0
- package/core/server/services/members/service.js +2 -1
- package/core/server/services/notifications/index.js +1 -1
- package/core/server/services/notifications/notifications.js +40 -35
- package/core/server/services/oembed.js +4 -9
- package/core/server/services/offers/service.js +16 -6
- package/core/server/services/permissions/public.js +6 -2
- package/core/server/services/route-settings/route-settings.js +1 -1
- package/core/server/services/settings/index.js +3 -1
- package/core/server/services/settings/settings-bread-service.js +42 -20
- package/core/server/services/slack.js +1 -1
- package/core/server/services/themes/activate.js +2 -2
- package/core/server/services/themes/activation-bridge.js +6 -6
- package/core/server/services/themes/storage.js +1 -1
- package/core/{frontend → server}/services/url/Queue.js +0 -0
- package/core/{frontend → server}/services/url/Resource.js +0 -0
- package/core/{frontend → server}/services/url/Resources.js +2 -2
- package/core/{frontend → server}/services/url/UrlGenerator.js +14 -14
- package/core/{frontend → server}/services/url/UrlService.js +12 -15
- package/core/{frontend → server}/services/url/Urls.js +1 -1
- package/core/{frontend → server}/services/url/configs/canary.js +0 -0
- package/core/{frontend → server}/services/url/configs/v2.js +0 -0
- package/core/{frontend → server}/services/url/configs/v3.js +0 -0
- package/core/{frontend → server}/services/url/configs/v4.js +0 -0
- package/core/{frontend → server}/services/url/index.js +0 -0
- package/core/server/services/xmlrpc.js +1 -1
- package/core/server/update-check.js +3 -3
- package/core/server/web/admin/controller.js +11 -0
- package/core/server/web/admin/views/default-prod.html +4 -4
- package/core/server/web/admin/views/default.html +4 -4
- package/core/server/web/api/app.js +8 -9
- package/core/server/web/members/app.js +1 -0
- package/core/server/web/oauth/app.js +4 -2
- package/core/server/web/parent/backend.js +3 -3
- package/core/server/web/parent/frontend.js +2 -2
- package/core/server/web/shared/middlewares/api/spam-prevention.js +0 -2
- package/core/server/web/shared/middlewares/custom-redirects.js +0 -8
- package/core/server/web/shared/middlewares/maintenance.js +1 -1
- package/core/server/web/well-known.js +10 -10
- package/core/shared/config/defaults.json +2 -2
- package/core/shared/config/overrides.json +1 -1
- package/core/shared/express.js +10 -0
- package/core/shared/html-to-plaintext.js +2 -2
- package/core/shared/labs.js +14 -6
- package/loggingrc.js +10 -0
- package/package.json +60 -57
- package/yarn.lock +1317 -914
- package/core/built/assets/ghost-dark-13627f10941a7dbb2b12e1d41dc51c34.css +0 -1
- package/core/built/assets/ghost.min-d9cbfb4eb2db8915fcd2bf2416218616.css +0 -1
- package/core/built/assets/img/themes/London-68501c8ab797de7f2851cf9ea0a28e26.jpg +0 -0
- package/core/frontend/services/routing/bootstrap.js +0 -114
- package/core/server/public/404-ghost.png +0 -0
- package/core/server/public/404-ghost@2x.png +0 -0
- package/core/server/web/site/index.js +0 -1
- package/core/server/web/site/routes.js +0 -9
- package/core/shared/i18n/i18n.js +0 -312
- package/core/shared/i18n/index.js +0 -6
- package/core/shared/i18n/translations/en.json +0 -675
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
const Promise = require('bluebird');
|
|
2
|
-
const
|
|
2
|
+
const tpl = require('@tryghost/tpl');
|
|
3
3
|
const errors = require('@tryghost/errors');
|
|
4
4
|
const models = require('../../models');
|
|
5
5
|
const auth = require('../../services/auth');
|
|
6
6
|
const api = require('./index');
|
|
7
7
|
|
|
8
|
+
const messages = {
|
|
9
|
+
accessDenied: 'Access denied.'
|
|
10
|
+
};
|
|
11
|
+
|
|
8
12
|
const session = {
|
|
9
13
|
read(frame) {
|
|
10
14
|
/*
|
|
@@ -20,7 +24,7 @@ const session = {
|
|
|
20
24
|
|
|
21
25
|
if (!object || !object.username || !object.password) {
|
|
22
26
|
return Promise.reject(new errors.UnauthorizedError({
|
|
23
|
-
message:
|
|
27
|
+
message: tpl(messages.accessDenied)
|
|
24
28
|
}));
|
|
25
29
|
}
|
|
26
30
|
|
|
@@ -40,7 +44,7 @@ const session = {
|
|
|
40
44
|
}).catch(async (err) => {
|
|
41
45
|
if (!errors.utils.isIgnitionError(err)) {
|
|
42
46
|
throw new errors.UnauthorizedError({
|
|
43
|
-
message:
|
|
47
|
+
message: tpl(messages.accessDenied),
|
|
44
48
|
err
|
|
45
49
|
});
|
|
46
50
|
}
|
|
@@ -2,11 +2,16 @@ const Promise = require('bluebird');
|
|
|
2
2
|
const _ = require('lodash');
|
|
3
3
|
const models = require('../../models');
|
|
4
4
|
const routeSettings = require('../../services/route-settings');
|
|
5
|
-
const
|
|
5
|
+
const tpl = require('@tryghost/tpl');
|
|
6
6
|
const {BadRequestError, NoPermissionError} = require('@tryghost/errors');
|
|
7
7
|
const settingsService = require('../../services/settings');
|
|
8
8
|
const membersService = require('../../services/members');
|
|
9
9
|
|
|
10
|
+
const messages = {
|
|
11
|
+
error: 'Failed to send email.',
|
|
12
|
+
accessCoreSettingFromExtReq: 'Attempted to access core setting from external request'
|
|
13
|
+
};
|
|
14
|
+
|
|
10
15
|
const settingsBREADService = settingsService.getSettingsBREADServiceInstance();
|
|
11
16
|
|
|
12
17
|
module.exports = {
|
|
@@ -109,7 +114,7 @@ module.exports = {
|
|
|
109
114
|
} catch (err) {
|
|
110
115
|
throw new BadRequestError({
|
|
111
116
|
err,
|
|
112
|
-
message:
|
|
117
|
+
message: tpl(messages.error)
|
|
113
118
|
});
|
|
114
119
|
}
|
|
115
120
|
}
|
|
@@ -162,7 +167,7 @@ module.exports = {
|
|
|
162
167
|
const firstCoreSetting = frame.data.settings.find(setting => setting.group === 'core');
|
|
163
168
|
if (firstCoreSetting) {
|
|
164
169
|
throw new NoPermissionError({
|
|
165
|
-
message:
|
|
170
|
+
message: tpl(messages.accessCoreSettingFromExtReq)
|
|
166
171
|
});
|
|
167
172
|
}
|
|
168
173
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const models = require('../../models');
|
|
2
|
-
const
|
|
2
|
+
const tpl = require('@tryghost/tpl');
|
|
3
3
|
const errors = require('@tryghost/errors');
|
|
4
4
|
|
|
5
|
+
const messages = {
|
|
6
|
+
couldNotGenerateSlug: 'Could not generate slug.'
|
|
7
|
+
};
|
|
5
8
|
const allowedTypes = {
|
|
6
9
|
post: models.Post,
|
|
7
10
|
tag: models.Tag,
|
|
@@ -36,9 +39,7 @@ module.exports = {
|
|
|
36
39
|
return models.Base.Model.generateSlug(allowedTypes[frame.options.type], frame.data.name, {status: 'all'})
|
|
37
40
|
.then((slug) => {
|
|
38
41
|
if (!slug) {
|
|
39
|
-
return Promise.reject(new errors.GhostError({
|
|
40
|
-
message: i18n.t('errors.api.slugs.couldNotGenerateSlug')
|
|
41
|
-
}));
|
|
42
|
+
return Promise.reject(new errors.GhostError({message: tpl(messages.couldNotGenerateSlug)}));
|
|
42
43
|
}
|
|
43
44
|
return slug;
|
|
44
45
|
});
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
const
|
|
1
|
+
const tpl = require('@tryghost/tpl');
|
|
2
2
|
const mapper = require('./utils/mapper');
|
|
3
3
|
const debug = require('@tryghost/debug')('api:v3:utils:serializers:output:authentication');
|
|
4
4
|
|
|
5
|
+
const messages = {
|
|
6
|
+
checkEmailForInstructions: 'Check your email for further instructions.',
|
|
7
|
+
passwordChanged: 'Password changed successfully.',
|
|
8
|
+
invitationAccepted: 'Invitation accepted.'
|
|
9
|
+
};
|
|
10
|
+
|
|
5
11
|
module.exports = {
|
|
6
12
|
setup(user, apiConfig, frame) {
|
|
7
13
|
frame.response = {
|
|
@@ -28,7 +34,7 @@ module.exports = {
|
|
|
28
34
|
generateResetToken(data, apiConfig, frame) {
|
|
29
35
|
frame.response = {
|
|
30
36
|
passwordreset: [{
|
|
31
|
-
message:
|
|
37
|
+
message: tpl(messages.checkEmailForInstructions)
|
|
32
38
|
}]
|
|
33
39
|
};
|
|
34
40
|
},
|
|
@@ -36,7 +42,7 @@ module.exports = {
|
|
|
36
42
|
resetPassword(data, apiConfig, frame) {
|
|
37
43
|
frame.response = {
|
|
38
44
|
passwordreset: [{
|
|
39
|
-
message:
|
|
45
|
+
message: tpl(messages.passwordChanged)
|
|
40
46
|
}]
|
|
41
47
|
};
|
|
42
48
|
},
|
|
@@ -46,7 +52,7 @@ module.exports = {
|
|
|
46
52
|
|
|
47
53
|
frame.response = {
|
|
48
54
|
invitation: [
|
|
49
|
-
{message:
|
|
55
|
+
{message: tpl(messages.invitationAccepted)}
|
|
50
56
|
]
|
|
51
57
|
};
|
|
52
58
|
},
|
|
@@ -55,9 +55,8 @@ module.exports = {
|
|
|
55
55
|
this.browse(...arguments);
|
|
56
56
|
},
|
|
57
57
|
|
|
58
|
-
edit(
|
|
59
|
-
|
|
60
|
-
this.browse(settingsKeyedJSON, apiConfig, frame);
|
|
58
|
+
edit() {
|
|
59
|
+
this.browse(...arguments);
|
|
61
60
|
},
|
|
62
61
|
|
|
63
62
|
download(bytes, apiConfig, frame) {
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
const debug = require('@tryghost/debug')('api:v3:utils:serializers:output:users');
|
|
2
|
-
const
|
|
2
|
+
const tpl = require('@tryghost/tpl');
|
|
3
3
|
const mapper = require('./utils/mapper');
|
|
4
4
|
|
|
5
|
+
const messages = {
|
|
6
|
+
pwdChangedSuccessfully: 'Password changed successfully.'
|
|
7
|
+
};
|
|
8
|
+
|
|
5
9
|
module.exports = {
|
|
6
10
|
browse(models, apiConfig, frame) {
|
|
7
11
|
debug('browse');
|
|
@@ -39,7 +43,7 @@ module.exports = {
|
|
|
39
43
|
debug('changePassword');
|
|
40
44
|
|
|
41
45
|
frame.response = {
|
|
42
|
-
password: [{message:
|
|
46
|
+
password: [{message: tpl(messages.pwdChangedSuccessfully)}]
|
|
43
47
|
};
|
|
44
48
|
},
|
|
45
49
|
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
const jsonSchema = require('../utils/json-schema');
|
|
2
2
|
const config = require('../../../../../../shared/config');
|
|
3
|
-
const
|
|
3
|
+
const tpl = require('@tryghost/tpl');
|
|
4
4
|
const errors = require('@tryghost/errors');
|
|
5
5
|
const {imageSize, blogIcon} = require('../../../../../lib/image');
|
|
6
6
|
|
|
7
|
+
const messages = {
|
|
8
|
+
isNotSquare: 'Please select a valid image file with square dimensions.',
|
|
9
|
+
invalidFile: 'Icon must be a square .ico or .png file between 60px – 1,000px, under 100kb.'
|
|
10
|
+
};
|
|
11
|
+
|
|
7
12
|
const profileImage = (frame) => {
|
|
8
13
|
return imageSize.getImageSizeFromPath(frame.file.path).then((response) => {
|
|
9
14
|
// save the image dimensions in new property for file
|
|
@@ -12,7 +17,7 @@ const profileImage = (frame) => {
|
|
|
12
17
|
// CASE: file needs to be a square
|
|
13
18
|
if (frame.file.dimensions.width !== frame.file.dimensions.height) {
|
|
14
19
|
return Promise.reject(new errors.ValidationError({
|
|
15
|
-
message:
|
|
20
|
+
message: tpl(messages.isNotSquare)
|
|
16
21
|
}));
|
|
17
22
|
}
|
|
18
23
|
});
|
|
@@ -28,7 +33,7 @@ const icon = (frame) => {
|
|
|
28
33
|
// CASE: file should not be larger than 100kb
|
|
29
34
|
if (!validIconFileSize(frame.file.size)) {
|
|
30
35
|
return Promise.reject(new errors.ValidationError({
|
|
31
|
-
message:
|
|
36
|
+
message: tpl(messages.invalidFile, {extensions: iconExtensions})
|
|
32
37
|
}));
|
|
33
38
|
}
|
|
34
39
|
|
|
@@ -39,7 +44,7 @@ const icon = (frame) => {
|
|
|
39
44
|
// CASE: file needs to be a square
|
|
40
45
|
if (frame.file.dimensions.width !== frame.file.dimensions.height) {
|
|
41
46
|
return Promise.reject(new errors.ValidationError({
|
|
42
|
-
message:
|
|
47
|
+
message: tpl(messages.invalidFile, {extensions: iconExtensions})
|
|
43
48
|
}));
|
|
44
49
|
}
|
|
45
50
|
|
|
@@ -47,14 +52,14 @@ const icon = (frame) => {
|
|
|
47
52
|
// .ico files can contain multiple sizes, we need at least a minimum of 60px (16px is ok, as long as 60px are present as well)
|
|
48
53
|
if (frame.file.dimensions.width < 60) {
|
|
49
54
|
return Promise.reject(new errors.ValidationError({
|
|
50
|
-
message:
|
|
55
|
+
message: tpl(messages.invalidFile, {extensions: iconExtensions})
|
|
51
56
|
}));
|
|
52
57
|
}
|
|
53
58
|
|
|
54
59
|
// CASE: icon needs to be smaller than or equal to 1000px
|
|
55
60
|
if (frame.file.dimensions.width > 1000) {
|
|
56
61
|
return Promise.reject(new errors.ValidationError({
|
|
57
|
-
message:
|
|
62
|
+
message: tpl(messages.invalidFile, {extensions: iconExtensions})
|
|
58
63
|
}));
|
|
59
64
|
}
|
|
60
65
|
});
|
|
@@ -77,4 +82,4 @@ module.exports = {
|
|
|
77
82
|
}
|
|
78
83
|
});
|
|
79
84
|
}
|
|
80
|
-
};
|
|
85
|
+
};
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
const Promise = require('bluebird');
|
|
2
2
|
const validator = require('@tryghost/validator');
|
|
3
3
|
const debug = require('@tryghost/debug')('api:v3:utils:validators:input:invitation');
|
|
4
|
-
const
|
|
4
|
+
const tpl = require('@tryghost/tpl');
|
|
5
5
|
const errors = require('@tryghost/errors');
|
|
6
6
|
|
|
7
|
+
const messages = {
|
|
8
|
+
noTokenProvided: 'No token provided.',
|
|
9
|
+
noEmailProvided: 'No email provided.',
|
|
10
|
+
noPasswordProvided: 'No password provided.',
|
|
11
|
+
noNameProvided: 'No name provided.',
|
|
12
|
+
invalidEmailReceived: 'The server did not receive a valid email'
|
|
13
|
+
};
|
|
14
|
+
|
|
7
15
|
module.exports = {
|
|
8
16
|
acceptInvitation(apiConfig, frame) {
|
|
9
17
|
debug('acceptInvitation');
|
|
@@ -11,19 +19,19 @@ module.exports = {
|
|
|
11
19
|
const data = frame.data.invitation[0];
|
|
12
20
|
|
|
13
21
|
if (!data.token) {
|
|
14
|
-
return Promise.reject(new errors.ValidationError({message:
|
|
22
|
+
return Promise.reject(new errors.ValidationError({message: tpl(messages.noTokenProvided)}));
|
|
15
23
|
}
|
|
16
24
|
|
|
17
25
|
if (!data.email) {
|
|
18
|
-
return Promise.reject(new errors.ValidationError({message:
|
|
26
|
+
return Promise.reject(new errors.ValidationError({message: tpl(messages.noEmailProvided)}));
|
|
19
27
|
}
|
|
20
28
|
|
|
21
29
|
if (!data.password) {
|
|
22
|
-
return Promise.reject(new errors.ValidationError({message:
|
|
30
|
+
return Promise.reject(new errors.ValidationError({message: tpl(messages.noPasswordProvided)}));
|
|
23
31
|
}
|
|
24
32
|
|
|
25
33
|
if (!data.name) {
|
|
26
|
-
return Promise.reject(new errors.ValidationError({message:
|
|
34
|
+
return Promise.reject(new errors.ValidationError({message: tpl(messages.noNameProvided)}));
|
|
27
35
|
}
|
|
28
36
|
},
|
|
29
37
|
|
|
@@ -34,7 +42,7 @@ module.exports = {
|
|
|
34
42
|
|
|
35
43
|
if (typeof email !== 'string' || !validator.isEmail(email)) {
|
|
36
44
|
throw new errors.BadRequestError({
|
|
37
|
-
message:
|
|
45
|
+
message: tpl(messages.invalidEmailReceived)
|
|
38
46
|
});
|
|
39
47
|
}
|
|
40
48
|
}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
const Promise = require('bluebird');
|
|
2
|
-
const
|
|
2
|
+
const tpl = require('@tryghost/tpl');
|
|
3
3
|
const errors = require('@tryghost/errors');
|
|
4
4
|
const models = require('../../../../../models');
|
|
5
5
|
|
|
6
|
+
const messages = {
|
|
7
|
+
userAlreadyRegistered: 'User is already registered.'
|
|
8
|
+
};
|
|
9
|
+
|
|
6
10
|
module.exports = {
|
|
7
11
|
add(apiConfig, frame) {
|
|
8
12
|
return models.User.findOne({email: frame.data.invites[0].email}, frame.options)
|
|
9
13
|
.then((user) => {
|
|
10
14
|
if (user) {
|
|
11
15
|
return Promise.reject(new errors.ValidationError({
|
|
12
|
-
message:
|
|
16
|
+
message: tpl(messages.userAlreadyRegistered)
|
|
13
17
|
}));
|
|
14
18
|
}
|
|
15
19
|
});
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
const Promise = require('bluebird');
|
|
2
|
-
const
|
|
2
|
+
const tpl = require('@tryghost/tpl');
|
|
3
3
|
const errors = require('@tryghost/errors');
|
|
4
4
|
|
|
5
|
+
const messages = {
|
|
6
|
+
noUrlProvided: 'No url provided.'
|
|
7
|
+
};
|
|
8
|
+
|
|
5
9
|
module.exports = {
|
|
6
10
|
read(apiConfig, frame) {
|
|
7
11
|
if (!frame.data.url || !frame.data.url.trim()) {
|
|
8
12
|
return Promise.reject(new errors.BadRequestError({
|
|
9
|
-
message:
|
|
13
|
+
message: tpl(messages.noUrlProvided)
|
|
10
14
|
}));
|
|
11
15
|
}
|
|
12
16
|
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
const Promise = require('bluebird');
|
|
2
2
|
const validator = require('@tryghost/validator');
|
|
3
3
|
const debug = require('@tryghost/debug')('api:v3:utils:validators:input:passwordreset');
|
|
4
|
-
const
|
|
4
|
+
const tpl = require('@tryghost/tpl');
|
|
5
5
|
const errors = require('@tryghost/errors');
|
|
6
6
|
|
|
7
|
+
const messages = {
|
|
8
|
+
newPasswordsDoNotMatch: 'Your new passwords do not match',
|
|
9
|
+
invalidEmailReceived: 'The server did not receive a valid email'
|
|
10
|
+
};
|
|
11
|
+
|
|
7
12
|
module.exports = {
|
|
8
13
|
resetPassword(apiConfig, frame) {
|
|
9
14
|
debug('resetPassword');
|
|
@@ -12,7 +17,7 @@ module.exports = {
|
|
|
12
17
|
|
|
13
18
|
if (data.newPassword !== data.ne2Password) {
|
|
14
19
|
return Promise.reject(new errors.ValidationError({
|
|
15
|
-
message:
|
|
20
|
+
message: tpl(messages.newPasswordsDoNotMatch)
|
|
16
21
|
}));
|
|
17
22
|
}
|
|
18
23
|
},
|
|
@@ -24,7 +29,7 @@ module.exports = {
|
|
|
24
29
|
|
|
25
30
|
if (typeof email !== 'string' || !validator.isEmail(email)) {
|
|
26
31
|
throw new errors.BadRequestError({
|
|
27
|
-
message:
|
|
32
|
+
message: tpl(messages.invalidEmailReceived)
|
|
28
33
|
});
|
|
29
34
|
}
|
|
30
35
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
const Promise = require('bluebird');
|
|
2
2
|
const _ = require('lodash');
|
|
3
|
-
const
|
|
3
|
+
const tpl = require('@tryghost/tpl');
|
|
4
4
|
const {NotFoundError, ValidationError, BadRequestError} = require('@tryghost/errors');
|
|
5
5
|
const validator = require('@tryghost/validator');
|
|
6
6
|
|
|
7
7
|
const messages = {
|
|
8
8
|
invalidEmailReceived: 'Please send a valid email',
|
|
9
|
-
invalidEmailTypeReceived: 'Invalid email type received'
|
|
9
|
+
invalidEmailTypeReceived: 'Invalid email type received',
|
|
10
|
+
problemFindingSetting: 'Problem finding setting: {key}'
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
module.exports = {
|
|
@@ -14,7 +15,7 @@ module.exports = {
|
|
|
14
15
|
// @NOTE: was removed https://github.com/TryGhost/Ghost/issues/10373
|
|
15
16
|
if (frame.options.key === 'ghost_head' || frame.options.key === 'ghost_foot') {
|
|
16
17
|
return Promise.reject(new NotFoundError({
|
|
17
|
-
message:
|
|
18
|
+
message: tpl(messages.problemFindingSetting, {
|
|
18
19
|
key: frame.options.key
|
|
19
20
|
})
|
|
20
21
|
}));
|
|
@@ -28,7 +29,7 @@ module.exports = {
|
|
|
28
29
|
if (setting.key === 'ghost_head' || setting.key === 'ghost_foot') {
|
|
29
30
|
// @NOTE: was removed https://github.com/TryGhost/Ghost/issues/10373
|
|
30
31
|
errors.push(new NotFoundError({
|
|
31
|
-
message:
|
|
32
|
+
message: tpl(messages.problemFindingSetting, {
|
|
32
33
|
key: setting.key
|
|
33
34
|
})
|
|
34
35
|
}));
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
const debug = require('@tryghost/debug')('api:v3:utils:validators:input:updateSetup');
|
|
2
|
-
const
|
|
2
|
+
const tpl = require('@tryghost/tpl');
|
|
3
3
|
const errors = require('@tryghost/errors');
|
|
4
4
|
|
|
5
|
+
const messages = {
|
|
6
|
+
notTheBlogOwner: 'You are not the site owner.'
|
|
7
|
+
};
|
|
8
|
+
|
|
5
9
|
module.exports = {
|
|
6
10
|
updateSetup(apiConfig, frame) {
|
|
7
11
|
debug('resetPassword');
|
|
8
12
|
|
|
9
13
|
if (!frame.options.context || !frame.options.context.user) {
|
|
10
|
-
throw new errors.NoPermissionError({message:
|
|
14
|
+
throw new errors.NoPermissionError({message: tpl(messages.notTheBlogOwner)});
|
|
11
15
|
}
|
|
12
16
|
}
|
|
13
17
|
};
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
const Promise = require('bluebird');
|
|
2
2
|
const debug = require('@tryghost/debug')('api:v3:utils:validators:input:users');
|
|
3
|
-
const
|
|
3
|
+
const tpl = require('@tryghost/tpl');
|
|
4
4
|
const errors = require('@tryghost/errors');
|
|
5
5
|
|
|
6
|
+
const messages = {
|
|
7
|
+
newPasswordsDoNotMatch: 'Your new passwords do not match'
|
|
8
|
+
};
|
|
9
|
+
|
|
6
10
|
module.exports = {
|
|
7
11
|
changePassword(apiConfig, frame) {
|
|
8
12
|
debug('changePassword');
|
|
@@ -11,7 +15,7 @@ module.exports = {
|
|
|
11
15
|
|
|
12
16
|
if (data.newPassword !== data.ne2Password) {
|
|
13
17
|
return Promise.reject(new errors.ValidationError({
|
|
14
|
-
message:
|
|
18
|
+
message: tpl(messages.newPasswordsDoNotMatch)
|
|
15
19
|
}));
|
|
16
20
|
}
|
|
17
21
|
}
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
2
|
const errors = require('@tryghost/errors');
|
|
3
|
-
const
|
|
3
|
+
const tpl = require('@tryghost/tpl');
|
|
4
4
|
const jsonSchema = require('../utils/json-schema');
|
|
5
5
|
|
|
6
|
+
const messages = {
|
|
7
|
+
schemaValidationFailed: 'Validation failed for \'{key}\'.',
|
|
8
|
+
noIntegrationIdProvidedContext: 'You may only create webhooks with \'integration_id\' when using session authentication.'
|
|
9
|
+
};
|
|
10
|
+
|
|
6
11
|
module.exports = {
|
|
7
12
|
add(apiConfig, frame) {
|
|
8
13
|
if (!_.get(frame, 'options.context.integration.id') && !_.get(frame.data, 'webhooks[0].integration_id')) {
|
|
9
14
|
return Promise.reject(new errors.ValidationError({
|
|
10
|
-
message:
|
|
15
|
+
message: tpl(messages.schemaValidationFailed, {
|
|
11
16
|
key: 'integration_id'
|
|
12
17
|
}),
|
|
13
|
-
context:
|
|
18
|
+
context: tpl(messages.noIntegrationIdProvidedContext),
|
|
14
19
|
property: 'integration_id'
|
|
15
20
|
}));
|
|
16
21
|
}
|
|
@@ -37,7 +37,8 @@ const BACKUP_TABLES = [
|
|
|
37
37
|
'members_paid_subscription_events',
|
|
38
38
|
'members_subscribe_events',
|
|
39
39
|
'members_product_events',
|
|
40
|
-
'offers'
|
|
40
|
+
'offers',
|
|
41
|
+
'offer_redemptions'
|
|
41
42
|
];
|
|
42
43
|
|
|
43
44
|
// NOTE: exposing only tables which are going to be included in a "default" export file
|
|
@@ -13,7 +13,7 @@ ImageHandler = {
|
|
|
13
13
|
directories: ['images', 'content'],
|
|
14
14
|
|
|
15
15
|
loadFile: function (files, baseDir) {
|
|
16
|
-
const store = storage.getStorage();
|
|
16
|
+
const store = storage.getStorage('images');
|
|
17
17
|
const baseDirRegex = baseDir ? new RegExp('^' + baseDir + '/') : new RegExp('');
|
|
18
18
|
|
|
19
19
|
const imageFolderRegexes = _.map(urlUtils.STATIC_IMAGE_URL_PREFIX.split('/'), function (dir) {
|
|
@@ -64,7 +64,7 @@ ImageImporter = {
|
|
|
64
64
|
return importData;
|
|
65
65
|
},
|
|
66
66
|
doImport: function (imageData) {
|
|
67
|
-
const store = storage.getStorage();
|
|
67
|
+
const store = storage.getStorage('images');
|
|
68
68
|
|
|
69
69
|
return Promise.map(imageData, function (image) {
|
|
70
70
|
return store.save(image, image.targetDir).then(function (result) {
|
|
@@ -4,27 +4,26 @@ const schema = require('../../schema').tables;
|
|
|
4
4
|
const logging = require('@tryghost/logging');
|
|
5
5
|
const schemaTables = Object.keys(schema);
|
|
6
6
|
|
|
7
|
-
module.exports.up =
|
|
7
|
+
module.exports.up = async (options) => {
|
|
8
8
|
const connection = options.connection;
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
await Promise.mapSeries(schemaTables, async (table) => {
|
|
11
11
|
logging.info('Creating table: ' + table);
|
|
12
|
-
|
|
12
|
+
await commands.createTable(table, connection);
|
|
13
13
|
});
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
17
|
@TODO: This works, but is very dangerous in the current state of the knex-migrator v3.
|
|
19
|
-
@TODO:
|
|
20
|
-
module.exports.down =
|
|
18
|
+
@TODO: Decide if we should enable or delete this
|
|
19
|
+
module.exports.down = async (options) => {
|
|
21
20
|
var connection = options.connection;
|
|
22
21
|
|
|
23
22
|
// Reference between tables!
|
|
24
23
|
schemaTables.reverse();
|
|
25
|
-
|
|
24
|
+
await Promise.mapSeries(schemaTables, async (table) => {
|
|
26
25
|
logging.info('Drop table: ' + table);
|
|
27
|
-
|
|
26
|
+
await commands.deleteTable(table, connection);
|
|
28
27
|
});
|
|
29
28
|
};
|
|
30
29
|
*/
|
|
@@ -7,20 +7,20 @@ module.exports.config = {
|
|
|
7
7
|
transaction: true
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
module.exports.up =
|
|
10
|
+
module.exports.up = async (options) => {
|
|
11
11
|
const localOptions = _.merge({
|
|
12
12
|
context: {internal: true},
|
|
13
13
|
migrating: true
|
|
14
14
|
}, options);
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
await Promise.mapSeries(fixtures.models, async (model) => {
|
|
17
17
|
logging.info('Model: ' + model.name);
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
await fixtures.utils.addFixturesForModel(model, localOptions);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
await Promise.mapSeries(fixtures.relations, async (relation) => {
|
|
23
|
+
logging.info('Relation: ' + relation.from.model + ' to ' + relation.to.model);
|
|
24
|
+
await fixtures.utils.addFixturesForRelation(relation, localOptions);
|
|
25
25
|
});
|
|
26
26
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const {addTable} = require('../../utils');
|
|
2
|
+
|
|
3
|
+
module.exports = addTable('offer_redemptions', {
|
|
4
|
+
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
|
5
|
+
offer_id: {type: 'string', maxlength: 24, nullable: false, references: 'offers.id', cascadeDelete: true},
|
|
6
|
+
member_id: {type: 'string', maxlength: 24, nullable: false, references: 'members.id', cascadeDelete: true},
|
|
7
|
+
subscription_id: {type: 'string', maxlength: 24, nullable: false, references: 'members_stripe_customers_subscriptions.id', cascadeDelete: true}
|
|
8
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const utils = require('../../utils');
|
|
2
|
+
|
|
3
|
+
const migration = utils.addTable('offer_redemptions', {
|
|
4
|
+
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
|
5
|
+
offer_id: {type: 'string', maxlength: 24, nullable: false, references: 'offers.id', cascadeDelete: true},
|
|
6
|
+
member_id: {type: 'string', maxlength: 24, nullable: false, references: 'members.id', cascadeDelete: true},
|
|
7
|
+
subscription_id: {type: 'string', maxlength: 24, nullable: false, references: 'members_stripe_customers_subscriptions.id', cascadeDelete: true}
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
// This reverses an "addTable" migration so that we
|
|
11
|
+
// drop the table going forwards and re-add it going back
|
|
12
|
+
const up = migration.down;
|
|
13
|
+
const down = migration.up;
|
|
14
|
+
|
|
15
|
+
migration.up = up;
|
|
16
|
+
migration.down = down;
|
|
17
|
+
|
|
18
|
+
module.exports = migration;
|
|
19
|
+
|