On-Premise installation

On-Premise plugins

Add plugins in your On-Premise installation

Introduction

Carbone On-premise gives the possibility to override functions at specific moments to add custom features, such as adding analytics, store data on a specific storage provider, custom authentication, etc... It is possible through:

Language

Plugins and middlewares can be only written using NodeJS.

Lifecycle

image

It is recommended to create a separate NodeJS repository:

# Create a separate folder
mkdir carbone-on-premise

# Initialize a node repository
npm init

# Move the carbone binary inside this folder
mv /path/to/carbone/binary ./carbone-on-premise

When Carbone On-premise is executed for the first time, default folders are created automatically (explanation here). Custom plugins MUST be inserted in the plugin folder.

Write template hook

To override template storage, create the file storage.js in the plugin folder. It will be possible to upload your template into an Object Storage, S3 API or other storage systems. Export a function called writeTemplate with 5 arguments:

Additional file informations are available the request header:

const fs = require('fs');
const path = require('path');
const os = require('os');

function writeTemplate (req, res, templateId, templatePathTemp, callback) {
  fs.rename(templatePathTemp, path.join(os.tmpdir(), 'PREFIX_' + templateId), (err) => {
    if (err) {
      return callback(err);
    }
    return callback(null);
  });
}

// Export the writeTemplate function
module.exports = {
  writeTemplate
}

Read template hook

To override template reading, the file storage.js in the plugin folder has to be created. The function to explort is readTemplate which is described as follow:

function readTemplate (req, templateId, callback) {
  // Read your template and return a local path for carbone
}

module.exports = {
  readTemplate
}

The function must return a local path because Carbone needs to read the file from a disk.

Delete template hook

To override template deletion, add the function deleteTemplate in the storage.js file in the plugin folder and export it, for instance:

// You can access req and res.
// For example, if you store your template on amazon S3, you could delete it
function deleteTemplate (req, res, templateId, callback) {
  // Delete the template and either return a local path to unlink it or just use res to return a response
  return callback(null, path.join(os.tmpdir(), 'PREFIX_' + templateId));
}

module.exports = {
  deleteTemplate
}

Before generation hook

Before render plugin can be used to add pre or post rendering behavior, such as adding a prefix to the rendered filename. To do this, add a function beforeRender and/or afterRender in the storage.js plugin and export it. In these functions, the req request variable is available and options can be altered.

function beforeRender (req, res, carboneData, carboneOptions, next) {
  // add a prefix to rendered filename
  carboneOptions.renderPrefix = 'myPrefix';
  next(null);
}

After generation hook

To override render writing, add the function afterRender in the storage.js file in the plugin folder and export it.

function afterRender (req, res, err, reportPath, reportName, statistics, next) {
  // Write or rename your render
  // TemplateID available: req.params.templateId
  return next(null)
}

module.exports = {
  afterRender
}

For example, this function can be used to move the render on Buckets, or it is also possible to change the response object:

res.send({
  success: true,
  data: {
    newField: reportName
  }
});

The statistics argument return an object with:

{
  "renderId"  : "",
  "template"  : "filename",
  "user"      : "if authentication enabled, the user ID is returned, it is coming from the JWT token",
  "options"   : "Rendering options as an object",
  "jsonSize"  : "size of the JSON data-set as bytes"
}

Read reports hook

The function readRender has to be exported in the storage.js located in the plugin folder.

function readRender (req, res, renderName, next) {
  // Return the directly render or a local path
}

This function can be used to return directly the file using res , it is also possible to return the new render name, or return a path from the afterRender function.

// Return the new render name
function readRender (req, res, renderName, next) {
  return next(null, 'newRenderName')
}

// OR

// Return the new path on disk
function (req, res, renderName, next) {
  return next(null, renderName, '/new/path/on/disk')
}

Authentication hook

For the authentication checking, it is possible to define a new location to store public keys. The file authentication.js has to be created in the plugin folder. Export the function getPublicKey described as follow:

const fs = require('fs');
const path = require('path');

/**
 * @param {Object} req : Request from the request
 * @param {Object} res : Response from the request
 * @param {Object} payload : https://github.com/Ideolys/kitten-jwt#api-usage to see object details
 * @param {Function} callback : Function to call at the end
 * @return (publicKeyContent)
 */
function getPublicKey (req, res, payload, callback) {
  // Read the public key on disk or somewhere else
  fs.readFile(path.join(__dirname, '..', 'config', 'key.pub'), 'utf8', (err, content) => {
    if (err) {
      return callback(new Error('Cannot read public key ' + err.toString()));
    }

    // Return the public key content in the callback
    return callback(content)
  });
}

// Export the getPublicKey function
module.exports = {
  getPublicKey
}

HTTP Request hook

Middlewares can be added before or after route. It can be useful to log or get stats about requests. Add a middlewares.js file in the plugin folder and export two arrays:

function beforeMiddleware (req, res, next) {
  console.log('I am executed before all route')
  return next()
}

function afterMiddleware (req, res, next) {
  console.log('I am executed after all route')
}

module.exports = {
  before: [beforeMiddleware], // Middlewares in this array will be executed before routes
  after: [afterMiddleware] // Middlewares in this array will be executed after routes
}