Socket
Socket
Sign inDemoInstall

swagger-tools

Package Overview
Dependencies
Maintainers
1
Versions
78
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

swagger-tools - npm Package Compare versions

Comparing version 0.3.1 to 0.3.2

360

index.js

@@ -203,4 +203,4 @@ /*

if (!_.isUndefined(defaultValue) && !_.isUndefined(type)) {
if (data.enum && _.isArray(data.enum) && data.enum.indexOf(defaultValue) === -1) {
if (!_.isUndefined(defaultValue)) {
if (!_.isUndefined(data.enum) && data.enum.indexOf(defaultValue) === -1) {
errors.push({

@@ -275,3 +275,3 @@ code: 'ENUM_MISMATCH',

case 'boolean':
if (['false', 'true'].indexOf(defaultValue) === -1) {
if (!_.isBoolean(defaultValue)) {
errors.push({

@@ -312,3 +312,3 @@ code: 'INVALID_TYPE',

if (model && model.properties && _.isObject(model.properties)) {
if (model) {
_.each(model.properties, function (prop, propName) {

@@ -396,48 +396,35 @@ if (composed[propName]) {

// Find references defined in the operations (Validation happens elsewhere but we have to be smart)
if (resource.apis && _.isArray(resource.apis)) {
_.each(resource.apis, function (api, index) {
var apiPath = '$.apis[' + index + ']';
_.each(resource.apis, function (api, index) {
var apiPath = '$.apis[' + index + ']';
if (!api.operations || !_.isArray(api.operations)) {
return;
_.each(api.operations, function (operation, index) {
var operationPath = apiPath + '.operations[' + index + ']';
// References in operation type
if (operation.type === 'array' && operation.items.$ref) {
addModelRef(operation.items.$ref, operationPath + '.items.$ref');
} else if (primitives.indexOf(operation.type) === -1) {
addModelRef(operation.type, operationPath + '.type');
}
_.each(api.operations, function (operation, index) {
var operationPath = apiPath + '.operations[' + index + ']';
// References in operation type
if (operation.type) {
if (operation.type === 'array' && _.isObject(operation.items) && operation.items.$ref) {
addModelRef(operation.items.$ref, operationPath + '.items.$ref');
} else if (primitives.indexOf(operation.type) === -1) {
addModelRef(operation.type, operationPath + '.type');
}
// References in operation parameters
_.each(operation.parameters, function (parameter, index) {
if (primitives.indexOf(parameter.type) === -1) {
addModelRef(parameter.type, operationPath + '.parameters[' + index + '].type');
} else if (parameter.type === 'array' && parameter.items.$ref) {
addModelRef(parameter.items.$ref, operationPath + '.parameters[' + index + '].items.$ref');
}
});
// References in operation parameters
if (operation.parameters && _.isObject(operation.parameters)) {
_.each(operation.parameters, function (parameter, index) {
if (parameter.type && primitives.indexOf(parameter.type) === -1) {
addModelRef(parameter.type, operationPath + '.parameters[' + index + '].type');
} else if (parameter.type === 'array' && _.isObject(parameter.items) && parameter.items.$ref) {
addModelRef(parameter.items.$ref, operationPath + '.parameters[' + index + '].items.$ref');
}
});
// References in response messages
_.each(operation.responseMessages, function (message, index) {
if (message.responseModel) {
addModelRef(message.responseModel, operationPath + '.responseMessages[' + index + '].responseModel');
}
// References in response messages
if (operation.responseMessages && _.isArray(operation.responseMessages)) {
_.each(operation.responseMessages, function (message, index) {
if (message.responseModel) {
addModelRef(message.responseModel, operationPath + '.responseMessages[' + index + '].responseModel');
}
});
}
});
});
}
});
// Find references defined in the models themselves (Validation happens elsewhere but we have to be smart)
if (models && _.isObject(models)) {
if (!_.isUndefined(models)) {
_.each(models, function (model, name) {

@@ -484,18 +471,16 @@ var modelPath = '$.models[\'' + name + '\']'; // Always use bracket notation just to be safe

// References in model properties
if (model.properties && _.isObject(model.properties)) {
_.each(model.properties, function (property, name) {
var propPath = modelPath + '.properties[\'' + name + '\']'; // Always use bracket notation just to be safe
_.each(model.properties, function (property, name) {
var propPath = modelPath + '.properties[\'' + name + '\']'; // Always use bracket notation just to be safe
if (property.$ref) {
addModelRef(property.$ref, propPath + '.$ref');
} else if (property.type === 'array' && _.isObject(property.items) && property.items.$ref) {
addModelRef(property.items.$ref, propPath + '.items.$ref');
} else {
mergeResults(errors, warnings, validateDefaultValue(property, propPath));
}
});
}
if (property.$ref) {
addModelRef(property.$ref, propPath + '.$ref');
} else if (property.type === 'array' && property.items.$ref) {
addModelRef(property.items.$ref, propPath + '.items.$ref');
} else {
mergeResults(errors, warnings, validateDefaultValue(property, propPath));
}
});
// References in model subTypes
if (model.subTypes && _.isArray(model.subTypes)) {
if (!_.isUndefined(model.subTypes)) {
_.each(model.subTypes, function (name, index) {

@@ -515,3 +500,3 @@ addModelRef(name, modelPath + '.subTypes[' + index + ']');

if (model.required && _.isArray(model.required)) {
if (!_.isUndefined(model.required)) {
var props = model.properties || {};

@@ -578,81 +563,74 @@

case '1.2':
if (resource.apis && _.isArray(resource.apis)) {
_.each(resource.apis, function (api, index) {
var apiPath = '$.apis[' + index + ']';
var seenMethods = [];
var seenNicknames = [];
_.each(resource.apis, function (api, index) {
var apiPath = '$.apis[' + index + ']';
var seenMethods = [];
var seenNicknames = [];
if (!api.operations || !_.isArray(api.operations)) {
return;
}
if (!api.operations || !_.isArray(api.operations)) {
return;
}
_.each(api.operations, function (operation, index) {
var operationPath = apiPath + '.operations[' + index + ']';
var seenResponseMessageCodes = [];
_.each(api.operations, function (operation, index) {
var operationPath = apiPath + '.operations[' + index + ']';
var seenResponseMessageCodes = [];
if (operation.parameters && _.isArray(operation.parameters)) {
_.each(operation.parameters, function (parameter, index) {
mergeResults(errors, warnings,
validateDefaultValue(parameter, operationPath + '.parameters[' + index + ']'));
});
}
// Validate the default value when necessary
_.each(operation.parameters, function (parameter, index) {
mergeResults(errors, warnings,
validateDefaultValue(parameter, operationPath + '.parameters[' + index + ']'));
});
// Identify duplicate operation methods
if (operation.method) {
if (seenMethods.indexOf(operation.method) > -1) {
errors.push({
code: 'DUPLICATE_OPERATION_METHOD',
message: 'Operation method already defined: ' + operation.method,
data: operation.method,
path: operationPath + '.method'
});
} else {
seenMethods.push(operation.method);
}
}
// Identify duplicate operation methods
if (seenMethods.indexOf(operation.method) > -1) {
errors.push({
code: 'DUPLICATE_OPERATION_METHOD',
message: 'Operation method already defined: ' + operation.method,
data: operation.method,
path: operationPath + '.method'
});
} else {
seenMethods.push(operation.method);
}
// Identify duplicate operation nicknames
if (operation.nickname) {
if (seenNicknames.indexOf(operation.nickname) > -1) {
errors.push({
code: 'DUPLICATE_OPERATION_NICKNAME',
message: 'Operation method already defined: ' + operation.nickname,
data: operation.nickname,
path: operationPath + '.nickname'
});
} else {
seenNicknames.push(operation.nickname);
}
}
// Identify duplicate operation nicknames
if (seenNicknames.indexOf(operation.nickname) > -1) {
errors.push({
code: 'DUPLICATE_OPERATION_NICKNAME',
message: 'Operation method already defined: ' + operation.nickname,
data: operation.nickname,
path: operationPath + '.nickname'
});
} else {
seenNicknames.push(operation.nickname);
}
// Identify duplicate operation responseMessage codes
if (operation.responseMessages && _.isArray(operation.responseMessages)) {
_.each(operation.responseMessages, function (responseMessage, index) {
if (responseMessage.code) {
if (seenResponseMessageCodes.indexOf(responseMessage.code) > -1) {
errors.push({
code: 'DUPLICATE_OPERATION_RESPONSEMESSAGE_CODE',
message: 'Operation responseMessage code already defined: ' + responseMessage.code,
data: responseMessage.code,
path: operationPath + '.responseMessages[' + index + '].code'
});
} else {
seenResponseMessageCodes.push(responseMessage.code);
}
// Identify duplicate operation responseMessage codes
if (!_.isUndefined(operation.responseMessages)) {
_.each(operation.responseMessages, function (responseMessage, index) {
if (responseMessage.code) {
if (seenResponseMessageCodes.indexOf(responseMessage.code) > -1) {
errors.push({
code: 'DUPLICATE_OPERATION_RESPONSEMESSAGE_CODE',
message: 'Operation responseMessage code already defined: ' + responseMessage.code,
data: responseMessage.code,
path: operationPath + '.responseMessages[' + index + '].code'
});
} else {
seenResponseMessageCodes.push(responseMessage.code);
}
});
}
}
});
}
// Identify operation summary greater than 120 characters
if (operation.summary && _.isString(operation.summary) && operation.summary.length > 120) {
warnings.push({
code: 'OPERATION_SUMMARY_LONG',
message: 'Operation summary is greater than 120 characters: ' + operation.summary.length,
data: operation.summary,
path: operationPath + '.summary'
});
}
});
// Identify operation summary greater than 120 characters
if (operation.summary && _.isString(operation.summary) && operation.summary.length > 120) {
warnings.push({
code: 'OPERATION_SUMMARY_LONG',
message: 'Operation summary is greater than 120 characters: ' + operation.summary.length,
data: operation.summary,
path: operationPath + '.summary'
});
}
});
}
});
}

@@ -757,19 +735,25 @@

var seenResourcePaths = [];
var swaggerVersion = resourceList.swaggerVersion;
var skipFurtherValidation = false;
// Validate the resource listing (structural)
mergeResults(result.errors, result.warnings, this.validate(resourceList, 'resourceListing.json'));
// Quick return if validation has failed already
if (result.errors.length > 0) {
return result;
}
// Generate list of declared API paths
if (_.isArray(resourceList.apis)) {
resourceList.apis.forEach(function (api, index) {
if (api.path) {
if (resourcePaths.indexOf(api.path) > -1) {
result.errors.push({
code: 'DUPLICATE_RESOURCE_PATH',
message: 'Resource path already defined: ' + api.path,
data: api.path,
path: '$.apis[' + index + '].path'
});
} else {
resourcePaths.push(api.path);
resourceRefs[api.path] = [];
}
if (resourcePaths.indexOf(api.path) > -1) {
result.errors.push({
code: 'DUPLICATE_RESOURCE_PATH',
message: 'Resource path already defined: ' + api.path,
data: api.path,
path: '$.apis[' + index + '].path'
});
} else {
resourcePaths.push(api.path);
resourceRefs[api.path] = [];
}

@@ -785,3 +769,3 @@ });

if (authorization.type === 'oauth2' && _.isArray(authorization.scopes)) {
if (authorization.type === 'oauth2') {
scopes = _.map(authorization.scopes, function (scope) {

@@ -795,5 +779,2 @@ return scope.scope;

// Validate the resource listing (structural)
mergeResults(result.errors, result.warnings, this.validate(resourceList, 'resourceListing.json'));
// Validate the resources

@@ -809,3 +790,3 @@ resources.forEach(function (resource, index) {

// Identify missing models (referenced but not declared)
// Identify missing authorizations (referenced but not declared)
if (_.isUndefined(scopes)) {

@@ -818,3 +799,3 @@ vResult.errors.push({

});
} else if (_.isArray(authorization) && authorization.length > 0) {
} else if (!_.isUndefined(authorization) && authorization.length > 0) {
if (scopes.length > 0) {

@@ -839,20 +820,14 @@ _.each(authorization, function (scope, index) {

if (swaggerVersion && resource.swaggerVersion && swaggerVersion !== resource.swaggerVersion) {
vResult.warnings.push({
code: 'SWAGGER_VERSION_MISMATCH',
message: 'Swagger version differs from resource listing (' + swaggerVersion + '): ' + resource.swaggerVersion,
data: resource.swaggerVersion,
path: '$.swaggerVersion'
});
}
// Do not procede with semantic validation if the resource is structurally invalid
if (vResult.errors.length > 0) {
skipFurtherValidation = true;
} else {
// References in resource
if (!_.isUndefined(resource.authorizations)) {
_.each(resource.authorizations, function (authorization, name) {
recordAuth(authorization, name, '$.authorizations[\'' + name + ']');
});
}
// References in resource
if (_.isObject(resource.authorizations)) {
_.each(resource.authorizations, function (authorization, name) {
recordAuth(authorization, name, '$.authorizations[\'' + name + ']');
});
}
// References in resource operations
if (_.isArray(resource.apis)) {
// References in resource operations
_.each(resource.apis, function (api, index) {

@@ -873,5 +848,3 @@ var aPath = '$.apis[' + index + ']';

});
}
if (resource.resourcePath) {
if (resourcePaths.indexOf(resource.resourcePath) === -1) {

@@ -901,41 +874,46 @@ vResult.errors.push({

// Identify unused resources (declared but not referenced)
_.difference(resourcePaths, seenResourcePaths).forEach(function (unused) {
var index = _.map(resourceList.apis, function (api) { return api.path; }).indexOf(unused);
// If the structural validation of a resource fails, we will skip all semantic validation. Due to this, untill all
// resource validate structurally, we cannot do this level of validation across the whole API.
result.errors.push({
code: 'UNUSED_RESOURCE',
message: 'Resource is defined but is not used: ' + unused,
data: resourceList.apis[index],
path: '$.apis[' + index + ']'
if (!skipFurtherValidation) {
// Identify unused resources (declared but not referenced)
_.difference(resourcePaths, seenResourcePaths).forEach(function (unused) {
var index = _.map(resourceList.apis, function (api) { return api.path; }).indexOf(unused);
result.errors.push({
code: 'UNUSED_RESOURCE',
message: 'Resource is defined but is not used: ' + unused,
data: resourceList.apis[index],
path: '$.apis[' + index + ']'
});
});
});
// Identify unused authorizations (declared but not referenced)
_.difference(Object.keys(authScopes), Object.keys(seenAuthScopes)).forEach(function (unused) {
result.warnings.push({
code: 'UNUSED_AUTHORIZATION',
message: 'Authorization is defined but is not used: ' + unused,
data: resourceList.authorizations[unused],
path: '$.authorizations[\'' + unused + '\']'
// Identify unused authorizations (declared but not referenced)
_.difference(Object.keys(authScopes), Object.keys(seenAuthScopes)).forEach(function (unused) {
result.warnings.push({
code: 'UNUSED_AUTHORIZATION',
message: 'Authorization is defined but is not used: ' + unused,
data: resourceList.authorizations[unused],
path: '$.authorizations[\'' + unused + '\']'
});
});
});
_.each(authScopes, function (scopes, name) {
var path = '$.authorizations[\'' + name + '\']';
_.each(authScopes, function (scopes, name) {
var path = '$.authorizations[\'' + name + '\']';
// Identify unused authorization scope (declared but not referenced)
_.difference(scopes, seenAuthScopes[name] || []).forEach(function (unused) {
var index = scopes.indexOf(unused);
// Identify unused authorization scope (declared but not referenced)
_.difference(scopes, seenAuthScopes[name] || []).forEach(function (unused) {
var index = scopes.indexOf(unused);
result.warnings.push({
code: 'UNUSED_AUTHORIZATION_SCOPE',
message: 'Authorization scope is defined but is not used: ' + unused,
data: resourceList.authorizations[name].scopes[index],
path: path + '.scopes[' + index + ']'
result.warnings.push({
code: 'UNUSED_AUTHORIZATION_SCOPE',
message: 'Authorization scope is defined but is not used: ' + unused,
data: resourceList.authorizations[name].scopes[index],
path: path + '.scopes[' + index + ']'
});
});
});
});
}
return result.errors.length + result.warnings.length + _.reduce(result.resources, function(count, resource) {
return result.errors.length + result.warnings.length + _.reduce(result.resources, function (count, resource) {
return count +

@@ -942,0 +920,0 @@ (_.isArray(resource.errors) ? resource.errors.length : 0) +

{
"name": "swagger-tools",
"version": "0.3.1",
"version": "0.3.2",
"description": "Various tools for using and integrating with Swagger.",

@@ -5,0 +5,0 @@ "main": "index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc