/** * @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. */ import {Oas30ValidationRule} from "./common.rule"; import {OasNode} from "../../models/node.model"; import {OasValidationRuleUtil} from "../validation"; import {Oas30LinkDefinition} from "../../models/3.0/link.model"; import {Oas30CallbackDefinition} from "../../models/3.0/callback.model"; import {Oas30ExampleDefinition} from "../../models/3.0/example.model"; import {Oas30RequestBodyDefinition} from "../../models/3.0/request-body.model"; import {Oas30HeaderDefinition} from "../../models/3.0/header.model"; import {Oas30SecurityRequirement} from "../../models/3.0/security-requirement.model"; import {Oas30PathItem} from "../../models/3.0/path-item.model"; import {Oas30Response, Oas30ResponseBase, Oas30ResponseDefinition} from "../../models/3.0/response.model"; import {Oas30Document} from "../../models/3.0/document.model"; import {Oas30SecurityScheme} from "../../models/3.0/security-scheme.model"; import {Oas30Schema, Oas30SchemaDefinition} from "../../models/3.0/schema.model"; import {Oas30ParameterDefinition} from "../../models/3.0/parameter.model"; import {Oas30Encoding} from "../../models/3.0/encoding.model"; import {Oas30MediaType} from "../../models/3.0/media-type.model"; /** * Implements the Invalid Property Name validation rule. This rule is responsible * for reporting whenever the **name** of a property fails to conform to the required * format defined by the specification. */ export class Oas30InvalidPropertyNameValidationRule extends Oas30ValidationRule { /** * Returns true if the definition name is valid. * @param name * @return {boolean} */ private static isValidDefinitionName(name: string): boolean { let definitionNamePattern: RegExp = /^[a-zA-Z0-9\.\-_]+$/; return definitionNamePattern.test(name); } /** * Returns true if the given schema has a property defined with the given name. * @param {Oas30Schema} schema * @param {string} propertyName * @return {boolean} */ private isValidSchemaProperty(schema: Oas30Schema, propertyName: string): boolean { if (this.isNullOrUndefined(schema)) { return false; } return !this.isNullOrUndefined(schema.property(propertyName)); } public visitPathItem(node: Oas30PathItem): void { this.reportIfInvalid("PATH-3-004", node.path().indexOf("/") === 0, node, `The path must start with a '/' character.`); } public visitResponse(node: Oas30Response): void { // The "default" response will have a statusCode of "null" if (this.hasValue(node.statusCode())) { this.reportIfInvalid("RES-3-001", OasValidationRuleUtil.isValidHttpCode(node.statusCode()), node, `Response status code "${node.statusCode()}" is not a valid HTTP response status code.`); } } public visitSecurityRequirement(node: Oas30SecurityRequirement): void { let srn: string[] = node.securityRequirementNames(); srn.forEach( name => { let doc: Oas30Document = node.ownerDocument() as Oas30Document; let scheme = doc.components.getSecurityScheme(name); this.reportIfInvalid("SREQ-3-001", !(scheme === undefined || scheme === null), node, `Security Requirement "${name}" does not correspond to a declared Security Scheme.`); }); } public visitSchemaDefinition(node: Oas30SchemaDefinition): void { this.reportIfInvalid("COMP-3-001", Oas30InvalidPropertyNameValidationRule.isValidDefinitionName(node.name()), node, `The Schema Definition name must match the regular expression: ^[a-zA-Z0-9\\.\\-_]+$`); } public visitParameterDefinition(node: Oas30ParameterDefinition): void { this.reportIfInvalid("COMP-3-002", Oas30InvalidPropertyNameValidationRule.isValidDefinitionName(node.parameterName()), node, `The Parameter Definition name must match the regular expression: ^[a-zA-Z0-9\\.\\-_]+$`); } public visitResponseDefinition(node: Oas30ResponseDefinition): void { this.reportIfInvalid("COMP-3-003", Oas30InvalidPropertyNameValidationRule.isValidDefinitionName(node.name()), node, `The Response Definition name must match the regular expression: ^[a-zA-Z0-9\\.\\-_]+$`); } public visitSecurityScheme(node: Oas30SecurityScheme): void { this.reportIfInvalid("COMP-3-004", Oas30InvalidPropertyNameValidationRule.isValidDefinitionName(node.schemeName()), node, `The Security Scheme name must match the regular expression: ^[a-zA-Z0-9\\.\\-_]+$`); } public visitExampleDefinition(node: Oas30ExampleDefinition): void { this.reportIfInvalid("COMP-3-005", Oas30InvalidPropertyNameValidationRule.isValidDefinitionName(node.name()), node, `The Example Definition name must match the regular expression: ^[a-zA-Z0-9\\.\\-_]+$`); } public visitRequestBodyDefinition(node: Oas30RequestBodyDefinition): void { this.reportIfInvalid("COMP-3-006", Oas30InvalidPropertyNameValidationRule.isValidDefinitionName(node.name()), node, `The Request Body Definition name must match the regular expression: ^[a-zA-Z0-9\\.\\-_]+$`); } public visitHeaderDefinition(node: Oas30HeaderDefinition): void { this.reportIfInvalid("COMP-3-007", Oas30InvalidPropertyNameValidationRule.isValidDefinitionName(node.name()), node, `The Header Definition name must match the regular expression: ^[a-zA-Z0-9\\.\\-_]+$`); } public visitLinkDefinition(node: Oas30LinkDefinition): void { this.reportIfInvalid("COMP-3-008", Oas30InvalidPropertyNameValidationRule.isValidDefinitionName(node.name()), node, `The Link Definition name must match the regular expression: ^[a-zA-Z0-9\\.\\-_]+$`); } public visitCallbackDefinition(node: Oas30CallbackDefinition): void { this.reportIfInvalid("COMP-3-009", Oas30InvalidPropertyNameValidationRule.isValidDefinitionName(node.name()), node, `The Callback Definition name must match the regular expression: ^[a-zA-Z0-9\\.\\-_]+$`); } public visitEncoding(node: Oas30Encoding): void { let name: string = node.name(); let schema: Oas30Schema = (node.parent() as Oas30MediaType).schema; this.reportIfInvalid("ENC-3-006", this.isValidSchemaProperty(schema, name), node, `The encoding property "${name}" cannot be found in the associated schema.`); } }