fastman
Version:
快速api测试及文档生成
298 lines • 18.5 kB
JavaScript
"use strict";
/**
* @license
* Copyright 2017 Red Hat
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var common_rule_1 = require("./common.rule");
var validation_1 = require("../validation");
var visitor_utils_1 = require("../../visitors/visitor.utils");
var visitor_base_1 = require("../../visitors/visitor.base");
/**
* Used to find an operation with a given operation id.
*/
var Oas30OperationFinder = /** @class */ (function (_super) {
__extends(Oas30OperationFinder, _super);
function Oas30OperationFinder(operationId) {
var _this = _super.call(this) || this;
_this.operationId = operationId;
return _this;
}
Oas30OperationFinder.prototype.visitOperation = function (node) {
if (node.operationId === this.operationId) {
this.foundOp = node;
}
};
Oas30OperationFinder.prototype.isFound = function () {
return validation_1.OasValidationRuleUtil.hasValue(this.foundOp);
};
return Oas30OperationFinder;
}(visitor_base_1.Oas30NodeVisitorAdapter));
exports.Oas30OperationFinder = Oas30OperationFinder;
/**
* Implements the Invalid Property Value validation rule. This rule is responsible
* for reporting whenever the **value** of a property fails to conform to requirements
* outlined by the specification. This is typically things like enums, where the
* *format* of the value is fine (e.g. correct data-type) but the valid is somehow
* invalid.
*/
var Oas30InvalidPropertyValueValidationRule = /** @class */ (function (_super) {
__extends(Oas30InvalidPropertyValueValidationRule, _super);
function Oas30InvalidPropertyValueValidationRule() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Returns true if the given value is a valid operationId.
* @param id
*/
Oas30InvalidPropertyValueValidationRule.prototype.isValidOperationId = function (id) {
// TODO implement a regex for this? should be something like camelCase
return true;
};
/**
* Parses the given path template for segments. For example, a path template might be
*
* /foo/{fooId}/resources/{resourceId}
*
* In this case, this method will return [ "fooId", "resourceId" ]
*
* @param pathTemplate
* @return {Array}
*/
Oas30InvalidPropertyValueValidationRule.prototype.parsePathTemplate = function (pathTemplate) {
var segments = [];
var split = pathTemplate.split('/');
split.forEach(function (seg) {
if (seg.indexOf('{') === 0) {
var segment = seg.substring(1, seg.lastIndexOf('}')).trim();
segments.push(segment);
}
});
return segments;
};
/**
* Parses the given server template for variable names. For example, a server template might be
*
* https://{username}.gigantic-server.com:{port}/{basePath}
*
* In this case, this method will return [ "username", "port", "basePath" ]
*
* @param serverTemplate
* @return {Array}
*/
Oas30InvalidPropertyValueValidationRule.prototype.parseServerTemplate = function (serverTemplate) {
if (!this.hasValue(serverTemplate)) {
return [];
}
var vars = [];
var startIdx = serverTemplate.indexOf('{');
var endIdx = -1;
while (startIdx != -1) {
endIdx = serverTemplate.indexOf('}', startIdx);
if (endIdx != -1) {
vars.push(serverTemplate.substring(startIdx + 1, endIdx));
startIdx = serverTemplate.indexOf('{', endIdx);
}
else {
startIdx = -1;
}
}
return vars;
};
/**
* Returns true if it's OK to use "wrapped" in the XML node. It's only OK to do this if
* the type being defined is an 'array' type.
* @param xml
* @return {boolean}
*/
Oas30InvalidPropertyValueValidationRule.prototype.isWrappedOK = function (xml) {
var schema = xml.parent();
return schema.type === "array";
};
/**
* Returns true if the given media type name is multipart/* or application/x-www-form-urlencoded
* @param {string} typeName
* @return {boolean}
*/
Oas30InvalidPropertyValueValidationRule.prototype.isValidMultipartType = function (typeName) {
return typeName === "application/x-www-form-urlencoded" || typeName.indexOf("multipart") == 0;
};
/**
* Returns true if the given operation is one of: POST, PUT, OPTIONS
* @param {Oas30Operation} operation
* @return {boolean}
*/
Oas30InvalidPropertyValueValidationRule.prototype.isValidRequestBodyOperation = function (operation) {
var method = operation.method();
return method === "put" || method === "post" || method === "options";
};
Oas30InvalidPropertyValueValidationRule.prototype.visitEncoding = function (node) {
if (node.getHeaders().length > 0) {
var mediaType = node.parent();
this.reportIfInvalid("ENC-3-001", mediaType.name().indexOf("multipart") === 0, node, "The \"headers\" property is only allowed for \"multipart\" request body media type encodings. Found media type \"" + mediaType.name() + "\" instead.");
}
if (this.hasValue(node.style)) {
var mediaType = node.parent();
this.reportIfInvalid("ENC-3-002", mediaType.name().indexOf("application/x-www-form-urlencoded") === 0, node, "The \"style\" property is only allowed for \"application/x-www-form-urlencoded\" request body media type encodings. Found media type \"" + mediaType.name() + "\" instead.");
this.reportIfInvalid("ENC-3-005", validation_1.OasValidationRuleUtil.isValidEnumItem(node.style, ["form", "spaceDelimited", "pipeDelimited", "deepObject"]), node, "The \"style\" property value must be one of: [\"form\", \"spaceDelimited\", \"pipeDelimited\", \"deepObject\"] Found value \"" + node.style + "\".");
}
if (this.hasValue(node.explode)) {
var mediaType = node.parent();
this.reportIf("ENC-3-003", mediaType.name() != "application/x-www-form-urlencoded", node, "The \"explode\" property is only allowed for \"application/x-www-form-urlencoded\" request body media type encodings.");
}
if (this.hasValue(node.allowReserved)) {
var mediaType = node.parent();
this.reportIf("ENC-3-004", mediaType.name() != "application/x-www-form-urlencoded", node, "The \"allowReserved\" property is only allowed for \"application/x-www-form-urlencoded\" request body media type encodings.");
}
};
Oas30InvalidPropertyValueValidationRule.prototype.visitHeader = function (node) {
if (this.hasValue(node.style)) {
this.reportIfInvalid("HEAD-3-003", validation_1.OasValidationRuleUtil.isValidEnumItem(node.style, ["simple"]), node, "The \"style\" property value must be \"simple\". Found value \"" + node.style + "\".");
}
this.reportIfInvalid("HEAD-3-004", node.getMediaTypes().length < 2, node, "The \"content\" property must contain at most one entry.");
};
Oas30InvalidPropertyValueValidationRule.prototype.visitHeaderDefinition = function (node) {
this.visitHeader(node);
};
Oas30InvalidPropertyValueValidationRule.prototype.visitLink = function (node) {
if (this.hasValue(node.operationId)) {
var opFinder = new Oas30OperationFinder(node.operationId);
visitor_utils_1.OasVisitorUtil.visitTree(node.ownerDocument(), opFinder);
this.reportIfInvalid("LINK-3-002", opFinder.isFound(), node, "The \"operationId\" property must refer to an existing Operation. Cannot find operation with ID \"" + node.operationId + "\".");
}
};
Oas30InvalidPropertyValueValidationRule.prototype.visitLinkDefinition = function (node) {
this.visitLink(node);
};
Oas30InvalidPropertyValueValidationRule.prototype.visitMediaType = function (node) {
if (node.getEncodings().length > 0) {
this.reportIfInvalid("MT-3-003", this.isValidMultipartType(node.name()), node, "The \"encoding\" property is only allowed for \"multipart\" and \"application/x-www-form-urlencoded\" request body media types. Found \"" + node.name() + "\" instead.");
}
};
Oas30InvalidPropertyValueValidationRule.prototype.visitOperation = function (node) {
if (this.hasValue(node.requestBody)) {
this.reportIfInvalid("OP-3-003", this.isValidRequestBodyOperation(node), node, "The \"requestBody\" property is only supported for POST, PUT, and OPTIONS operations.");
}
};
Oas30InvalidPropertyValueValidationRule.prototype.visitResponses = function (node) {
this.reportIfInvalid("OP-3-005", node.responses().length > 0, node.parent(), "There must be at least one Response documented.");
};
Oas30InvalidPropertyValueValidationRule.prototype.visitParameter = function (node) {
if (this.hasValue(node.in)) {
this.reportIfInvalid("PAR-3-002", validation_1.OasValidationRuleUtil.isValidEnumItem(node.in, ["query", "header", "path", "cookie"]), node, "The \"in\" property value must be one of: [\"path\", \"query\", \"header\", \"cookie\"] (Found value: '" + node.in + "')");
}
if (this.hasValue(node.allowEmptyValue)) {
this.reportIfInvalid("PAR-3-007", validation_1.OasValidationRuleUtil.isValidEnumItem(node.in, ["query"]), node, "The \"allowEmptyValue\" property is only allowed for \"query\" parameters.");
}
if (this.hasValue(node.style)) {
this.reportIfInvalid("PAR-3-009", validation_1.OasValidationRuleUtil.isValidEnumItem(node.style, ["matrix", "label", "form", "simple", "spaceDelimited", "pipeDelimited", "deepObject"]), node, "The \"style\" property value must be one of: [\"matrix\", \"label\", \"form\", \"simple\", \"spaceDelimited\", \"pipeDelimited\", \"deepObject\"] (Found value \"" + node.style + "\").");
if (node.in === "query") {
this.reportIfInvalid("PAR-3-011", validation_1.OasValidationRuleUtil.isValidEnumItem(node.style, ["form", "spaceDelimited", "pipeDelimited", "deepObject"]), node, "For \"query\" parameters, the \"style\" property value must be one of: [\"form\", \"spaceDelimited\", \"pipeDelimited\", \"deepObject\"] (Found value \"" + node.style + "\").");
}
if (node.in === "cookie") {
this.reportIfInvalid("PAR-3-012", validation_1.OasValidationRuleUtil.isValidEnumItem(node.style, ["form"]), node, "For \"cookie\" parameters, the \"style\" property value must be \"form\". (Found value \"" + node.style + "\")");
}
if (node.in === "header") {
this.reportIfInvalid("PAR-3-013", validation_1.OasValidationRuleUtil.isValidEnumItem(node.style, ["simple"]), node, "For \"header\" parameters, the \"style\" property value must be \"simple\". (Found value \"" + node.style + "\").");
}
}
if (node.in === "path") {
var pathItem = void 0;
if (node.parent()["_path"]) {
pathItem = (node.parent());
}
else {
pathItem = (node.parent().parent());
}
var path = pathItem.path();
var pathVars = this.parsePathTemplate(path);
this.reportIfInvalid("PAR-3-018", validation_1.OasValidationRuleUtil.isValidEnumItem(node.name, pathVars), node, "The \"name\" property value for a 'path' style parameter must match one of the items in the path template. Invalid path property name found: \"" + node.name + "\"");
this.reportIfInvalid("PAR-3-006", node.required === true, node, "The \"required\" property is required for \"path\" parameters, and must have a value of \"true\".");
if (this.hasValue(node.style)) {
this.reportIfInvalid("PAR-3-010", validation_1.OasValidationRuleUtil.isValidEnumItem(node.style, ["matrix", "label", "simple"]), node, "For \"path\" parameters, the \"style\" property value must be one of: [\"matrix\", \"label\", \"simple\"] (Found value \"" + node.style + "\").");
}
}
if (node.in === "header" && this.hasValue(node.name)) {
var hname = node.name.toLowerCase();
this.reportIf("PAR-3-019", hname === "accept" || hname === "content-type" || hname === "authorization", node, "Header parameters \"Accept\", \"Content-Type\", and \"Authorization\" are ignored.");
}
if (this.hasValue(node.allowReserved)) {
this.reportIfInvalid("PAR-3-014", node.in === "query", node, "The \"allowReserved\" property is only allowed for \"query\" parameters.");
}
if (this.hasValue(node.content)) {
this.reportIfInvalid("PAR-3-016", node.getMediaTypes().length < 2, node, "The \"content\" property must contain at most one entry.");
}
};
Oas30InvalidPropertyValueValidationRule.prototype.visitParameterDefinition = function (node) {
this.visitParameter(node);
};
Oas30InvalidPropertyValueValidationRule.prototype.visitXML = function (node) {
if (this.hasValue(node.wrapped)) {
this.reportIfInvalid("XML-3-002", this.isWrappedOK(node), node, "The \"wrapped\" property is only valid for 'array' types.");
}
};
Oas30InvalidPropertyValueValidationRule.prototype.visitDiscriminator = function (node) {
var schema = node.parent();
this.reportIfInvalid("SCH-3-001", this.hasValue(schema.oneOf) || this.hasValue(schema.anyOf) || this.hasValue(schema.allOf), node, "The \"discriminator\" property is only valid when using one of: [\"oneOf\", \"anyOf\", \"allOf\"]");
};
Oas30InvalidPropertyValueValidationRule.prototype.visitSecurityScheme = function (node) {
if (this.hasValue(node.type)) {
this.reportIfInvalid("SS-3-008", validation_1.OasValidationRuleUtil.isValidEnumItem(node.type, ["apiKey", "http", "oauth2", "openIdConnect"]), node, "The \"type\" property value must be one of: [\"apiKey\", \"http\", \"oauth2\", \"openIdConnect\"] (Found value: '" + node.type + "')");
}
if (this.hasValue(node.in)) {
this.reportIfInvalid("SS-3-010", validation_1.OasValidationRuleUtil.isValidEnumItem(node.in, ["query", "header", "cookie"]), node, "The \"in\" property value must be one of: [\"query\", \"header\", \"cookie\"] (Found value: '" + node.in + "')");
}
if (this.hasValue(node.scheme)) {
this.reportIfInvalid("SS-3-013", validation_1.OasValidationRuleUtil.isValidEnumItem(node.scheme, ["basic", "bearer", "digest", "hoba", "mutual", "negotiate", "oauth", "vapid", "scram-sha-1", "scram-sha-256"]), node, "The \"scheme\" property value must be one of: [\"basic\", \"bearer\", \"digest\", \"hoba\", \"mutual\", \"negotiate\", \"oauth\", \"vapid\", \"scram-sha-1\", \"scram-sha-256\"] (Found value: '" + node.scheme + "')");
}
if (this.hasValue(node.bearerFormat)) {
this.reportIfInvalid("SS-3-011", node.type === "http" && node.scheme === "bearer", node, "The \"bearerFormat\" property is only valid for \"http\" security schemes of type \"bearer\".");
}
};
Oas30InvalidPropertyValueValidationRule.prototype.visitSecurityRequirement = function (node) {
var _this = this;
var snames = node.securityRequirementNames();
snames.forEach(function (sname) {
var scopes = node.scopes(sname);
_this.reportIfInvalid("SREQ-3-003", _this.hasValue(scopes) && Array.isArray(scopes), node, "The value for security requirement \"" + sname + "\" must be an array.");
// If the security requirement contains some scopes, then it must be pointing to an oauth2 or openIdConnect security scheme!
if (_this.hasValue(scopes) && scopes.length > 0) {
var scheme = node.ownerDocument().components.getSecurityScheme(sname);
if (_this.hasValue(scheme)) {
_this.reportIfInvalid("SREQ-3-002", _this.hasValue(scheme) && (scheme.type === "oauth2" || scheme.type === "openIdConnect"), node, "The value for security requirement \"" + sname + "\" must be an empty array (required for Security Schemes of type other than \"oauth2\" and \"openIdConnect\").");
}
}
});
};
Oas30InvalidPropertyValueValidationRule.prototype.visitServerVariable = function (node) {
var varName = node.name();
var server = node.parent();
var vars = this.parseServerTemplate(server.url);
this.reportIfInvalid("SVAR-3-003", validation_1.OasValidationRuleUtil.isValidEnumItem(varName, vars), node, "The server variable \"" + varName + "\" is not found in the server url template.");
};
return Oas30InvalidPropertyValueValidationRule;
}(common_rule_1.Oas30ValidationRule));
exports.Oas30InvalidPropertyValueValidationRule = Oas30InvalidPropertyValueValidationRule;
//# sourceMappingURL=invalid-property-value.rule.js.map