/
migration.test.js
304 lines (250 loc) · 18.5 KB
/
migration.test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
const should = require('should');
const sinon = require('sinon');
const testUtils = require('../../utils');
const _ = require('lodash');
const Models = require('../../../core/server/models');
const KnexMigrator = require('knex-migrator');
const path = require('path');
const semver = require('semver');
const knexMigrator = new KnexMigrator({
knexMigratorFilePath: path.join(__dirname, '../../../')
});
const db = require('../../../core/server/data/db');
const dbUtils = require('../../utils/db-utils');
const currentVersion = require('@tryghost/version');
const currentMajor = semver.major(currentVersion.original);
const previousMinor = semver.minor(currentVersion.original) - 1;
const previousVersion = `${currentMajor}.${previousMinor}`;
describe('Migrations', function () {
beforeEach(async function () {
await dbUtils.teardown();
});
afterEach(function () {
sinon.restore();
});
describe('Database initialization + rollback', function () {
beforeEach(async function () {
await knexMigrator.reset({force: true});
await knexMigrator.init();
});
it('can rollback to the previous minor version', async function () {
await knexMigrator.rollback({
version: previousVersion,
force: true
});
});
it('can rollback to the previous minor version and then forwards again', async function () {
await knexMigrator.rollback({
version: previousVersion,
force: true
});
await knexMigrator.migrate({
force: true
});
});
it('should have idempotent migrations', async function () {
// Delete all knowledge that we've run migrations so we can run them again
if (dbUtils.isMySQL()) {
await db.knex('migrations').whereILike('version', `${currentMajor}.%`).del();
} else {
await db.knex('migrations').whereLike('version', `${currentMajor}.%`).del();
}
await knexMigrator.migrate({
force: true
});
});
});
describe('Fixtures', function () {
// Custom assertion for detection that a permissions is assigned to the correct roles
should.Assertion.add('AssignedToRoles', function (roles) {
let roleNames;
this.params = {operator: 'to have role'};
should.exist(this.obj);
this.obj.should.be.an.Object().with.property(['roles']);
this.obj.roles.should.be.an.Array();
// Ensure the roles are in id order
roleNames = _(this.obj.roles).sortBy('id').map('name').value();
roleNames.should.eql(roles);
});
should.Assertion.add('havePermission', function (name, roles = null) {
const permission = this.obj.find((p) => {
return p.name === name;
});
should.exist(permission, `Could not find permission ${name}`);
if (roles) {
permission.should.be.AssignedToRoles(roles);
}
});
// Custom assertion to wrap all permissions
should.Assertion.add('CompletePermissions', function () {
this.params = {operator: 'to have a complete set of permissions'};
const permissions = this.obj;
// If you have to change this number, please add the relevant `havePermission` checks below
permissions.length.should.eql(120);
permissions.should.havePermission('Export database', ['Administrator', 'DB Backup Integration']);
permissions.should.havePermission('Import database', ['Administrator', 'Self-Serve Migration Integration', 'DB Backup Integration']);
permissions.should.havePermission('Delete all content', ['Administrator', 'DB Backup Integration']);
permissions.should.havePermission('Backup database', ['Administrator', 'DB Backup Integration']);
permissions.should.havePermission('Send mail', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Browse notifications', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Add notifications', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Delete notifications', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Browse posts', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Read posts', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Edit posts', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Add posts', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Delete posts', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Publish posts', ['Administrator', 'Editor', 'Admin Integration', 'Scheduler Integration']);
permissions.should.havePermission('Browse settings', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Read settings', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Edit settings', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Generate slugs', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Browse tags', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Read tags', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration', 'Self-Serve Migration Integration']);
permissions.should.havePermission('Edit tags', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Add tags', ['Administrator', 'Editor', 'Author', 'Admin Integration']);
permissions.should.havePermission('Delete tags', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Browse themes', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Edit themes', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Activate themes', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('View active theme details', ['Administrator', 'Editor', 'Author', 'Admin Integration']);
permissions.should.havePermission('Upload themes', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Download themes', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Delete themes', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Browse users', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Read users', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Edit users', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Add users', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Delete users', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Assign a role', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Browse roles', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Browse invites', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Read invites', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Edit invites', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Add invites', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Delete invites', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Download redirects', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Upload redirects', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Add webhooks', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Edit webhooks', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Delete webhooks', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Browse integrations', ['Administrator']);
permissions.should.havePermission('Read integrations', ['Administrator']);
permissions.should.havePermission('Edit integrations', ['Administrator']);
permissions.should.havePermission('Add integrations', ['Administrator']);
permissions.should.havePermission('Delete integrations', ['Administrator']);
permissions.should.havePermission('Browse API keys', ['Administrator']);
permissions.should.havePermission('Read API keys', ['Administrator']);
permissions.should.havePermission('Edit API keys', ['Administrator']);
permissions.should.havePermission('Add API keys', ['Administrator']);
permissions.should.havePermission('Delete API keys', ['Administrator']);
permissions.should.havePermission('Browse Actions', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Email preview', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Send test email', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Browse emails', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Read emails', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Retry emails', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Browse snippets', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Read snippets', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Edit snippets', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Add snippets', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Delete snippets', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Browse labels', ['Administrator', 'Editor', 'Author', 'Admin Integration']);
permissions.should.havePermission('Read labels', ['Administrator', 'Editor', 'Author', 'Admin Integration']);
permissions.should.havePermission('Edit labels', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Add labels', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Delete labels', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Read member signin urls');
permissions.should.havePermission('Read identities');
permissions.should.havePermission('Auth Stripe Connect for Members');
permissions.should.havePermission('Browse Members');
permissions.should.havePermission('Read Members');
permissions.should.havePermission('Edit Members');
permissions.should.havePermission('Add Members', ['Administrator', 'Admin Integration', 'Self-Serve Migration Integration']);
permissions.should.havePermission('Delete Members');
permissions.should.havePermission('Browse offers');
permissions.should.havePermission('Read offers');
permissions.should.havePermission('Edit offers');
permissions.should.havePermission('Add offers');
permissions.should.havePermission('Browse Products', ['Administrator', 'Editor', 'Author', 'Admin Integration']);
permissions.should.havePermission('Read Products', ['Administrator', 'Editor', 'Author', 'Admin Integration']);
permissions.should.havePermission('Edit Products', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Add Products', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Delete Products', ['Administrator']);
permissions.should.havePermission('Reset all passwords', ['Administrator']);
permissions.should.havePermission('Browse custom theme settings', ['Administrator']);
permissions.should.havePermission('Edit custom theme settings', ['Administrator']);
permissions.should.havePermission('Browse newsletters', ['Administrator', 'Editor', 'Author', 'Admin Integration']);
permissions.should.havePermission('Read newsletters', ['Administrator', 'Editor', 'Author', 'Admin Integration']);
permissions.should.havePermission('Edit newsletters', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Add newsletters', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Read explore data', ['Administrator', 'Admin Integration', 'Ghost Explore Integration']);
permissions.should.havePermission('Browse comments', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Read comments', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Edit comments', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Add comments', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Delete comments', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Moderate comments', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Like comments', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Unlike comments', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Report comments', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Browse links', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Browse mentions', ['Administrator', 'Admin Integration']);
permissions.should.havePermission('Browse collections', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Read collections', ['Administrator', 'Editor', 'Author', 'Contributor', 'Admin Integration']);
permissions.should.havePermission('Edit collections', ['Administrator', 'Editor', 'Admin Integration']);
permissions.should.havePermission('Add collections', ['Administrator', 'Editor', 'Author', 'Admin Integration']);
permissions.should.havePermission('Delete collections', ['Administrator', 'Editor', 'Admin Integration']);
});
describe('Populate', function () {
beforeEach(testUtils.setup('default'));
it('should populate all fixtures correctly', async function () {
const [posts, tags, users, roles, permissions] = await Promise.all([
Models.Post.findAll({withRelated: ['tags']}),
Models.Tag.findAll(),
Models.User.findAll({
filter: 'status:inactive',
context: {internal: true},
withRelated: ['roles']
}),
Models.Role.findAll(),
Models.Permission.findAll({withRelated: ['roles']})
]);
// Post
should.exist(posts);
posts.length.should.eql(7);
posts.at(0).get('title').should.eql('Start here for a quick overview of everything you need to know');
posts.at(6).get('title').should.eql('Setting up apps and custom integrations');
// Tag
should.exist(tags);
tags.length.should.eql(1);
tags.at(0).get('name').should.eql('Getting Started');
// Post Tag relation
posts.at(0).related('tags').length.should.eql(1);
posts.at(0).related('tags').at(0).get('name').should.eql('Getting Started');
// User (Owner)
should.exist(users);
users.length.should.eql(1);
users.at(0).get('name').should.eql('Ghost');
users.at(0).get('status').should.eql('inactive');
users.at(0).related('roles').length.should.eql(1);
users.at(0).related('roles').at(0).get('name').should.eql('Owner');
// Roles
should.exist(roles);
roles.length.should.eql(10);
roles.at(0).get('name').should.eql('Administrator');
roles.at(1).get('name').should.eql('Editor');
roles.at(2).get('name').should.eql('Author');
roles.at(3).get('name').should.eql('Contributor');
roles.at(4).get('name').should.eql('Owner');
roles.at(5).get('name').should.eql('Admin Integration');
roles.at(6).get('name').should.eql('Ghost Explore Integration');
roles.at(7).get('name').should.eql('Self-Serve Migration Integration');
roles.at(8).get('name').should.eql('DB Backup Integration');
roles.at(9).get('name').should.eql('Scheduler Integration');
// Permissions
permissions.toJSON().should.be.CompletePermissions();
});
});
});
});