ezpaarse-project/ezpaarse

View on GitHub
client/store/settings.js

Summary

Maintainability
D
2 days
Test Coverage
// eslint-disable-next-line import/no-extraneous-dependencies
import Vue from 'vue';
import { isEqual } from 'lodash';
import api from './api';

const defaultSettings = {
  fullName: '',
  country: '',
  headers: [],
  cryptedFields: ['host', 'login'],
  dateFormat: '',
  logType: '',
  logFormat: '',
  forceParser: '',
  outputFormat: 'text/csv',
  tracesLevel: 'info',
  notificationMails: [],
  addedFields: [],
  removedFields: [],
  additionalsMiddlewares: []
};

/**
 * Get settings from a predefined object
 * @param  {String} setting predefined setting
 * @return {Object}         settings
 */
function parseSettings (predefined) {
  if (!predefined || !predefined.headers) { return null; }

  const settings = JSON.parse(JSON.stringify(defaultSettings));

  settings.fullName = predefined.fullName;
  settings.country = predefined.country;
  settings.predefined = predefined.predefined;
  settings.id = predefined.id;

  // Index headers by lowercased name
  const headers = {};
  Object.entries(predefined.headers).forEach(([name, value]) => {
    headers[name.toLowerCase()] = { name, value };
  });

  if (headers['ezpaarse-middlewares']) {
    const { value: mwString } = headers['ezpaarse-middlewares'];

    if (!/^\(\s*(before|after|only)\s*(.*?)\s*\)(.+)$/i.test(mwString)) {
      settings.additionalsMiddlewares = mwString.split(',').map(mw => mw.trim()).filter(mw => mw);
      delete headers['ezpaarse-middlewares'];
    }
  }

  if (headers['date-format']) {
    settings.dateFormat = headers['date-format'].value;
    delete headers['date-format'];
  }
  if (headers['force-parser']) {
    settings.forceParser = headers['force-parser'].value;
    delete headers['force-parser'];
  }
  if (headers['traces-level']) {
    settings.tracesLevel = headers['traces-level'].value;
    delete headers['traces-level'];
  }

  if (headers['accept']) {
    const { value } = headers['accept'];
    if (['application/json', 'text/csv', 'text/tab-separated-values'].indexOf(value) !== -1) {
      settings.outputFormat = value;
      delete headers['accept'];
    }
  }

  if (headers['output-fields']) {
    const outputFields = headers['output-fields'].value.split(',').map(f => f.trim()).filter(f => f);
    outputFields.forEach(field => {
      if (field.charAt(0) === '-') {
        settings.removedFields.push(field.substr(1));
      } else {
        settings.addedFields.push(field.substr(1));
      }
    });

    delete headers['output-fields'];
  }

  if (headers['crypted-fields']) {
    const cryptedFields = headers['crypted-fields'].value;

    if (cryptedFields.toLowerCase() === 'none') {
      settings.cryptedFields = [];
    } else {
      settings.cryptedFields = cryptedFields.split(',').map(f => f.trim()).filter(f => f);
    }

    delete headers['crypted-fields'];
  }

  if (headers['filter-platforms']) {
    const filterPlatforms = headers['filter-platforms'].value;

    if (filterPlatforms) {
      settings.filterPlatforms = filterPlatforms.split(',').map(f => f.trim()).filter(f => f);
    }

    delete headers['filter-platforms'];
  }

  if (headers['ezpaarse-job-notifications']) {
    const { value } = headers['ezpaarse-job-notifications'];
    const reg = /mail<(.+?)>/g;

    settings.notificationMails = [];
    let match = reg.exec(value);

    while (match) {
      settings.notificationMails.push(match[1]);
      match = reg.exec(value);
    }

    delete headers['ezpaarse-job-notifications'];
  }

  Object.values(headers).forEach(({ name, value }) => {
    if (/^Log-Format-[a-z]+$/i.test(name)) {
      settings.logFormat = value;
      settings.logType = name.substr(11).toLowerCase();
    } else if (name.toLowerCase() === 'ezpaarse-middlewares') {
      settings.headers.push({
        name,
        value: value.split(',').map(r => r.trim())
      });
    } else {
      settings.headers.push({ name, value });
    }
  });

  return settings;
}

/**
 * Returns settings as a list of headers for a request
 */
function getHeaders (settings) {
  if (!settings) { return {}; }
  const headers = {};

  if (settings.outputFormat) { headers['Accept'] = settings.outputFormat; }
  if (settings.forceParser) { headers['Force-Parser'] = settings.forceParser; }
  if (settings.dateFormat) { headers['Date-Format'] = settings.dateFormat; }
  if (settings.tracesLevel) { headers['Traces-Level'] = settings.tracesLevel; }

  if (settings.logType && settings.logFormat) {
    headers[`Log-Format-${settings.logType}`] = settings.logFormat;
  }

  // Create notification header
  if (Array.isArray(settings.notificationMails) && settings.notificationMails.length > 0) {
    headers['ezPAARSE-Job-Notifications'] = settings.notificationMails.map(mail => `mail<${mail.trim()}>`).join(',');
  }

  if (settings.cryptedFields && settings.cryptedFields.length > 0) {
    headers['Crypted-Fields'] = settings.cryptedFields.join(',');
  } else {
    headers['Crypted-Fields'] = 'none';
  }

  if (settings.filterPlatforms && settings.filterPlatforms.length > 0) {
    headers['filter-platforms'] = settings.filterPlatforms.join(',');
  }

  // Create Output-Fields headers
  if (settings.addedFields || settings.removedFields) {
    const plus = (settings.addedFields || []).map(f => `+${f}`);
    const minus = (settings.removedFields || []).map(f => `-${f}`);

    if ((plus.length + minus.length) > 0) {
      headers['Output-Fields'] = plus.concat(minus).join(',');
    }
  }

  const middlewares = settings.additionalsMiddlewares;

  if (Array.isArray(middlewares) && middlewares.length > 0) {
    headers['ezPAARSE-Middlewares'] = middlewares.join(',');
  }

  if (Array.isArray(settings.headers)) {
    settings.headers.forEach(({ name, value }) => {
      let headerValue = value;
      if (!name || !value) { return; }

      // Look case-insensitively for a header with the same name
      const headerNames = Object.keys(headers);
      const existingHeader = headerNames.find(h => h.toLowerCase() === name.toLowerCase());

      if (name.toLowerCase() === 'ezpaarse-middlewares') {
        if (Array.isArray(headerValue)) {
          headerValue = headerValue.join(',');
        }
      }

      if (existingHeader) {
        headers[existingHeader] = headerValue;
      } else {
        headers[name] = headerValue;
      }
    });
  }

  return headers;
}

export default {
  state: () => ({
    predefinedSettings: [],
    customSettings: [],
    countries: [],
    treatments: [],
    settings: JSON.parse(JSON.stringify(defaultSettings))
  }),
  getters: {
    allSettings (state) {
      return state.predefinedSettings.concat(state.customSettings);
    },
    hasBeenModified (state) {
      if (!state.settings || !state.settings.id) {
        return !isEqual(state.settings, defaultSettings);
      }

      const allSettings = state.predefinedSettings.concat(state.customSettings);
      const selectedSetting = allSettings.find(s => s.id === state.settings.id);
      return !isEqual(state.settings, parseSettings(selectedSetting));
    }
  },
  mutations: {
    SET_PREDEFINED_SETTINGS (state, data) {
      Vue.set(state, 'predefinedSettings', data);
    },
    SET_CUSTOM_SETTINGS (state, data) {
      Vue.set(state, 'customSettings', data);
    },
    SET_COUNTRIES (state, data) {
      Vue.set(state, 'countries', data);
    },
    SET_SETTINGS (state, settings) {
      Vue.set(state, 'settings', settings);
    },
    SET_FIELD (state, { name, value }) {
      Vue.set(state.settings, name, value);
    },
    ADD_HEADER (state, name, value) {
      state.settings.headers.push({ name: name || '', value: value || '' });
    },
    REMOVE_HEADER (state, index) {
      state.settings.headers.splice(index, 1);
    },
    SET_HEADER_NAME (state, { index, value }) {
      const header = state.settings.headers[index];
      if (header) {
        header.name = value;
      }
    },
    SET_HEADER_VALUE (state, { index, value }) {
      const header = state.settings.headers[index];
      if (header) {
        header.value = value;
      }
    }
  },
  actions: {
    async GET_PREDEFINED_SETTINGS ({ commit }) {
      const data = await api.getPredefinedSettings();
      // Change object into an array with key as ID
      const settings = Object.entries(data).map(([id, setting]) => ({
        id,
        ...setting,
        predefined: true
      }));

      commit('SET_PREDEFINED_SETTINGS', settings);
      commit('SET_CUSTOM_SETTINGS', await api.getCustomSettings());
    },
    async GET_CUSTOM_PREDEFINED_SETTINGS ({ commit }) {
      const data = await api.getCustomSettings();
      commit('SET_CUSTOM_SETTINGS', data.map(d => parseSettings(d)));
    },
    APPLY_PREDEFINED_SETTINGS ({ commit, getters, dispatch }, key) {
      const settings = getters.allSettings.find(s => s.id === key);

      if (settings) {
        commit('SET_SETTINGS', parseSettings(settings));
      } else {
        dispatch('RESET_SETTINGS');
      }
    },
    SET_FIELD ({ commit }, { name, value }) {
      if (name) {
        commit('SET_FIELD', { name, value });
      }
    },
    ADD_HEADER ({ commit }, name, value) {
      commit('ADD_HEADER', name, value);
    },
    REMOVE_HEADER ({ commit }, index) {
      commit('REMOVE_HEADER', index);
    },
    SET_HEADER_NAME ({ commit }, { index, value }) {
      commit('SET_HEADER_NAME', { index, value });
    },
    SET_HEADER_VALUE ({ commit }, { index, value }) {
      commit('SET_HEADER_VALUE', { index, value });
    },
    GET_HEADERS ({ state }) {
      return getHeaders(state.settings);
    },
    RESET_SETTINGS ({ commit }) {
      commit('SET_SETTINGS', JSON.parse(JSON.stringify(defaultSettings)));
    },
    SAVE_CUSTOM_PREDEFINED_SETTINGS (ctx, settings) {
      const { id, fullName, country } = settings;
      return api.saveCustomSettings({
        id,
        fullName,
        country,
        headers: getHeaders(settings)
      });
    },
    UPDATE_CUSTOM_PREDEFINED_SETTINGS (ctx, settings) {
      const { id, fullName, country } = settings;
      return api.updateCustomSettings({
        id,
        fullName,
        country,
        headers: getHeaders(settings)
      });
    },
    async GET_COUNTRIES ({ commit }) {
      commit('SET_COUNTRIES', await api.getCountries());
    },
    async REMOVE_CUSTOM_PREDEFINED_SETTINGS ({ commit, dispatch, state }, id) {
      await api.removeCustomSettings(id);
      commit('SET_CUSTOM_SETTINGS', state.customSettings.filter(s => s.id !== id));
      dispatch('RESET_SETTINGS');
    },
    uploadFile ({ commit }, setting) {
      commit('SET_SETTINGS', parseSettings(setting));
    }
  }
};