ghost 4.34.3 → 4.35.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.
- package/README.md +1 -1
- package/core/built/assets/ghost-dark-cf32b34face01b83c9f3f30d650ba9a8.css +1 -0
- package/core/built/assets/ghost.min-73194305644461704a99cd2eb522637a.css +1 -0
- package/core/built/assets/{ghost.min-4886fb099a526cb6ca5b733bbfbb5d3a.js → ghost.min-f3a45466144e8273938175e32f788438.js} +1520 -1307
- package/core/built/assets/icons/get-started-members.svg +6 -0
- package/core/built/assets/icons/get-started-migrations.svg +6 -0
- package/core/built/assets/icons/get-started.svg +3 -0
- package/core/built/assets/{vendor.min-079fa61c64e24f0984f2cd7d2ebbf3c3.js → vendor.min-b36a93f4fb64127af926ceefa488b00e.js} +1304 -1260
- package/core/frontend/helpers/prev_post.js +1 -1
- package/core/frontend/helpers/products.js +2 -6
- package/core/frontend/helpers/tpl/content-cta.hbs +1 -1
- package/core/frontend/services/routing/controllers/email-post.js +1 -1
- package/core/frontend/services/routing/controllers/preview.js +1 -1
- package/core/frontend/services/routing/controllers/static.js +1 -1
- package/core/frontend/services/routing/helpers/entry-lookup.js +1 -1
- package/core/frontend/services/routing/helpers/fetch-data.js +1 -1
- package/core/frontend/views/unsubscribe.hbs +4 -2
- package/core/server/api/canary/email-post.js +1 -1
- package/core/server/api/canary/pages-public.js +1 -1
- package/core/server/api/canary/pages.js +1 -1
- package/core/server/api/canary/posts-public.js +1 -1
- package/core/server/api/canary/posts.js +1 -1
- package/core/server/api/canary/utils/serializers/input/pages.js +1 -9
- package/core/server/api/canary/utils/serializers/input/posts.js +1 -9
- package/core/server/api/canary/utils/serializers/output/email-posts.js +2 -2
- package/core/server/api/canary/utils/serializers/output/pages.js +9 -5
- package/core/server/api/canary/utils/serializers/output/posts.js +9 -5
- package/core/server/api/canary/utils/serializers/output/preview.js +3 -2
- package/core/server/api/canary/utils/serializers/output/products.js +2 -0
- package/core/server/api/canary/utils/serializers/output/utils/clean.js +0 -9
- package/core/server/api/canary/utils/serializers/output/utils/mapper.js +18 -3
- package/core/server/api/canary/utils/validators/input/pages.js +1 -1
- package/core/server/api/canary/utils/validators/input/posts.js +1 -1
- package/core/server/data/exporter/table-lists.js +1 -0
- package/core/server/data/migrations/versions/4.35/2022-01-20-05-55-add-post-products-table.js +8 -0
- package/core/server/data/migrations/versions/4.35/2022-01-30-15-17-set-welcome-page-url-from-settings.js +45 -0
- package/core/server/data/migrations/versions/4.35/2022-02-01-11-48-update-email-recipient-filter-column-type.js +18 -0
- package/core/server/data/migrations/versions/4.35/2022-02-01-12-03-update-recipient-filter-column-type.js +18 -0
- package/core/server/data/migrations/versions/4.35/2022-02-02-10-38-add-default-content-visibility-tiers-setting.js +8 -0
- package/core/server/data/migrations/versions/4.35/2022-02-02-13-10-transform-specific-tiers-default-content-visibility.js +147 -0
- package/core/server/data/migrations/versions/4.35/2022-02-04-04-34-populate-empty-portal-products.js +60 -0
- package/core/server/data/schema/default-settings.json +4 -0
- package/core/server/data/schema/schema.js +10 -4
- package/core/server/models/post.js +29 -5
- package/core/server/services/mega/template.js +1 -1
- package/core/server/services/members/content-gating.js +6 -1
- package/core/server/services/members/middleware.js +20 -3
- package/core/server/services/members/service.js +30 -4
- package/core/server/services/posts/posts-service.js +25 -1
- package/core/server/web/admin/views/default-prod.html +4 -4
- package/core/server/web/admin/views/default.html +4 -4
- package/core/shared/labs.js +1 -1
- package/package.json +33 -33
- package/yarn.lock +811 -799
- package/core/built/assets/ghost-dark-2de4c728f3d2deae25e45092ea0e811f.css +0 -1
- package/core/built/assets/ghost.min-b1d3e45166f2023dd56b35f720636979.css +0 -1
|
@@ -27,7 +27,7 @@ const buildApiOptions = function buildApiOptions(options, post) {
|
|
|
27
27
|
/**
|
|
28
28
|
* @deprecated: single authors was superceded by multiple authors in Ghost 1.22.0
|
|
29
29
|
*/
|
|
30
|
-
include: 'author,authors,tags',
|
|
30
|
+
include: 'author,authors,tags,tiers',
|
|
31
31
|
order: 'published_at ' + order,
|
|
32
32
|
limit: 1,
|
|
33
33
|
// This line deliberately uses double quotes because GQL cannot handle either double quotes
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
const {labs} = require('../services/proxy');
|
|
7
7
|
const {SafeString} = require('../services/rendering');
|
|
8
8
|
|
|
9
|
-
const nql = require('@nexes/nql');
|
|
10
9
|
const isString = require('lodash/isString');
|
|
11
10
|
|
|
12
11
|
function products(options = {}) {
|
|
@@ -29,11 +28,8 @@ function products(options = {}) {
|
|
|
29
28
|
accessProductsList = productsList;
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
if (this.visibility === '
|
|
33
|
-
|
|
34
|
-
accessProductsList = productsList.filter((product) => {
|
|
35
|
-
return nqlFilter.queryJSON({product: product.slug});
|
|
36
|
-
});
|
|
31
|
+
if (this.visibility === 'tiers') {
|
|
32
|
+
accessProductsList = this.tiers;
|
|
37
33
|
}
|
|
38
34
|
|
|
39
35
|
if (accessProductsList.length > 0) {
|
|
@@ -13,7 +13,7 @@ function processQuery(query, locals) {
|
|
|
13
13
|
// We override the `include` property for now, because the full data set is required anyway.
|
|
14
14
|
if (_.get(query, 'resource') === 'posts' || _.get(query, 'resource') === 'pages') {
|
|
15
15
|
_.extend(query.options, {
|
|
16
|
-
include: 'authors,tags'
|
|
16
|
+
include: 'authors,tags,tiers'
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -42,8 +42,10 @@
|
|
|
42
42
|
{{#if member}}
|
|
43
43
|
<p>
|
|
44
44
|
<span class="gh-flow-em">{{member.email}}</span> has been successfully unsubscribed from emails.
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
{{#match member.status "!=" "free"}}
|
|
46
|
+
<br>
|
|
47
|
+
Don't worry, this will not cancel your paid subscription to {{@site.title}}.
|
|
48
|
+
{{/match}}
|
|
47
49
|
</p>
|
|
48
50
|
<p>Didn't mean to do this? Manage your account <a href="{{@site.url}}/#/portal/account">here</a>.</p>
|
|
49
51
|
{{/if}}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const tpl = require('@tryghost/tpl');
|
|
2
2
|
const errors = require('@tryghost/errors');
|
|
3
3
|
const models = require('../../models');
|
|
4
|
-
const ALLOWED_INCLUDES = ['authors', 'tags'];
|
|
4
|
+
const ALLOWED_INCLUDES = ['authors', 'tags', 'tiers'];
|
|
5
5
|
|
|
6
6
|
const messages = {
|
|
7
7
|
postNotFound: 'Post not found.'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const tpl = require('@tryghost/tpl');
|
|
2
2
|
const errors = require('@tryghost/errors');
|
|
3
3
|
const models = require('../../models');
|
|
4
|
-
const ALLOWED_INCLUDES = ['tags', 'authors'];
|
|
4
|
+
const ALLOWED_INCLUDES = ['tags', 'authors', 'tiers'];
|
|
5
5
|
|
|
6
6
|
const messages = {
|
|
7
7
|
pageNotFound: 'Page not found.'
|
|
@@ -2,7 +2,7 @@ const models = require('../../models');
|
|
|
2
2
|
const tpl = require('@tryghost/tpl');
|
|
3
3
|
const errors = require('@tryghost/errors');
|
|
4
4
|
const getPostServiceInstance = require('../../services/posts/posts-service');
|
|
5
|
-
const ALLOWED_INCLUDES = ['tags', 'authors', 'authors.roles'];
|
|
5
|
+
const ALLOWED_INCLUDES = ['tags', 'authors', 'authors.roles', 'tiers'];
|
|
6
6
|
const UNSAFE_ATTRS = ['status', 'authors', 'visibility'];
|
|
7
7
|
|
|
8
8
|
const messages = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const models = require('../../models');
|
|
2
2
|
const tpl = require('@tryghost/tpl');
|
|
3
3
|
const errors = require('@tryghost/errors');
|
|
4
|
-
const allowedIncludes = ['tags', 'authors'];
|
|
4
|
+
const allowedIncludes = ['tags', 'authors', 'tiers'];
|
|
5
5
|
|
|
6
6
|
const messages = {
|
|
7
7
|
postNotFound: 'Post not found.'
|
|
@@ -2,7 +2,7 @@ const models = require('../../models');
|
|
|
2
2
|
const tpl = require('@tryghost/tpl');
|
|
3
3
|
const errors = require('@tryghost/errors');
|
|
4
4
|
const getPostServiceInstance = require('../../services/posts/posts-service');
|
|
5
|
-
const allowedIncludes = ['tags', 'authors', 'authors.roles', 'email'];
|
|
5
|
+
const allowedIncludes = ['tags', 'authors', 'authors.roles', 'email', 'tiers'];
|
|
6
6
|
const unsafeAttrs = ['status', 'authors', 'visibility'];
|
|
7
7
|
|
|
8
8
|
const messages = {
|
|
@@ -38,7 +38,7 @@ function defaultRelations(frame) {
|
|
|
38
38
|
return false;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
frame.options.withRelated = ['tags', 'authors', 'authors.roles'];
|
|
41
|
+
frame.options.withRelated = ['tags', 'authors', 'authors.roles', 'tiers'];
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
function setDefaultOrder(frame) {
|
|
@@ -102,13 +102,6 @@ const forceStatusFilter = (frame) => {
|
|
|
102
102
|
}
|
|
103
103
|
};
|
|
104
104
|
|
|
105
|
-
const transformPageVisibilityFilters = (frame) => {
|
|
106
|
-
if (frame.data.pages[0].visibility === 'filter' && frame.data.pages[0].visibility_filter) {
|
|
107
|
-
frame.data.pages[0].visibility = frame.data.pages[0].visibility_filter;
|
|
108
|
-
}
|
|
109
|
-
delete frame.data.pages[0].visibility_filter;
|
|
110
|
-
};
|
|
111
|
-
|
|
112
105
|
module.exports = {
|
|
113
106
|
browse(apiConfig, frame) {
|
|
114
107
|
debug('browse');
|
|
@@ -187,7 +180,6 @@ module.exports = {
|
|
|
187
180
|
});
|
|
188
181
|
}
|
|
189
182
|
|
|
190
|
-
transformPageVisibilityFilters(frame);
|
|
191
183
|
handlePostsMeta(frame);
|
|
192
184
|
defaultFormat(frame);
|
|
193
185
|
defaultRelations(frame);
|
|
@@ -38,7 +38,7 @@ function defaultRelations(frame) {
|
|
|
38
38
|
return false;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
frame.options.withRelated = ['tags', 'authors', 'authors.roles', 'email'];
|
|
41
|
+
frame.options.withRelated = ['tags', 'authors', 'authors.roles', 'email', 'tiers'];
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
function setDefaultOrder(frame) {
|
|
@@ -111,13 +111,6 @@ const transformLegacyEmailRecipientFilters = (frame) => {
|
|
|
111
111
|
}
|
|
112
112
|
};
|
|
113
113
|
|
|
114
|
-
const transformPostVisibilityFilters = (frame) => {
|
|
115
|
-
if (frame.data.posts[0].visibility === 'filter' && frame.data.posts[0].visibility_filter) {
|
|
116
|
-
frame.data.posts[0].visibility = frame.data.posts[0].visibility_filter;
|
|
117
|
-
}
|
|
118
|
-
delete frame.data.posts[0].visibility_filter;
|
|
119
|
-
};
|
|
120
|
-
|
|
121
114
|
module.exports = {
|
|
122
115
|
browse(apiConfig, frame) {
|
|
123
116
|
debug('browse');
|
|
@@ -212,7 +205,6 @@ module.exports = {
|
|
|
212
205
|
});
|
|
213
206
|
}
|
|
214
207
|
|
|
215
|
-
transformPostVisibilityFilters(frame);
|
|
216
208
|
transformLegacyEmailRecipientFilters(frame);
|
|
217
209
|
handlePostsMeta(frame);
|
|
218
210
|
defaultFormat(frame);
|
|
@@ -2,8 +2,8 @@ const mapper = require('./utils/mapper');
|
|
|
2
2
|
const gating = require('./utils/post-gating');
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
|
-
read(model, apiConfig, frame) {
|
|
6
|
-
const emailPost = mapper.mapPost(model, frame);
|
|
5
|
+
async read(model, apiConfig, frame) {
|
|
6
|
+
const emailPost = await mapper.mapPost(model, frame);
|
|
7
7
|
gating.forPost(emailPost, frame);
|
|
8
8
|
|
|
9
9
|
frame.response = {
|
|
@@ -2,25 +2,29 @@ const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:pa
|
|
|
2
2
|
const mapper = require('./utils/mapper');
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
|
-
all(models, apiConfig, frame) {
|
|
5
|
+
async all(models, apiConfig, frame) {
|
|
6
6
|
debug('all');
|
|
7
7
|
|
|
8
8
|
// CASE: e.g. destroy returns null
|
|
9
9
|
if (!models) {
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
let pages = [];
|
|
13
13
|
if (models.meta) {
|
|
14
|
+
for (let model of models.data) {
|
|
15
|
+
let page = await mapper.mapPage(model, frame);
|
|
16
|
+
pages.push(page);
|
|
17
|
+
}
|
|
14
18
|
frame.response = {
|
|
15
|
-
pages
|
|
19
|
+
pages,
|
|
16
20
|
meta: models.meta
|
|
17
21
|
};
|
|
18
22
|
|
|
19
23
|
return;
|
|
20
24
|
}
|
|
21
|
-
|
|
25
|
+
let page = await mapper.mapPage(models, frame);
|
|
22
26
|
frame.response = {
|
|
23
|
-
pages: [
|
|
27
|
+
pages: [page]
|
|
24
28
|
};
|
|
25
29
|
}
|
|
26
30
|
};
|
|
@@ -2,25 +2,29 @@ const debug = require('@tryghost/debug')('api:canary:utils:serializers:output:po
|
|
|
2
2
|
const mapper = require('./utils/mapper');
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
|
-
all(models, apiConfig, frame) {
|
|
5
|
+
async all(models, apiConfig, frame) {
|
|
6
6
|
debug('all');
|
|
7
7
|
|
|
8
8
|
// CASE: e.g. destroy returns null
|
|
9
9
|
if (!models) {
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
let posts = [];
|
|
13
13
|
if (models.meta) {
|
|
14
|
+
for (let model of models.data) {
|
|
15
|
+
let post = await mapper.mapPost(model, frame);
|
|
16
|
+
posts.push(post);
|
|
17
|
+
}
|
|
14
18
|
frame.response = {
|
|
15
|
-
posts
|
|
19
|
+
posts,
|
|
16
20
|
meta: models.meta
|
|
17
21
|
};
|
|
18
22
|
|
|
19
23
|
return;
|
|
20
24
|
}
|
|
21
|
-
|
|
25
|
+
let post = await mapper.mapPost(models, frame);
|
|
22
26
|
frame.response = {
|
|
23
|
-
posts: [
|
|
27
|
+
posts: [post]
|
|
24
28
|
};
|
|
25
29
|
}
|
|
26
30
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
const mapper = require('./utils/mapper');
|
|
2
2
|
|
|
3
3
|
module.exports = {
|
|
4
|
-
all(model, apiConfig, frame) {
|
|
4
|
+
async all(model, apiConfig, frame) {
|
|
5
|
+
const data = await mapper.mapPost(model, frame);
|
|
5
6
|
frame.response = {
|
|
6
|
-
preview: [
|
|
7
|
+
preview: [data]
|
|
7
8
|
};
|
|
8
9
|
frame.response.preview[0].page = model.get('type') === 'page';
|
|
9
10
|
}
|
|
@@ -75,6 +75,7 @@ function serializeProduct(product, options, apiType) {
|
|
|
75
75
|
slug: json.slug,
|
|
76
76
|
active: json.active,
|
|
77
77
|
type: json.type,
|
|
78
|
+
welcome_page_url: json.welcome_page_url,
|
|
78
79
|
created_at: json.created_at,
|
|
79
80
|
updated_at: json.updated_at,
|
|
80
81
|
stripe_prices: json.stripePrices ? json.stripePrices.map(price => serializeStripePrice(price, hideStripeData)) : null,
|
|
@@ -164,6 +165,7 @@ function createSerializer(debugString, serialize) {
|
|
|
164
165
|
* @prop {string} description
|
|
165
166
|
* @prop {boolean} active
|
|
166
167
|
* @prop {string} type
|
|
168
|
+
* @prop {string} welcome_page_url
|
|
167
169
|
* @prop {Date} created_at
|
|
168
170
|
* @prop {Date} updated_at
|
|
169
171
|
* @prop {StripePrice[]} [stripe_prices]
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
2
|
const localUtils = require('../../../index');
|
|
3
|
-
const labsService = require('../../../../../../../shared/labs');
|
|
4
3
|
|
|
5
4
|
const tag = (attrs, frame) => {
|
|
6
5
|
if (localUtils.isContentAPI(frame)) {
|
|
@@ -122,14 +121,6 @@ const post = (attrs, frame) => {
|
|
|
122
121
|
delete attrs.primary_author;
|
|
123
122
|
}
|
|
124
123
|
|
|
125
|
-
// Handles visibility filter for multiple products
|
|
126
|
-
if (attrs.visibility && labsService.isSet('multipleProducts')) {
|
|
127
|
-
if (!['members', 'public', 'paid'].includes(attrs.visibility)) {
|
|
128
|
-
attrs.visibility_filter = attrs.visibility;
|
|
129
|
-
attrs.visibility = 'filter';
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
124
|
delete attrs.locale;
|
|
134
125
|
delete attrs.author;
|
|
135
126
|
delete attrs.type;
|
|
@@ -7,6 +7,10 @@ const clean = require('./clean');
|
|
|
7
7
|
const extraAttrs = require('./extra-attrs');
|
|
8
8
|
const postsMetaSchema = require('../../../../../../data/schema').tables.posts_meta;
|
|
9
9
|
const mega = require('../../../../../../services/mega');
|
|
10
|
+
const labsService = require('../../../../../../../shared/labs');
|
|
11
|
+
|
|
12
|
+
const getPostServiceInstance = require('../../../../../../services/posts/posts-service');
|
|
13
|
+
const postsService = getPostServiceInstance('canary');
|
|
10
14
|
|
|
11
15
|
const mapUser = (model, frame) => {
|
|
12
16
|
const jsonModel = model.toJSON ? model.toJSON(frame.options) : model;
|
|
@@ -27,7 +31,7 @@ const mapTag = (model, frame) => {
|
|
|
27
31
|
return jsonModel;
|
|
28
32
|
};
|
|
29
33
|
|
|
30
|
-
const mapPost = (model, frame) => {
|
|
34
|
+
const mapPost = async (model, frame) => {
|
|
31
35
|
const extendedOptions = Object.assign(_.cloneDeep(frame.options), {
|
|
32
36
|
extraProperties: ['canonical_url']
|
|
33
37
|
});
|
|
@@ -38,6 +42,17 @@ const mapPost = (model, frame) => {
|
|
|
38
42
|
|
|
39
43
|
extraAttrs.forPost(frame, model, jsonModel);
|
|
40
44
|
|
|
45
|
+
// Attach tiers to custom nql visibility filter
|
|
46
|
+
if (labsService.isSet('multipleProducts')
|
|
47
|
+
&& jsonModel.visibility
|
|
48
|
+
&& !['members', 'public', 'paid', 'tiers'].includes(jsonModel.visibility)
|
|
49
|
+
) {
|
|
50
|
+
const tiers = await postsService.getProductsFromVisibilityFilter(jsonModel.visibility);
|
|
51
|
+
|
|
52
|
+
jsonModel.visibility = 'tiers';
|
|
53
|
+
jsonModel.tiers = tiers;
|
|
54
|
+
}
|
|
55
|
+
|
|
41
56
|
if (utils.isContentAPI(frame)) {
|
|
42
57
|
// Content api v2 still expects page prop
|
|
43
58
|
if (jsonModel.type === 'page') {
|
|
@@ -88,8 +103,8 @@ const mapPost = (model, frame) => {
|
|
|
88
103
|
return jsonModel;
|
|
89
104
|
};
|
|
90
105
|
|
|
91
|
-
const mapPage = (model, frame) => {
|
|
92
|
-
const jsonModel = mapPost(model, frame);
|
|
106
|
+
const mapPage = async (model, frame) => {
|
|
107
|
+
const jsonModel = await mapPost(model, frame);
|
|
93
108
|
|
|
94
109
|
delete jsonModel.email_subject;
|
|
95
110
|
delete jsonModel.email_recipient_filter;
|
|
@@ -16,7 +16,7 @@ const validateVisibility = async function (frame) {
|
|
|
16
16
|
const visibility = frame.data.pages[0].visibility;
|
|
17
17
|
const visibilityFilter = frame.data.pages[0].visibility_filter;
|
|
18
18
|
if (visibility) {
|
|
19
|
-
if (!['public', 'members', 'paid'].includes(visibility)) {
|
|
19
|
+
if (!['public', 'members', 'paid', 'tiers'].includes(visibility)) {
|
|
20
20
|
// check filter is valid
|
|
21
21
|
try {
|
|
22
22
|
await models.Member.findPage({filter: visibilityFilter, limit: 1});
|
|
@@ -16,7 +16,7 @@ const validateVisibility = async function (frame) {
|
|
|
16
16
|
const visibility = frame.data.posts[0].visibility;
|
|
17
17
|
const visibilityFilter = frame.data.posts[0].visibility_filter;
|
|
18
18
|
if (visibility) {
|
|
19
|
-
if (!['public', 'members', 'paid'].includes(visibility)) {
|
|
19
|
+
if (!['public', 'members', 'paid', 'tiers'].includes(visibility)) {
|
|
20
20
|
// check filter is valid
|
|
21
21
|
try {
|
|
22
22
|
await models.Member.findPage({filter: visibilityFilter, limit: 1});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const {addTable} = require('../../utils');
|
|
2
|
+
|
|
3
|
+
module.exports = addTable('posts_products', {
|
|
4
|
+
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
|
5
|
+
post_id: {type: 'string', maxlength: 24, nullable: false, references: 'posts.id', cascadeDelete: true},
|
|
6
|
+
product_id: {type: 'string', maxlength: 24, nullable: false, references: 'products.id', cascadeDelete: true},
|
|
7
|
+
sort_order: {type: 'integer', nullable: false, unsigned: true, defaultTo: 0}
|
|
8
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const logging = require('@tryghost/logging');
|
|
2
|
+
|
|
3
|
+
// For DML - data changes
|
|
4
|
+
const {createTransactionalMigration} = require('../../utils');
|
|
5
|
+
|
|
6
|
+
module.exports = createTransactionalMigration(
|
|
7
|
+
async function up(knex) {
|
|
8
|
+
logging.info('Setting welcome_page_url from settings');
|
|
9
|
+
|
|
10
|
+
const paidSignupRedirect = await knex('settings')
|
|
11
|
+
.select('value')
|
|
12
|
+
.where('key', 'members_paid_signup_redirect')
|
|
13
|
+
.first();
|
|
14
|
+
|
|
15
|
+
const freeSignupRedirect = await knex('settings')
|
|
16
|
+
.select('value')
|
|
17
|
+
.where('key', 'members_free_signup_redirect')
|
|
18
|
+
.first();
|
|
19
|
+
|
|
20
|
+
if (paidSignupRedirect) {
|
|
21
|
+
logging.info(`Setting paid Tiers welcome_page_url to ${paidSignupRedirect.value}`);
|
|
22
|
+
|
|
23
|
+
await knex('products')
|
|
24
|
+
.update('welcome_page_url', paidSignupRedirect.value)
|
|
25
|
+
.where('type', 'paid');
|
|
26
|
+
} else {
|
|
27
|
+
logging.info(`No members_paid_signup_redirect setting found`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (freeSignupRedirect) {
|
|
31
|
+
logging.info(`Setting free Tiers welcome_page_url to ${freeSignupRedirect.value}`);
|
|
32
|
+
|
|
33
|
+
await knex('products')
|
|
34
|
+
.update('welcome_page_url', freeSignupRedirect.value)
|
|
35
|
+
.where('type', 'free');
|
|
36
|
+
} else {
|
|
37
|
+
logging.info(`No members_free_signup_redirect setting found`);
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
async function down(knex) {
|
|
41
|
+
logging.info('Setting welcome_page_url to NULL');
|
|
42
|
+
await knex('products')
|
|
43
|
+
.update('welcome_page_url', null);
|
|
44
|
+
}
|
|
45
|
+
);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const logging = require('@tryghost/logging');
|
|
2
|
+
const {createNonTransactionalMigration} = require('../../utils');
|
|
3
|
+
|
|
4
|
+
module.exports = createNonTransactionalMigration(
|
|
5
|
+
async function up(knex) {
|
|
6
|
+
if (knex.client.config.client === 'sqlite3') {
|
|
7
|
+
logging.warn('Skipping migration for SQLite3');
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
logging.info('Changing posts.email_recipient_filter column from VARCHAR(50) to TEXT');
|
|
11
|
+
await knex.schema.alterTable('posts', function (table) {
|
|
12
|
+
table.text('email_recipient_filter').alter();
|
|
13
|
+
});
|
|
14
|
+
},
|
|
15
|
+
async function down() {
|
|
16
|
+
logging.warn('Not changing posts.email_recipient_filter column');
|
|
17
|
+
}
|
|
18
|
+
);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const logging = require('@tryghost/logging');
|
|
2
|
+
const {createNonTransactionalMigration} = require('../../utils');
|
|
3
|
+
|
|
4
|
+
module.exports = createNonTransactionalMigration(
|
|
5
|
+
async function up(knex) {
|
|
6
|
+
if (knex.client.config.client === 'sqlite3') {
|
|
7
|
+
logging.warn('Skipping migration for SQLite3');
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
logging.info('Changing emails.recipient_filter column from VARCHAR(50) to TEXT');
|
|
11
|
+
await knex.schema.alterTable('emails', function (table) {
|
|
12
|
+
table.text('recipient_filter').alter();
|
|
13
|
+
});
|
|
14
|
+
},
|
|
15
|
+
async function down() {
|
|
16
|
+
logging.warn('Not changing emails.recipient_filter column');
|
|
17
|
+
}
|
|
18
|
+
);
|