HG188-add user identity (#86)

* HG-188 Move to erlang 19 dialyzer and user identity access

* HG-188 Postreview refactoring
This commit is contained in:
Artem Ocheredko 2017-05-17 11:50:18 +03:00 committed by Andrew Mayorov
parent ae2ec46239
commit ab4ffe8569
23 changed files with 231 additions and 117 deletions

2
Jenkinsfile vendored
View File

@ -31,7 +31,7 @@ build('hellgate', 'docker-host', finalHook) {
sh 'make wc_xref' sh 'make wc_xref'
} }
runStage('dialyze') { runStage('dialyze') {
withWsCache("_build/default/rebar3_18.3_plt") { withWsCache("_build/default/rebar3_19.1_plt") {
sh 'make wc_dialyze' sh 'make wc_dialyze'
} }
} }

View File

@ -17,7 +17,7 @@ BASE_IMAGE_NAME := service_erlang
BASE_IMAGE_TAG := 13454a94990acb72f753623ec13599a9f6f4f852 BASE_IMAGE_TAG := 13454a94990acb72f753623ec13599a9f6f4f852
# Build image tag to be used # Build image tag to be used
BUILD_IMAGE_TAG := 7f6c3f231c0cffbf11e67f5a5e38366bef1c798f BUILD_IMAGE_TAG := 4fa802d2f534208b9dc2ae203e2a5f07affbf385
CALL_ANYWHERE := all submodules rebar-update compile xref lint dialyze start devrel release clean distclean CALL_ANYWHERE := all submodules rebar-update compile xref lint dialyze start devrel release clean distclean

View File

@ -16,7 +16,8 @@
woody, woody,
gproc, gproc,
hg_proto, hg_proto,
dmt_client dmt_client,
woody_user_identity
]}, ]},
{env, []}, {env, []},
{modules, []}, {modules, []},

View File

@ -1,19 +1,18 @@
-module(hg_access_control). -module(hg_access_control).
-include_lib("dmsl/include/dmsl_payment_processing_thrift.hrl").
%%% HG access controll %%% HG access controll
-export([check_user_info/2]). -export([check_user/2]).
%% -spec check_user(woody_user_identity:user_identity(), dmsl_domain_thrift:'PartyID'())->
-spec check_user_info(dmsl_payment_processing_thrift:'UserInfo'(), dmsl_domain_thrift:'PartyID'()) ->
ok | invalid_user. ok | invalid_user.
check_user_info(#payproc_UserInfo{id = PartyID, type = {external_user, #payproc_ExternalUser{}}}, PartyID) -> check_user(#{id := PartyID, realm := <<"external">>}, PartyID) ->
ok; ok;
check_user_info(#payproc_UserInfo{id = _AnyID, type = {internal_user, #payproc_InternalUser{}}}, _PartyID) -> check_user(#{id := _AnyID, realm := <<"internal">>}, _PartyID) ->
ok; ok;
check_user_info(#payproc_UserInfo{id = _AnyID, type = {service_user, #payproc_ServiceUser{}}}, _PartyID) -> %% @TODO must be deleted when we get rid of #payproc_ServiceUser
check_user(#{id := _AnyID, realm := <<"service">>}, _PartyID) ->
ok; ok;
check_user_info(_, _) -> check_user(_, _) ->
invalid_user. invalid_user.

View File

@ -69,7 +69,7 @@ find(Revision, Ref) ->
extract_data(#'VersionedObject'{object = {_Tag, {_Name, _Ref, Data}}}) -> extract_data(#'VersionedObject'{object = {_Tag, {_Name, _Ref, Data}}}) ->
Data. Data.
-spec commit(revision(), dmt:commit()) -> ok. -spec commit(revision(), dmt_client:commit()) -> ok | no_return().
commit(Revision, Commit) -> commit(Revision, Commit) ->
Revision = dmt_client:commit(Revision, Commit) - 1, Revision = dmt_client:commit(Revision, Commit) - 1,
@ -78,7 +78,7 @@ commit(Revision, Commit) ->
%% convenience shortcuts, use carefully %% convenience shortcuts, use carefully
-spec insert(object() | [object()]) -> ok. -spec insert(object() | [object()]) -> ok | no_return().
insert(Object) when not is_list(Object) -> insert(Object) when not is_list(Object) ->
insert([Object]); insert([Object]);
@ -93,7 +93,7 @@ insert(Objects) ->
}, },
commit(head(), Commit). commit(head(), Commit).
-spec update(object() | [object()]) -> ok. -spec update(object() | [object()]) -> ok | no_return().
update(NewObject) when not is_list(NewObject) -> update(NewObject) when not is_list(NewObject) ->
update([NewObject]); update([NewObject]);
@ -111,7 +111,7 @@ update(NewObjects) ->
}, },
commit(head(), Commit). commit(head(), Commit).
-spec upsert(object() | [object()]) -> ok. -spec upsert(object() | [object()]) -> ok | no_return().
upsert(NewObject) when not is_list(NewObject) -> upsert(NewObject) when not is_list(NewObject) ->
upsert([NewObject]); upsert([NewObject]);
@ -136,7 +136,7 @@ upsert(NewObjects) ->
}, },
commit(head(), Commit). commit(head(), Commit).
-spec remove(object() | [object()]) -> ok. -spec remove(object() | [object()]) -> ok | no_return().
remove(Object) when not is_list(Object) -> remove(Object) when not is_list(Object) ->
remove([Object]); remove([Object]);
@ -151,7 +151,7 @@ remove(Objects) ->
}, },
commit(head(), Commit). commit(head(), Commit).
-spec cleanup() -> ok. -spec cleanup() -> ok | no_return().
cleanup() -> cleanup() ->
Domain = all(head()), Domain = all(head()),

View File

@ -45,7 +45,7 @@
%% %%
-record(st, { -record(st, {
invoice :: invoice(), invoice :: undefined | invoice(),
payments = [] :: [{payment_id(), payment_st()}], payments = [] :: [{payment_id(), payment_st()}],
sequence = 0 :: 0 | sequence(), sequence = 0 :: 0 | sequence(),
pending = invoice :: pending = invoice ::
@ -587,10 +587,10 @@ validate_invoice_access(UserInfo, St = #st{}) ->
St. St.
validate_party_access(UserInfo, PartyID) -> validate_party_access(UserInfo, PartyID) ->
case hg_access_control:check_user_info(UserInfo, PartyID) of UserIdentity = hg_woody_handler_utils:get_user_identity(UserInfo),
case hg_access_control:check_user(UserIdentity, PartyID) of
ok -> ok ->
ok; ok;
invalid_user -> invalid_user ->
throw(#payproc_InvalidUser{}) throw(#payproc_InvalidUser{})
end. end.

View File

@ -44,7 +44,7 @@
payment :: payment(), payment :: payment(),
route :: route(), route :: route(),
cashflow :: cashflow(), cashflow :: cashflow(),
session :: session() session :: undefined | session()
}). }).
-type st() :: #st{}. -type st() :: #st{}.
@ -365,11 +365,11 @@ handle_proxy_intent(#'FinishIntent'{status = {success, _}}, _ProxyState, Action,
PaymentID = get_payment_id(St), PaymentID = get_payment_id(St),
Target = get_target(St), Target = get_target(St),
case get_target(St) of case get_target(St) of
?captured() -> {captured, _} ->
_AccountsState = commit_plan(St, Options); _AccountsState = commit_plan(St, Options);
?cancelled(_) -> {cancelled, _} ->
_AccountsState = rollback_plan(St, Options); _AccountsState = rollback_plan(St, Options);
?processed() -> {processed, _} ->
ok ok
end, end,
Events = [?payment_ev(?payment_status_changed(PaymentID, Target))], Events = [?payment_ev(?payment_status_changed(PaymentID, Target))],

View File

@ -152,8 +152,7 @@ handle_function(Func, Args, Opts) ->
fun() -> handle_function_(Func, Args, Opts) end fun() -> handle_function_(Func, Args, Opts) end
). ).
-spec handle_function_(func(), woody:args(), hg_woody_wrapper:handler_opts()) -> -spec handle_function_(func(), woody:args(), #{ns := ns()}) -> term() | no_return().
term() | no_return().
handle_function_('ProcessSignal', [Args], #{ns := Ns} = _Opts) -> handle_function_('ProcessSignal', [Args], #{ns := Ns} = _Opts) ->
#'SignalArgs'{signal = {Type, Signal}, machine = #'Machine'{id = ID} = Machine} = Args, #'SignalArgs'{signal = {Type, Signal}, machine = #'Machine'{id = ID} = Machine} = Args,

View File

@ -64,6 +64,8 @@
-type shop_params() :: dmsl_payment_processing_thrift:'ShopParams'(). -type shop_params() :: dmsl_payment_processing_thrift:'ShopParams'().
-type currency() :: dmsl_domain_thrift:'CurrencyRef'(). -type currency() :: dmsl_domain_thrift:'CurrencyRef'().
-type category() :: dmsl_domain_thrift:'CategoryRef'(). -type category() :: dmsl_domain_thrift:'CategoryRef'().
-type contract_template_ref() :: dmsl_domain_thrift:'ContractTemplateRef'().
-type contractor() :: dmsl_domain_thrift:'Contractor'().
-type timestamp() :: dmsl_base_thrift:'Timestamp'(). -type timestamp() :: dmsl_base_thrift:'Timestamp'().
-type revision() :: hg_domain:revision(). -type revision() :: hg_domain:revision().
@ -91,29 +93,21 @@ get_party_id(#domain_Party{id = ID}) ->
ID. ID.
-spec create_contract(contract_params(), revision(), party()) -> -spec create_contract(contract_params(), revision(), party()) ->
contract(). contract() | no_return().
create_contract(Params, Revision, Party) -> create_contract(Params, Revision, Party) ->
#payproc_ContractParams{ #payproc_ContractParams{
contractor = Contractor, contractor = Contractor,
template = TemplateRef template = TemplateRef
} = ensure_contract_creation_params(Params, Revision), } = ensure_contract_creation_params(Params, Revision),
ContractID = get_next_contract_id(Party), prepare_contract(TemplateRef, Contractor, Revision, Party).
Contract = instantiate_contract_template(TemplateRef, Revision),
Contract#domain_Contract{
id = ContractID,
contractor = Contractor,
status = {active, #domain_ContractActive{}},
adjustments = [],
payout_tools = []
}.
-spec create_test_contract(revision(), party()) -> -spec create_test_contract(revision(), party()) ->
contract(). contract() | no_return().
create_test_contract(Revision, Party) -> create_test_contract(Revision, Party) ->
Params = #payproc_ContractParams{template = get_test_template_ref(Revision)}, TemplateRef = ensure_contract_template(get_test_template_ref(Revision), Revision),
create_contract(Params, Revision, Party). prepare_contract(TemplateRef, undefined, Revision, Party).
-spec get_contract(contract_id(), party()) -> -spec get_contract(contract_id(), party()) ->
contract(). contract().
@ -162,11 +156,10 @@ create_contract_adjustment(Params, Revision, Contract) ->
template = TemplateRef template = TemplateRef
} = ensure_adjustment_creation_params(Params, Revision), } = ensure_adjustment_creation_params(Params, Revision),
ID = get_next_contract_adjustment_id(Contract), ID = get_next_contract_adjustment_id(Contract),
#domain_Contract{ {ValidSince, ValidUntil, TermSetHierarchyRef} = instantiate_contract_template(
valid_since = ValidSince, TemplateRef,
valid_until = ValidUntil, Revision
terms = TermSetHierarchyRef ),
} = instantiate_contract_template(TemplateRef, Revision),
#domain_ContractAdjustment{ #domain_ContractAdjustment{
id = ID, id = ID,
valid_since = ValidSince, valid_since = ValidSince,
@ -226,10 +219,10 @@ get_payments_service_terms(Contract, Timestamp) ->
create_shop(ShopParams, Timestamp, Revision, Party) -> create_shop(ShopParams, Timestamp, Revision, Party) ->
create_shop(ShopParams, ?suspended(), Timestamp, Revision, Party). create_shop(ShopParams, ?suspended(), Timestamp, Revision, Party).
create_shop(ShopParams, Suspension, Timestamp, Revision, Party) -> create_shop(ShopParams0, Suspension, Timestamp, Revision, Party) ->
Contract = get_contract(ShopParams#payproc_ShopParams.contract_id, Party), Contract = get_contract(ShopParams0#payproc_ShopParams.contract_id, Party),
Shop = ensure_shop_category( ShopParams = ensure_shop_params_category(ShopParams0, Contract, Timestamp, Revision),
#domain_Shop{ Shop = #domain_Shop{
id = get_next_shop_id(Party), id = get_next_shop_id(Party),
blocking = ?unblocked(<<>>), blocking = ?unblocked(<<>>),
suspension = Suspension, suspension = Suspension,
@ -239,10 +232,6 @@ create_shop(ShopParams, Suspension, Timestamp, Revision, Party) ->
payout_tool_id = ShopParams#payproc_ShopParams.payout_tool_id, payout_tool_id = ShopParams#payproc_ShopParams.payout_tool_id,
proxy = ShopParams#payproc_ShopParams.proxy proxy = ShopParams#payproc_ShopParams.proxy
}, },
Contract,
Timestamp,
Revision
),
ok = assert_shop_contract_valid(Shop, Contract, Timestamp, Revision), ok = assert_shop_contract_valid(Shop, Contract, Timestamp, Revision),
ok = assert_shop_payout_tool_valid(Shop, Contract), ok = assert_shop_payout_tool_valid(Shop, Contract),
Shop. Shop.
@ -251,16 +240,16 @@ create_shop(ShopParams, Suspension, Timestamp, Revision, Party) ->
shop(). shop().
create_test_shop(ContractID, Revision, Party) -> create_test_shop(ContractID, Revision, Party) ->
Params = get_shop_prototype_params(ContractID, Revision), ShopPrototype = get_shop_prototype(Revision),
#domain_Shop{ #domain_Shop{
id = get_next_shop_id(Party), id = get_next_shop_id(Party),
blocking = ?unblocked(<<>>), blocking = ?unblocked(<<>>),
suspension = ?active(), suspension = ?active(),
details = Params#payproc_ShopParams.details, details = ShopPrototype#domain_ShopPrototype.details,
category = Params#payproc_ShopParams.category, category = ShopPrototype#domain_ShopPrototype.category,
contract_id = Params#payproc_ShopParams.contract_id, contract_id = ContractID,
payout_tool_id = Params#payproc_ShopParams.payout_tool_id, payout_tool_id = undefined,
proxy = Params#payproc_ShopParams.proxy proxy = undefined
}. }.
-spec get_shop(shop_id(), party()) -> -spec get_shop(shop_id(), party()) ->
@ -316,14 +305,6 @@ get_account_state(AccountID, Party) ->
%% Internals %% Internals
get_shop_prototype_params(ContractID, Revision) ->
ShopPrototype = get_shop_prototype(Revision),
#payproc_ShopParams{
contract_id = ContractID,
category = ShopPrototype#domain_ShopPrototype.category,
details = ShopPrototype#domain_ShopPrototype.details
}.
get_globals(Revision) -> get_globals(Revision) ->
hg_domain:get(Revision, {globals, #domain_GlobalsRef{}}). hg_domain:get(Revision, {globals, #domain_GlobalsRef{}}).
@ -345,6 +326,8 @@ ensure_adjustment_creation_params(#payproc_ContractAdjustmentParams{template = T
template = ensure_contract_template(TemplateRef, Revision) template = ensure_contract_template(TemplateRef, Revision)
}. }.
-spec ensure_contract_template(contract_template_ref(), revision()) -> contract_template_ref() | no_return().
ensure_contract_template(#domain_ContractTemplateRef{} = TemplateRef, Revision) -> ensure_contract_template(#domain_ContractTemplateRef{} = TemplateRef, Revision) ->
try try
_GoodTemplate = get_template(TemplateRef, Revision), _GoodTemplate = get_template(TemplateRef, Revision),
@ -357,10 +340,10 @@ ensure_contract_template(#domain_ContractTemplateRef{} = TemplateRef, Revision)
ensure_contract_template(undefined, Revision) -> ensure_contract_template(undefined, Revision) ->
get_default_template_ref(Revision). get_default_template_ref(Revision).
ensure_shop_category(Shop = #domain_Shop{category = #domain_CategoryRef{}}, _, _, _) -> ensure_shop_params_category(ShopParams = #payproc_ShopParams{category = #domain_CategoryRef{}}, _, _, _) ->
Shop; ShopParams;
ensure_shop_category(Shop = #domain_Shop{category = undefined}, Contract, Timestamp, Revision) -> ensure_shop_params_category(ShopParams = #payproc_ShopParams{category = undefined}, Contract, Timestamp, Revision) ->
Shop#domain_Shop{ ShopParams#payproc_ShopParams{
category = get_default_contract_category(Contract, Timestamp, Revision) category = get_default_contract_category(Contract, Timestamp, Revision)
}. }.
@ -368,6 +351,23 @@ get_default_contract_category(Contract, Timestamp, Revision) ->
Categories = get_contract_categories(Contract, Timestamp, Revision), Categories = get_contract_categories(Contract, Timestamp, Revision),
erlang:hd(ordsets:to_list(Categories)). erlang:hd(ordsets:to_list(Categories)).
-spec prepare_contract(contract_template_ref(), undefined | contractor(), revision(), party()) ->
contract() | no_return().
prepare_contract(TemplateRef, Contractor, Revision, Party) ->
ContractID = get_next_contract_id(Party),
{ValidSince, ValidUntil, TermSetHierarchyRef} = instantiate_contract_template(TemplateRef, Revision),
#domain_Contract{
id = ContractID,
contractor = Contractor,
status = {active, #domain_ContractActive{}},
valid_since = ValidSince,
valid_until = ValidUntil,
terms = TermSetHierarchyRef,
adjustments = [],
payout_tools = []
}.
-spec reduce_selector_to_value(Selector, #{}, revision()) -spec reduce_selector_to_value(Selector, #{}, revision())
-> ordsets:ordset(currency()) | ordsets:ordset(category()) | no_return() -> ordsets:ordset(currency()) | ordsets:ordset(category()) | no_return()
when Selector :: dmsl_domain_thrift:'CurrencySelector'() | dmsl_domain_thrift:'CategorySelector'(). when Selector :: dmsl_domain_thrift:'CurrencySelector'() | dmsl_domain_thrift:'CategorySelector'().
@ -414,11 +414,7 @@ instantiate_contract_template(TemplateRef, Revision) ->
{interval, IntervalVU} -> {interval, IntervalVU} ->
add_interval(VS, IntervalVU) add_interval(VS, IntervalVU)
end, end,
#domain_Contract{ {VS, VU, TermSetHierarchyRef}.
valid_since = VS,
valid_until = VU,
terms = TermSetHierarchyRef
}.
add_interval(Timestamp, Interval) -> add_interval(Timestamp, Interval) ->
#domain_LifetimeInterval{ #domain_LifetimeInterval{

View File

@ -33,7 +33,7 @@
-define(NS, <<"party">>). -define(NS, <<"party">>).
-record(st, { -record(st, {
party :: party(), party :: undefined | party(),
timestamp :: timestamp(), timestamp :: timestamp(),
claims = #{} :: #{claim_id() => claim()}, claims = #{} :: #{claim_id() => claim()},
sequence = 0 :: 0 | sequence() sequence = 0 :: 0 | sequence()
@ -508,9 +508,7 @@ is_shop_modification_need_acceptance({suspension, _}) ->
is_shop_modification_need_acceptance({account_created, _}) -> is_shop_modification_need_acceptance({account_created, _}) ->
false; false;
is_shop_modification_need_acceptance({update, ShopUpdate}) -> is_shop_modification_need_acceptance({update, ShopUpdate}) ->
is_shop_update_need_acceptance(ShopUpdate); is_shop_update_need_acceptance(ShopUpdate).
is_shop_modification_need_acceptance(_) ->
true.
is_shop_update_need_acceptance(ShopUpdate = #payproc_ShopUpdate{}) -> is_shop_update_need_acceptance(ShopUpdate = #payproc_ShopUpdate{}) ->
RecordInfo = record_info(fields, payproc_ShopUpdate), RecordInfo = record_info(fields, payproc_ShopUpdate),

View File

@ -42,22 +42,38 @@ handle_function_('GetContract', [UserInfo, PartyID, ContractID], _Opts) ->
Party = hg_party_machine:get_party(PartyID), Party = hg_party_machine:get_party(PartyID),
hg_party:get_contract(ContractID, Party); hg_party:get_contract(ContractID, Party);
handle_function_('BindContractLegalAgreemnet', [UserInfo, PartyID, ContractID, LegalAgreement], _Opts) -> handle_function_(
'BindContractLegalAgreemnet',
[UserInfo, PartyID, ContractID, LegalAgreement],
_Opts
) ->
_ = set_party_mgmt_meta(PartyID, UserInfo), _ = set_party_mgmt_meta(PartyID, UserInfo),
ok = assert_party_accessible(UserInfo, PartyID), ok = assert_party_accessible(UserInfo, PartyID),
hg_party_machine:call(PartyID, {bind_contract_legal_agreemnet, ContractID, LegalAgreement}); hg_party_machine:call(PartyID, {bind_contract_legal_agreemnet, ContractID, LegalAgreement});
handle_function_('TerminateContract', [UserInfo, PartyID, ContractID, Reason], _Opts) -> handle_function_(
'TerminateContract',
[UserInfo, PartyID, ContractID, Reason],
_Opts
) ->
_ = set_party_mgmt_meta(PartyID, UserInfo), _ = set_party_mgmt_meta(PartyID, UserInfo),
ok = assert_party_accessible(UserInfo, PartyID), ok = assert_party_accessible(UserInfo, PartyID),
hg_party_machine:call(PartyID, {terminate_contract, ContractID, Reason}); hg_party_machine:call(PartyID, {terminate_contract, ContractID, Reason});
handle_function_('CreateContractAdjustment', [UserInfo, PartyID, ContractID, Params], _Opts) -> handle_function_(
'CreateContractAdjustment',
[UserInfo, PartyID, ContractID, Params],
_Opts
) ->
_ = set_party_mgmt_meta(PartyID, UserInfo), _ = set_party_mgmt_meta(PartyID, UserInfo),
ok = assert_party_accessible(UserInfo, PartyID), ok = assert_party_accessible(UserInfo, PartyID),
hg_party_machine:call(PartyID, {create_contract_adjustment, ContractID, Params}); hg_party_machine:call(PartyID, {create_contract_adjustment, ContractID, Params});
handle_function_('CreatePayoutTool', [UserInfo, PartyID, ContractID, Params], _Opts) -> handle_function_(
'CreatePayoutTool',
[UserInfo, PartyID, ContractID, Params],
_Opts
) ->
_ = set_party_mgmt_meta(PartyID, UserInfo), _ = set_party_mgmt_meta(PartyID, UserInfo),
ok = assert_party_accessible(UserInfo, PartyID), ok = assert_party_accessible(UserInfo, PartyID),
hg_party_machine:call(PartyID, {create_payout_tool, ContractID, Params}); hg_party_machine:call(PartyID, {create_payout_tool, ContractID, Params});
@ -163,11 +179,15 @@ handle_function_('GetShopAccount', [UserInfo, PartyID, ShopID], _Opts) ->
%% %%
-spec assert_party_accessible(dmsl_payment_processing_thrift:'UserInfo'(), dmsl_domain_thrift:'PartyID'()) -> -spec assert_party_accessible(
dmsl_payment_processing_thrift:'UserInfo'(),
dmsl_domain_thrift:'PartyID'()
) ->
ok | no_return(). ok | no_return().
assert_party_accessible(UserInfo, PartyID) -> assert_party_accessible(UserInfo, PartyID) ->
case hg_access_control:check_user_info(UserInfo, PartyID) of UserIdentity = hg_woody_handler_utils:get_user_identity(UserInfo),
case hg_access_control:check_user(UserIdentity, PartyID) of
ok -> ok ->
ok; ok;
invalid_user -> invalid_user ->
@ -179,5 +199,3 @@ set_party_mgmt_meta(PartyID, #payproc_UserInfo{id = ID, type = {Type, _}}) ->
party_id => PartyID, party_id => PartyID,
user_info => #{id => ID, type => Type} user_info => #{id => ID, type => Type}
}). }).

View File

@ -8,10 +8,9 @@
%% %%
-type t() :: dmsl_domain_thrift:'InvoicePaymentRoute'(). -type t() :: dmsl_domain_thrift:'InvoicePaymentRoute'().
-type varset() :: #{}. % FIXME
%%-type risk_score() :: dmsl_domain_thrift:'RiskScore'(). %%-type risk_score() :: dmsl_domain_thrift:'RiskScore'().
-spec choose(varset(), hg_domain:revision()) -> -spec choose(hg_selector:varset(), hg_domain:revision()) ->
t() | undefined. t() | undefined.
choose(VS, Revision) -> choose(VS, Revision) ->

View File

@ -26,9 +26,17 @@
_. %% FIXME _. %% FIXME
-type varset() :: #{ -type varset() :: #{
%% TODO category => dmsl_domain_thrift:'CategoryRef'(),
currency => dmsl_domain_thrift:'CurrencyRef'(),
cost => dmsl_domain_thrift:'Cash'(),
payment_tool=> dmsl_domain_thrift:'PaymentTool'(),
party => dmsl_domain_thrift:'Party'(),
shop => dmsl_domain_thrift:'Shop'(),
risk_score => high | low
}. }.
-export_type([varset/0]).
-export([fold/3]). -export([fold/3]).
-export([collect/1]). -export([collect/1]).
-export([reduce/3]). -export([reduce/3]).

View File

@ -0,0 +1,31 @@
-module(hg_woody_handler_utils).
-include_lib("dmsl/include/dmsl_payment_processing_thrift.hrl").
-export([get_user_identity/1]).
-spec get_user_identity(dmsl_payment_processing_thrift:'UserInfo'()) ->
woody_user_identity:user_identity().
get_user_identity(UserInfo) ->
try
Context = hg_context:get(),
woody_user_identity:get(Context)
catch
throw:{missing_required, _Key} ->
map_user_info(UserInfo)
end.
map_user_info(#payproc_UserInfo{id = PartyID, type = Type}) ->
#{
id => PartyID,
realm => map_user_type(Type)
}.
map_user_type({external_user, #payproc_ExternalUser{}}) ->
<<"external">>;
map_user_type({internal_user, #payproc_InternalUser{}}) ->
<<"internal">>;
map_user_type({service_user, #payproc_ServiceUser{}}) ->
<<"service">>.

View File

@ -78,6 +78,15 @@ start_app(hellgate = AppName) ->
hellgate_root_url => get_hellgate_url() hellgate_root_url => get_hellgate_url()
}}; }};
start_app(dmt_client = AppName) ->
{start_app(AppName, [
{cache_update_interval, 5000}, % milliseconds
{service_urls, #{
'Repository' => <<"http://dominant:8022/v1/domain/repository">>,
'RepositoryClient' => <<"http://dominant:8022/v1/domain/repository_client">>
}}
]), #{}};
start_app(AppName) -> start_app(AppName) ->
{genlib_app:start_application(AppName), #{}}. {genlib_app:start_application(AppName), #{}}.

View File

@ -48,7 +48,7 @@ groups() ->
-spec init_per_suite(config()) -> config(). -spec init_per_suite(config()) -> config().
init_per_suite(C) -> init_per_suite(C) ->
{Apps, Ret} = hg_ct_helper:start_apps([lager, woody, hellgate]), {Apps, Ret} = hg_ct_helper:start_apps([lager, woody, dmt_client, hellgate]),
ok = hg_domain:insert(construct_domain_fixture()), ok = hg_domain:insert(construct_domain_fixture()),
[{root_url, maps:get(hellgate_root_url, Ret)}, {apps, Apps} | C]. [{root_url, maps:get(hellgate_root_url, Ret)}, {apps, Apps} | C].

View File

@ -82,7 +82,7 @@ init_per_suite(C) ->
% _ = dbg:p(all, c), % _ = dbg:p(all, c),
% _ = dbg:tpl({'hg_client_party', '_', '_'}, x), % _ = dbg:tpl({'hg_client_party', '_', '_'}, x),
CowboySpec = hg_dummy_provider:get_http_cowboy_spec(), CowboySpec = hg_dummy_provider:get_http_cowboy_spec(),
{Apps, Ret} = hg_ct_helper:start_apps([lager, woody, hellgate, {cowboy, CowboySpec}]), {Apps, Ret} = hg_ct_helper:start_apps([lager, woody, dmt_client, hellgate, {cowboy, CowboySpec}]),
ok = hg_domain:insert(construct_domain_fixture()), ok = hg_domain:insert(construct_domain_fixture()),
RootUrl = maps:get(hellgate_root_url, Ret), RootUrl = maps:get(hellgate_root_url, Ret),
PartyID = hg_utils:unique_id(), PartyID = hg_utils:unique_id(),

View File

@ -194,7 +194,7 @@ groups() ->
-spec init_per_suite(config()) -> config(). -spec init_per_suite(config()) -> config().
init_per_suite(C) -> init_per_suite(C) ->
{Apps, Ret} = hg_ct_helper:start_apps([lager, woody, hellgate]), {Apps, Ret} = hg_ct_helper:start_apps([lager, woody, dmt_client, hellgate]),
ok = hg_domain:insert(construct_domain_fixture()), ok = hg_domain:insert(construct_domain_fixture()),
[{root_url, maps:get(hellgate_root_url, Ret)}, {apps, Apps} | C]. [{root_url, maps:get(hellgate_root_url, Ret)}, {apps, Apps} | C].
@ -882,13 +882,27 @@ party_access_control(C) ->
#domain_Party{id = PartyID} = hg_client_party:get(GoodExternalClient), #domain_Party{id = PartyID} = hg_client_party:get(GoodExternalClient),
% External Reject % External Reject
BadExternalClient = hg_client_party:start( BadExternalClient0 = hg_client_party:start(
#payproc_UserInfo{id = <<"FakE1D">>, type = {external_user, #payproc_ExternalUser{}}}, #payproc_UserInfo{id = <<"FakE1D">>, type = {external_user, #payproc_ExternalUser{}}},
PartyID, PartyID,
hg_client_api:new(?c(root_url, C)) hg_client_api:new(?c(root_url, C))
), ),
?invalid_user() = hg_client_party:get(BadExternalClient), ?invalid_user() = hg_client_party:get(BadExternalClient0),
hg_client_party:stop(BadExternalClient), hg_client_party:stop(BadExternalClient0),
% UserIdentity has priority
UserIdentity = #{
id => PartyID,
realm => <<"internal">>
},
Context = woody_user_identity:put(UserIdentity, woody_context:new()),
UserIdentityClient1 = hg_client_party:start(
#payproc_UserInfo{id = <<"FakE1D">>, type = {external_user, #payproc_ExternalUser{}}},
PartyID,
hg_client_api:new(?c(root_url, C), Context)
),
#domain_Party{id = PartyID} = hg_client_party:get(UserIdentityClient1),
hg_client_party:stop(UserIdentityClient1),
% Internal Success % Internal Success
GoodInternalClient = hg_client_party:start( GoodInternalClient = hg_client_party:start(

View File

@ -16,7 +16,7 @@
get_service_spec(Name) -> get_service_spec(Name) ->
get_service_spec(Name, #{}). get_service_spec(Name, #{}).
-spec get_service_spec(Name :: atom(), Opts :: #{}) -> service_spec(). -spec get_service_spec(Name :: atom(), Opts :: map()) -> service_spec().
get_service_spec(eventsink, #{}) -> get_service_spec(eventsink, #{}) ->
Service = {dmsl_payment_processing_thrift, 'EventSink'}, Service = {dmsl_payment_processing_thrift, 'EventSink'},

View File

@ -7,7 +7,10 @@
-export([handle_function/4]). -export([handle_function/4]).
-export_type([handler_opts/0]). -export_type([handler_opts/0]).
-type handler_opts() :: #{handler => module()}. -type handler_opts() :: #{
handler => module(),
user_identity => undefined | woody_user_identity:user_identity()
}.
%% Callbacks %% Callbacks
@ -26,7 +29,11 @@
handle_function(Func, Args, Context, #{handler := Handler} = Opts) -> handle_function(Func, Args, Context, #{handler := Handler} = Opts) ->
hg_context:set(Context), hg_context:set(Context),
try try
Result = Handler:handle_function(Func, Args, Opts), Result = Handler:handle_function(
Func,
Args,
Opts
),
{ok, Result} {ok, Result}
catch catch
throw:Reason -> throw:Reason ->

View File

@ -12,6 +12,14 @@
]} ]}
]}, ]},
{dmt_client, [
{cache_update_interval, 5000}, % milliseconds
{service_urls, #{
'Repository' => <<"http://dominant:8022/v1/domain/repository">>,
'RepositoryClient' => <<"http://dominant:8022/v1/domain/repository_client">>
}}
]},
{hellgate, [ {hellgate, [
{ip, "::"}, {ip, "::"},
{port, 8022}, {port, 8022},

View File

@ -34,6 +34,11 @@
{gproc, "0.6.1"}, {gproc, "0.6.1"},
{genlib, {git, "https://github.com/rbkmoney/genlib.git", {branch, "master"}}}, {genlib, {git, "https://github.com/rbkmoney/genlib.git", {branch, "master"}}},
{woody, {git, "git@github.com:rbkmoney/woody_erlang.git", {branch, "master"}}}, {woody, {git, "git@github.com:rbkmoney/woody_erlang.git", {branch, "master"}}},
{woody_user_identity,
{git, "git@github.com:rbkmoney/woody_erlang_user_identity.git",
{branch, "master"}
}
},
{dmsl, {git, "git@github.com:rbkmoney/damsel_erlang.git", {branch, "master"}}}, {dmsl, {git, "git@github.com:rbkmoney/damsel_erlang.git", {branch, "master"}}},
{dmt_client, {git, "git@github.com:rbkmoney/dmt_client.git", {branch, "master"}}} {dmt_client, {git, "git@github.com:rbkmoney/dmt_client.git", {branch, "master"}}}
]}. ]}.

View File

@ -1,3 +1,4 @@
{"1.1.0",
[{<<"certifi">>,{pkg,<<"certifi">>,<<"0.7.0">>},2}, [{<<"certifi">>,{pkg,<<"certifi">>,<<"0.7.0">>},2},
{<<"cowboy">>,{pkg,<<"cowboy">>,<<"1.0.4">>},1}, {<<"cowboy">>,{pkg,<<"cowboy">>,<<"1.0.4">>},1},
{<<"cowlib">>,{pkg,<<"cowlib">>,<<"1.0.2">>},2}, {<<"cowlib">>,{pkg,<<"cowlib">>,<<"1.0.2">>},2},
@ -5,14 +6,14 @@
{git,"git@github.com:rbkmoney/damsel_erlang.git", {git,"git@github.com:rbkmoney/damsel_erlang.git",
{ref,"56fb48e6a23471e49a88c0d646680fba14e74d35"}}, {ref,"56fb48e6a23471e49a88c0d646680fba14e74d35"}},
0}, 0},
{<<"dmt">>,
{git,"git@github.com:rbkmoney/dmt_core.git",
{ref,"cbcc1d24b8e50afc50a884a829c808d30da1a521"}},
1},
{<<"dmt_client">>, {<<"dmt_client">>,
{git,"git@github.com:rbkmoney/dmt_client.git", {git,"git@github.com:rbkmoney/dmt_client.git",
{ref,"601f7bfb22953dd0603fdda5d44e0b23895a22d0"}}, {ref,"d2be019477bce6df639c4ded7670d8cc4df37f6a"}},
0}, 0},
{<<"dmt_core">>,
{git,"git@github.com:rbkmoney/dmt_core.git",
{ref,"fdc4c1a3b7c22c148e04bbbdbbb83aeba9f99ea3"}},
1},
{<<"genlib">>, {<<"genlib">>,
{git,"https://github.com/rbkmoney/genlib.git", {git,"https://github.com/rbkmoney/genlib.git",
{ref,"82ff16f4314fc406dd90752467a08fe401b009ef"}}, {ref,"82ff16f4314fc406dd90752467a08fe401b009ef"}},
@ -38,9 +39,30 @@
{<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.1">>},2}, {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.1">>},2},
{<<"thrift">>, {<<"thrift">>,
{git,"https://github.com/rbkmoney/thrift_erlang.git", {git,"https://github.com/rbkmoney/thrift_erlang.git",
{ref,"aca7fca9f1a7161a1324bf5b92f8402c90d0519e"}}, {ref,"240bbc842f6e9b90d01bd07838778cf48752b510"}},
1}, 1},
{<<"woody">>, {<<"woody">>,
{git,"git@github.com:rbkmoney/woody_erlang.git", {git,"git@github.com:rbkmoney/woody_erlang.git",
{ref,"b5ae9ae3abc8da470f68d2e2ca15ccc606801225"}}, {ref,"992c279466e7eb1c24a9d9c6e7e8d66c597bc7e1"}},
0}]. 0},
{<<"woody_user_identity">>,
{git,"git@github.com:rbkmoney/woody_erlang_user_identity.git",
{ref,"9c7ad2b8beac9c88c54594b264743dec7b9cf696"}},
0}]}.
[
{pkg_hash,[
{<<"certifi">>, <<"861A57F3808F7EB0C2D1802AFEAAE0FA5DE813B0DF0979153CBAFCD853ABABAF">>},
{<<"cowboy">>, <<"A324A8DF9F2316C833A470D918AAF73AE894278B8AA6226CE7A9BF699388F878">>},
{<<"cowlib">>, <<"9D769A1D062C9C3AC753096F868CA121E2730B9A377DE23DEC0F7E08B1DF84EE">>},
{<<"goldrush">>, <<"2024BA375CEEA47E27EA70E14D2C483B2D8610101B4E852EF7F89163CDB6E649">>},
{<<"gproc">>, <<"4579663E5677970758A05D8F65D13C3E9814EC707AD51D8DCEF7294EDA1A730C">>},
{<<"hackney">>, <<"96A0A5E7E65B7ACAD8031D231965718CC70A9B4131A8B033B7543BBD673B8210">>},
{<<"idna">>, <<"AC62EE99DA068F43C50DC69ACF700E03A62A348360126260E87F2B54ECED86B2">>},
{<<"jsx">>, <<"749BEC6D205C694AE1786D62CEA6CC45A390437E24835FD16D12D74F07097727">>},
{<<"lager">>, <<"EEF4E18B39E4195D37606D9088EA05BF1B745986CF8EC84F01D332456FE88D17">>},
{<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>},
{<<"mimerl">>, <<"993F9B0E084083405ED8252B99460C4F0563E41729AB42D9074FD5E52439BE88">>},
{<<"ranch">>, <<"E4965A144DC9FBE70E5C077C65E73C57165416A901BD02EA899CFD95AA890986">>},
{<<"rfc3339">>, <<"2075653DC9407541C84B1E15F8BDA2ABE95FB17C9694025E079583F2D19C1060">>},
{<<"ssl_verify_fun">>, <<"28A4D65B7F59893BC2C7DE786DEC1E1555BD742D336043FE644AE956C3497FBE">>}]}
].