Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DRY user-input validation (clientside, serverside) using JSON-schema

As part of a extensive test-case, I'm building an ajax-based CMS-like application which provides CRUD-functionality on various documenttypes, e.g: articles, tags, etc.

on the server and client-side I'm considering to use JSON-schema ( http://json-schema.org/ ) as a way to do user input validation in a DRY way (i.e: 1 validation-schema, to be used both on the server and client-side, no duplicate-code and all that) . This seems great, because:

  • JSON-schema is both implemented in JS and Java, so one schema could in theory handle client-side and server-side validation

  • all CUD-operations requests and responses are JSON (through ajax)

However besides the usual validations on user-input I would like to have some additional checks on the server (e.g: like checking if the name of a Tag a user wants to create already exists)

Ideally, I want these type of checks to be included in my general server-side validation code (which as said would be based on JSON-schema). However, I'm not entirely convinced that this is the right approach, because these additional checks are not based on the provided JSON-data alone, but need additional data to validate (e.g: the names of existing tags in the system to check if a tag-name already exists).

So, would it be a good idea (design / architectual wise) to incorporate additional checks like the one described above in the json-schema based validation-framework on the server-side? Would this be an elegant solution? Or would you keep them seperate altogether? If not, why not and what other alternative approached would you suggest to stay DRY concerning client and server-side validation?

What do you think?

Some additional context/ goals of the text-case below for some background info.

Thanks, Geert-Jan


Some context / goals:

  • ajax-based CMS using REST approach

  • CUD-requests are performed through ajax using a rest approach (i.e: mapping on POST, PUT, DELETE respectively). Requests and responses are all done through JSON.

  • CMS without forms. Instead use in-place editing (e.g using Aloha-editor: http://www.aloha-editor.org/

  • staying DRY.

    1. templating: done through Mustache templating on client and server-side. Intial rendering and incremental rendering through ajax are done based on 1 and the same template. I wanted to go for something different than Mustache (bc. of it's lack of expressive power), but it works for this prototype at least. (See previous question for alternatives, on which I'm still looking for an answer: Client-side templating language with java compiler as well (DRY templating) )

    2. DRY input-validation: as described above


Validation flow ( in case of failure):

  1. user creates/updates/deletes item.

  2. a validation-failure on the client would instantly give feedback to the user as what to repair. (The Javascript JSON-schema-validator would ideally return JSON which is formatted to the user)

  3. when client-side validation succeeds, the CUD-operation is performed using ajax.

  4. if server-side validation fails, a status-code 400 (Bad request) is returned, with a Json-object containing the validation-failure(s) which is picked up by jquery's error-callback

    $.ajax({
        ....
        error: function(xhr, status, error) {
            var validationJSON = JSON.parse(xhr.responseText);
            //handle server-side validation failure 
        },
        ....
    });
    
  5. JSON-object containing server-side validation failures are presented to the user (analogously to client-side)

like image 575
Geert-Jan Avatar asked Aug 01 '11 13:08

Geert-Jan


People also ask

Can server-side validation and client-side validation be used together?

Doing input validation on both the client side and server side has a number of benefits: It helps reduce server load since invalid data is never submitted in the first place. It helps prevent malicious users from submitting invalid data.

What is JSON input validation?

Validation of the input JSON message or the message tree is performed against the JSON schema files or OpenAPI definition files that are deployed. JSON schema must be contained in a file with a . json file extension, and it must either contain schema in the name (for example, . schema.

What is the value of using JSON Schema for validation?

The primary strength of JSON Schema is that it generates clear, human- and machine-readable documentation. It's easy to accurately describe the structure of data in a way that developers can use for automated validation. This makes work easier for developers and testers, but the benefits go beyond productivity.


1 Answers

It is very possible and one of the most gratifying things to have a single definition of validations in one place (per model) on the server that can then generate appropriate JS for client-side and AJAX-based validations.

Yii framework for PHP has a fantastic architecture for accomplishing this in an elegant way that stores all the validation rules together in the model (divvied up into appropriate "scenarios" as needed). From there, it's a matter of flipping a few switches to make a particular form client-side or AJAX-validateable. I believe Yii's interfaces for this were based on Rails.

Anyway I would highly recommend checking out the following key points from Yii's design; even if you don't know PHP, you can use this for inspiration:

  • CModel::rules() => The DRY source for model validation rules
  • CActiveForm => Used to generate form elements based on model attributes
    • See for example CActiveForm::textField()
  • CValidator => Base class for validators which provisions for the ability to client-validate

I think it's wise to pursue DRY validation rule declaration and in my experience it is not at all unrealistic to achieve that 100% and still have rich forms—and rich validation rules. (And boy will you love life when you don't have to manage all that client-validate JS...)

Hope this helps.

like image 184
Ezekiel Victor Avatar answered Oct 08 '22 00:10

Ezekiel Victor