Skip to content

Commit

Permalink
Merge pull request #16 from dynamiccast/check-json-api-inputs
Browse files Browse the repository at this point in the history
Check json api inputs
  • Loading branch information
dynamiccast authored Jul 11, 2016
2 parents aa1b49a + 2a06020 commit e6b6858
Show file tree
Hide file tree
Showing 10 changed files with 582 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/api/blueprints/destroy.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module.exports = function destroyOneRecord(req, res) {
query.exec((err, record) => {

if (err) return res.serverError(err);
if (!record) return res.notFound('No record found with the specified `id`.');
if (!record) return res.notFound('No record found with the specified id.');

return Model.destroy(pk).exec((err) => {

Expand Down
33 changes: 33 additions & 0 deletions lib/api/responses/invalidJsonApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* 400 (Bad Request) Invalid JSON API Handler
*
* Usage:
* return res.invalidJsonApi();
*
*/

module.exports = function invalidJsonApi(data, options) {

// Get access to `req`, `res`, & `sails`
var req = this.req;
var res = this.res;
var sails = req._sails;

// Set status code
res.status(400);

sails.log.verbose('Sending 400 ("Bad Request") invalid JSON API input');

return res.json({
'errors': [
{
status: "400",
title: 'Bad request',
detail: 'Invalid JSON API data',
links: {
self: 'http://jsonapi.org/format/'
}
}
]
});
};
6 changes: 6 additions & 0 deletions lib/api/services/JsonApiService.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const _ = require("lodash");
const cleanObject = require('clean-object');
const JSONAPISerializer = require('json-api-serializer');
const jsonApiValidator = require('../../context-aware-jsonapi-validator/validator');
const Serializer = new JSONAPISerializer();

var findRecords = require('../blueprints/find');
Expand Down Expand Up @@ -153,5 +154,10 @@ module.exports = {
}

return errors;
},

validate: function(doc, strategy) {

return jsonApiValidator.isValid(doc, strategy);
}
}
21 changes: 21 additions & 0 deletions lib/context-aware-jsonapi-validator/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# context-aware-jsonapi-validator

A fork from https://github.com/elliotttf/jsonapi-validator with the addition of context checking for JSON API.
In addition to testing JSON to be valid, this module tests given JSON in a specify context.

For example, a JSON API error object, while valid, is not expected when a server receives data to be updated.

# Usage

````
const jsonApiValidator = require('context-aware-jsonapi-validator');

return jsonApiValidator.isValid(doc, context);

````

`doc` is the document to validate against.
`context` is the context whithin which the document is suppoed to be valid.

Possible values are **CONTEXT_UPDATE**, **CONTEXT_CREATE** and undefined.
A context with the value *undefined* validation the document to be a valid JSON API response.
216 changes: 216 additions & 0 deletions lib/context-aware-jsonapi-validator/create-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "JSON API Schema",
"description": "This is a schema for updating resource in the JSON API format. For more, see http://jsonapi.org",
"oneOf": [
{
"$ref": "#/definitions/success"
}
],

"definitions": {
"success": {
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/definitions/data"
},
"meta": {
"$ref": "#/definitions/meta"
},
"jsonapi": {
"$ref": "#/definitions/jsonapi"
}
},
"additionalProperties": false
},

"meta": {
"description": "Non-standard meta-information that can not be represented as an attribute or relationship.",
"type": "object",
"additionalProperties": true
},
"data": {
"description": "he PATCH request MUST include a single resource object as primary data.",
"oneOf": [
{
"$ref": "#/definitions/resource"
}
]
},
"resource": {
"description": "\"Resource objects\" appear in a JSON API document to represent resources.",
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string"
},
"id": {
"type": "string"
},
"attributes": {
"$ref": "#/definitions/attributes"
},
"relationships": {
"$ref": "#/definitions/relationships"
},
"links": {
"$ref": "#/definitions/links"
},
"meta": {
"$ref": "#/definitions/meta"
}
},
"additionalProperties": false
},

"links": {
"description": "A resource object **MAY** contain references to other resource objects (\"relationships\"). Relationships may be to-one or to-many. Relationships can be specified by including a member in a resource's links object.",
"type": "object",
"properties": {
"self": {
"description": "A `self` member, whose value is a URL for the relationship itself (a \"relationship URL\"). This URL allows the client to directly manipulate the relationship. For example, it would allow a client to remove an `author` from an `article` without deleting the people resource itself.",
"type": "string",
"format": "uri"
},
"related": {
"$ref": "#/definitions/link"
}
},
"additionalProperties": true
},
"link": {
"description": "A link **MUST** be represented as either: a string containing the link's URL or a link object.",
"oneOf": [
{
"description": "A string containing the link's URL.",
"type": "string",
"format": "uri"
},
{
"type": "object",
"required": [
"href"
],
"properties": {
"href": {
"description": "A string containing the link's URL.",
"type": "string",
"format": "uri"
},
"meta": {
"$ref": "#/definitions/meta"
}
}
}
]
},

"attributes": {
"description": "Members of the attributes object (\"attributes\") represent information about the resource object in which it's defined.",
"type": "object",
"patternProperties": {
"^(?!relationships$|links$)\\w[-\\w_]*$": {
"description": "Attributes may contain any valid JSON value."
}
},
"additionalProperties": false
},

"relationships": {
"description": "Members of the relationships object (\"relationships\") represent references from the resource object in which it's defined to other resource objects.",
"type": "object",
"patternProperties": {
"^\\w[-\\w_]*$": {
"properties": {
"links": {
"$ref": "#/definitions/links"
},
"data": {
"description": "Member, whose value represents \"resource linkage\".",
"oneOf": [
{
"$ref": "#/definitions/relationshipToOne"
},
{
"$ref": "#/definitions/relationshipToMany"
}
]
},
"meta": {
"$ref": "#/definitions/meta"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"relationshipToOne": {
"description": "References to other resource objects in a to-one (\"relationship\"). Relationships can be specified by including a member in a resource's links object.",
"anyOf": [
{
"$ref": "#/definitions/empty"
},
{
"$ref": "#/definitions/linkage"
}
]
},
"relationshipToMany": {
"description": "An array of objects each containing \"type\" and \"id\" members for to-many relationships.",
"type": "array",
"items": {
"$ref": "#/definitions/linkage"
},
"uniqueItems": true
},
"empty": {
"description": "Describes an empty to-one relationship.",
"type": ["object", "null"],
"properties": {},
"additionalProperties": false
},
"linkage": {
"description": "The \"type\" and \"id\" to non-empty members.",
"type": "object",
"required": [
"type",
"id"
],
"properties": {
"type": {
"type": "string"
},
"id": {
"type": "string"
},
"meta": {
"$ref": "#/definitions/meta"
}
},
"additionalProperties": false
},

"jsonapi": {
"description": "An object describing the server's implementation",
"type": "object",
"properties": {
"version": {
"type": "string"
},
"meta": {
"$ref": "#/definitions/meta"
}
},
"additionalProperties": false
}

}
}
Loading

0 comments on commit e6b6858

Please sign in to comment.