LIVR implementation for Erlang
Erlang Other
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
include
src
test
.travis.yml fix travis to use only 17.5 erlang Jan 29, 2016
Makefile
README.md
erlang.mk add tuple with ok or error atom to resultset Aug 11, 2015
olifer.iml
start-dev.sh fixed issue #1 Oct 26, 2015

README.md

#DESCRIPTION

Olifer is lightweight validator supporting Language Independent Validation Rules Specification (LIVR) for Erlang

See http://livr-spec.org for detailed documentation and list of supported rules.

Build Status Coverage Status

Features:

  • Rules are declarative and language independent
  • Any number of rules for each field
  • Return together errors for all fields
  • Excludes all fields that do not have validation rules described
  • Has possibility to validatate complex hierarchical structures
  • Easy to describe and undersand rules
  • Returns understandable error codes(not error messages)
  • Easy to add own rules
  • Rules are be able to change results output ("trim", "nested_object", for example)
  • Multipurpose (user input validation, configs validation, contracts programming etc)

#GETTING STARTED

  1. Add as a dependency in your project:
  • For rebar add to rebar.config
   {olifer, ".*",
        {git, "git@github.com:Prots/olifer.git", {branch, master}}
   }
  • For erlang.mk add to make file:
   DEPS = olifer
   dep_olifer = git@github.com:Prots/olifer.git master
  1. Add in your_project.app.src file in tuple applications:
    {applications, [
                    kernel,
                    stdlib,
                    olifer
                    ]
      }
  2. Run olifer:start() in your project start function.
  3. Thats all, now you can validate data, register your own rules or aliased built-in rules.

#USAGE 1. Validate data

Simple example:

1> Input =  [{<<"first_name">>,<<"Vasya">>}].

2> Rule = [{<<"first_name">>,[{<<"length_between">>,[4,6]}]}].

3> olifer:validate(Input, Rule).

4> {ok, [{<<"first_name">>,<<"Vasya">>}]}

5> Input1 =  [{<<"number1">>,-1.12}].

6> Rule1 = [{<<"number1">>,<<"integer">>}].

7> olifer:validate(Input1, Rule1).

8> {errors, [{<<"number1">>,<<"NOT_INTEGER">>}]}

More complex example

1> Input =  [{<<"address">>,
                [{<<"country">>, <<"Ukraine">>},
                 {<<"zip">>, <<"12345">>},
                 {<<"street">>, <<"10">>},
                 {<<"building">>, <<"10">>},
                 {<<"extra_field">>, <<"will be removed">>}]},
            {<<"extra_field">>, <<"will be removed">>}].

2> Rules = [{<<"address">>,
                [<<"required">>,
                 [{<<"nested_object">>,
                   [{<<"country">>, [<<"required">>, [{<<"one_of">>, [[<<"Ukraine">>, <<"USA">>]]}]]},
                    {<<"zip">>, <<"positive_integer">>},
                    {<<"street">>, <<"required">>},
                    {<<"building">>, [<<"required">>, <<"positive_integer">>]}]}]]}].

3> olifer:validate(Input, Rules).

4> {ok, [{<<"address">>,
           [{<<"country">>, <<"Ukraine">>},
            {<<"zip">>, <<"12345">>},
            {<<"street">>, <<"10">>},
            {<<"building">>, <<"10">>}]}]}

2. Register aliased rule

The "name" and "rules" fields is required, "error" is not required for alias definition

1> Alias1 = [[{<<"name">>, <<"adult_age">>},
              {<<"rules">>, [<<"positive_integer">>, [{<<"min_number">>, 18}]]}]].

2> Alias2 = [[{<<"name">>, <<"adult_age_with_custom_error">>},
              {<<"rules">>, [<<"positive_integer">>, [{<<"min_number">>, 18}]]},
              {<<"error">>, <<"WRONG_AGE">>}]].

3> olifer:register_aliased_rule(Alias1).
ok
4> olifer:register_aliased_rule(Alias2).
ok
5> Rules =  [{<<"age1">>, <<"adult_age">>}, {<<"age2">>, <<"adult_age_with_custom_error">>}].

6> Input = [{<<"age1">>, 14}].

7> Input1 = [{<<"age1">>, 32}].

8> Input2 = [{<<"age2">>, 15}].

9> olifer:validate(Input, Rules).
{errors, [{<<"age1">>,<<"TOO_LOW">>}]}

10> olifer:validate(Input1, Rules).
{ok, [{<<"age1">>, 32}]}

11> olifer:validate(Input2, Rules).
{errors, [{<<"age2">>, <<"WRONG_AGE">>}]}

3. Register new rule

You can create your own rules, for example:

-module(new_rules).

-export([strong_password/2]).

strong_password(Value, [MinLength]) ->
    strong_password(Value, MinLength);
strong_password(Value, MinLength) when is_binary(Value), byte_size(Value) >= MinLength ->
    {ok, Value};
strong_password(Value, _Args) when is_binary(Value) ->
    {error, <<"WEAK_PSSSWORD">>};
strong_password(_Value, _Args) ->
    {error, <<"FORMAT_ERROR">>}.

The function that describe the rule should has 2 arguments, first argument is Value for validation and second argument is a value/list of values for rule. After creation your own rule you should register it:

1> olifer:register_rule(<<"strong_password">>, new_rules, strong_password).
ok
2> Rules = [{<<"password1">>, [{<<"strong_password">>, 15}]}, {<<"password2">>, [{<<"strong_password">>,[15]}]}].

3> Input = [{<<"password1">>, <<"123456789012345">>}, {<<"password2">>, <<"asdasdasdasdasdasd">>}].

4> olifer:validate(Input, Rules).
{ok, [{<<"password1">>, <<"123456789012345">>}, {<<"password2">>, <<"asdasdasdasdasdasd">>}]}

5> Input1 = [{<<"password1">>, <<"1234">>}, {<<"password2">>, <<"asdasd">>}].

6> olifer:validate(Input1, Rules).
{errors, [{<<"password1">>, <<"WEAK_PSSSWORD">>}, {<<"password2">>, <<"WEAK_PSSSWORD">>}]}