leap-protocol/leap-js

View on GitHub
src/configVerifier.js

Summary

Maintainability
C
7 hrs
Test Coverage
// Copyright © 2020 Hoani Bryson
// License: MIT (https://mit-license.org/)
//
// Configuration Verifier
//
// Verifies the a L3aP protocol configuration object
//

const dataVerifier = require('./configDataVerifier.js');

exports.ConfigVerifier = class ConfigVerifier {
  constructor() {
    this._data_verifier = new dataVerifier.DataVerifier()
    this._reset();
  }

  _reset() {
    this.section = "";
    this.failure = "";
    this._data_verifier.reset();
  }

  verify(config) {
    this._reset();

    if (config.length == 0) {
      this.section = "Config";
      this.print_failure = "Configuration is empty";
    }
    else if (this.verify_category(config) == false) {
      this.section = "Category";
    }
    else if (this.verify_version(config) == false) {
      this.section = "Version";
    }
    else if (this.verify_symbols(config) == false) {
      this.section = "Symbols";
    }
    else if (this._data_verifier.verify(config, "root") == false) {
      this.section = this._data_verifier.get_section();
      this.failure = this._data_verifier.get_failure();
    }
    else {
      return true;
    }

    return false;
  }

  print_failure() {
    if (this.section != "") {
      console.log("---");
      console.log("Config Verification Failed");
      console.log("");
      console.log(`Section: ${this.section}`);
      console.log(`Failure: ${this.failure}`);
      console.log("---");
    }
  }

  verify_symbols(config) {
    const symbols = ["separator", "compound", "end"];

    for (let i in symbols) {
      const symbol = symbols[i];
      if ((symbol in config) == false) {
        this.failure = `Missing ${symbol} key in root data structure`;
        return false;
      }

      if ((typeof config[symbol] === "string") == false) {
        this.failure = `${symbol} must be assigned to a single character e.g. ">"`;
        return false;
      }

      if (/^[\W]{1}$/.exec(config[symbol]) == null) {
        this.failure = `${symbol} must be a single character and non-alphanumeric e.g. ">"`;
        return false;
      }
    }

    if ((config['separator'] == config['compound']) ||
      (config['separator'] == config['end']) ||
      (config['compound'] == config['end'])
    ) {
      this.failure = '"separator", "compound" and "end" characters must all be different from eachother';
      return false;
    }
    return true;
  }


  verify_category(config) {
    if (("category" in config) == false) {
      this.failure = "Missing category key in root data structure";
      return false;
    }

    const category = config['category'];
    const keys = Object.keys(category);
    const values = Object.values(category);

    if (keys.length == 0) {
      this.failure = 'There must be at least one category item';
      return false;
    }

    for (let i in keys) {
      const key = keys[i];
      if (/^[A-Za-z]/.exec(key) == null) {
        this.failure = "Category keys must be strings";
        return false;
      }

      if (/^[A-Za-z0-9\-_]+$/.exec(key) == null) {
        this.failure = "Category keys may only contain alphanumeric symbols, underscores(_) and dashes (-)";
        return false;
      }
    }


    for (let i in values) {
      const value = values[i];
      if ((typeof value === "string") == false) {
        this.failure = 'A category must be assigned to a single capital letter e.g. "C"';
        return false;
      }

      if (/^[A-Z]{1}$/.exec(value) == null) {
        this.failure = 'A category must be assigned to a single capital letter e.g. "C"';
        return false;
      }
    }

    return true;
  }


  verify_version(config) {
    if (("version" in config) == false) {
      this.failure = "Missing version key in root data structure";
    }
    else {
      const version = config["version"];
      const keys = Object.keys(version);
      const segments = ["major", "minor", "patch"];

      for (let i in segments) {
        const segment = segments[i];
        if ((segment in version) == false) {
          this.failure = `Missing "${segment}" in "version" data structure`;
          break;
        }

        if (Number.isInteger(version[segment]) == false) {
          this.failure = `"version" "${segment}" must be an integer`;
          break;
        }
      }

      if (keys.length != 3) {
        this.failure = '"version" must only contain items "major", "minor" and "patch"';
      }
    }

    return (this.failure === "");
  }
}