From 21bb7e71e61addbaf113ed040dfbcb7b27bc7570 Mon Sep 17 00:00:00 2001 From: 0x42 Date: Mon, 17 Dec 2018 16:18:47 +0300 Subject: [PATCH] FF-33 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit добавил тест для большого deposit; код для проверки лимитов кошелька убрал в ff_party изменено: apps/ff_cth/src/ct_payment_system.erl новый файл: apps/ff_server/rebar.config изменено: apps/ff_server/src/ff_server.erl изменено: apps/ff_transfer/rebar.config изменено: apps/ff_transfer/src/ff_deposit.erl изменено: apps/ff_transfer/src/ff_withdrawal.erl изменено: apps/ff_transfer/test/ff_transfer_SUITE.erl изменено: apps/fistful/rebar.config изменено: apps/fistful/src/ff_party.erl --- apps/ff_cth/src/ct_payment_system.erl | 11 ++++- apps/ff_server/rebar.config | 3 ++ apps/ff_server/src/ff_server.erl | 2 +- apps/ff_transfer/rebar.config | 3 ++ apps/ff_transfer/src/ff_deposit.erl | 14 ++++-- apps/ff_transfer/src/ff_withdrawal.erl | 35 +------------ apps/ff_transfer/test/ff_transfer_SUITE.erl | 54 ++++++++++++++++++++- apps/fistful/rebar.config | 3 ++ apps/fistful/src/ff_party.erl | 38 +++++++++++++-- 9 files changed, 120 insertions(+), 43 deletions(-) create mode 100644 apps/ff_server/rebar.config diff --git a/apps/ff_cth/src/ct_payment_system.erl b/apps/ff_cth/src/ct_payment_system.erl index a1a2deb..c474a7f 100644 --- a/apps/ff_cth/src/ct_payment_system.erl +++ b/apps/ff_cth/src/ct_payment_system.erl @@ -64,7 +64,16 @@ start_processing_apps(Options) -> client => ff_woody_client:new(<<"http://machinegun:8022/v1/automaton">>) }}, {StartedApps, _StartupCtx} = ct_helper:start_apps([ - lager, + {lager, [ + {error_logger_hwm, 600}, + % {log_root, "/var/log/fistful-server"}, + {crash_log, "crash.log"}, + {handlers, [ + {lager_console_backend, [ + {level, warning} + ]} + ]} + ]}, scoper, woody, dmt_client, diff --git a/apps/ff_server/rebar.config b/apps/ff_server/rebar.config new file mode 100644 index 0000000..ae207ed --- /dev/null +++ b/apps/ff_server/rebar.config @@ -0,0 +1,3 @@ +{erl_opts, [ + {parse_transform, lager_transform} +]}. \ No newline at end of file diff --git a/apps/ff_server/src/ff_server.erl b/apps/ff_server/src/ff_server.erl index cabe4ea..6d20100 100644 --- a/apps/ff_server/src/ff_server.erl +++ b/apps/ff_server/src/ff_server.erl @@ -34,7 +34,7 @@ start() -> application:ensure_all_started(?MODULE). %% Application - + -spec start(normal, any()) -> {ok, pid()} | {error, any()}. diff --git a/apps/ff_transfer/rebar.config b/apps/ff_transfer/rebar.config index e69de29..ae207ed 100644 --- a/apps/ff_transfer/rebar.config +++ b/apps/ff_transfer/rebar.config @@ -0,0 +1,3 @@ +{erl_opts, [ + {parse_transform, lager_transform} +]}. \ No newline at end of file diff --git a/apps/ff_transfer/src/ff_deposit.erl b/apps/ff_transfer/src/ff_deposit.erl index e692ddc..9f41d0b 100644 --- a/apps/ff_transfer/src/ff_deposit.erl +++ b/apps/ff_transfer/src/ff_deposit.erl @@ -154,7 +154,7 @@ events(ID, Range) -> process_transfer(Deposit) -> Activity = deduce_activity(Deposit), - do_process_transfer(Activity, Deposit). + do_process_transfer(Activity, Deposit). -spec process_failure(any(), deposit()) -> {ok, process_result()} | @@ -220,8 +220,16 @@ create_p_transfer(Deposit) -> -spec finish_transfer(deposit()) -> {ok, {ff_transfer_machine:action(), [ff_transfer_machine:event(ff_transfer:event())]}} | {error, _Reason}. -finish_transfer(_Deposit) -> - {ok, {continue, [{status_changed, succeeded}]}}. +finish_transfer(Deposit) -> + Body = body(Deposit), + #{ + wallet_id := WalletID, + wallet_account := WalletAccount + } = params(Deposit), + do(fun () -> + valid = ff_party:validate_wallet_limits(WalletID, Body, WalletAccount), + {continue, [{status_changed, succeeded}]} + end). -spec construct_p_transfer_id(id()) -> id(). construct_p_transfer_id(ID) -> diff --git a/apps/ff_transfer/src/ff_withdrawal.erl b/apps/ff_transfer/src/ff_withdrawal.erl index 7a93e5b..af5b197 100644 --- a/apps/ff_transfer/src/ff_withdrawal.erl +++ b/apps/ff_transfer/src/ff_withdrawal.erl @@ -62,16 +62,13 @@ -type id() :: ff_transfer_machine:id(). -type body() :: ff_transfer:body(). --type wallet() :: ff_wallet:wallet(). -type account() :: ff_account:account(). -type provider() :: ff_withdrawal_provider:provider(). -type wallet_id() :: ff_wallet:id(). --type timestamp() :: ff_time:timestamp_ms(). -type cash_flow_plan() :: ff_cash_flow:cash_flow_plan(). -type destination_id() :: ff_destination:id(). -type process_result() :: {ff_transfer_machine:action(), [event()]}. -type final_cash_flow() :: ff_cash_flow:final_cash_flow(). --type withdrawal_terms() :: dmsl_domain_thrift:'WithdrawalServiceTerms'(). %% Accessors @@ -121,7 +118,7 @@ create(ID, #{wallet_id := WalletID, destination_id := DestinationID, body := Bod unwrap(destination, ff_destination:get_machine(DestinationID)) ), ok = unwrap(destination, valid(authorized, ff_destination:status(Destination))), - Terms = unwrap(contract, get_contract_terms(Wallet, Body, ff_time:now())), + Terms = unwrap(contract, ff_party:get_contract_terms(Wallet, Body, ff_time:now())), valid = unwrap(terms, ff_party:validate_withdrawal_creation(Terms, Body, WalletAccount)), CashFlowPlan = unwrap(cash_flow_plan, ff_party:get_withdrawal_cash_flow_plan(Terms)), @@ -271,7 +268,7 @@ create_session(Withdrawal) -> destination_account := DestinationAccount } = params(Withdrawal), do(fun () -> - valid = validate_wallet_limits(WalletID, Body, WalletAccount), + valid = ff_party:validate_wallet_limits(WalletID, Body, WalletAccount), #{provider_id := ProviderID} = route(Withdrawal), SenderSt = unwrap(ff_identity_machine:get(ff_account:identity(WalletAccount))), ReceiverSt = unwrap(ff_identity_machine:get(ff_account:identity(DestinationAccount))), @@ -316,29 +313,6 @@ poll_session_completion(Withdrawal) -> end end). --spec get_contract_terms(wallet(), body(), timestamp()) -> Result when - Result :: {ok, withdrawal_terms()} | {error, Error}, - Error :: - {party_not_found, id()} | - {party_not_exists_yet, id()} | - {exception, any()}. -get_contract_terms(Wallet, Body, Timestamp) -> - WalletID = ff_wallet:id(Wallet), - IdentityID = ff_wallet:identity(Wallet), - do(fun() -> - IdentityMachine = unwrap(ff_identity_machine:get(IdentityID)), - Identity = ff_identity_machine:identity(IdentityMachine), - ContractID = ff_identity:contract(Identity), - PartyID = ff_identity:party(Identity), - {_Amount, CurrencyID} = Body, - TermVarset = #{ - amount => Body, - wallet_id => WalletID, - currency_id => CurrencyID - }, - unwrap(ff_party:get_contract_terms(PartyID, ContractID, TermVarset, Timestamp)) - end). - -spec get_route_provider(route()) -> {ok, provider()}. get_route_provider(#{provider_id := ProviderID}) -> ff_withdrawal_provider:get(ProviderID). @@ -364,11 +338,6 @@ finalize_cash_flow(CashFlowPlan, WalletAccount, DestinationAccount, SystemAccoun }), ff_cash_flow:finalize(CashFlowPlan, Accounts, Constants). -validate_wallet_limits(WalletID, Body, Account) -> - Wallet = ff_wallet_machine:wallet(unwrap(wallet, ff_wallet_machine:get(WalletID))), - Terms = unwrap(contract, get_contract_terms(Wallet, Body, ff_time:now())), - unwrap(wallet_limit, ff_party:validate_wallet_limits(Account, Terms)). - -spec maybe_migrate(ff_transfer:event() | ff_transfer:legacy_event()) -> ff_transfer:event(). maybe_migrate(Ev) -> diff --git a/apps/ff_transfer/test/ff_transfer_SUITE.erl b/apps/ff_transfer/test/ff_transfer_SUITE.erl index 5ec9e72..9d372c1 100644 --- a/apps/ff_transfer/test/ff_transfer_SUITE.erl +++ b/apps/ff_transfer/test/ff_transfer_SUITE.erl @@ -15,6 +15,7 @@ -export([get_missing_fails/1]). -export([deposit_via_admin_ok/1]). +-export([deposit_via_admin_bad/1]). -export([deposit_withdrawal_ok/1]). -type config() :: ct_helper:config(). @@ -34,6 +35,7 @@ groups() -> {default, [parallel], [ get_missing_fails, deposit_via_admin_ok, + deposit_via_admin_bad, deposit_withdrawal_ok ]} ]. @@ -80,6 +82,7 @@ end_per_testcase(_Name, _C) -> -spec get_missing_fails(config()) -> test_return(). -spec deposit_via_admin_ok(config()) -> test_return(). +-spec deposit_via_admin_bad(config()) -> test_return(). -spec deposit_withdrawal_ok(config()) -> test_return(). get_missing_fails(_C) -> @@ -131,6 +134,55 @@ deposit_via_admin_ok(C) -> ), ok = await_wallet_balance({20000, <<"RUB">>}, WalID). +deposit_via_admin_bad(C) -> + Party = create_party(C), + IID = create_person_identity(Party, C), + WalID = create_wallet(IID, <<"HAHA NO">>, <<"RUB">>, C), + ok = await_wallet_balance({0, <<"RUB">>}, WalID), + + % Create source + {ok, Src1} = admin_call('CreateSource', [#fistful_SourceParams{ + name = <<"HAHA NO">>, + identity_id = IID, + currency = #'CurrencyRef'{symbolic_code = <<"RUB">>}, + resource = #fistful_SourceResource{details = <<"Infinite source of cash">>} + }]), + unauthorized = Src1#fistful_Source.status, + SrcID = Src1#fistful_Source.id, + authorized = ct_helper:await( + authorized, + fun () -> + {ok, Src} = admin_call('GetSource', [SrcID]), + Src#fistful_Source.status + end + ), + % Process deposit + % dbg:tracer(), + % dbg:tp(ff_transfer_machine, []), + % dbg:tp(ff_deposit, process_transfer, 1, []), + % dbg:p(all, c), + {ok, Dep1} = admin_call('CreateDeposit', [#fistful_DepositParams{ + source = SrcID, + destination = WalID, + body = #'Cash'{ + amount = 10000002, + currency = #'CurrencyRef'{symbolic_code = <<"RUB">>} + } + }]), + + DepID = Dep1#fistful_Deposit.id, + {pending, _} = Dep1#fistful_Deposit.status, + failed = ct_helper:await( + failed, + fun () -> + {ok, Dep} = admin_call('GetDeposit', [DepID]), + {Status, _} = Dep#fistful_Deposit.status, + Status + end, + genlib_retry:linear(15, 1000) + ), + ok = await_wallet_balance({0, <<"RUB">>}, WalID). + deposit_withdrawal_ok(C) -> Party = create_party(C), IID = create_person_identity(Party, C), @@ -145,7 +197,7 @@ deposit_withdrawal_ok(C) -> DestID = create_destination(IID, C), pass_identification(ICID, IID, C), - + process_withdrawal(WalID, DestID). create_party(_C) -> diff --git a/apps/fistful/rebar.config b/apps/fistful/rebar.config index e69de29..ae207ed 100644 --- a/apps/fistful/rebar.config +++ b/apps/fistful/rebar.config @@ -0,0 +1,3 @@ +{erl_opts, [ + {parse_transform, lager_transform} +]}. \ No newline at end of file diff --git a/apps/fistful/src/ff_party.erl b/apps/fistful/src/ff_party.erl index ed94021..43a535f 100644 --- a/apps/fistful/src/ff_party.erl +++ b/apps/fistful/src/ff_party.erl @@ -43,12 +43,13 @@ -export([validate_account_creation/2]). -export([validate_withdrawal_creation/3]). -export([validate_wallet_limits/2]). - +-export([validate_wallet_limits/3]). +-export([get_contract_terms/3]). -export([get_contract_terms/4]). -export([get_withdrawal_cash_flow_plan/1]). %% Internal types - +-type body() :: ff_transfer:body(). -type cash() :: ff_transaction:body(). -type terms() :: dmsl_domain_thrift:'TermSet'(). -type wallet_terms() :: dmsl_domain_thrift:'WalletServiceTerms'() | undefined. @@ -58,6 +59,7 @@ -type domain_cash() :: dmsl_domain_thrift:'Cash'(). -type cash_range() :: dmsl_domain_thrift:'CashRange'(). -type timestamp() :: ff_time:timestamp_ms(). +-type wallet() :: ff_wallet:wallet(). -type currency_validation_error() :: {terms_violation, {not_allowed_currency, _Details}}. -type withdrawal_currency_error() :: {invalid_withdrawal_currency, currency_id(), {wallet_currency, currency_id()}}. @@ -65,7 +67,7 @@ %% Pipeline --import(ff_pipeline, [do/1, unwrap/1]). +-import(ff_pipeline, [do/1, unwrap/1, unwrap/2]). %% @@ -133,7 +135,28 @@ change_contractor_level(ID, ContractID, ContractorLevel) -> ok end). -%% +-spec get_contract_terms(wallet(), body(), timestamp()) -> Result when + Result :: {ok, wallet_terms()} | {error, Error}, + Error :: + {party_not_found, id()} | + {party_not_exists_yet, id()} | + {exception, any()}. +get_contract_terms(Wallet, Body, Timestamp) -> + WalletID = ff_wallet:id(Wallet), + IdentityID = ff_wallet:identity(Wallet), + do(fun() -> + IdentityMachine = unwrap(ff_identity_machine:get(IdentityID)), + Identity = ff_identity_machine:identity(IdentityMachine), + ContractID = ff_identity:contract(Identity), + PartyID = ff_identity:party(Identity), + {_Amount, CurrencyID} = Body, + TermVarset = #{ + amount => Body, + wallet_id => WalletID, + currency_id => CurrencyID + }, + unwrap(get_contract_terms(PartyID, ContractID, TermVarset, Timestamp)) + end). -spec get_contract_terms(id(), contract_id(), term_varset(), timestamp()) -> Result when Result :: {ok, terms()} | {error, Error}, @@ -448,6 +471,13 @@ validate_wallet_limits(Account, #domain_TermSet{wallets = WalletTerms}) -> valid = unwrap(validate_cash_range(ExpMaxCash, CashRange)) end). +-spec validate_wallet_limits(machinery:id(), body(), ff_account:account()) -> + valid | {error, cash_range_validation_error()}. +validate_wallet_limits(WalletID, Body, Account) -> + Wallet = ff_wallet_machine:wallet(unwrap(wallet, ff_wallet_machine:get(WalletID))), + Terms = unwrap(contract, get_contract_terms(Wallet, Body, ff_time:now())), + unwrap(wallet_limit, validate_wallet_limits(Account, Terms)). + -spec validate_wallet_limits_terms_is_reduced(wallet_terms()) -> {ok, valid} | {error, {invalid_terms, _Details}}. validate_wallet_limits_terms_is_reduced(Terms) ->