Erlang OTP 21 to v2 (#342)

* CAPI-351: Erlang 21 to CAPI V2 (#339)

* First step of migration

* spec fix, changed headers to map

* Bumped back swag commit

* Bumped swag commit

* reverted bump

* Second migration step

* Linter fixes

* Bump build_image_tag

* Update build utils

* Gave up on using deprecated ranch child spec

* Updated plt version

* Bumped service-erlang

* Actually use stream_handlers, bump woody

* removed commeted funnctions

* CAPI-353: OTP 21 logger (#341)

* Initial lager migration

* Added missing comma

* Fix config typos and indentation, bumped formatter

* Fixed oops body responce

* Fixed wrong reply format, refactored oops body retrieval

* Bumped hackney and thrift, fixed inet version

* Renamed and fixed stream handler, fixed wrong handlers order

* Test for oops_body

* Use join to make file path

* MSPF-476: Add operation_id to access log

* Upgrade to Erlang 21.3.8.4

* Refactor access log configuration

* lager -> logger

* Upgrade woody

* Fix default logger config
This commit is contained in:
Toporkov Igor 2019-07-03 11:11:31 +03:00 committed by Sergey Elin
parent 83543f1aec
commit 456b9a91e1
42 changed files with 482 additions and 301 deletions

2
Jenkinsfile vendored
View File

@ -33,7 +33,7 @@ build('capi', 'docker-host', finalHook) {
sh 'make wc_xref'
}
runStage('dialyze') {
withWsCache("_build/default/rebar3_19.3_plt") {
withWsCache("_build/default/rebar3_21.3.8.4_plt") {
sh 'make wc_dialyze'
}
}

View File

@ -16,10 +16,10 @@ SERVICE_IMAGE_TAG ?= $(shell git rev-parse HEAD)
SERVICE_IMAGE_PUSH_TAG ?= $(SERVICE_IMAGE_TAG)
# Base image for the service
BASE_IMAGE_NAME := service_erlang
BASE_IMAGE_TAG := 16e2b3ef17e5fdefac8554ced9c2c74e5c6e9e11
BASE_IMAGE_NAME := service-erlang
BASE_IMAGE_TAG := 294d280ff42e6c0cc68ab40fe81e76a6262636c4
BUILD_IMAGE_TAG := 562313697353c29d4b34fb081a8b70e8c2207134
BUILD_IMAGE_TAG := cd38c35976f3684fe7552533b6175a4c3460e88b
CALL_ANYWHERE := \
submodules \

View File

@ -1,4 +1 @@
{erl_opts, [
{parse_transform, lager_transform},
{lager_extra_sinks, [capi_access]}
]}.

View File

@ -7,8 +7,7 @@
kernel,
stdlib,
public_key,
lager,
lager_logstash_formatter,
logger_logstash_formatter,
genlib,
woody,
capi_woody_client,

View File

@ -42,7 +42,7 @@ authorize_api_key(OperationID, ApiKey) ->
end.
log_auth_error(OperationID, Error) ->
lager:info("API Key authorization failed for ~p due to ~p", [OperationID, Error]).
logger:info("API Key authorization failed for ~p due to ~p", [OperationID, Error]).
-spec parse_api_key(ApiKey :: swag_server:api_key()) ->
{ok, {bearer, Credentials :: binary()}} | {error, Reason :: atom()}.

View File

@ -97,7 +97,7 @@ ensure_store_key(Keyname, Source) ->
{ok, KeyInfo} ->
KeyInfo;
{error, Reason} ->
_ = lager:error("Error importing key ~p: ~p", [Keyname, Reason]),
_ = logger:error("Error importing key ~p: ~p", [Keyname, Reason]),
exit({import_error, Keyname, Source, Reason})
end.
@ -106,10 +106,10 @@ select_signee({ok, Keyname}, KeyInfos) ->
{ok, #{sign := true}} ->
set_signee(Keyname);
{ok, KeyInfo} ->
_ = lager:error("Error setting signee: signing with ~p is not allowed", [Keyname]),
_ = logger:error("Error setting signee: signing with ~p is not allowed", [Keyname]),
exit({invalid_signee, Keyname, KeyInfo});
error ->
_ = lager:error("Error setting signee: no key named ~p", [Keyname]),
_ = logger:error("Error setting signee: no key named ~p", [Keyname]),
exit({nonexstent_signee, Keyname})
end;
select_signee(error, _KeyInfos) ->

View File

@ -11,26 +11,25 @@
policy_init(Req) ->
{ok, Req, undefined_state}.
-spec allowed_origins(cowboy_req:req(), any()) -> {'*', cowboy_req:req(), any()}.
-spec allowed_origins(cowboy_req:req(), any()) -> {'*', any()}.
allowed_origins(Req, State) ->
{'*', Req, State}.
allowed_origins(_, State) ->
{'*', State}.
-spec allowed_headers(cowboy_req:req(), any()) -> {[binary()], cowboy_req:req(), any()}.
-spec allowed_headers(cowboy_req:req(), any()) -> {[binary()], any()}.
allowed_headers(Req, State) ->
allowed_headers(_, State) ->
{[
<<"access-control-allow-headers">>,
<<"origin">>,
<<"x-requested-with">>,
<<"content-type">>,
<<"accept">>,
<<"authorization">>,
<<"x-request-id">>,
<<"x-request-deadline">>
], Req, State}.
], State}.
-spec allowed_methods(cowboy_req:req(), any()) -> {[binary()], cowboy_req:req(), any()}.
-spec allowed_methods(cowboy_req:req(), any()) -> {[binary()], any()}.
allowed_methods(Req, State) ->
{[<<"GET">>, <<"POST">>, <<"PUT">>, <<"DELETE">>, <<"OPTIONS">>], Req, State}.
allowed_methods(_, State) ->
{[<<"GET">>, <<"POST">>, <<"PUT">>, <<"DELETE">>, <<"OPTIONS">>], State}.

View File

@ -7,8 +7,8 @@
-behaviour(swag_server_logic_handler).
%% API callbacks
-export([authorize_api_key/2]).
-export([handle_request/3]).
-export([authorize_api_key/3]).
-export([handle_request/4]).
%% Handler behaviour
@ -30,10 +30,10 @@
%% @WARNING Must be refactored in case of different classes of users using this API
-define(REALM, <<"external">>).
-spec authorize_api_key(swag_server:operation_id(), swag_server:api_key()) ->
-spec authorize_api_key(swag_server:operation_id(), swag_server:api_key(), handler_opts()) ->
Result :: false | {true, capi_auth:context()}.
authorize_api_key(OperationID, ApiKey) ->
authorize_api_key(OperationID, ApiKey, _HandlerOpts) ->
_ = capi_utils:logtag_process(operation_id, OperationID),
capi_auth:authorize_api_key(OperationID, ApiKey).
@ -41,7 +41,8 @@ authorize_api_key(OperationID, ApiKey) ->
-type operation_id() :: swag_server:operation_id().
-type request_context() :: swag_server:request_context().
-type response() :: swag_server_logic_handler:response().
-type response() :: swag_server:response().
-type handler_opts() :: swag_server:handler_opts(_).
-type processing_context() :: #{
swagger_context := swag_server:request_context(),
woody_context := woody_context:ctx()
@ -72,12 +73,13 @@ get_handlers() ->
-spec handle_request(
OperationID :: operation_id(),
Req :: request_data(),
SwagContext :: request_context()
SwagContext :: request_context(),
HandlerOpts :: handler_opts()
) ->
{ok | error, response()}.
handle_request(OperationID, Req, SwagContext = #{auth_context := AuthContext}) ->
_ = lager:info("Processing request ~p", [OperationID]),
handle_request(OperationID, Req, SwagContext = #{auth_context := AuthContext}, _HandlerOpts) ->
_ = logger:info("Processing request ~p", [OperationID]),
try
case capi_auth:authorize_operation(OperationID, Req, AuthContext) of
ok ->
@ -85,14 +87,14 @@ handle_request(OperationID, Req, SwagContext = #{auth_context := AuthContext}) -
Context = create_processing_context(SwagContext, WoodyContext),
process_request(OperationID, Req, Context, get_handlers());
{error, _} = Error ->
_ = lager:info("Operation ~p authorization failed due to ~p", [OperationID, Error]),
{ok, {401, [], undefined}}
_ = logger:info("Operation ~p authorization failed due to ~p", [OperationID, Error]),
{ok, {401, #{}, undefined}}
end
catch
error:{woody_error, {Source, Class, Details}} ->
process_woody_error(Source, Class, Details);
throw:{bad_deadline, Deadline} ->
_ = lager:warning("Operation ~p failed due to invalid deadline ~p", [OperationID, Deadline]),
_ = logger:warning("Operation ~p failed due to invalid deadline ~p", [OperationID, Deadline]),
{ok, logic_error(invalidDeadline, <<"Invalid data in X-Request-Deadline header">>)}
end.
@ -124,7 +126,7 @@ create_processing_context(SwaggerContext, WoodyContext) ->
create_woody_context(#{'X-Request-ID' := RequestID}, AuthContext) ->
RpcID = #{trace_id := TraceID} = woody_context:new_rpc_id(genlib:to_binary(RequestID)),
_ = lager:debug("Created TraceID:~p for RequestID:~p", [TraceID , RequestID]),
_ = logger:debug("Created TraceID:~p for RequestID:~p", [TraceID , RequestID]),
woody_user_identity:put(collect_user_identity(AuthContext), woody_context:new(RpcID)).
collect_user_identity(AuthContext) ->

View File

@ -17,7 +17,7 @@ process_request('GetAccountByID', Req, Context) ->
Call = {party_management, 'GetAccountState', [genlib:to_int(maps:get('accountID', Req))]},
case capi_handler_utils:service_call_with([user_info, party_id, party_creation], Call, Context) of
{ok, S} ->
{ok, {200, [], decode_account_state(S)}};
{ok, {200, #{}, decode_account_state(S)}};
{exception, #payproc_AccountNotFound{}} ->
{ok, general_error(404, <<"Account not found">>)}
end;

View File

@ -70,13 +70,13 @@ process_merchant_stat_result(customers_rate_stat = StatType, {ok, #merchstat_Sta
[ ] -> #{<<"uniqueCount">> => 0};
[StatResponse] -> decode_stat_info(StatType, StatResponse)
end,
{ok, {200, [], Resp}};
{ok, {200, #{}, Resp}};
process_merchant_stat_result(StatType, Result) ->
case Result of
{ok, #merchstat_StatResponse{data = {'records', Stats}}} ->
Resp = [decode_stat_info(StatType, S) || S <- Stats],
{ok, {200, [], Resp}};
{ok, {200, #{}, Resp}};
{exception, #'InvalidRequest'{errors = Errors}} ->
FormattedErrors = capi_handler_utils:format_request_errors(Errors),
{ok, logic_error(invalidRequest, FormattedErrors)};

View File

@ -15,12 +15,12 @@
process_request('GetCategories', _Req, #{woody_context := WoodyContext}) ->
Categories = capi_utils:unwrap(capi_domain:get_categories(WoodyContext)),
{ok, {200, [], [decode_category(C) || C <- Categories]}};
{ok, {200, #{}, [decode_category(C) || C <- Categories]}};
process_request('GetCategoryByRef', Req, Context) ->
case get_category_by_id(genlib:to_int(maps:get(categoryID, Req)), Context) of
{ok, Category} ->
{ok, {200, [], decode_category(Category)}};
{ok, {200, #{}, decode_category(Category)}};
{error, not_found} ->
{ok, general_error(404, <<"Category not found">>)}
end;

View File

@ -18,7 +18,7 @@ process_request('GetClaims', Req, Context) ->
Claims = capi_utils:unwrap(
capi_handler_utils:service_call_with([user_info, party_id, party_creation], Call, Context)
),
{ok, {200, [], decode_claims(filter_claims(maps:get('claimStatus', Req), Claims))}};
{ok, {200, #{}, decode_claims(filter_claims(maps:get('claimStatus', Req), Claims))}};
process_request('GetClaimByID', Req, Context) ->
Call = {
@ -33,7 +33,7 @@ process_request('GetClaimByID', Req, Context) ->
%% filter this out
{ok, general_error(404, <<"Claim not found">>)};
false ->
{ok, {200, [], decode_claim(Claim)}}
{ok, {200, #{}, decode_claim(Claim)}}
end;
{exception, #payproc_ClaimNotFound{}} ->
{ok, general_error(404, <<"Claim not found">>)}
@ -45,7 +45,7 @@ process_request('CreateClaim', Req, Context) ->
Call = {party_management, 'CreateClaim', [capi_handler_utils:get_party_id(Context), Changeset]},
case capi_handler_utils:service_call_with([user_info, party_creation], Call, Context) of
{ok, Claim} ->
{ok, {201, [], decode_claim(Claim)}};
{ok, {201, #{}, decode_claim(Claim)}};
{exception, Exception} ->
case Exception of
#payproc_InvalidPartyStatus{} ->
@ -81,7 +81,7 @@ process_request('CreateClaim', Req, Context) ->
% Party = capi_utils:unwrap(
% capi_handler_utils:service_call_with([user_info, party_id, party_creation], Call, Context)
% ),
% {ok, {200, [], capi_handler_utils:capi_handler_decoder_party:decode_party(Party)}};
% {ok, {200, #{}, capi_handler_utils:capi_handler_decoder_party:decode_party(Party)}};
process_request('RevokeClaimByID', Req, Context) ->
Call =
@ -92,7 +92,7 @@ process_request('RevokeClaimByID', Req, Context) ->
]},
case capi_handler_utils:service_call_with([user_info, party_id, party_creation], Call, Context) of
{ok, _} ->
{ok, {204, [], undefined}};
{ok, {204, #{}, undefined}};
{exception, Exception} ->
case Exception of
#payproc_InvalidPartyStatus{} ->

View File

@ -16,7 +16,7 @@
process_request('GetContracts', _Req, Context) ->
Party = capi_utils:unwrap(capi_handler_utils:get_my_party(Context)),
{ok, {200, [], decode_contracts_map(Party#domain_Party.contracts, Party#domain_Party.contractors)}};
{ok, {200, #{}, decode_contracts_map(Party#domain_Party.contracts, Party#domain_Party.contractors)}};
process_request('GetContractByID', Req, Context) ->
ContractID = maps:get('contractID', Req),
@ -25,14 +25,14 @@ process_request('GetContractByID', Req, Context) ->
undefined ->
{ok, general_error(404, <<"Contract not found">>)};
Contract ->
{ok, {200, [], decode_contract(Contract, Party#domain_Party.contractors)}}
{ok, {200, #{}, decode_contract(Contract, Party#domain_Party.contractors)}}
end;
process_request('GetContractAdjustments', Req, Context) ->
case capi_handler_utils:get_contract_by_id(maps:get('contractID', Req), Context) of
{ok, #domain_Contract{adjustments = Adjustments}} ->
Resp = [decode_contract_adjustment(A) || A <- Adjustments],
{ok, {200, [], Resp}};
{ok, {200, #{}, Resp}};
{exception, #payproc_ContractNotFound{}} ->
{ok, general_error(404, <<"Contract not found">>)}
end;
@ -43,7 +43,7 @@ process_request('GetContractAdjustmentByID', Req, Context) ->
AdjustmentID = maps:get('adjustmentID', Req),
case lists:keyfind(AdjustmentID, #domain_ContractAdjustment.id, Adjustments) of
#domain_ContractAdjustment{} = A ->
{ok, {200, [], decode_contract_adjustment(A)}};
{ok, {200, #{}, decode_contract_adjustment(A)}};
false ->
{ok, general_error(404, <<"Adjustment not found">>)}
end;

View File

@ -18,7 +18,7 @@ process_request('CreateCustomer', Req, Context) ->
Call = {customer_management, 'Create', [encode_customer_params(PartyID, maps:get('Customer', Req))]},
case capi_handler_utils:service_call_with([party_creation], Call, Context) of
{ok, Customer} ->
{ok, {201, [], make_customer_and_token(Customer, PartyID)}};
{ok, {201, #{}, make_customer_and_token(Customer, PartyID)}};
{exception, Exception} ->
case Exception of
#'InvalidRequest'{errors = Errors} ->
@ -42,7 +42,7 @@ process_request('CreateCustomer', Req, Context) ->
process_request('GetCustomerById', Req, Context) ->
case get_customer_by_id(maps:get('customerID', Req), Context) of
{ok, Customer} ->
{ok, {200, [], decode_customer(Customer)}};
{ok, {200, #{}, decode_customer(Customer)}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->
@ -55,7 +55,7 @@ process_request('GetCustomerById', Req, Context) ->
process_request('DeleteCustomer', Req, Context) ->
case capi_handler_utils:service_call({customer_management, 'Delete', [maps:get(customerID, Req)]}, Context) of
{ok, _} ->
{ok, {204, [], undefined}};
{ok, {204, #{}, undefined}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->
@ -77,7 +77,7 @@ process_request('CreateCustomerAccessToken', Req, Context) ->
capi_handler_utils:get_party_id(Context),
{customer, CustomerID}
),
{ok, {201, [], Response}};
{ok, {201, #{}, Response}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->
@ -99,7 +99,7 @@ process_request('CreateBinding', Req, Context) ->
case Result of
{ok, CustomerBinding} ->
{ok, {201, [], decode_customer_binding(CustomerBinding, Context)}};
{ok, {201, #{}, decode_customer_binding(CustomerBinding, Context)}};
{exception, Exception} ->
case Exception of
#'InvalidRequest'{errors = Errors} ->
@ -137,7 +137,7 @@ process_request('CreateBinding', Req, Context) ->
process_request('GetBindings', Req, Context) ->
case get_customer_by_id(maps:get(customerID, Req), Context) of
{ok, #payproc_Customer{bindings = Bindings}} ->
{ok, {200, [], [decode_customer_binding(B, Context) || B <- Bindings]}};
{ok, {200, #{}, [decode_customer_binding(B, Context) || B <- Bindings]}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->
@ -152,7 +152,7 @@ process_request('GetBinding', Req, Context) ->
{ok, #payproc_Customer{bindings = Bindings}} ->
case lists:keyfind(maps:get(customerBindingID, Req), #payproc_CustomerBinding.id, Bindings) of
#payproc_CustomerBinding{} = B ->
{ok, {200, [], decode_customer_binding(B, Context)}};
{ok, {200, #{}, decode_customer_binding(B, Context)}};
false ->
{ok, general_error(404, <<"Customer binding not found">>)}
end;
@ -183,7 +183,7 @@ process_request('GetCustomerEvents', Req, Context) ->
),
case Result of
{ok, Events} when is_list(Events) ->
{ok, {200, [], Events}};
{ok, {200, #{}, Events}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->

View File

@ -24,7 +24,7 @@ process_request('GetLocationsNames', Req, Context) ->
[],
LocationNames
),
{ok, {200, [], PreparedLocationNames}};
{ok, {200, #{}, PreparedLocationNames}};
{exception, #'InvalidRequest'{errors = Errors}} ->
FormattedErrors = capi_handler_utils:format_request_errors(Errors),
{ok, logic_error(invalidRequest, FormattedErrors)}

View File

@ -26,7 +26,7 @@ process_request('CreateInvoiceTemplate', Req, Context) ->
)
of
{ok, InvoiceTpl} ->
{ok, {201, [], make_invoice_tpl_and_token(InvoiceTpl, PartyID, ExtraProperties)}};
{ok, {201, #{}, make_invoice_tpl_and_token(InvoiceTpl, PartyID, ExtraProperties)}};
{exception, Exception} ->
case Exception of
#'InvalidRequest'{errors = Errors} ->
@ -50,7 +50,7 @@ process_request('GetInvoiceTemplateByID', Req, Context) ->
Call = {invoice_templating, 'Get', [maps:get('invoiceTemplateID', Req)]},
case capi_handler_utils:service_call_with([user_info, party_creation], Call, Context) of
{ok, InvoiceTpl} ->
{ok, {200, [], decode_invoice_tpl(InvoiceTpl)}};
{ok, {200, #{}, decode_invoice_tpl(InvoiceTpl)}};
{exception, E} when
E == #payproc_InvalidUser{};
E == #payproc_InvoiceTemplateNotFound{};
@ -66,7 +66,7 @@ process_request('UpdateInvoiceTemplate', Req, Context) ->
capi_handler_utils:service_call_with([user_info, party_creation], Call, Context)
of
{ok, InvoiceTpl} ->
{ok, {200, [], decode_invoice_tpl(InvoiceTpl)}};
{ok, {200, #{}, decode_invoice_tpl(InvoiceTpl)}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->
@ -100,7 +100,7 @@ process_request('DeleteInvoiceTemplate', Req, Context) ->
Call = {invoice_templating, 'Delete', [maps:get('invoiceTemplateID', Req)]},
case capi_handler_utils:service_call_with([user_info, party_creation], Call, Context) of
{ok, _R} ->
{ok, {204, [], undefined}};
{ok, {204, #{}, undefined}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->
@ -123,7 +123,7 @@ process_request('CreateInvoiceWithTemplate' = OperationID, Req, Context) ->
ExtraProperties = capi_handler_utils:get_extra_properties(Context),
try create_invoice(PartyID, InvoiceTplID, InvoiceParams, Context, OperationID) of
{ok, #'payproc_Invoice'{invoice = Invoice}} ->
{ok, {201, [], capi_handler_decoder_invoicing:make_invoice_and_token(
{ok, {201, #{}, capi_handler_decoder_invoicing:make_invoice_and_token(
Invoice, capi_handler_utils:get_party_id(Context), ExtraProperties)
}};
{exception, Exception} ->
@ -161,7 +161,7 @@ process_request('GetInvoicePaymentMethodsByTemplateID', Req, Context) ->
case Result of
{ok, PaymentMethods0} when is_list(PaymentMethods0) ->
PaymentMethods = capi_utils:deduplicate_payment_methods(PaymentMethods0),
{ok, {200, [], PaymentMethods}};
{ok, {200, #{}, PaymentMethods}};
{exception, E} when
E == #payproc_InvalidUser{};
E == #payproc_InvoiceTemplateNotFound{};

View File

@ -20,7 +20,7 @@ process_request('CreateInvoice' = OperationID, Req, Context) ->
InvoiceParams = maps:get('InvoiceParams', Req),
try create_invoice(PartyID, InvoiceParams, Context, OperationID) of
{ok, #'payproc_Invoice'{invoice = Invoice}} ->
{ok, {201, [], capi_handler_decoder_invoicing:make_invoice_and_token(Invoice, PartyID, ExtraProperties)}};
{ok, {201, #{}, capi_handler_decoder_invoicing:make_invoice_and_token(Invoice, PartyID, ExtraProperties)}};
{exception, Exception} ->
case Exception of
#'InvalidRequest'{errors = Errors} ->
@ -50,7 +50,7 @@ process_request('CreateInvoiceAccessToken', Req, Context) ->
capi_handler_utils:get_party_id(Context),
{invoice, InvoiceID}
),
{ok, {201, [], Response}};
{ok, {201, #{}, Response}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->
@ -63,7 +63,7 @@ process_request('CreateInvoiceAccessToken', Req, Context) ->
process_request('GetInvoiceByID', Req, Context) ->
case capi_handler_utils:get_invoice_by_id(maps:get(invoiceID, Req), Context) of
{ok, #'payproc_Invoice'{invoice = Invoice}} ->
{ok, {200, [], capi_handler_decoder_invoicing:decode_invoice(Invoice)}};
{ok, {200, #{}, capi_handler_decoder_invoicing:decode_invoice(Invoice)}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->
@ -77,7 +77,7 @@ process_request('FulfillInvoice', Req, Context) ->
Call = {invoicing, 'Fulfill', [maps:get(invoiceID, Req), maps:get(<<"reason">>, maps:get('Reason', Req))]},
case capi_handler_utils:service_call_with([user_info], Call, Context) of
{ok, _} ->
{ok, {204, [], undefined}};
{ok, {204, #{}, undefined}};
{exception, Exception} ->
case Exception of
#payproc_InvalidInvoiceStatus{} ->
@ -97,7 +97,7 @@ process_request('RescindInvoice', Req, Context) ->
Call = {invoicing, 'Rescind', [maps:get(invoiceID, Req), maps:get(<<"reason">>, maps:get('Reason', Req))]},
case capi_handler_utils:service_call_with([user_info], Call, Context) of
{ok, _} ->
{ok, {204, [], undefined}};
{ok, {204, #{}, undefined}};
{exception, Exception} ->
case Exception of
#payproc_InvalidInvoiceStatus{} ->
@ -133,7 +133,7 @@ process_request('GetInvoiceEvents', Req, Context) ->
),
case Result of
{ok, Events} when is_list(Events) ->
{ok, {200, [], Events}};
{ok, {200, #{}, Events}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->
@ -152,7 +152,7 @@ process_request('GetInvoicePaymentMethods', Req, Context) ->
case capi_handler_decoder_invoicing:construct_payment_methods(invoicing, [maps:get(invoiceID, Req)], Context) of
{ok, PaymentMethods0} when is_list(PaymentMethods0) ->
PaymentMethods = capi_utils:deduplicate_payment_methods(PaymentMethods0),
{ok, {200, [], PaymentMethods}};
{ok, {200, #{}, PaymentMethods}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->

View File

@ -14,22 +14,22 @@
process_request('GetMyParty', _Req, Context) ->
Party = capi_utils:unwrap(capi_handler_utils:get_my_party(Context)),
{ok, {200, [], capi_handler_decoder_party:decode_party(Party)}};
{ok, {200, #{}, capi_handler_decoder_party:decode_party(Party)}};
process_request('ActivateMyParty', _Req, Context) ->
Call = {party_management, 'Activate', []},
case capi_handler_utils:service_call_with([user_info, party_id, party_creation], Call, Context) of
{ok, _R} ->
{ok, {204, [], undefined}};
{ok, {204, #{}, undefined}};
{exception, #payproc_InvalidPartyStatus{status = {suspension, {active, _}}}} ->
{ok, {204, [], undefined}}
{ok, {204, #{}, undefined}}
end;
process_request('SuspendMyParty', _Req, Context) ->
Call = {party_management, 'Suspend', []},
case capi_handler_utils:service_call_with([user_info, party_id, party_creation], Call, Context) of
{ok, _R} ->
{ok, {204, [], undefined}};
{ok, {204, #{}, undefined}};
{exception, #payproc_InvalidPartyStatus{status = {suspension, {suspended, _}}}} ->
{ok, {204, [], undefined}}
{ok, {204, #{}, undefined}}
end;
%%

View File

@ -34,7 +34,7 @@ process_request('GetPaymentInstitutions', Req, #{woody_context := WoodyContext})
end,
PaymentInstObjects
),
{ok, {200, [], Resp}}
{ok, {200, #{}, Resp}}
catch
throw:{encode_residence, invalid_residence} ->
{ok, logic_error(invalidRequest, <<"Invalid residence">>)}
@ -44,7 +44,7 @@ process_request('GetPaymentInstitutionByRef', Req, #{woody_context := WoodyConte
PaymentInstitutionID = genlib:to_int(maps:get(paymentInstitutionID, Req)),
case capi_domain:get({payment_institution, ?payment_institution_ref(PaymentInstitutionID)}, WoodyContext) of
{ok, PaymentInstitution} ->
{ok, {200, [], decode_payment_institution_obj(PaymentInstitution)}};
{ok, {200, #{}, decode_payment_institution_obj(PaymentInstitution)}};
{error, not_found} ->
{ok, general_error(404, <<"Payment institution not found">>)}
end;
@ -53,7 +53,7 @@ process_request('GetPaymentInstitutionPaymentTerms', Req, Context) ->
PaymentInstitutionID = genlib:to_int(maps:get(paymentInstitutionID, Req)),
case compute_payment_institution_terms(PaymentInstitutionID, #payproc_Varset{}, Context) of
{ok, #domain_TermSet{payments = PaymentTerms}} ->
{ok, {200, [], decode_payment_terms(PaymentTerms)}};
{ok, {200, #{}, decode_payment_terms(PaymentTerms)}};
{exception, #payproc_PaymentInstitutionNotFound{}} ->
{ok, general_error(404, <<"Payment institution not found">>)}
end;
@ -62,7 +62,7 @@ process_request('GetPaymentInstitutionPayoutMethods', Req, Context) ->
PaymentInstitutionID = genlib:to_int(maps:get(paymentInstitutionID, Req)),
case compute_payment_institution_terms(PaymentInstitutionID, prepare_varset(Req), Context) of
{ok, #domain_TermSet{payouts = #domain_PayoutsServiceTerms{payout_methods = PayoutMethods}}} ->
{ok, {200, [], decode_payout_methods_selector(PayoutMethods)}};
{ok, {200, #{}, decode_payout_methods_selector(PayoutMethods)}};
{ok, #domain_TermSet{payouts = undefined}} ->
{ok, general_error(404, <<"Automatic payouts not allowed">>)};
{exception, #payproc_PaymentInstitutionNotFound{}} ->
@ -73,7 +73,7 @@ process_request('GetPaymentInstitutionPayoutSchedules', Req, Context) ->
PaymentInstitutionID = genlib:to_int(maps:get(paymentInstitutionID, Req)),
case compute_payment_institution_terms(PaymentInstitutionID, prepare_varset(Req), Context) of
{ok, #domain_TermSet{payouts = #domain_PayoutsServiceTerms{payout_schedules = Schedules}}} ->
{ok, {200, [], decode_business_schedules_selector(Schedules)}};
{ok, {200, #{}, decode_business_schedules_selector(Schedules)}};
{ok, #domain_TermSet{payouts = undefined}} ->
{ok, general_error(404, <<"Automatic payouts not allowed">>)};
{exception, #payproc_PaymentInstitutionNotFound{}} ->

View File

@ -33,7 +33,7 @@ process_request('CreatePayment' = OperationID, Req, Context) ->
case Result of
{ok, Payment} ->
{ok, {201, [], decode_invoice_payment(InvoiceID, Payment, Context)}};
{ok, {201, #{}, decode_invoice_payment(InvoiceID, Payment, Context)}};
{exception, Exception} ->
case Exception of
#payproc_InvalidInvoiceStatus{} ->
@ -86,7 +86,7 @@ process_request('GetPayments', Req, Context) ->
InvoiceID = maps:get(invoiceID, Req),
case capi_handler_utils:get_invoice_by_id(InvoiceID, Context) of
{ok, #'payproc_Invoice'{payments = Payments}} ->
{ok, {200, [], [decode_invoice_payment(InvoiceID, P, Context) || P <- Payments]}};
{ok, {200, #{}, [decode_invoice_payment(InvoiceID, P, Context) || P <- Payments]}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->
@ -100,7 +100,7 @@ process_request('GetPaymentByID', Req, Context) ->
InvoiceID = maps:get(invoiceID, Req),
case capi_handler_utils:get_payment_by_id(InvoiceID, maps:get(paymentID, Req), Context) of
{ok, Payment} ->
{ok, {200, [], decode_invoice_payment(InvoiceID, Payment, Context)}};
{ok, {200, #{}, decode_invoice_payment(InvoiceID, Payment, Context)}};
{exception, Exception} ->
case Exception of
#payproc_InvoicePaymentNotFound{} ->
@ -116,7 +116,7 @@ process_request('GetPaymentByExternalID', Req, Context) ->
ExternalID = maps:get(externalID, Req),
case get_payment_by_external_id(ExternalID, Context) of
{ok, InvoiceID, Payment} ->
{ok, {200, [], decode_invoice_payment(InvoiceID, Payment, Context)}};
{ok, {200, #{}, decode_invoice_payment(InvoiceID, Payment, Context)}};
{error, internal_id_not_found} ->
{ok, general_error(404, <<"Payment not found">>)};
{error, invoice_not_found} ->
@ -137,7 +137,7 @@ process_request('CancelPayment', Req, Context) ->
Call = {invoicing, 'CancelPayment', CallArgs},
case capi_handler_utils:service_call_with([user_info], Call, Context) of
{ok, _} ->
{ok, {202, [], undefined}};
{ok, {202, #{}, undefined}};
{exception, Exception} ->
case Exception of
#payproc_InvoicePaymentNotFound{} ->
@ -179,7 +179,7 @@ process_request('CapturePayment', Req, Context) ->
Call = {invoicing, 'CapturePaymentNew', CallArgs},
case capi_handler_utils:service_call_with([user_info], Call, Context) of
{ok, _} ->
{ok, {202, [], undefined}};
{ok, {202, #{}, undefined}};
{exception, Exception} ->
case Exception of
#payproc_InvoicePaymentNotFound{} ->
@ -227,7 +227,7 @@ process_request('CreateRefund', Req, Context) ->
Call = {invoicing, 'RefundPayment', [InvoiceID, PaymentID, Params]},
case capi_handler_utils:service_call_with([user_info], Call, Context) of
{ok, Refund} ->
{ok, {201, [], capi_handler_decoder_invoicing:decode_refund(Refund, Context)}};
{ok, {201, #{}, capi_handler_decoder_invoicing:decode_refund(Refund, Context)}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->
@ -284,7 +284,7 @@ process_request('CreateRefund', Req, Context) ->
process_request('GetRefunds', Req, Context) ->
case capi_handler_utils:get_payment_by_id(maps:get(invoiceID, Req), maps:get(paymentID, Req), Context) of
{ok, #payproc_InvoicePayment{refunds = Refunds}} ->
{ok, {200, [], [capi_handler_decoder_invoicing:decode_refund(R, Context) || R <- Refunds]}};
{ok, {200, #{}, [capi_handler_decoder_invoicing:decode_refund(R, Context) || R <- Refunds]}};
{exception, Exception} ->
case Exception of
#payproc_InvalidUser{} ->
@ -301,7 +301,7 @@ process_request('GetRefundByID', Req, Context) ->
{invoicing, 'GetPaymentRefund', [maps:get(invoiceID, Req), maps:get(paymentID, Req), maps:get(refundID, Req)]},
case capi_handler_utils:service_call_with([user_info], Call, Context) of
{ok, Refund} ->
{ok, {200, [], capi_handler_decoder_invoicing:decode_refund(Refund, Context)}};
{ok, {200, #{}, capi_handler_decoder_invoicing:decode_refund(Refund, Context)}};
{exception, Exception} ->
case Exception of
#payproc_InvoicePaymentRefundNotFound{} ->

View File

@ -18,7 +18,7 @@
process_request('GetPayoutTools', Req, Context) ->
case capi_handler_utils:get_contract_by_id(maps:get('contractID', Req), Context) of
{ok, #domain_Contract{payout_tools = PayoutTools}} ->
{ok, {200, [], [decode_payout_tool(P) || P <- PayoutTools]}};
{ok, {200, #{}, [decode_payout_tool(P) || P <- PayoutTools]}};
{exception, #payproc_ContractNotFound{}} ->
{ok, general_error(404, <<"Contract not found">>)}
end;
@ -29,7 +29,7 @@ process_request('GetPayoutToolByID', Req, Context) ->
PayoutToolID = maps:get('payoutToolID', Req),
case lists:keyfind(PayoutToolID, #domain_PayoutTool.id, PayoutTools) of
#domain_PayoutTool{} = P ->
{ok, {200, [], decode_payout_tool(P)}};
{ok, {200, #{}, decode_payout_tool(P)}};
false ->
{ok, general_error(404, <<"PayoutTool not found">>)}
end;
@ -43,7 +43,7 @@ process_request('GetPayout', Req, Context) ->
{ok, Payout} ->
case check_party_in_payout(capi_handler_utils:get_party_id(Context), Payout) of
true ->
{ok, {200, [], decode_payout(Payout)}};
{ok, {200, #{}, decode_payout(Payout)}};
false ->
{ok, general_error(404, <<"Payout not found">>)}
end;
@ -58,7 +58,7 @@ process_request('CreatePayout', Req, Context) ->
),
case capi_handler_utils:service_call({payouts, 'CreatePayout', [CreateRequest]}, Context) of
{ok, Payout} ->
{ok, {201, [], decode_payout(Payout)}};
{ok, {201, #{}, decode_payout(Payout)}};
{exception, Exception} ->
case Exception of
#'payout_processing_InvalidPayoutTool'{} ->
@ -74,7 +74,7 @@ process_request('CreatePayout', Req, Context) ->
process_request('GetScheduleByRef', Req, Context) ->
case get_schedule_by_id(genlib:to_int(maps:get(scheduleID, Req)), Context) of
{ok, Schedule} ->
{ok, {200, [], decode_business_schedule(Schedule)}};
{ok, {200, #{}, decode_business_schedule(Schedule)}};
{error, not_found} ->
{ok, general_error(404, <<"Schedule not found">>)}
end;

View File

@ -30,7 +30,7 @@ process_request('GetReports', Req, Context) ->
Call = {reporting, 'GetReports', [ReportRequest, ReportTypes]},
case capi_handler_utils:service_call(Call, Context) of
{ok, Reports} ->
{ok, {200, [], [decode_report(R) || R <- Reports]}};
{ok, {200, #{}, [decode_report(R) || R <- Reports]}};
{exception, Exception} ->
case Exception of
#'InvalidRequest'{errors = Errors} ->
@ -48,7 +48,7 @@ process_request('GetReport', Req, Context) ->
Call = {reporting, 'GetReport', [PartyId, ShopId, ReportId]},
case capi_handler_utils:service_call(Call, Context) of
{ok, Report} ->
{ok, {200, [], decode_report(Report)}};
{ok, {200, #{}, decode_report(Report)}};
{exception, #reports_ReportNotFound{}} ->
{ok, general_error(404, <<"Report not found">>)}
end;
@ -73,7 +73,7 @@ process_request('CreateReport', Req, Context) ->
{reporting, 'GetReport', [PartyId, ShopId, ReportId]},
Context
),
{ok, {201, [], decode_report(Report)}};
{ok, {201, #{}, decode_report(Report)}};
{exception, Exception} ->
case Exception of
#'InvalidRequest'{errors = Errors} ->
@ -113,7 +113,7 @@ generate_report_presigned_url(FileID, Context) ->
Call = {reporting, 'GeneratePresignedUrl', [FileID, ExpiresAt]},
case capi_handler_utils:service_call(Call, Context) of
{ok, URL} ->
{ok, {200, [], #{<<"url">> => URL}}};
{ok, {200, #{}, #{<<"url">> => URL}}};
{exception, Exception} ->
case Exception of
#'InvalidRequest'{errors = Errors} ->

View File

@ -144,7 +144,7 @@ process_search_request_result(QueryType, Result, Context, #{decode_fun := Decode
<<"totalCount">> => TotalCount,
<<"continuationToken">> => ContinuationToken
}),
{ok, {200, [], Resp}};
{ok, {200, #{}, Resp}};
{exception, #'InvalidRequest'{errors = Errors}} ->
FormattedErrors = capi_handler_utils:format_request_errors(Errors),
{ok, logic_error(invalidRequest, FormattedErrors)};

View File

@ -17,13 +17,13 @@ process_request('ActivateShop', Req, Context) ->
Call = {party_management, 'ActivateShop', [maps:get(shopID, Req)]},
case capi_handler_utils:service_call_with([user_info, party_id, party_creation], Call, Context) of
{ok, _R} ->
{ok, {204, [], undefined}};
{ok, {204, #{}, undefined}};
{exception, Exception} ->
case Exception of
#payproc_ShopNotFound{} ->
{ok, general_error(404, <<"Shop not found">>)};
#payproc_InvalidShopStatus{status = {suspension, {active, _}}} ->
{ok, {204, [], undefined}}
{ok, {204, #{}, undefined}}
end
end;
@ -31,25 +31,25 @@ process_request('SuspendShop', Req, Context) ->
Call = {party_management, 'SuspendShop', [maps:get(shopID, Req)]},
case capi_handler_utils:service_call_with([user_info, party_id, party_creation], Call, Context) of
{ok, _R} ->
{ok, {204, [], undefined}};
{ok, {204, #{}, undefined}};
{exception, Exception} ->
case Exception of
#payproc_ShopNotFound{} ->
{ok, general_error(404, <<"Shop not found">>)};
#payproc_InvalidShopStatus{status = {suspension, {suspended, _}}} ->
{ok, {204, [], undefined}}
{ok, {204, #{}, undefined}}
end
end;
process_request('GetShops', _Req, Context) ->
Party = capi_utils:unwrap(capi_handler_utils:get_my_party(Context)),
{ok, {200, [], decode_shops_map(Party#domain_Party.shops)}};
{ok, {200, #{}, decode_shops_map(Party#domain_Party.shops)}};
process_request('GetShopByID', Req, Context) ->
Call = {party_management, 'GetShop', [maps:get(shopID, Req)]},
case capi_handler_utils:service_call_with([user_info, party_id, party_creation], Call, Context) of
{ok, Shop} ->
{ok, {200, [], decode_shop(Shop)}};
{ok, {200, #{}, decode_shop(Shop)}};
{exception, #payproc_ShopNotFound{}} ->
{ok, general_error(404, <<"Shop not found">>)}
end;

View File

@ -47,7 +47,7 @@ process_request('CreatePaymentResource' = OperationID, Req, Context) ->
payment_session_id = PaymentSessionID,
client_info = capi_handler_encoder:encode_client_info(ClientInfo)
},
{ok, {201, [], capi_handler_decoder_party:decode_disposable_payment_resource(PaymentResource)}}
{ok, {201, #{}, capi_handler_decoder_party:decode_disposable_payment_resource(PaymentResource)}}
catch
Result -> Result
end;
@ -66,7 +66,7 @@ enrich_client_info(ClientInfo, Context) ->
false ->
prepare_client_ip(Context);
Value ->
_ = lager:notice("Unexpected ip_replacement_allowed value: ~p", [Value]),
_ = logger:notice("Unexpected ip_replacement_allowed value: ~p", [Value]),
prepare_client_ip(Context)
end,
ClientInfo#{<<"ip">> => IP}.

View File

@ -35,11 +35,11 @@
-type processing_context() :: capi_handler:processing_context().
-type response() :: capi_handler:response().
-spec general_error(integer(), binary()) ->
-spec general_error(cowboy:http_status(), binary()) ->
response().
general_error(Code, Message) ->
create_erorr_resp(Code, #{<<"message">> => genlib:to_binary(Message)}).
create_error_resp(Code, #{<<"message">> => genlib:to_binary(Message)}).
-spec logic_error
(term(), io_lib:chars() | binary()) -> response();
@ -52,26 +52,26 @@ logic_error(externalIDConflict, {ID, ExternalID}) ->
<<"externalID">> => ExternalID,
<<"id">> => ID,
<<"message">> => <<"This 'externalID' has been used by another request">>},
create_erorr_resp(409, Data);
create_error_resp(409, Data);
logic_error(externalIDConflict, ExternalID) ->
Data = #{
<<"externalID">> => ExternalID,
<<"message">> => <<"This 'externalID' has been used by another request">>},
create_erorr_resp(409, Data);
create_error_resp(409, Data);
logic_error(Code, Message) ->
Data = #{<<"code">> => genlib:to_binary(Code), <<"message">> => genlib:to_binary(Message)},
create_erorr_resp(400, Data).
create_error_resp(400, Data).
create_erorr_resp(Code, Data) ->
create_erorr_resp(Code, [], Data).
create_erorr_resp(Code, Headers, Data) ->
create_error_resp(Code, Data) ->
create_error_resp(Code, #{}, Data).
create_error_resp(Code, Headers, Data) ->
{Code, Headers, Data}.
-spec server_error(integer()) ->
{integer(), [], <<>>}.
{integer(), #{}, <<>>}.
server_error(Code) when Code >= 500 andalso Code < 600 ->
{Code, [], <<>>}.
{Code, #{}, <<>>}.
-spec format_request_errors(list()) ->
binary().
@ -98,7 +98,7 @@ service_call_with_([party_id|T], {ServiceName, Function, Args}, Context) ->
service_call_with_([party_creation|T], Call, Context) ->
case service_call_with_(T, Call, Context) of
{exception, #payproc_PartyNotFound{}} ->
_ = lager:info("Attempting to create a missing party"),
_ = logger:info("Attempting to create a missing party"),
CreateCall = {party_management, 'Create', [get_party_params(Context)]},
case service_call_with([user_info, party_id], CreateCall, Context) of
{ok , _ } -> service_call_with_(T, Call, Context);

View File

@ -23,7 +23,7 @@ process_request('CreateWebhook', Req, Context) ->
Webhook = capi_utils:unwrap(
capi_handler_utils:service_call({webhook_manager, 'Create', [WebhookParams]}, Context)
),
{ok, {201, [], decode_webhook(Webhook)}};
{ok, {201, #{}, decode_webhook(Webhook)}};
{exception, #payproc_ShopNotFound{}} ->
{ok, logic_error(invalidShopID, <<"Shop not found">>)}
end;
@ -32,14 +32,14 @@ process_request('GetWebhooks', _Req, Context) ->
Webhooks = capi_utils:unwrap(
capi_handler_utils:service_call_with([party_id], {webhook_manager, 'GetList', []}, Context)
),
{ok, {200, [], [decode_webhook(V) || V <- Webhooks]}};
{ok, {200, #{}, [decode_webhook(V) || V <- Webhooks]}};
process_request('GetWebhookByID', Req, Context) ->
case encode_webhook_id(maps:get(webhookID, Req)) of
{ok, WebhookID} ->
case get_webhook(WebhookID, Context) of
{ok, Webhook} ->
{ok, {200, [], decode_webhook(Webhook)}};
{ok, {200, #{}, decode_webhook(Webhook)}};
{exception, #webhooker_WebhookNotFound{}} ->
{ok, general_error(404, <<"Webhook not found">>)}
end;
@ -52,9 +52,9 @@ process_request('DeleteWebhookByID', Req, Context) ->
{ok, WebhookID} ->
case delete_webhook(WebhookID, Context) of
{ok, _} ->
{ok, {204, [], undefined}};
{ok, {204, #{}, undefined}};
{exception, #webhooker_WebhookNotFound{}} ->
{ok, {204, [], undefined}}
{ok, {204, #{}, undefined}}
end;
error ->
{ok, general_error(404, <<"Webhook not found">>)}

View File

@ -0,0 +1,79 @@
-module(capi_stream_h).
-behaviour(cowboy_stream).
-define(APP, capi).
%% callback exports
-export([init/3]).
-export([data/4]).
-export([info/3]).
-export([terminate/3]).
-export([early_error/5]).
-type state() :: #{
next := any()
}.
%% callbacks
-spec init(cowboy_stream:streamid(), cowboy_req:req(), cowboy:opts())
-> {cowboy_stream:commands(), state()}.
init(StreamID, Req, Opts) ->
{Commands0, Next} = cowboy_stream:init(StreamID, Req, Opts),
{Commands0, #{next => Next}}.
-spec data(cowboy_stream:streamid(), cowboy_stream:fin(), cowboy_req:resp_body(), State)
-> {cowboy_stream:commands(), State} when State::state().
data(StreamID, IsFin, Data, #{next := Next0} = State) ->
{Commands0, Next} = cowboy_stream:data(StreamID, IsFin, Data, Next0),
{Commands0, State#{next => Next}}.
-spec info(cowboy_stream:streamid(), any(), State)
-> {cowboy_stream:commands(), State} when State::state().
info(StreamID, {response, _, _, _} = Info, #{next := Next0} = State) ->
Resp1 = handle_response(Info),
{Commands0, Next} = cowboy_stream:info(StreamID, Resp1, Next0),
{Commands0, State#{next => Next}};
info(StreamID, Info, #{next := Next0} = State) ->
{Commands0, Next} = cowboy_stream:info(StreamID, Info, Next0),
{Commands0, State#{next => Next}}.
-spec terminate(cowboy_stream:streamid(), cowboy_stream:reason(), state()) -> any().
terminate(StreamID, Reason, #{next := Next}) ->
cowboy_stream:terminate(StreamID, Reason, Next).
-spec early_error(cowboy_stream:streamid(), cowboy_stream:reason(),
cowboy_stream:partial_req(), Resp, cowboy:opts()) -> Resp
when Resp::cowboy_stream:resp_command().
early_error(StreamID, Reason, PartialReq, Resp, Opts) ->
Resp1 = handle_response(Resp),
cowboy_stream:early_error(StreamID, Reason, PartialReq, Resp1, Opts).
%% private functions
handle_response({response, Code, Headers, Body}) when Code >= 500 ->
send_oops_resp(Code, Headers, get_oops_body_safe(Code), Body);
handle_response({response, _, _, _} = Resp) ->
Resp.
send_oops_resp(Code, Headers, undefined, Body) ->
{response, Code, Headers, Body};
send_oops_resp(Code, Headers0, File, _) ->
FileSize = filelib:file_size(File),
Headers = maps:merge(Headers0, #{
<<"content-type">> => <<"text/plain; charset=utf-8">>,
<<"content-length">> => integer_to_list(FileSize)
}),
{response, Code, Headers, {sendfile, 0, FileSize, File}}.
get_oops_body_safe(Code) ->
try get_oops_body(Code)
catch
Error:Reason ->
_ = logger:warning("Invalid oops body config for code: ~p. Error: ~p:~p", [Code, Error, Reason]),
undefined
end.
get_oops_body(Code) ->
genlib_map:get(Code, genlib_app:env(?APP, oops_bodies, #{}), undefined).

View File

@ -1,8 +1,6 @@
-module(capi_swagger_server).
-export([child_spec /1]).
-export([request_hook /1]).
-export([response_hook/4]).
-export([child_spec /1]).
-define(APP, capi).
-define(DEFAULT_ACCEPTORS_POOLSIZE, 100).
@ -18,14 +16,13 @@
child_spec({HealthRoutes, LogicHandler}) ->
{Transport, TransportOpts} = get_socket_transport(),
CowboyOpts = get_cowboy_config(HealthRoutes, LogicHandler),
AcceptorsPool = genlib_app:env(?APP, acceptors_poolsize, ?DEFAULT_ACCEPTORS_POOLSIZE),
ranch:child_spec(?MODULE, AcceptorsPool,
Transport, TransportOpts, cowboy_protocol, CowboyOpts).
ranch:child_spec(?MODULE, Transport, TransportOpts, cowboy_clear, CowboyOpts).
get_socket_transport() ->
{ok, IP} = inet:parse_address(genlib_app:env(?APP, ip, ?DEFAULT_IP_ADDR)),
Port = genlib_app:env(?APP, port, ?DEFAULT_PORT),
{ranch_tcp, [{ip, IP}, {port, Port}]}.
AcceptorsPool = genlib_app:env(?APP, acceptors_poolsize, ?DEFAULT_ACCEPTORS_POOLSIZE),
{ranch_tcp, #{socket_opts => [{ip, IP}, {port, Port}], num_acceptors => AcceptorsPool}}.
get_cowboy_config(HealthRoutes, LogicHandler) ->
Dispatch =
@ -33,19 +30,25 @@ get_cowboy_config(HealthRoutes, LogicHandler) ->
HealthRoutes ++
swag_server_router:get_paths(LogicHandler)
)),
[
{env, [
{dispatch, Dispatch},
{cors_policy, capi_cors_policy}
]},
{middlewares, [
CowboyOpts = #{
env => #{
dispatch => Dispatch,
cors_policy => capi_cors_policy
},
middlewares => [
cowboy_router,
cowboy_cors,
cowboy_handler
]},
{onrequest, cowboy_access_log:get_request_hook()},
{onresponse, fun ?MODULE:response_hook/4}
].
],
stream_handlers => [
cowboy_access_log_h, capi_stream_h, cowboy_stream_h
]
},
cowboy_access_log_h:set_extra_info_fun(
mk_operation_id_getter(CowboyOpts),
CowboyOpts
).
squash_routes(Routes) ->
orddict:to_list(lists:foldl(
@ -54,73 +57,18 @@ squash_routes(Routes) ->
Routes
)).
-spec request_hook(cowboy_req:req()) ->
cowboy_req:req().
request_hook(Req) ->
cowboy_req:set_meta(?START_TIME_TAG, genlib_time:ticks(), Req).
-spec response_hook(cowboy:http_status(), cowboy:http_headers(), iodata(), cowboy_req:req()) ->
cowboy_req:req().
response_hook(Code, Headers, Body, Req) ->
try
{Code1, Headers1, Req1} = handle_response(Code, Headers, Req),
_ = log_access(Code1, Headers1, Body, Req1),
Req1
catch
Class:Reason ->
Stack = genlib_format:format_stacktrace(erlang:get_stacktrace(), [newlines]),
_ = lager:warning(
"Response hook failed for: [~p, ~p, ~p]~nwith: ~p:~p~nstacktrace: ~ts",
[Code, Headers, Req, Class, Reason, Stack]
),
Req
end.
handle_response(Code, Headers, Req) when Code >= 500 ->
send_oops_resp(Code, Headers, get_oops_body_safe(Code), Req);
handle_response(Code, Headers, Req) ->
{Code, Headers, Req}.
%% cowboy_req:reply/4 has a faulty spec in case of response body fun.
-dialyzer({[no_contracts, no_fail_call], send_oops_resp/4}).
send_oops_resp(Code, Headers, undefined, Req) ->
{Code, Headers, Req};
send_oops_resp(Code, Headers, File, Req) ->
FileSize = filelib:file_size(File),
F = fun(Socket, Transport) ->
case Transport:sendfile(Socket, File) of
{ok, _} ->
ok;
{error, Error} ->
_ = lager:warning("Failed to send oops body: ~p", [Error]),
ok
mk_operation_id_getter(#{env := Env}) ->
fun (Req) ->
case cowboy_router:execute(Req, Env) of
{ok, _, #{handler_opts := {Operations, _Handler}}} ->
Method = cowboy_req:method(Req),
case maps:find(Method, Operations) of
error ->
#{};
{ok, OperationID} ->
#{operation_id => OperationID}
end;
_ ->
#{}
end
end,
Headers1 = lists:foldl(
fun({K, V}, Acc) -> lists:keystore(K, 1, Acc, {K, V}) end,
Headers,
[
{<<"content-type">>, <<"text/plain; charset=utf-8">>},
{<<"content-length">>, integer_to_list(FileSize)}
]
),
{ok, Req1} = cowboy_req:reply(Code, Headers1, {FileSize, F}, Req),
{Code, Headers1, Req1}.
get_oops_body_safe(Code) ->
try get_oops_body(Code)
catch
Error:Reason ->
_ = lager:warning("Invalid oops body config for code: ~p. Error: ~p:~p", [Code, Error, Reason]),
undefined
end.
get_oops_body(Code) ->
genlib_map:get(Code, genlib_app:env(?APP, oops_bodies, #{}), undefined).
log_access(Code, Headers, Body, Req) ->
LogFun = cowboy_access_log:get_response_hook(capi_access_lager_event),
LogFun(Code, Headers, Body, Req).
end.

View File

@ -13,6 +13,7 @@
-export([unwrap/1]).
-export([define/2]).
-export([get_process_metadata/0]).
-export([deduplicate_payment_methods/1]).
-define(MAX_DEADLINE_TIME, 1*60*1000). % 1 min
@ -21,14 +22,14 @@
logtag_process(Key, Value) when is_atom(Key) ->
% TODO preformat into binary?
lager:md(orddict:store(Key, Value, lager:md())).
logger:update_process_metadata(maps:put(Key, Value, capi_utils:get_process_metadata())).
-spec base64url_to_map(binary()) -> map() | no_return().
base64url_to_map(Base64) when is_binary(Base64) ->
try jsx:decode(base64url:decode(Base64), [return_maps])
catch
Class:Reason ->
_ = lager:debug("decoding base64 ~p to map failed with ~p:~p", [Base64, Class, Reason]),
_ = logger:debug("decoding base64 ~p to map failed with ~p:~p", [Base64, Class, Reason]),
erlang:error(badarg)
end.
@ -37,7 +38,7 @@ map_to_base64url(Map) when is_map(Map) ->
try base64url:encode(jsx:encode(Map))
catch
Class:Reason ->
_ = lager:debug("encoding map ~p to base64 failed with ~p:~p", [Map, Class, Reason]),
_ = logger:debug("encoding map ~p to base64 failed with ~p:~p", [Map, Class, Reason]),
erlang:error(badarg)
end.
@ -159,6 +160,14 @@ clamp_max_deadline(Value) when is_integer(Value)->
Value
end.
-spec get_process_metadata() -> logger:metadata().
get_process_metadata() ->
% perhaps use scopper:collect()?
case logger:get_process_metadata() of
undefined -> #{};
Metadata -> Metadata
end.
-spec deduplicate_payment_methods(list()) -> list().
deduplicate_payment_methods(Methods) ->

View File

@ -5,9 +5,11 @@
-include_lib("dmsl/include/dmsl_domain_config_thrift.hrl").
-export([init_suite/2]).
-export([init_suite/3]).
-export([start_app/1]).
-export([start_app/2]).
-export([start_capi/1]).
-export([start_capi/2]).
-export([issue_token/2]).
-export([issue_token/3]).
-export([issue_token/4]).
@ -32,10 +34,15 @@
-spec init_suite(module(), config()) ->
config().
init_suite(Module, Config) ->
init_suite(Module, Config, []).
-spec init_suite(module(), config(), any()) ->
config().
init_suite(Module, Config, CapiEnv) ->
SupPid = start_mocked_service_sup(Module),
Apps1 =
start_app(lager) ++
start_app(woody),
ServiceURLs = mock_services_([
{
@ -46,23 +53,12 @@ init_suite(Module, Config) ->
], SupPid),
Apps2 =
start_app(dmt_client, [{max_cache_size, #{}}, {service_urls, ServiceURLs}, {cache_update_interval, 50000}]) ++
start_capi(Config),
start_capi(Config, CapiEnv),
[{apps, lists:reverse(Apps2 ++ Apps1)}, {suite_test_sup, SupPid} | Config].
-spec start_app(app_name()) ->
[app_name()].
start_app(lager = AppName) ->
start_app(AppName, [
{async_threshold, 1},
{async_threshold_window, 0},
{error_logger_hwm, 600},
{suppress_application_start_stop, true},
{handlers, [
{lager_common_test_backend, [warning, {lager_logstash_formatter, []}]}
]}
]);
start_app(woody = AppName) ->
start_app(AppName, [
{acceptors_pool_size, 4}
@ -81,7 +77,13 @@ start_app(AppName, Env) ->
[app_name()].
start_capi(Config) ->
CapiEnv = [
start_capi(Config, []).
-spec start_capi(config(), list()) ->
[app_name()].
start_capi(Config, ExtraEnv) ->
CapiEnv = ExtraEnv ++ [
{ip, ?CAPI_IP},
{port, ?CAPI_PORT},
{service_type, real},

View File

@ -0,0 +1,131 @@
-module(capi_self_tests_SUITE).
-include_lib("common_test/include/ct.hrl").
-include_lib("dmsl/include/dmsl_domain_config_thrift.hrl").
-include_lib("capi_dummy_data.hrl").
-include_lib("jose/include/jose_jwk.hrl").
-export([all/0]).
-export([groups/0]).
-export([init_per_suite/1]).
-export([end_per_suite/1]).
-export([init_per_group/2]).
-export([end_per_group/2]).
-export([init_per_testcase/2]).
-export([end_per_testcase/2]).
-export([init/1]).
-export([
oops_body_test/1
]).
-type test_case_name() :: atom().
-type config() :: [{atom(), any()}].
-type group_name() :: atom().
-behaviour(supervisor).
-define(OOPS_BODY, filename:join(?config(data_dir, Config), "cutest_cat_alive")).
-spec init([]) ->
{ok, {supervisor:sup_flags(), [supervisor:child_spec()]}}.
init([]) ->
{ok, {#{strategy => one_for_all, intensity => 1, period => 1}, []}}.
-spec all() ->
[test_case_name()].
all() ->
[
{group, stream_handler_tests}
].
-spec groups() ->
[{group_name(), list(), [test_case_name()]}].
groups() ->
[
{stream_handler_tests, [],
[
oops_body_test
]
}
].
%%
%% starting/stopping
%%
-spec init_per_suite(config()) ->
config().
init_per_suite(Config) ->
capi_ct_helper:init_suite(?MODULE, Config, [{oops_bodies, #{
500 => ?OOPS_BODY
}}]).
-spec end_per_suite(config()) ->
_.
end_per_suite(C) ->
_ = capi_ct_helper:stop_mocked_service_sup(?config(suite_test_sup, C)),
[application:stop(App) || App <- proplists:get_value(apps, C)],
ok.
-spec init_per_group(group_name(), config()) ->
config().
init_per_group(stream_handler_tests, Config) ->
BasePermissions = [
{[invoices], write},
{[invoices], read},
{[party], write},
{[party], read},
{[invoices, payments], write},
{[invoices, payments], read},
{[customers], write},
{[payouts], write},
{[payouts], read}
],
{ok, Token} = capi_ct_helper:issue_token(BasePermissions, unlimited),
Context = capi_ct_helper:get_context(Token),
[{context, Context} | Config];
init_per_group(_, Config) ->
Config.
-spec end_per_group(group_name(), config()) ->
_.
end_per_group(_Group, _C) ->
ok.
-spec init_per_testcase(test_case_name(), config()) ->
config().
init_per_testcase(_Name, C) ->
[{test_sup, capi_ct_helper:start_mocked_service_sup(?MODULE)} | C].
-spec end_per_testcase(test_case_name(), config()) ->
config().
end_per_testcase(_Name, C) ->
capi_ct_helper:stop_mocked_service_sup(?config(test_sup, C)),
ok.
%%% Tests
-spec oops_body_test(config()) ->
_.
oops_body_test(Config) ->
_ = capi_ct_helper:mock_services([{party_management, fun('Get', _) -> {ok, "spanish inquisition"} end}], Config),
Context = ?config(context, Config),
Token = maps:get(token, Context),
{ok, 500, _, OopsBody} = hackney:request(
get,
"localhost:8080/v2/processing/me",
[
{<<"Authorization">>, <<<<"Bearer ">>/binary, Token/binary>>},
{<<"Content-Type">>, <<"application/json; charset=UTF-8">>},
{<<"X-Request-ID">>, list_to_binary(integer_to_list(rand:uniform(100000)))}
],
<<"{}">>,
[
with_body
]
),
{ok, OopsBody} = file:read_file(?OOPS_BODY).

View File

@ -0,0 +1,3 @@
|\__/,| (`\
_.|o o |_ ) )
-(((---(((--------

View File

@ -0,0 +1,9 @@
-----BEGIN RSA PRIVATE KEY-----
MIIBOwIBAAJBAK9fx7qOJT7Aoseu7KKgaLagBh3wvDzg7F/ZMtGbPFikJnnvRWvF
B5oEGbMPblvtF0/fjqfu+eqjP3Z1tUSn7TkCAwEAAQJABUY5KIgr4JZEjwLYxQ9T
9uIbLP1Xe/E7yqoqmBk2GGhSrPY0OeRkYnUVLcP96UPQhF63iuG8VF6uZ7oAPsq+
gQIhANZy3jSCzPjXYHRU1kRqQzpt2S+OqoEiqQ6YG1HrC/VxAiEA0Vq6JlQK2tOX
37SS00dK0Qog4Qi8dN73GliFQNP18EkCIQC4epSA48zkfJMzQBAbRraSuxDNApPX
BzQbo+pMrEDbYQIgY4AncQgIkLB4Qk5kah48JNYXglzQlQtTjiX8Ty9ueGECIQCM
GD3UbQKiA0gf5plBA24I4wFVKxxa4wXbW/7SfP6XmQ==
-----END RSA PRIVATE KEY-----

View File

@ -40,13 +40,13 @@
-type protocol() :: ipv4 | ipv6.
-export_type([protocol/0]).
-type protocol_opts() :: [{connect_options, [inet4 | inet6]}].
-type protocol_opts() :: [{connect_options, [inet | inet6]}].
-export_type([protocol_opts/0]).
-spec protocol_to_opt(protocol()) ->
protocol_opts().
protocol_to_opt(ipv4) ->
[{connect_options, [inet4]}];
[{connect_options, [inet]}];
protocol_to_opt(ipv6) ->
[{connect_options, [inet6]}].

View File

@ -7,7 +7,6 @@
thrift,
dmsl,
bender_proto,
genlib,
lager
genlib
]}
]}.

View File

@ -70,26 +70,27 @@ format_event(_EventType, _RpcID, _EventMeta, _Msg) ->
%%
log(RpcID, {Level, {Format, Args}}, MD) ->
lager:log(Level, [{pid, self()}] ++ rpc_id_to_md(RpcID) ++ orddict:to_list(MD), Format, Args).
logger:log(Level, Format, Args, maps:merge(MD, rpc_id_to_md(RpcID))).
rpc_id_to_md(undefined) ->
[];
#{};
rpc_id_to_md(RpcID = #{}) ->
maps:to_list(RpcID).
RpcID.
%%
enter(Name, Meta) ->
lager:md(collect(Name, Meta)).
logger:update_process_metadata(collect(Name, Meta)).
leave(Name) ->
lager:md(orddict:erase(Name, lager:md())).
logger:set_process_metadata(maps:remove(Name, capi_utils:get_process_metadata())).
collect(Name, Meta) ->
orddict:store(Name, maps:merge(find_scope(Name), Meta), lager:md()).
% basically an update?
PreparedMeta = maps:merge(find_scope(Name), Meta),
maps:put(Name, PreparedMeta, capi_utils:get_process_metadata()).
find_scope(Name) ->
case orddict:find(Name, lager:md()) of
case maps:find(Name, capi_utils:get_process_metadata()) of
{ok, V = #{}} -> V;
error -> #{}
end.

@ -1 +1 @@
Subproject commit 269686d735abef363f9f40a1bf4e1b7c751f3722
Subproject commit ea4aa042f482551d624fd49a570d28488f479e93

View File

@ -1,28 +1,31 @@
[
{lager, [
{error_logger_hwm, 600},
{log_root, "/var/log/capi"},
{handlers, [
{lager_console_backend, debug},
{lager_file_backend, [
{file, "console.json"},
{level, debug},
{formatter, lager_logstash_formatter}
]}
]},
{extra_sinks, [
{capi_access_lager_event, [
{handlers, [
{lager_file_backend, [
{file, "access_log.json"},
{level, info},
{formatter, lager_logstash_formatter}
]}
]},
{async_threshold, 20},
{async_threshold_window, 5}
]}
{kernel, [
{logger_level, info},
{logger, [
{handler, default, logger_std_h, #{
level => debug,
config => #{
type => {file, "/var/log/capi/console.json"},
sync_mode_qlen => 20,
burst_limit_enable => true,
burst_limit_max_count => 600,
burst_limit_window_time => 1000
},
filters => [{access_log, {fun logger_filters:domain/2, {stop, equal, [cowboy_access_log]}}}],
formatter => {logger_logstash_formatter, #{}}
}},
{handler, access_logger, logger_std_h, #{
level => info,
config => #{
type => {file, "/var/log/capi/access_log.json"},
sync_mode_qlen => 20,
burst_limit_enable => true,
burst_limit_max_count => 600,
burst_limit_window_time => 1000
},
filters => [{access_log, {fun logger_filters:domain/2, {stop, not_equal, [cowboy_access_log]}}}],
formatter => {logger_logstash_formatter, #{}}
}}
]}
]},

View File

@ -23,7 +23,7 @@
]
}},
{elvis_style, no_if_expression},
{elvis_style, invalid_dynamic_call, #{ignore => [capi_swagger_server]}},
{elvis_style, invalid_dynamic_call, #{ignore => [capi_swagger_server, capi_stream_handler]}},
{elvis_style, used_ignored_variable},
{elvis_style, no_behavior_info},
{elvis_style, module_naming_convention, #{regex => "^[a-z]([a-z0-9]*_?)*(_SUITE)?$"}},

View File

@ -17,20 +17,18 @@
warn_shadow_vars,
warn_unused_import,
warn_unused_function,
warn_deprecated_function,
warn_deprecated_function
% at will
% bin_opt_info
% no_auto_import
% warn_missing_spec_all
{parse_transform, lager_transform}
]}.
%% Common project dependencies.
{deps, [
{cowboy, "1.0.4"},
{cowboy, "2.5.0"},
{jose, "1.7.9"},
{lager, "3.2.4"},
{base64url, "0.0.1"},
{rfc3339,
{git, "https://github.com/rbkmoney/rfc3339.git",
@ -72,13 +70,13 @@
{branch, "master"}
}
},
{lager_logstash_formatter,
{git, "git@github.com:rbkmoney/lager_logstash_formatter.git",
{logger_logstash_formatter,
{git, "git@github.com:rbkmoney/logger_logstash_formatter.git",
{branch, "master"}
}
},
{cowboy_cors,
{git, "https://github.com/danielwhite/cowboy_cors.git",
{git, "https://github.com/rbkmoney/cowboy_cors.git",
{branch, "master"}
}
},

View File

@ -9,28 +9,29 @@
{git,"git@github.com:rbkmoney/binbase-proto.git",
{ref,"13bcd24e994ccfd1f25af1cda081399b9b58a014"}},
0},
{<<"cache">>,{pkg,<<"cache">>,<<"2.2.0">>},1},
{<<"certifi">>,{pkg,<<"certifi">>,<<"0.4.0">>},1},
{<<"cg_mon">>,
{git,"https://github.com/rbkmoney/cg_mon.git",
{ref,"5a87a37694e42b6592d3b4164ae54e0e87e24e18"}},
1},
{<<"cowboy">>,{pkg,<<"cowboy">>,<<"1.0.4">>},0},
{<<"cowboy">>,{pkg,<<"cowboy">>,<<"2.5.0">>},0},
{<<"cowboy_access_log">>,
{git,"git@github.com:rbkmoney/cowboy_access_log.git",
{ref,"c91ae2316f3daf5465ec12e9fdd0ae37082885c0"}},
{ref,"de3ebbf8705dbd18a445ac179ab564c1cfd1fd24"}},
0},
{<<"cowboy_cors">>,
{git,"https://github.com/danielwhite/cowboy_cors.git",
{ref,"392f5804b63fff2bd0fda67671d5b2fbe0badd37"}},
{git,"https://github.com/rbkmoney/cowboy_cors.git",
{ref,"4cac7528845a8610d471b6fbb92321f79d93f0b8"}},
0},
{<<"cowlib">>,{pkg,<<"cowlib">>,<<"1.0.2">>},1},
{<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.6.0">>},1},
{<<"dmsl">>,
{git,"git@github.com:rbkmoney/damsel.git",
{ref,"b45975832a5c5911c58ad8f206bf9ba465eadfa3"}},
0},
{<<"dmt_client">>,
{git,"git@github.com:rbkmoney/dmt_client.git",
{ref,"ea5b1fd6d0812b7f8d7dbe95996cfdf9318ad830"}},
{ref,"6bb0b65a183910c2031b5b81eb84fee045b7de8a"}},
0},
{<<"dmt_core">>,
{git,"git@github.com:rbkmoney/dmt_core.git",
@ -38,7 +39,7 @@
1},
{<<"erl_health">>,
{git,"https://github.com/rbkmoney/erlang-health.git",
{ref,"ab3ca1ccab6e77905810aa270eb936dbe70e02f8"}},
{ref,"2575c7b63d82a92de54d2d27e504413675e64811"}},
0},
{<<"folsom">>,
{git,"git@github.com:folsom-project/folsom.git",
@ -46,25 +47,28 @@
1},
{<<"genlib">>,
{git,"https://github.com/rbkmoney/genlib.git",
{ref,"7fc1ca1a57dbe2b8b837951095e314c32afd6c9a"}},
{ref,"f805a11f6e73faffb05656c5192fbe199df36f27"}},
0},
{<<"goldrush">>,{pkg,<<"goldrush">>,<<"0.1.9">>},1},
{<<"hackney">>,{pkg,<<"hackney">>,<<"1.5.7">>},0},
{<<"gproc">>,{pkg,<<"gproc">>,<<"0.8.0">>},1},
{<<"gun">>,
{git,"https://github.com/ninenines/gun.git",
{ref,"e7dd9f227e46979d8073e71c683395a809b78cb4"}},
1},
{<<"hackney">>,{pkg,<<"hackney">>,<<"1.15.0">>},0},
{<<"how_are_you">>,
{git,"https://github.com/rbkmoney/how_are_you.git",
{ref,"e960df58c1e8a764894206623eaed0ec57878b91"}},
0},
{<<"idna">>,{pkg,<<"idna">>,<<"1.2.0">>},1},
{<<"jesse">>,
{git,"git@github.com:rbkmoney/jesse.git",
{ref,"39105922d1ce5834383d8e8aa877c60319b9834a"}},
{git,"https://github.com/rbkmoney/jesse.git",
{ref,"723e835708a022bbce9e57807ecf220b00fb771a"}},
0},
{<<"jose">>,{pkg,<<"jose">>,<<"1.7.9">>},0},
{<<"jsx">>,{pkg,<<"jsx">>,<<"2.8.2">>},0},
{<<"lager">>,{pkg,<<"lager">>,<<"3.2.4">>},0},
{<<"lager_logstash_formatter">>,
{git,"git@github.com:rbkmoney/lager_logstash_formatter.git",
{ref,"83a0f21c03dacbd876c7289435f369f573c749b1"}},
{<<"logger_logstash_formatter">>,
{git,"git@github.com:rbkmoney/logger_logstash_formatter.git",
{ref,"4348f24487c400da0579032422d93acd89c6e121"}},
0},
{<<"metrics">>,{pkg,<<"metrics">>,<<"1.0.1">>},1},
{<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.0.2">>},1},
@ -80,15 +84,14 @@
{git,"git@github.com:rbkmoney/payproc-errors-erlang.git",
{ref,"9c720534eb88edc6ba47af084939efabceb9b2d6"}},
0},
{<<"pooler">>,{pkg,<<"pooler">>,<<"1.5.0">>},0},
{<<"ranch">>,{pkg,<<"ranch">>,<<"1.3.2">>},1},
{<<"ranch">>,{pkg,<<"ranch">>,<<"1.6.2">>},1},
{<<"rfc3339">>,
{git,"https://github.com/rbkmoney/rfc3339.git",
{ref,"ee3a1a6b1ee60219c49fdcaa9f36a25e91962bb5"}},
0},
{<<"scoper">>,
{git,"git@github.com:rbkmoney/scoper.git",
{ref,"802057089bac258f45e35263eb2223961618468d"}},
{ref,"e03318fd1feea0e2bb0ba5c634bb38b18aa81efa"}},
1},
{<<"snowflake">>,
{git,"https://github.com/rbkmoney/snowflake.git",
@ -97,11 +100,11 @@
{<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.0">>},1},
{<<"thrift">>,
{git,"https://github.com/rbkmoney/thrift_erlang.git",
{ref,"240bbc842f6e9b90d01bd07838778cf48752b510"}},
{ref,"d393ef9cdb10f3d761ba3a603df2b2929dc19a10"}},
1},
{<<"woody">>,
{git,"git@github.com:rbkmoney/woody_erlang.git",
{ref,"98469234e415214c1b197f08539612c20b3a3ee5"}},
{ref,"5ee89dd0b2d52ff955a4107a8d9dc0f8fdd365a0"}},
0},
{<<"woody_user_identity">>,
{git,"git@github.com:rbkmoney/woody_erlang_user_identity.git",
@ -111,18 +114,17 @@
{pkg_hash,[
{<<"base64url">>, <<"36A90125F5948E3AFD7BE97662A1504B934DD5DAC78451CA6E9ABF85A10286BE">>},
{<<"bear">>, <<"16264309AE5D005D03718A5C82641FCC259C9E8F09ADEB6FD79CA4271168656F">>},
{<<"cache">>, <<"3C11DBF4CD8FCD5787C95A5FB2A04038E3729CFCA0386016EEA8C953AB48A5AB">>},
{<<"certifi">>, <<"A7966EFB868B179023618D29A407548F70C52466BF1849B9E8EBD0E34B7EA11F">>},
{<<"cowboy">>, <<"A324A8DF9F2316C833A470D918AAF73AE894278B8AA6226CE7A9BF699388F878">>},
{<<"cowlib">>, <<"9D769A1D062C9C3AC753096F868CA121E2730B9A377DE23DEC0F7E08B1DF84EE">>},
{<<"goldrush">>, <<"F06E5D5F1277DA5C413E84D5A2924174182FB108DABB39D5EC548B27424CD106">>},
{<<"hackney">>, <<"F3809C0A17A3E523A865C65F6552B526F6B799ACD0389803A05F88573EA26162">>},
{<<"cowboy">>, <<"4EF3AE066EE10FE01EA3272EDC8F024347A0D3EB95F6FBB9AED556DACBFC1337">>},
{<<"cowlib">>, <<"8AA629F81A0FC189F261DC98A42243FA842625FEEA3C7EC56C48F4CCDB55490F">>},
{<<"gproc">>, <<"CEA02C578589C61E5341FCE149EA36CCEF236CC2ECAC8691FBA408E7EA77EC2F">>},
{<<"hackney">>, <<"287A5D2304D516F63E56C469511C42B016423BCB167E61B611F6BAD47E3CA60E">>},
{<<"idna">>, <<"AC62EE99DA068F43C50DC69ACF700E03A62A348360126260E87F2B54ECED86B2">>},
{<<"jose">>, <<"9DC5A14AB62DB4E41677FCC97993752562FB57AD0B8BA062589682EDD3ACB91F">>},
{<<"jsx">>, <<"7ACC7D785B5ABE8A6E9ADBDE926A24E481F29956DD8B4DF49E3E4E7BCC92A018">>},
{<<"lager">>, <<"A6DEB74DAE7927F46BD13255268308EF03EB206EC784A94EAF7C1C0F3B811615">>},
{<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>},
{<<"mimerl">>, <<"993F9B0E084083405ED8252B99460C4F0563E41729AB42D9074FD5E52439BE88">>},
{<<"pooler">>, <<"0FD4BE5D2976E6A2E9A1617623031758C26F200C1FCA89E4A3C542747BEC6371">>},
{<<"ranch">>, <<"E4965A144DC9FBE70E5C077C65E73C57165416A901BD02EA899CFD95AA890986">>},
{<<"ranch">>, <<"6DB93C78F411EE033DBB18BA8234C5574883ACB9A75AF0FB90A9B82EA46AFA00">>},
{<<"ssl_verify_fun">>, <<"EDEE20847C42E379BF91261DB474FFBE373F8ACB56E9079ACB6038D4E0BF414F">>}]}
].