UNPKG

fastman

Version:

快速api测试及文档生成

298 lines 18.5 kB
"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