Skip to content

Commit

Permalink
Issue 1639 - query validation (hyperledger-archives#1656)
Browse files Browse the repository at this point in the history
* Validation for queries

* Merged changes and added new exception
  • Loading branch information
dselman authored Jul 25, 2017
1 parent 476e733 commit aac35a3
Show file tree
Hide file tree
Showing 34 changed files with 1,032 additions and 146 deletions.
18 changes: 11 additions & 7 deletions packages/composer-common/api.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
class BaseException extends Error {
+ void constructor(string)
}
class BaseFileException extends BaseException {
+ void constructor(string,string,string)
+ string getFileLocation()
+ string getShortMessage()
}
class BusinessNetworkDefinition {
+ void constructor(String,String,object,String)
+ String getIdentifier()
Expand Down Expand Up @@ -52,12 +57,7 @@ class IdCard {
+ Map getTlsCertificates()
+ Promise fromArchive(Buffer)
}
class BaseModelException extends BaseException {
+ void constructor(string,string,string)
+ string getFileLocation()
+ string getShortMessage()
}
class IllegalModelException extends BaseModelException {
class IllegalModelException extends BaseFileException {
+ void constructor(String,ModelFile,Object,String,String,String,String)
+ string getModelFile()
}
Expand All @@ -66,7 +66,7 @@ class Introspector {
+ ClassDeclaration[] getClassDeclarations()
+ ClassDeclaration getClassDeclaration(String) throws Error
}
class ParseException extends BaseModelException {
class ParseException extends BaseFileException {
+ void constructor(string,string)
}
class ConsoleLogger {
Expand Down Expand Up @@ -112,6 +112,10 @@ class ValidatedResource extends Resource {
+ void addArrayValue(string,string) throws Error
+ void validate() throws Error
}
class InvalidQueryException extends BaseFileException {
+ void constructor(String,QueryFile,Object,String,String,String,String)
+ QueryFile getQueryFile()
}
class SecurityContext {
+ void constructor(Connection,string)
+ Connection getConnection()
Expand Down
3 changes: 2 additions & 1 deletion packages/composer-common/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
#
# Note that the latest public API is documented using JSDocs and is available in api.txt.
#
Version 0.10.1 {ac4a5b035d77bfa46eeadf4b312eab8f} 2017-07-21
Version 0.10.1 {fe6fa1850003a7c5d47bf43e3ab8d628} 2017-07-24
- Added InvalidQueryException, BaseFileException
- Added IdCard to composer-common package

Version 0.9.2 {60327250ee4f059647020f8aee5ed67b} 2017-07-06
Expand Down
2 changes: 1 addition & 1 deletion packages/composer-common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ module.exports.AclFile = require('./lib/acl/aclfile');
module.exports.AclManager = require('./lib/aclmanager');
module.exports.AssetDeclaration = require('./lib/introspect/assetdeclaration');
module.exports.BaseException = require('./lib/baseexception');
module.exports.BaseModelException = require('./lib/introspect/basemodelexception');
module.exports.BaseFileException = require('./lib/basefileexception');
module.exports.BusinessNetworkDefinition = require('./lib/businessnetworkdefinition');
module.exports.BusinessNetworkMetadata = require('./lib/businessnetworkmetadata');
module.exports.ClassDeclaration = require('./lib/introspect/classdeclaration');
Expand Down
2 changes: 1 addition & 1 deletion packages/composer-common/lib/acl/aclfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class AclFile {
}

/**
* Returns the identifier of this ACL File.
* Returns the name of this ACL File.
* @return {string} the identifier of this ACL File
*/
getIdentifier() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

'use strict';

const BaseException = require('../baseexception');
const BaseException = require('./baseexception');

/**
* Exception throws when a composer file is semantically invalid
Expand All @@ -23,7 +23,7 @@ const BaseException = require('../baseexception');
* @class
* @memberof module:composer-common
*/
class BaseModelException extends BaseException {
class BaseFileException extends BaseException {

/**
* Create an IllegalModelException
Expand Down Expand Up @@ -54,4 +54,4 @@ class BaseModelException extends BaseException {
}
}

module.exports = BaseModelException;
module.exports = BaseFileException;
49 changes: 37 additions & 12 deletions packages/composer-common/lib/introspect/classdeclaration.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const ModelUtil = require('../modelutil');
* ClassDeclaration defines the structure (model/schema) of composite data.
* It is composed of a set of Properties, may have an identifying field, and may
* have a super-type.
* A ClassDeclaration is conceptually owned with a ModelFile which
* A ClassDeclaration is conceptually owned by a ModelFile which
* defines all the classes that are part of a namespace.
*
* @private
Expand Down Expand Up @@ -177,14 +177,6 @@ class ClassDeclaration {
throw new IllegalModelException(`${typeName} (${this.getName()}) cannot extend ${superTypeName} (${supertypeDeclaration.getName()})`, this.modelFile, this.ast.location);
}
}

// TODO (DCS)
// else {
// // check that assets only inherit from assets etc.
// if( Object.getPrototypeOf(classDecl) !== Object.getPrototypeOf(this)) {
// throw new Error('Invalid super type for ' + this.name + ' is must be of type ' + Object.getPrototypeOf(this) );
// }
// }
}

if(this.idField) {
Expand Down Expand Up @@ -319,8 +311,7 @@ class ClassDeclaration {
}

/**
* Returns true if this class can be pointed to by a relationship in a
* system model
* Returns true is this type is in the system namespace
*
* @return {boolean} true if the class may be pointed to by a relationship
*/
Expand Down Expand Up @@ -563,6 +554,41 @@ class ClassDeclaration {
return result;
}

/**
* Get a nested property using a dotted property path
* @param {string} propertyPath The property name or name with nested structure e.g a.b.c
* @returns {Property} the property
* @throws {IllegalModelException} if the property path is invalid or the property does not exist
*/
getNestedProperty(propertyPath) {

const propertyNames = propertyPath.split('.');
let classDeclaration = this;
let result = null;

for (let n = 0; n < propertyNames.length; n++) {

// get the nth property
result = classDeclaration.getProperty(propertyNames[n]);

if (result === null) {
throw new IllegalModelException('Property ' + propertyNames[n] + ' does not exist on ' + classDeclaration.getFullyQualifiedName(), this.modelFile, this.ast.location);
}
// not the last element, get the class of the element
else if( n < propertyNames.length-1) {
if(result.isPrimitive() || result.isTypeEnum()) {
throw new Error('Property ' + propertyNames[n] + ' is a primitive or enum. Invalid property path: ' + propertyPath );
}
else {
// get the nested type, this throws if the type is missing or if the type is an enum
classDeclaration = classDeclaration.getModelFile().getModelManager().getType(result.getFullyQualifiedTypeName());
}
}
}

return result;
}

/**
* Returns the string representation of this class
* @return {String} the string representation of the class
Expand All @@ -575,7 +601,6 @@ class ClassDeclaration {
return 'ClassDeclaration {id=' + this.getFullyQualifiedName() + superType + ' enum=' + this.isEnum() + ' abstract=' + this.isAbstract() + '}';
}


}

module.exports = ClassDeclaration;
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@

'use strict';

const BaseModelException = require('./basemodelexception');
const BaseFileException = require('../basefileexception');

/**
* Exception throws when a composer file is semantically invalid
* @extends BaseModelException
* @see See [BaseModelException]{@link module:composer-common.BaseModelException}
* @extends BaseFileException
* @see See [BaseFileException]{@link module:composer-common.BaseFileException}
* @class
* @memberof module:composer-common
*/
class IllegalModelException extends BaseModelException {
class IllegalModelException extends BaseFileException {

/**
* Create an IllegalModelException.
Expand Down
8 changes: 4 additions & 4 deletions packages/composer-common/lib/introspect/parseexception.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@

'use strict';

const BaseModelException = require('./basemodelexception');
const BaseFileException = require('../basefileexception');

/**
* Exception throws when a Composer file is syntactically invalid
* @extends BaseModelException
* @see See [BaseModelException]{@link module:composer-common.BaseModelException}
* @extends BaseFileException
* @see See [BaseFileException]{@link module:composer-common.BaseFileException}
* @class
* @memberof module:composer-common
*/
class ParseException extends BaseModelException {
class ParseException extends BaseFileException {

/**
* Create an ParseException
Expand Down
1 change: 0 additions & 1 deletion packages/composer-common/lib/modelutil.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ class ModelUtil {
return type;
}
}

}

module.exports = ModelUtil;
67 changes: 67 additions & 0 deletions packages/composer-common/lib/query/invalidqueryexception.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* 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.
*/

'use strict';

const BaseFileException = require('../basefileexception');

/**
* Exception thrown for invalid queries
* @extends BaseFileException
* @see See [BaseFileException]{@link module:composer-common.BaseFileException}
* @class
* @memberof module:composer-common
*/
class InvalidQueryException extends BaseFileException {

/**
* Create an InvalidQueryException.
* @param {String} message - the message for the exception
* @param {QueryFile} [queryFile] - the optional queryFile associated with the exception
* @param {Object} [fileLocation] - location details of the error within the model file.
* @param {String} fileLocation.start.line - start line of the error location.
* @param {String} fileLocation.start.column - start column of the error location.
* @param {String} fileLocation.end.line - end line of the error location.
* @param {String} fileLocation.end.column - end column of the error location.
*/
constructor(message, queryFile, fileLocation) {

let messageSuffix = '';
if(queryFile && queryFile.getIdentifier()) {
messageSuffix = 'File \'' + queryFile.getIdentifier() + '\': ' ;
}

if(fileLocation) {
messageSuffix = messageSuffix + 'line ' + fileLocation.start.line + ' column ' +
fileLocation.start.column + ', to line ' + fileLocation.end.line + ' column ' +
fileLocation.end.column + '. ';
}

// First character to be uppercase
messageSuffix = messageSuffix.charAt(0).toUpperCase() + messageSuffix.slice(1);

super(message, fileLocation, message + ' ' + messageSuffix);
this.queryFile = queryFile;
}

/**
* Returns the query file associated with the exception or null
* @return {QueryFile} the optional query file associated with the exception
*/
getQueryFile() {
return this.queryFile;
}
}

module.exports = InvalidQueryException;
1 change: 0 additions & 1 deletion packages/composer-common/lib/query/limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ class Limit {
* @private
*/
validate() {
// TODO (DCS) walk the AST and check that the properties exist in the model!
}

/**
Expand Down
4 changes: 3 additions & 1 deletion packages/composer-common/lib/query/orderby.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ class OrderBy {
* @private
*/
validate() {
// TODO (DCS) check that the fields we are sorting by exist!
for(let n=0; n < this.sortCriteria.length; n++) {
this.sortCriteria[n].validate();
}
}

/**
Expand Down
Loading

0 comments on commit aac35a3

Please sign in to comment.