diff --git a/core/server/data/migrations/versions/5.3/2022-07-06-07-58-add-ghost-explore-integration-role.js b/core/server/data/migrations/versions/5.3/2022-07-06-07-58-add-ghost-explore-integration-role.js new file mode 100644 index 0000000000..6d3dafa160 --- /dev/null +++ b/core/server/data/migrations/versions/5.3/2022-07-06-07-58-add-ghost-explore-integration-role.js @@ -0,0 +1,31 @@ +const logging = require('@tryghost/logging'); +const {default: ObjectID} = require('bson-objectid'); +const {createTransactionalMigration, meta} = require('../../utils'); + +module.exports = createTransactionalMigration( + async function up(knex) { + logging.info('Creating "Ghost Explore Integration" role'); + const existingRole = await knex('roles').where({ + name: 'Ghost Explore Integration' + }).first(); + + if (existingRole) { + logging.warn('"Ghost Explore Integration" role already exists, skipping'); + return; + } + + await knex('roles').insert({ + id: (new ObjectID()).toHexString(), + name: 'Ghost Explore Integration', + description: 'Internal Integration for the Ghost Explore directory', + created_by: meta.MIGRATION_USER, + created_at: knex.raw('current_timestamp') + }); + }, + async function down(knex) { + logging.info('Deleting role "Ghost Explore Integration"'); + await knex('roles').where({ + name: 'Ghost Explore Integration' + }).del(); + } +); diff --git a/core/server/data/migrations/versions/5.3/2022-07-06-09-17-add-ghost-explore-integration.js b/core/server/data/migrations/versions/5.3/2022-07-06-09-17-add-ghost-explore-integration.js new file mode 100644 index 0000000000..74d6aef954 --- /dev/null +++ b/core/server/data/migrations/versions/5.3/2022-07-06-09-17-add-ghost-explore-integration.js @@ -0,0 +1,38 @@ +const logging = require('@tryghost/logging'); +const {default: ObjectID} = require('bson-objectid'); +const {createTransactionalMigration, meta} = require('../../utils'); + +module.exports = createTransactionalMigration( + async function up(knex) { + logging.info('Creating Ghost Explore Integration'); + const existingIntegration = await knex('integrations').where({ + type: 'internal', + name: 'Ghost Explore', + slug: 'ghost-explore' + }).first(); + + if (existingIntegration) { + logging.warn('Integration already exists, skipping'); + return; + } + + await knex('integrations').insert({ + id: (new ObjectID()).toHexString(), + type: 'internal', + name: 'Ghost Explore', + description: 'Internal Integration for the Ghost Explore directory', + slug: 'ghost-explore', + created_at: knex.raw('current_timestamp'), + created_by: meta.MIGRATION_USER + }); + }, + async function down(knex) { + logging.info('Deleting Ghost Explore Integration'); + + await knex('integrations').where({ + type: 'internal', + name: 'Ghost Explore', + slug: 'ghost-explore' + }).del(); + } +); diff --git a/core/server/data/migrations/versions/5.3/2022-07-06-09-26-add-ghost-explore-integration-api-key.js b/core/server/data/migrations/versions/5.3/2022-07-06-09-26-add-ghost-explore-integration-api-key.js new file mode 100644 index 0000000000..90bfe9507b --- /dev/null +++ b/core/server/data/migrations/versions/5.3/2022-07-06-09-26-add-ghost-explore-integration-api-key.js @@ -0,0 +1,73 @@ +const {InternalServerError} = require('@tryghost/errors'); +const logging = require('@tryghost/logging'); +const security = require('@tryghost/security'); +const {default: ObjectID} = require('bson-objectid'); +const {createTransactionalMigration, meta} = require('../../utils'); + +module.exports = createTransactionalMigration( + async function up(knex) { + logging.info('Adding Admin API key for Ghost Explore Integration'); + + const integration = await knex('integrations').where({ + slug: 'ghost-explore', + type: 'internal', + name: 'Ghost Explore' + }).first(); + + if (!integration) { + throw new InternalServerError('Could not find Ghost Explore Integration'); + } + + const role = await knex('roles').where({ + name: 'Ghost Explore Integration' + }).first(); + + if (!role) { + throw new InternalServerError('Could not find Ghost Explore Integration Role'); + } + + const existingKey = await knex('api_keys').where({ + integration_id: integration.id, + role_id: role.id + }).first(); + + if (existingKey) { + logging.warn('Admin API key already exists'); + return; + } + + await knex('api_keys').insert({ + id: (new ObjectID()).toHexString(), + type: 'admin', + secret: security.secret.create('admin'), + role_id: role.id, + integration_id: integration.id, + created_at: knex.raw('current_timestamp'), + created_by: meta.MIGRATION_USER + }); + }, + async function down(knex) { + logging.info('Removing Ghost Explore API key'); + + const integration = await knex('integrations').where({ + slug: 'ghost-explore', + type: 'internal', + name: 'Ghost Explore' + }).first(); + + const role = await knex('roles').where({ + name: 'Ghost Explore Integration' + }).first(); + + if (!role || !integration) { + logging.warn('Could not delete API key'); + return; + } + + logging.info('Deleting API Key'); + await knex('api_keys').where({ + integration_id: integration.id, + role_id: role.id + }).del(); + } +); diff --git a/core/server/data/schema/fixtures/fixtures.json b/core/server/data/schema/fixtures/fixtures.json index 007efc1053..4ab2dbb28e 100644 --- a/core/server/data/schema/fixtures/fixtures.json +++ b/core/server/data/schema/fixtures/fixtures.json @@ -69,6 +69,10 @@ "name": "Admin Integration", "description": "External Apps" }, + { + "name": "Ghost Explore Integration", + "description": "Internal Integration for the Ghost Explore directory" + }, { "name": "DB Backup Integration", "description": "Internal DB Backup Client" @@ -614,6 +618,13 @@ "type": "builtin", "api_keys": [{"type": "admin"}] }, + { + "slug": "ghost-explore", + "name": "Ghost Explore", + "description": "Built-in Ghost Explore integration", + "type": "internal", + "api_keys": [{"type": "admin", "role": "Ghost Explore Integration"}] + }, { "slug": "ghost-backup", "name": "Ghost Backup", diff --git a/test/e2e-api/admin/roles.test.js b/test/e2e-api/admin/roles.test.js index 374d678a93..305ba238b6 100644 --- a/test/e2e-api/admin/roles.test.js +++ b/test/e2e-api/admin/roles.test.js @@ -25,7 +25,7 @@ describe('Roles API', function () { should.exist(response); should.exist(response.roles); localUtils.API.checkResponse(response, 'roles'); - response.roles.should.have.length(8); + response.roles.should.have.length(9); localUtils.API.checkResponse(response.roles[0], 'role'); localUtils.API.checkResponse(response.roles[1], 'role'); localUtils.API.checkResponse(response.roles[2], 'role'); @@ -34,6 +34,7 @@ describe('Roles API', function () { localUtils.API.checkResponse(response.roles[5], 'role'); localUtils.API.checkResponse(response.roles[6], 'role'); localUtils.API.checkResponse(response.roles[7], 'role'); + localUtils.API.checkResponse(response.roles[8], 'role'); }); it('Can request roles which i am able to assign to other users', async function () { diff --git a/test/integration/migrations/migration.test.js b/test/integration/migrations/migration.test.js index ee945887d3..99dae6044b 100644 --- a/test/integration/migrations/migration.test.js +++ b/test/integration/migrations/migration.test.js @@ -213,15 +213,16 @@ describe('Database Migration (special functions)', function () { // Roles should.exist(result.roles); - result.roles.length.should.eql(8); + result.roles.length.should.eql(9); result.roles.at(0).get('name').should.eql('Administrator'); result.roles.at(1).get('name').should.eql('Editor'); result.roles.at(2).get('name').should.eql('Author'); result.roles.at(3).get('name').should.eql('Contributor'); result.roles.at(4).get('name').should.eql('Owner'); result.roles.at(5).get('name').should.eql('Admin Integration'); - result.roles.at(6).get('name').should.eql('DB Backup Integration'); - result.roles.at(7).get('name').should.eql('Scheduler Integration'); + result.roles.at(6).get('name').should.eql('Ghost Explore Integration'); + result.roles.at(7).get('name').should.eql('DB Backup Integration'); + result.roles.at(8).get('name').should.eql('Scheduler Integration'); // Permissions result.permissions.length.should.eql(96); diff --git a/test/unit/server/data/schema/integrity.test.js b/test/unit/server/data/schema/integrity.test.js index 6ab6c098e5..cdba1f759c 100644 --- a/test/unit/server/data/schema/integrity.test.js +++ b/test/unit/server/data/schema/integrity.test.js @@ -36,7 +36,7 @@ const validateRouteSettings = require('../../../../../core/server/services/route describe('DB version integrity', function () { // Only these variables should need updating const currentSchemaHash = '2f4266e6e5087ad92dd30f3e721d46e5'; - const currentFixturesHash = '2509ff2c1f6e0293a3c3d84f08593b2f'; + const currentFixturesHash = 'b9103927f61cfc9aab2784e402b58a34'; const currentSettingsHash = '0b138cdd40e48b5b7dc4ebac2a7819a7'; const currentRoutesHash = '3d180d52c663d173a6be791ef411ed01'; diff --git a/test/utils/fixtures/fixtures.json b/test/utils/fixtures/fixtures.json index fd6f764762..10fde0180a 100644 --- a/test/utils/fixtures/fixtures.json +++ b/test/utils/fixtures/fixtures.json @@ -69,6 +69,10 @@ "name": "Admin Integration", "description": "External Apps" }, + { + "name": "Ghost Explore Integration", + "description": "Internal Integration for the Ghost Explore directory" + }, { "name": "DB Backup Integration", "description": "Internal DB Backup Client" @@ -787,6 +791,13 @@ "type": "builtin", "api_keys": [{"type": "admin"}] }, + { + "slug": "ghost-explore", + "name": "Ghost Explore", + "description": "Built-in Ghost Explore integration", + "type": "internal", + "api_keys": [{"type": "admin", "role": "Ghost Explore Integration"}] + }, { "slug": "ghost-backup", "name": "Ghost Backup",