Ejemplo n.º 1
0
  var blacklist = _.reduce(apiDefinition.references, function (list, metadata, ptr) {
    var refPath = JsonRefs.pathFromPtr(ptr);

    list.push(JsonRefs.pathToPtr(refPath));

    return list;
  }, []);
Ejemplo n.º 2
0
 _.forEach(_.difference(_.keys(definedPathParameters), declaredPathParameters), function (name) {
   response.errors.push({
     code: 'MISSING_PATH_PARAMETER_DECLARATION',
     message: 'Path parameter is defined but is not declared: ' + name,
     path: JsonRefs.pathFromPtr(definedPathParameters[name])
   });
 });
Ejemplo n.º 3
0
 _.forEach(_.difference(referenceable, Object.keys(references)), function (ptr) {
   response.warnings.push({
     code: 'UNUSED_DEFINITION',
     message: 'Definition is not used: ' + ptr,
     path: JsonRefs.pathFromPtr(ptr)
   });
 });
Ejemplo n.º 4
0
  _.each(apiDefinition.references, function (refDetails, refPtr) {
    var refPath = JsonRefs.pathFromPtr(refPtr);
    var err;

    if (refDetails.missing) {
      err = {
        code: 'UNRESOLVABLE_REFERENCE',
        message: 'Reference could not be resolved: ' + refDetails.uri,
        path: refPath.concat('$ref')
      };

      if (_.has(refDetails, 'error')) {
        err.error = refDetails.error;
      }

      results.errors.push(err);
    } else if (refDetails.type === 'invalid') {
      results.errors.push({
        code: 'INVALID_REFERENCE',
        message: refDetails.error || 'Invalid JSON Reference',
        path: refPath.concat('$ref')
      });
    } else if (_.has(refDetails, 'warning')) {
      // json-refs only creates warnings for JSON References with superfluous properties which will be ignored
      results.warnings.push({
        code: 'EXTRA_REFERENCE_PROPERTIES',
        message: refDetails.warning,
        path: refPath
      });
    }
  });
Ejemplo n.º 5
0
  _.forEach(api.references, function (metadata, ptr) {
    var ptrPath = JsonRefs.pathFromPtr(ptr);

    if (!_.has(metadata, 'missing')) {
      addReference(metadata.uri, ptr);

      if (ptrPath[ptrPath.length - 2] === 'allOf') {
        addAncestor(JsonRefs.pathToPtr(ptrPath.slice(0, ptrPath.length - 2)), metadata.uri);
      }
    }
  });
Ejemplo n.º 6
0
  _.forEach(inheritanceDetails, function (details, ptr) {
    walkLineage(ptr, undefined, details.lineage);

    if (details.lineage.length > 1 && details.lineage[details.lineage.length - 1] === ptr ||
        details.parents[0] === ptr) {
      response.errors.push({
        code: 'CIRCULAR_INHERITANCE',
        lineage: [ptr].concat(details.lineage),
        message: 'Schema object inherits from itself: ' + ptr,
        path: JsonRefs.pathFromPtr(ptr)
      });
    }
  });
Ejemplo n.º 7
0
  _.forEach(apiDefinition.references, function (metadata, ptr) {
    var ptrPath = JsonRefs.pathFromPtr(ptr);

    if (!_.has(metadata, 'missing')) {
      // This reference is a document reference, record it for later
      if (['relative', 'remote'].indexOf(metadata.type) > -1 && metadata.fqURI.indexOf('#') === -1) {
        if (_.isUndefined(docReferences[metadata.fqURI])) {
          docReferences[metadata.fqURI] = [];
        }

        docReferences[metadata.fqURI].push(ptr);
      }

      addReference(metadata.fqURI, ptr);

      if (ptrPath[ptrPath.length - 2] === 'allOf') {
        addAncestor(JsonRefs.pathToPtr(ptrPath.slice(0, ptrPath.length - 2)), metadata.uri);
      }
    }
  });
Ejemplo n.º 8
0
/**
 * Object representing a parameter value.
 *
 * **Note:** Do not use directly.
 *
 * @param {module:sway.Parameter} parameterObject - The `Parameter` object
 * @param {*} raw - The original/raw value
 *
 * @property {Error} error - The error(s) encountered during processing/validating the parameter value
 * @property {module:sway.Parameter} parameterObject - The `Parameter` object
 * @property {*} raw - The original parameter value *(Does not take default values into account)*
 * @property {boolean} valid - Whether or not this parameter is valid based on its JSON Schema
 * @property {*} value - The processed value *(Takes default values into account and does type coercion when necessary
 * and possible)*.  This can the original value in the event that processing the value is impossible
 * *(missing schema type)* or `undefined` if processing the value failed *(invalid types, etc.)*.
 *
 * @constructor
 *
 * @memberof module:sway
 */
function ParameterValue (parameterObject, raw) {
  var pPath = JsonRefs.pathFromPtr(parameterObject.ptr);
  var processed = false;
  var schema = parameterObject.schema;
  var error;
  var isValid;
  var processedValue;

  this.parameterObject = parameterObject;
  this.raw = raw;

  // Use Object.defineProperty for 'value' to allow for lazy processing of the raw value
  Object.defineProperties(this, {
    error: {
      enumerable: true,
      get: function () {
        // Always call this.valid to ensure we validate the value prior to returning any values
        if (this.valid === true) {
          return undefined;
        } else {
          return error;
        }
      }
    },
    valid: {
      enumerable: true,
      get: function () {
        var result = {
          errors: [],
          warnings: []
        };
        var skipValidation = false;
        var value;
        var vError;

        if (_.isUndefined(isValid)) {
          isValid = true;
          value = this.value;

          if (_.isUndefined(error)) {
            try {
              // Validate requiredness
              if (parameterObject.required === true && _.isUndefined(value)) {
                vError = new Error('Value is required but was not provided');

                vError.code = 'REQUIRED';

                throw vError;
              }

              // Cases we do not want to do schema validation:
              //
              //   * The schema explicitly allows empty values and the value is empty
              //   * The schema allow optional values and the value is undefined
              //   * The schema defines a file parameter
              //   * The schema is for a string type with date/date-time format and the value is a date
              //   * The schema is for a string type and the value is a Buffer
              if ((_.isUndefined(parameterObject.required) || parameterObject.required === false) &&
                  _.isUndefined(value)) {
                skipValidation = true;
              } else if (schema.allowEmptyValue === true && value === '') {
                skipValidation = true;
              } else if (parameterObject.type === 'file') {
                skipValidation = true;
              } else if (schema.type === 'string') {
                if (['date', 'date-time'].indexOf(schema.format) > -1 && _.isDate(value)) {
                  skipValidation = true;
                } else if (schema.type === 'string' && _.isFunction(value.readUInt8)) {
                  skipValidation = true;
                }
              }

              if (!skipValidation) {
                // Validate against JSON Schema
                result = helpers.validateAgainstSchema(helpers.getJSONSchemaValidator(), parameterObject.schema, value);
              }

              if (result.errors.length > 0) {
                vError = new Error('Value failed JSON Schema validation');

                vError.code = 'SCHEMA_VALIDATION_FAILED';
                vError.errors = result.errors;

                throw vError;
              }
            } catch (err) {
              err.failedValidation = true;
              err.path = pPath;

              error = err;
              isValid = false;
            }
          } else {
            isValid = false;
          }
        }

        return isValid;
      }
    },
    value: {
      enumerable: true,
      get: function () {
        var vError;

        if (!processed) {
          if (schema.type === 'file') {
            processedValue = raw;
          } else {
            // Convert/Coerce the raw value from the request object
            try {
              // Validate emptiness (prior to coercion for better error handling)
              if (parameterObject.allowEmptyValue === false && raw === '') {
                vError = new Error('Value is not allowed to be empty');

                vError.code = 'EMPTY_NOT_ALLOWED';

                // Since this error is not a coercion error, the value is set to raw
                if (schema.type === 'string') {
                  processedValue = raw;
                }

                throw vError;
              }

              processedValue = helpers.convertValue(schema, {
                collectionFormat: parameterObject.collectionFormat
              }, raw);
            } catch (err) {
              error = err;
            }

            // If there is still no value and there are no errors, use the default value if available (no coercion)
            if (_.isUndefined(processedValue) && _.isUndefined(error)) {
              if (schema.type === 'array') {
                if (_.isArray(schema.items)) {
                  processedValue = _.reduce(schema.items, function (items, item) {
                    items.push(item.default);

                    return items;
                  }, []);

                  // If none of the items have a default value reset the processed value to 'undefined'
                  if (_.every(processedValue, _.isUndefined)) {
                    processedValue = undefined;
                  }
                } else {
                  if (!_.isUndefined(schema.items) && !_.isUndefined(schema.items.default)) {
                    processedValue = [schema.items.default];
                  }
                }
              }

              // If the processed value is still undefined and if there's a global default set
              // for the array, we use it
              if (_.isUndefined(processedValue) && !_.isUndefined(schema.default)) {
                processedValue = schema.default;
              }
            }
          }

          processed = true;
        }

        return processedValue;
      }
    }
  });
}