platform-helpers/tiq-helper.js

const axios = require('axios');
const qs = require('qs');
const crypto = require('crypto');
const rootRequire = require('rpcm-root-require');
rootRequire('/platform-helpers/string-extensions');

/**
 * IQ Helper class.
 *
 * @static
 * @requires axios
 * @requires qs
 * @requires crypto
 * @requires string-extensions
 */

class TiqHelper {
  /**
   * Keeps session details in-memory whilst instance is in use
   * @private
   */
  static sessionDetails = { utk: null, jsessionId: null };

  /**
   * Provides an object with one TIQ session details.
   * Keeps session details in-memory throughout the context.
   *
   * @method
   * @public
   * @param {string} account the CDH profile to use for authentication / token generation
   * @param {string} profile the CDH profile to use for authentication / token generation
   * @param {string} tealUser the Tealium user email
   * @param {string} tealPass the Tealium user pass
   * @returns {object} { utk, jsessionId }
   */
  static getTiqSessionDetails = async (account, profile, tealUser, tealPass) => {
    const pingCallStatus = await TiqHelper.ping(account, profile, TiqHelper.sessionDetails.utk, TiqHelper.sessionDetails.jsessionId);

    switch (pingCallStatus) {
      case 200: {
        return TiqHelper.sessionDetails;
      }
      case 401: {
        const loginRequest = await TiqHelper.loginUser(tealUser, tealPass);
        const setCookies = loginRequest.headers['set-cookie'] || [];
        const re = /^JSESSIONID=([^;]*);/;
        TiqHelper.sessionDetails = { utk: null, jsessionId: null };
        if (loginRequest.data.utk) TiqHelper.sessionDetails.utk = loginRequest.data.utk;
        for (let i = 0; i < setCookies.length; i++) {
          const match = re.exec(setCookies[i]);
          if (match && match[1]) {
            TiqHelper.sessionDetails.jsessionId = match[1];
            break;
          }
        }
        return TiqHelper.sessionDetails;
      }
      default: {
        TiqHelper.sessionDetails = { utk: null, jsessionId: null };
        return TiqHelper.sessionDetails;
      }
    }
  };

  /**
   * Sends a Teal TIQ login request.
   *
   * @method
   * @param {string} email
   * @param {string} pass
   * @returns {object} An axios network call providing session details if successful
   */
  static loginUser = async (email, pass) => {
    return await axios.post('https://api.tealiumiq.com/v1/login', qs.stringify({
      username: email,
      password: pass
    }), {
      headers: { 'content-type': 'application/x-www-form-urlencoded' }
    });
  };

  /**
   * Pings Teal TIQ to check session status
   *
   * @method
   * @param {string} account
   * @param {string} profile
   * @param {string} tiqUtk
   * @param {string} jSessionId
   * @returns {object} An axios network call
   */
  static ping = async (account, profile, tiqUtk, jSessionId) => {
    try {
      const pingCall = await axios.post('https://my.tealiumiq.com/urest/ping?utk={0}'.format(tiqUtk), {
        account: account,
        profile: profile
      }, {
        headers: {
          Cookie: 'JSESSIONID={0}'.format(jSessionId),
          Accept: 'application/json'
        }
      });
      return pingCall.status;
    } catch (error) {
      return error && error.response && error.response.status;
    }
  };

  /**
   * Provides a new GUID
   *
   * @method
   * @returns {string} A new random GUID
   */
  static generateNewVisitorId = () => {
    return crypto.randomBytes(16).toString('hex');
  };

  /**
   * Provides the UTAG environment based on the {{profile}} of the utag.js URL of the HTML script tag
   *
   * @method
   * @param {Array} collection A collection of strings
   *
   * @example
   * const rootRequire = require('rpcm-root-require');
   * const tiqHelper = rootRequire('/platform-helpers/tiq-helper');
   *
   * // DOM query
   * var collectionTags = jQuery("script").map((i, el)=> el.src);
   *
   * // get environment
   * const env = tiqHelper.getTealiumEnvironment(collectionTags);
   *
   * // check
   * console.log(env); // should print the environment
   *
   * @returns {string} The current tealium environment or undefined if not found
   */
  static getTealiumEnvironment = (collection) => {
    try {
      const re = /\/([^/]*)\/utag\.js(\?.*)*$/;
      for (let i = 0; i < collection.length; i++) {
        const result = re.exec(collection[i]); // can be null
        if (result && result[1]) { // [1] is the result of the match
          return result[1];
        }
      }
    } catch (error) {}
  };
}

module.exports = TiqHelper;