-
-
Notifications
You must be signed in to change notification settings - Fork 224
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
579 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
const Command = require('../command'); | ||
|
||
class ImportCommand extends Command { | ||
async run(argv) { | ||
const importTask = require('../tasks/import'); | ||
const StartCommand = require('./start'); | ||
const {SystemError} = require('../errors'); | ||
|
||
const instance = this.system.getInstance(); | ||
const isRunning = await instance.running(); | ||
|
||
if (!isRunning) { | ||
const shouldStart = await this.ui.confirm('Ghost instance is not currently running. Would you like to start it?'); | ||
|
||
if (!shouldStart) { | ||
throw new SystemError('Ghost instance is not currently running'); | ||
} | ||
|
||
await this.runCommand(StartCommand, argv); | ||
} | ||
|
||
await importTask(this.ui, instance, argv.file); | ||
} | ||
} | ||
|
||
ImportCommand.description = 'Import a Ghost export'; | ||
ImportCommand.params = '[file]'; | ||
|
||
module.exports = ImportCommand; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
const fs = require('fs-extra'); | ||
const got = require('got'); | ||
const get = require('lodash/get'); | ||
const semver = require('semver'); | ||
const FormData = require('form-data'); | ||
const {Cookie} = require('tough-cookie'); | ||
|
||
const {SystemError} = require('../../errors'); | ||
|
||
const bases = { | ||
1: '/ghost/api/v0.1', | ||
2: '/ghost/api/v2/admin', | ||
3: '/ghost/api/v3/admin' | ||
}; | ||
|
||
function getBaseUrl(version, url) { | ||
const basePath = bases[semver.major(version)]; | ||
|
||
if (!basePath) { | ||
throw new SystemError(`Unsupported version: ${version}`); | ||
} | ||
|
||
return `${url.replace(/\/?$/, '')}${basePath}`; | ||
} | ||
|
||
async function isSetup(version, url) { | ||
const baseUrl = getBaseUrl(version, url); | ||
const {body} = await got('/authentication/setup/', {baseUrl, json: true}); | ||
return get(body, 'setup[0].status', false); | ||
} | ||
|
||
async function setup(version, url, data) { | ||
const baseUrl = getBaseUrl(version, url); | ||
const {name, email, password, blogTitle} = data; | ||
const body = { | ||
setup: [{name, email, password, blogTitle}] | ||
}; | ||
|
||
await got.post('/authentication/setup/', {baseUrl, body, json: true}); | ||
} | ||
|
||
async function getAuthOpts(version, url, {username, password}) { | ||
const baseUrl = getBaseUrl(version, url); | ||
|
||
if (semver.major(version) === 1) { | ||
const {body: configBody} = await got('/configuration/', {baseUrl, json: true}); | ||
const {clientId, clientSecret} = get(configBody, 'configuration[0]', {}); | ||
const {body: authBody} = await got.post('/authentication/token/', { | ||
baseUrl, | ||
json: true, | ||
form: true, | ||
body: { | ||
grant_type: 'password', | ||
client_id: clientId, | ||
client_secret: clientSecret, | ||
username, | ||
password | ||
} | ||
}); | ||
|
||
return { | ||
baseUrl, | ||
headers: { | ||
Authorization: `Bearer ${authBody.access_token}` | ||
} | ||
}; | ||
} | ||
|
||
const {headers} = await got.post('/session/', { | ||
baseUrl, | ||
headers: { | ||
Origin: url, | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify({username, password}) | ||
}); | ||
|
||
const cookies = (headers['set-cookie'] || []) | ||
.map(Cookie.parse) | ||
.filter(Boolean) | ||
.map(c => c.cookieString()); | ||
|
||
return { | ||
baseUrl, | ||
headers: { | ||
Origin: url, | ||
Cookie: cookies | ||
} | ||
}; | ||
} | ||
|
||
async function runImport(version, url, auth, exportFile) { | ||
const authOpts = await getAuthOpts(version, url, auth); | ||
const body = new FormData(); | ||
|
||
body.append('importfile', fs.createReadStream(exportFile)); | ||
await got.post('/db/', {...authOpts, body}); | ||
} | ||
|
||
module.exports = { | ||
getBaseUrl, | ||
isSetup, | ||
setup, | ||
runImport | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
const validator = require('validator'); | ||
|
||
const parseExport = require('./parse-export'); | ||
const {isSetup, setup, runImport} = require('./api'); | ||
|
||
async function task(ui, instance, exportFile) { | ||
const {data} = parseExport(exportFile); | ||
const url = instance.config.get('url'); | ||
|
||
const {email: username} = data; | ||
const {password} = await ui.prompt({ | ||
type: 'password', | ||
name: 'password', | ||
message: 'Enter the password for your Ghost user account', | ||
validate: val => validator.isLength(`${val}`, {min: 10}) || 'Password must be at least 10 characters long' | ||
}); | ||
|
||
return ui.listr([{ | ||
title: 'Running blog setup', | ||
task: () => setup(instance.version, url, {...data, password}), | ||
skip: () => isSetup(instance.version, url) | ||
}, { | ||
title: 'Running blog import', | ||
task: () => runImport(instance.version, url, {username, password}, exportFile) | ||
}]); | ||
} | ||
|
||
module.exports = task; | ||
module.exports.parseExport = parseExport; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
const fs = require('fs-extra'); | ||
const get = require('lodash/get'); | ||
const find = require('lodash/find'); | ||
const semver = require('semver'); | ||
|
||
const {SystemError} = require('../../errors'); | ||
|
||
const pre1xVersion = /^00[1-9]$/; | ||
|
||
/* eslint-disable camelcase */ | ||
function parse(content) { | ||
const data = get(content, 'db[0].data', content.data || null); | ||
const {id: role_id} = find(data.roles, {name: 'Owner'}) || {}; | ||
const {user_id} = find(data.roles_users, {role_id}) || {}; | ||
const {name, email} = find(data.users, {id: user_id}) || {}; | ||
const {value: blogTitle} = find(data.settings, {key: 'title'}) || {}; | ||
|
||
return {name, email, blogTitle}; | ||
} | ||
/* eslint-enable camelcase */ | ||
|
||
module.exports = function parseExport(file) { | ||
let content = {}; | ||
|
||
try { | ||
content = fs.readJsonSync(file); | ||
} catch (err) { | ||
throw new SystemError({ | ||
message: 'Import file not found or is not valid JSON', | ||
err | ||
}); | ||
} | ||
|
||
const version = get(content, 'db[0].meta.version', get(content, 'meta.version', null)); | ||
if (!version) { | ||
throw new SystemError('Unable to determine export version'); | ||
} | ||
|
||
const validVersion = pre1xVersion.test(version) || semver.valid(version); | ||
if (!validVersion) { | ||
throw new SystemError(`Unrecognized export version: ${version}`); | ||
} | ||
|
||
const data = parse(content); | ||
return { | ||
version: pre1xVersion.test(version) ? '0.11.14' : version, | ||
data | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.