Skip to content
Snippets Groups Projects
Commit 855c2d14 authored by Mihail Dunaev's avatar Mihail Dunaev
Browse files

refactor(ink-backend): perform sanity checks at root of middleware

instead of doing sanity checks in each function, we can assume they will not be used independently
and check for missing config only once

re #351
parent 467b1ded
No related branches found
No related tags found
No related merge requests found
...@@ -22,11 +22,13 @@ function checkInkConfig(inkConfig) { ...@@ -22,11 +22,13 @@ function checkInkConfig(inkConfig) {
/** /**
* Sanity checks on inkConfig * Sanity checks on inkConfig
* *
* config must have pubsweet-component-ink-backend with * @param {object} inkConfig - pubsweet-component-ink-backend config
* { inkEndpoint, email, password, recipes, pusher }
* *
* config.get will throw if there is no pubsweet-component-ink-backend * @typedef {object} inkConfigReturn
* so no need to worry about that * @property {boolean} correct - ink config is correct or not
* @property {string} errorMessage - error message to be printed
*
* @returns {inkConfigReturn}
* *
* More at * More at
* https://gitlab.coko.foundation/pubsweet/pubsweet/tree/master/packages/components/packages/Ink-server * https://gitlab.coko.foundation/pubsweet/pubsweet/tree/master/packages/components/packages/Ink-server
...@@ -50,13 +52,20 @@ function checkInkConfig(inkConfig) { ...@@ -50,13 +52,20 @@ function checkInkConfig(inkConfig) {
maxRetries: Joi.number(), maxRetries: Joi.number(),
} }
const { error } = Joi.validate(inkConfig, inkSchema) const { error } = Joi.validate(inkConfig, inkSchema)
if (error === null) return if (error === null) return { correct: true, errorMessage: '' }
// error here // error here
logger.warn(baseInkConfigErrorMessage + error) logger.warn(baseInkConfigErrorMessage + error)
return {
correct: false,
errorMessage: baseInkConfigErrorMessage + error,
}
} }
checkInkConfig(inkConfig) const {
correct: correctInkConfig,
errorMessage: inkConfigErrorMessage,
} = checkInkConfig(inkConfig)
// Generate the absolute URL // Generate the absolute URL
const inkUrl = path => `${inkConfig.inkEndpoint}api/${path}` const inkUrl = path => `${inkConfig.inkEndpoint}api/${path}`
...@@ -64,23 +73,13 @@ const inkUrl = path => `${inkConfig.inkEndpoint}api/${path}` ...@@ -64,23 +73,13 @@ const inkUrl = path => `${inkConfig.inkEndpoint}api/${path}`
// Connect to the INK Pusher/Slanger endpoint // Connect to the INK Pusher/Slanger endpoint
const connectToPusher = ({ appKey, ...options }) => new Pusher(appKey, options) const connectToPusher = ({ appKey, ...options }) => new Pusher(appKey, options)
let pusher let pusher
if (typeof inkConfig.pusher !== 'undefined') { if (correctInkConfig) {
pusher = connectToPusher(inkConfig.pusher) pusher = connectToPusher(inkConfig.pusher)
} }
// Sign in // Sign in
const authorize = async () => { const authorize = async () =>
if (typeof inkConfig.email === 'undefined') { rp({
throw new Error(
`${baseInkConfigErrorMessage}ink config is missing the email field`,
)
}
if (typeof inkConfig.password === 'undefined') {
throw new Error(
`${baseInkConfigErrorMessage}ink config is missing the password field`,
)
}
return rp({
method: 'POST', method: 'POST',
uri: inkUrl('auth/sign_in'), uri: inkUrl('auth/sign_in'),
formData: { formData: {
...@@ -95,16 +94,10 @@ const authorize = async () => { ...@@ -95,16 +94,10 @@ const authorize = async () => {
client: res.headers.client, client: res.headers.client,
'access-token': res.headers['access-token'], 'access-token': res.headers['access-token'],
})) }))
}
// Upload file to INK and execute the recipe // Upload file to INK and execute the recipe
const upload = async (recipeId, inputFile, auth) => { const upload = async (recipeId, inputFile, auth) =>
if (typeof inkConfig.email === 'undefined') { rp({
throw new Error(
`${baseInkConfigErrorMessage}ink config is missing the email field`,
)
}
return rp({
method: 'POST', method: 'POST',
uri: inkUrl(`recipes/${recipeId}/execute`), uri: inkUrl(`recipes/${recipeId}/execute`),
headers: { headers: {
...@@ -117,16 +110,10 @@ const upload = async (recipeId, inputFile, auth) => { ...@@ -117,16 +110,10 @@ const upload = async (recipeId, inputFile, auth) => {
json: true, json: true,
timeout: 60 * 60 * 1000, // 3600 seconds timeout: 60 * 60 * 1000, // 3600 seconds
}) })
}
// Download the output file // Download the output file
const download = async (chainId, auth, outputFileName) => { const download = async (chainId, auth, outputFileName) =>
if (typeof inkConfig.email === 'undefined') { rp({
throw new Error(
`${baseInkConfigErrorMessage}ink config is missing the email field`,
)
}
return rp({
uri: inkUrl(`process_chains/${chainId}/download_output_file`), uri: inkUrl(`process_chains/${chainId}/download_output_file`),
qs: { qs: {
relative_path: outputFileName, relative_path: outputFileName,
...@@ -136,16 +123,10 @@ const download = async (chainId, auth, outputFileName) => { ...@@ -136,16 +123,10 @@ const download = async (chainId, auth, outputFileName) => {
...auth, ...auth,
}, },
}) })
}
// Find the ID of a recipe by name // Find the ID of a recipe by name
const findRecipeId = async (name = 'Editoria Typescript', auth) => { const findRecipeId = async (name = 'Editoria Typescript', auth) =>
if (typeof inkConfig.email === 'undefined') { rp({
throw new Error(
`${baseInkConfigErrorMessage}ink config is missing the email field`,
)
}
return rp({
method: 'GET', method: 'GET',
uri: inkUrl('recipes'), uri: inkUrl('recipes'),
headers: { headers: {
...@@ -158,7 +139,6 @@ const findRecipeId = async (name = 'Editoria Typescript', auth) => { ...@@ -158,7 +139,6 @@ const findRecipeId = async (name = 'Editoria Typescript', auth) => {
return recipe ? recipe.id : null return recipe ? recipe.id : null
}) })
}
const process = async (inputFile, options) => { const process = async (inputFile, options) => {
const auth = await authorize().catch(err => { const auth = await authorize().catch(err => {
...@@ -167,11 +147,6 @@ const process = async (inputFile, options) => { ...@@ -167,11 +147,6 @@ const process = async (inputFile, options) => {
}) })
// either use the recipe id from the configuration or search for it by name // either use the recipe id from the configuration or search for it by name
if (typeof inkConfig.recipes === 'undefined') {
throw new Error(
`${baseInkConfigErrorMessage}ink config is missing the recipes field`,
)
}
const recipeId = const recipeId =
inkConfig.recipes[options.recipe] || inkConfig.recipes[options.recipe] ||
(await findRecipeId(options.recipe, auth)) (await findRecipeId(options.recipe, auth))
...@@ -186,11 +161,6 @@ const process = async (inputFile, options) => { ...@@ -186,11 +161,6 @@ const process = async (inputFile, options) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// subscribe to the "process chain execution" channel // subscribe to the "process chain execution" channel
if (typeof pusher === 'undefined') {
throw new Error(
`${baseInkConfigErrorMessage}ink config is missing the pusher field`,
)
}
const channel = pusher.subscribe('process_chain_execution') const channel = pusher.subscribe('process_chain_execution')
// wait for a "subscription succeeded" event // wait for a "subscription succeeded" event
...@@ -255,6 +225,10 @@ const process = async (inputFile, options) => { ...@@ -255,6 +225,10 @@ const process = async (inputFile, options) => {
const InkBackend = app => { const InkBackend = app => {
// TODO: authentication on this route // TODO: authentication on this route
app.use('/api/ink', (req, res, next) => { app.use('/api/ink', (req, res, next) => {
if (!correctInkConfig) {
next(new Error(inkConfigErrorMessage))
return
}
const fileStream = new Busboy({ headers: req.headers }) const fileStream = new Busboy({ headers: req.headers })
fileStream.on( fileStream.on(
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment