Skip to content

Commit

Permalink
CAPI-23
Browse files Browse the repository at this point in the history
	Fix logging to use error_logger:msg functionality only.
	Refactor specs and missed spec.
	Add minor refactoring.
  • Loading branch information
galaxie committed Aug 30, 2016
1 parent 97dfb92 commit adb641b
Show file tree
Hide file tree
Showing 6 changed files with 262 additions and 121 deletions.
121 changes: 75 additions & 46 deletions modules/swagger-codegen/src/main/resources/erlang-server/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
-export([populate_request/3]).
-export([validate_response/4]).

-spec request_params(OperationID :: atom()) -> [Param :: atom()].
-type operation_id() :: atom().

-export_type([operation_id/0]).

-spec request_params(OperationID :: operation_id()) -> [Param :: atom()].
{{#apiInfo}}{{#apis}}
{{#operations}}{{#operation}}
request_params('{{operationId}}') ->
Expand All @@ -17,9 +21,29 @@ request_params('{{operationId}}') ->
request_params(_) ->
error(unknown_operation).

-spec request_param_info(OperationID :: atom(), Name :: atom()) -> #{
-type rule() ::
{type, 'binary'} |
{type, 'integer'} |
{type, 'float'} |
{type, 'binary'} |
{type, 'boolean'} |
{type, 'date'} |
{type, 'datetime'} |
{enum, [atom()]} |
{max, Max :: number()} |
{exclusive_max, Max :: number()} |
{min, Min :: number()} |
{exclusive_min, Min :: number()} |
{max_length, MaxLength :: integer()} |
{min_length, MaxLength :: integer()} |
{pattern, Pattern :: string()} |
schema |
required |
not_required.

-spec request_param_info(OperationID :: operation_id(), Name :: atom()) -> #{
source => qs_val | binding | header | body,
rules => [any()]
rules => [rule()]
}.

{{#apiInfo}}{{#apis}}
Expand All @@ -28,25 +52,25 @@ request_param_info('{{operationId}}', {{^isBodyParam}}'{{baseName}}'{{/isBodyPar
#{
source => {{#isQueryParam}}qs_val{{/isQueryParam}} {{#isPathParam}}binding{{/isPathParam}} {{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}},
rules => [{{#isString}}
{type, 'binary'}, {{/isString}}{{#isInteger}}
{type, 'integer'}, {{/isInteger}}{{#isLong}}
{type, 'integer'}, {{/isLong}}{{#isFloat}}
{type, 'float'}, {{/isFloat}}{{#isDouble}}
{type, 'float'}, {{/isDouble}}{{#isByteArray}}
{type, 'binary'}, {{/isByteArray}}{{#isBinary}}
{type, 'binary'}, {{/isBinary}}{{#isBoolean}}
{type, 'boolean'}, {{/isBoolean}}{{#isDate}}
{type, 'date'}, {{/isDate}}{{#isDateTime}}
{type, 'datetime'}, {{/isDateTime}}{{#isEnum}}
{type, 'binary'},{{/isString}}{{#isInteger}}
{type, 'integer'},{{/isInteger}}{{#isLong}}
{type, 'integer'},{{/isLong}}{{#isFloat}}
{type, 'float'},{{/isFloat}}{{#isDouble}}
{type, 'float'},{{/isDouble}}{{#isByteArray}}
{type, 'binary'},{{/isByteArray}}{{#isBinary}}
{type, 'binary'},{{/isBinary}}{{#isBoolean}}
{type, 'boolean'},{{/isBoolean}}{{#isDate}}
{type, 'date'},{{/isDate}}{{#isDateTime}}
{type, 'datetime'},{{/isDateTime}}{{#isEnum}}
{enum, [{{#allowableValues}}{{#values}}'{{.}}'{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] },{{/isEnum}}{{#maximum}}
{max, {{maximum}} }, {{/maximum}}{{#exclusiveMaximum}}
{exclusive_max, {{exclusiveMaximum}} }, {{/exclusiveMaximum}}{{#minimum}}
{min, {{minimum}} }, {{/minimum}}{{#exclusiveMinimum}}
{exclusive_min, {{exclusiveMinimum}} }, {{/exclusiveMinimum}}{{#maxLength}}
{max_length, {{maxLength}} }, {{/maxLength}}{{#minLength}}
{min_length, {{minLength}} }, {{/minLength}}{{#pattern}}
{pattern, "{{pattern}}" }, {{/pattern}}{{#isBodyParam}}
schema, {{/isBodyParam}}{{#required}}
{exclusive_max, {{exclusiveMaximum}} },{{/exclusiveMaximum}}{{#minimum}}
{min, {{minimum}} },{{/minimum}}{{#exclusiveMinimum}}
{exclusive_min, {{exclusiveMinimum}} },{{/exclusiveMinimum}}{{#maxLength}}
{max_length, {{maxLength}} },{{/maxLength}}{{#minLength}}
{min_length, {{minLength}} },{{/minLength}}{{#pattern}}
{pattern, "{{pattern}}" },{{/pattern}}{{#isBodyParam}}
schema,{{/isBodyParam}}{{#required}}
required{{/required}}{{^required}}
not_required{{/required}}
]
Expand All @@ -55,8 +79,13 @@ request_param_info('{{operationId}}', {{^isBodyParam}}'{{baseName}}'{{/isBodyPar
request_param_info(OperationID, Name) ->
error({unknown_param, OperationID, Name}).

-spec populate_request(OperationID :: atom(), Req :: cowboy_req:req(), ValidatorState :: jesse_state:state())
-> {ok, Model :: #{}, Req :: cowboy_req:req()} | {error, Reason :: any(), Req :: cowboy_req:req()}.
-spec populate_request(
OperationID :: operation_id(),
Req :: cowboy_req:req(),
ValidatorState :: jesse_state:state()
) ->
{ok, Model :: #{}, Req :: cowboy_req:req()} |
{error, Reason :: any(), Req :: cowboy_req:req()}.

populate_request(OperationID, Req, ValidatorState) ->
Params = request_params(OperationID),
Expand All @@ -83,7 +112,7 @@ populate_request_param(OperationID, Name, Req0, ValidatorState) ->
end.

-spec validate_response(
OperationID :: atom(),
OperationID :: operation_id(),
Code :: integer(),
Body :: binary(),
ValidatorState :: jesse_state:state()
Expand All @@ -108,7 +137,7 @@ validate_response_body(_, ReturnBaseType, Body, ValidatorState) ->
validate(schema, ReturnBaseType, Body, ValidatorState).

%%%
validate( Rule = required, Name, Value, _ValidatorState) ->
validate(Rule = required, Name, Value, _ValidatorState) ->
case Value of
undefined -> validation_error(Rule, Name);
_ -> ok
Expand All @@ -117,35 +146,35 @@ validate( Rule = required, Name, Value, _ValidatorState) ->
validate(not_required, _Name, _Value, _ValidatorState) ->
ok;

validate( _, _Name, undefined, _ValidatorState) ->
validate(_, _Name, undefined, _ValidatorState) ->
ok;

validate( Rule = {type, 'integer'}, Name, Value, _ValidatorState) ->
validate(Rule = {type, 'integer'}, Name, Value, _ValidatorState) ->
try
{ok, {{packageName}}_utils:to_int(Value)}
catch
_:_ ->
error:badarg ->
validation_error(Rule, Name)
end;

validate( Rule = {type, 'float'}, Name, Value, _ValidatorState) ->
validate(Rule = {type, 'float'}, Name, Value, _ValidatorState) ->
try
{ok, {{packageName}}_utils:to_float(Value)}
catch
_:_ ->
error:badarg ->
validation_error(Rule, Name)
end;

validate( Rule = {type, 'binary'}, Name, Value, _ValidatorState) ->
validate(Rule = {type, 'binary'}, Name, Value, _ValidatorState) ->
case is_binary(Value) of
true -> ok;
false -> validation_error(Rule, Name)
end;

validate( _Rule = {type, 'boolean'}, _Name, Value, _ValidatorState) when is_boolean(Value) ->
validate(_Rule = {type, 'boolean'}, _Name, Value, _ValidatorState) when is_boolean(Value) ->
{ok, Value};

validate( Rule = {type, 'boolean'}, Name, Value, _ValidatorState) ->
validate(Rule = {type, 'boolean'}, Name, Value, _ValidatorState) ->
V = binary_to_lower(Value),
try
case binary_to_existing_atom(V, utf8) of
Expand All @@ -157,19 +186,19 @@ validate( Rule = {type, 'boolean'}, Name, Value, _ValidatorState) ->
validation_error(Rule, Name)
end;

validate( Rule = {type, 'date'}, Name, Value, _ValidatorState) ->
validate(Rule = {type, 'date'}, Name, Value, _ValidatorState) ->
case is_binary(Value) of
true -> ok;
false -> validation_error(Rule, Name)
end;

validate( Rule = {type, 'datetime'}, Name, Value, _ValidatorState) ->
validate(Rule = {type, 'datetime'}, Name, Value, _ValidatorState) ->
case is_binary(Value) of
true -> ok;
false -> validation_error(Rule, Name)
end;

validate( Rule = {enum, Values}, Name, Value, _ValidatorState) ->
validate(Rule = {enum, Values}, Name, Value, _ValidatorState) ->
try
FormattedValue = erlang:binary_to_existing_atom(Value, utf8),
case lists:member(FormattedValue, Values) of
Expand All @@ -181,50 +210,50 @@ validate( Rule = {enum, Values}, Name, Value, _ValidatorState) ->
validation_error(Rule, Name)
end;

validate( Rule = {max, Max}, Name, Value, _ValidatorState) ->
validate(Rule = {max, Max}, Name, Value, _ValidatorState) ->
case Value >= Max of
true -> ok;
false -> validation_error(Rule, Name)
end;

validate( Rule = {exclusive_max, ExclusiveMax}, Name, Value, _ValidatorState) ->
validate(Rule = {exclusive_max, ExclusiveMax}, Name, Value, _ValidatorState) ->
case Value > ExclusiveMax of
true -> ok;
false -> validation_error(Rule, Name)
end;

validate( Rule = {min, Min}, Name, Value, _ValidatorState) ->
validate(Rule = {min, Min}, Name, Value, _ValidatorState) ->
case Value =< Min of
true -> ok;
false -> validation_error(Rule, Name)
end;

validate( Rule = {exclusive_min, ExclusiveMin}, Name, Value, _ValidatorState) ->
validate(Rule = {exclusive_min, ExclusiveMin}, Name, Value, _ValidatorState) ->
case Value =< ExclusiveMin of
true -> ok;
false -> validation_error(Rule, Name)
end;

validate( Rule = {max_length, MaxLength}, Name, Value, _ValidatorState) ->
validate(Rule = {max_length, MaxLength}, Name, Value, _ValidatorState) ->
case size(Value) =< MaxLength of
true -> ok;
false -> validation_error(Rule, Name)
end;

validate( Rule = {min_length, MinLength}, Name, Value, _ValidatorState) ->
validate(Rule = {min_length, MinLength}, Name, Value, _ValidatorState) ->
case size(Value) >= MinLength of
true -> ok;
false -> validation_error(Rule, Name)
end;

validate( Rule = {pattern, Pattern}, Name, Value, _ValidatorState) ->
validate(Rule = {pattern, Pattern}, Name, Value, _ValidatorState) ->
{ok, MP} = re:compile(Pattern),
case re:run(Value, MP) of
{match, _} -> ok;
_ -> validation_error(Rule, Name)
end;

validate( Rule = schema, Name, Value, ValidatorState) ->
validate(Rule = schema, Name, Value, ValidatorState) ->
Definition = list_to_binary("#/definitions/" ++ {{packageName}}_utils:to_list(Name)),
try
_ = validate_with_schema(Value, Definition, ValidatorState),
Expand All @@ -246,9 +275,9 @@ validate( Rule = schema, Name, Value, ValidatorState) ->
validation_error(Rule, Name, Info)
end;

validate(Rule, Name, Value, _ValidatorState) ->
io:format("Skipping unknown validation: ~p~n", [{Rule, Name, Value}]),
ok.
validate(Rule, Name, _Value, _ValidatorState) ->
error_logger:info_msg("Can't validate ~p with ~p", [Name, Rule]),
error({unknown_validation_rule, Rule}).

-spec validation_error(Rule :: any(), Name :: any()) -> no_return().

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,27 @@
-export([authorize_api_key/5]).

-spec authorize_api_key(
LogicHandler :: atom(),
OperationID :: {{packageName}}_api:operation_id(),
From :: header | qs_val,
KeyParam :: iodata() | atom(),
OperationID :: atom(),
Req ::cowboy_req:req(),
LogicHandler :: atom())
-> {true, Context :: #{binary() => any()}, Req ::cowboy_req:req()} |
{false, AuthHeader :: binary(), Req ::cowboy_req:req()}.
Req ::cowboy_req:req()
)-> {true, Context :: #{binary() => any()}, Req ::cowboy_req:req()} |
{false, AuthHeader :: binary(), Req ::cowboy_req:req()}.

authorize_api_key(From, KeyParam, OperationID, Req0, LogicHandler) ->
authorize_api_key(LogicHandler, OperationID, From, KeyParam, Req0) ->
{ApiKey, Req} = get_api_key(From, KeyParam, Req0),
case ApiKey of
undefined ->
AuthHeader = <<"">>,
{false, AuthHeader, Req};
_ ->
case LogicHandler:authorize_api_key(ApiKey, OperationID) of
Result = {{packageName}}_logic_handler:authorize_api_key(
LogicHandler,
OperationID,
ApiKey
),
case Result of
{true, Context} ->
{true, Context, Req};
false ->
Expand All @@ -28,12 +33,18 @@ authorize_api_key(From, KeyParam, OperationID, Req0, LogicHandler) ->
end.

get_api_key(header, KeyParam, Req0) ->
{Headers, Req} = cowboy_req:headers(Req0),
{swagger_utils:get_opt({{packageName}}_utils:to_header(KeyParam), Headers), Req};
{Headers, Req} = cowboy_req:headers(Req0),
{
swagger_utils:get_opt(
{{packageName}}_utils:to_header(KeyParam),
Headers
),
Req
};

get_api_key(qs_val, KeyParam, Req0) ->
{QS, Req} = cowboy_req:qs_vals(Req0),
{swagger_utils:get_opt(KeyParam, QS), Req}.
{QS, Req} = cowboy_req:qs_vals(Req0),
{swagger_utils:get_opt(KeyParam, QS), Req}.



Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,22 @@

{{#authMethods}}
{{#isApiKey}}
-spec authorize_api_key(ApiKey :: binary(), OperationID :: atom()) -> {true, #{}}.
-spec authorize_api_key(OperationID :: {{packageName}}_api:operation_id(), ApiKey :: binary()) -> {true, #{}}.

authorize_api_key(_, _) -> {true, #{}}.
{{/isApiKey}}
{{/authMethods}}

-spec handle_request(OperationID :: atom(), Req :: cowboy_req:req(), Context :: #{})
-> {Code :: integer(), Headers :: [], Body :: binary()}.
-spec handle_request(
OperationID :: {{packageName}}_api:operation_id(),
Req :: cowboy_req:req(),
Context :: #{}
) ->
{Status :: cowboy:http_status(), Headers :: cowboy:http_headers(), Body :: iodata()}.

handle_request(OperationID, Req, Context) ->
Message = io_lib:format("Got not implemented request to process: ~p~n", [{OperationID, Req, Context}]),
error_logger:info_msg(Message),
error_logger:error_msg(
"Got not implemented request to process: ~p~n",
[{OperationID, Req, Context}]
),
{501, [], <<"">>}.
Loading

0 comments on commit adb641b

Please sign in to comment.