| @@ -0,0 +1,103 @@ | ||
| %%%------------------------------------------------------------------- | ||
| %%% @copyright | ||
| %%% @doc | ||
| %%% | ||
| %%% @end | ||
| %%% @contributors | ||
| %%%------------------------------------------------------------------- | ||
| -module(kz_srs_filter_prefix). | ||
|
|
||
| -export([handle_req/5]). | ||
|
|
||
| -include("stepswitch_resource_selectors.hrl"). | ||
|
|
||
| -define(MOD_NAME, <<"filter_prefix">>). | ||
| -define(ALLOWED_FILTER_MODES, [<<"empty_ok">> | ||
| ,<<"empty_fail">> | ||
| ]). | ||
| -define(DEFAULT_FILTER_MODE, <<"empty_fail">>). | ||
|
|
||
| -spec handle_req(stepswitch_resources:resources(), ne_binary(), kapi_offnet_resource:req(), ne_binary(), kz_json:object()) -> | ||
| stepswitch_resources:resources(). | ||
| handle_req(Resources, Number, OffnetJObj, DB, Params) -> | ||
| SourceA = kz_srs_util:get_source(kz_json:get_value(<<"value_a">>, Params)), | ||
| ValueA = kz_srs_util:get_value(SourceA, Resources, Number, OffnetJObj, DB, <<>>), | ||
| 'ok' = kz_srs_util:check_value(fun is_binary/1, ValueA), | ||
| SourceB = maybe_db_type(kz_srs_util:get_source(kz_json:get_value(<<"value_b">>, Params)), Resources, ValueA), | ||
| ValueB = kz_srs_util:get_value(SourceB, Resources, Number, OffnetJObj, DB, []), | ||
| 'ok' = kz_srs_util:check_value(fun is_list/1, ValueB), | ||
| Action = kz_srs_util:select_filter_action(Params), | ||
| PrefixMode = kz_srs_util:select_filter_mode(Params, ?ALLOWED_FILTER_MODES, ?DEFAULT_FILTER_MODE), | ||
| case SourceB of | ||
| {'database', _, _} -> filter_by_db_prefix(Resources, ValueB, Action, PrefixMode); | ||
| _ -> filter_by_prefix(Resources, ValueA, ValueB, Action, PrefixMode) | ||
| end. | ||
|
|
||
| filter_by_db_prefix(Resources, Result, Action, PrefixMode) -> | ||
| lists:filter(fun(R) -> | ||
| Id = stepswitch_resources:get_resrc_id(R), | ||
| Value = props:get_value(Id, Result), | ||
| match_db_prefixes(Id, Value, Action, PrefixMode) | ||
| end | ||
| ,Resources | ||
| ). | ||
|
|
||
| filter_by_prefix(Resources, ValueA, ValueB, Action, PrefixMode) -> | ||
| SetA = sets:from_list(build_prefixes(ValueA)), | ||
| lists:filter(fun(R) -> | ||
| Id = stepswitch_resources:get_resrc_id(R), | ||
| SetB = sets:from_list(props:get_value(Id, ValueB, [])), | ||
| match_prefixes(Id, sets:intersection(SetA, SetB), Action, PrefixMode) | ||
| end | ||
| ,Resources | ||
| ). | ||
|
|
||
| maybe_db_type({'database', SelectorName}, Resources, PrefixSrc) -> | ||
| Prefixes = build_prefixes(PrefixSrc), | ||
| Keys = [[stepswitch_resources:get_resrc_id(R), SelectorName, P] || R <- Resources, P <- Prefixes], | ||
| Options = [{'keys', Keys}], | ||
| View = <<"selectors/resource_name_data_listing">>, | ||
| {'database', View, Options}; | ||
| maybe_db_type(Other, _Resources, _PrefixSrc) -> Other. | ||
|
|
||
| -spec build_prefixes(ne_binary()) -> ne_binaries(). | ||
| build_prefixes(<<"+", Rest/binary>>) -> build_prefixes(Rest); | ||
| build_prefixes(<<D:1/binary, Rest/binary>>) -> | ||
| build_prefixes(Rest, D, [D]). | ||
|
|
||
| -spec build_prefixes(ne_binary(), ne_binary(), ne_binaries()) -> ne_binaries(). | ||
| build_prefixes(<<D:1/binary, Rest/binary>>, Prefix, Acc) -> | ||
| build_prefixes(Rest, <<Prefix/binary, D/binary>>, [<<Prefix/binary, D/binary>> | Acc]); | ||
| build_prefixes(<<>>, _, Acc) -> Acc. | ||
|
|
||
| match_prefixes(Id, Set, 'keep', _PrefixMode) -> | ||
| case sets:size(Set) of | ||
| 0 -> | ||
| lager:debug("resource ~s dont match prefix, droping", [Id]), | ||
| 'false'; | ||
| _ -> | ||
| lager:debug("resource ~s matched prefix, keeping", [Id]), | ||
| 'true' | ||
| end; | ||
| match_prefixes(Id, Set, 'drop', _PrefixMode) -> | ||
| case sets:size(Set) of | ||
| 0 -> | ||
| lager:debug("resource ~s dont match prefix, keeping", [Id]), | ||
| 'true'; | ||
| _ -> | ||
| lager:debug("resource ~s matched prefix, droping", [Id]), | ||
| 'false' | ||
| end. | ||
|
|
||
| match_db_prefixes(Id, 'undefined', 'keep', _PrefixMode) -> | ||
| lager:debug("resource ~s dont match prefix, droping", [Id]), | ||
| 'false'; | ||
| match_db_prefixes(Id, [_|_], 'keep', _PrefixMode) -> | ||
| lager:debug("resource ~s matched prefix, keeping", [Id]), | ||
| 'true'; | ||
| match_db_prefixes(Id, 'undefined', 'drop', _PrefixMode) -> | ||
| lager:debug("resource ~s dont match prefix, keeping", [Id]), | ||
| 'true'; | ||
| match_db_prefixes(Id, [_|_], 'drop', _PrefixMode) -> | ||
| lager:debug("resource ~s matched prefix, droping", [Id]), | ||
| 'false'. |
| @@ -0,0 +1,99 @@ | ||
| %%%------------------------------------------------------------------- | ||
| %%% @copyright | ||
| %%% @doc | ||
| %%% | ||
| %%% @end | ||
| %%% @contributors | ||
| %%%------------------------------------------------------------------- | ||
| -module(kz_srs_filter_regex). | ||
|
|
||
| -export([handle_req/5]). | ||
|
|
||
| -include("stepswitch_resource_selectors.hrl"). | ||
|
|
||
| -define(MOD_NAME, <<"filter_regex">>). | ||
| -define(ALLOWED_FILTER_MODES, [<<"empty_ok">> | ||
| ,<<"empty_fail">> | ||
| ]). | ||
| -define(DEFAULT_FILTER_MODE, <<"empty_fail">>). | ||
|
|
||
| -spec handle_req(stepswitch_resources:resources() | ||
| ,ne_binary() | ||
| ,kapi_offnet_resource:req() | ||
| ,ne_binary() | ||
| ,kz_json:object() | ||
| ) -> stepswitch_resources:resources(). | ||
| handle_req(Resources, Number, OffnetJObj, DB, Params) -> | ||
| SourceA = kz_srs_util:get_source(kz_json:get_value(<<"value_a">>, Params)), | ||
| ValueA = kz_srs_util:get_value(SourceA, Resources, Number, OffnetJObj, DB, <<>>), | ||
| 'ok' = kz_srs_util:check_value(fun is_binary/1, ValueA), | ||
| SourceB = kz_srs_util:get_source(kz_json:get_value(<<"value_b">>, Params)), | ||
| ValueB = kz_srs_util:get_value(SourceB, Resources, Number, OffnetJObj, DB, []), | ||
| 'ok' = kz_srs_util:check_value(fun is_list/1, ValueB), | ||
| Action = kz_srs_util:select_filter_action(Params), | ||
| EmptyMode = kz_srs_util:select_filter_mode(Params, ?ALLOWED_FILTER_MODES, ?DEFAULT_FILTER_MODE), | ||
| filter_by_regex(Resources, ValueA, ValueB, Action, EmptyMode). | ||
|
|
||
| -spec filter_by_regex(stepswitch_resources:resources() | ||
| ,ne_binary() | ||
| ,kz_proplists() | ||
| ,atom() | ||
| ,ne_binary() | ||
| ) -> stepswitch_resources:resources(). | ||
| filter_by_regex(Resources, ValueA, Regexes, Action, EmptyMode) -> | ||
| lager:debug("filter resources by ~s with regex rules, and ~s matched", [ValueA, Action]), | ||
| lists:filtermap(fun(R) -> | ||
| Id = stepswitch_resources:get_resrc_id(R), | ||
| Rules = props:get_value(Id, Regexes, []), | ||
| evaluate_rules(Id, Rules, ValueA, Action, EmptyMode) | ||
| end | ||
| ,Resources | ||
| ). | ||
|
|
||
| -spec evaluate_rules(ne_binary(), re:mp(), ne_binary(), atom(), ne_binary()) -> boolean(). | ||
| evaluate_rules(Id, [], _Data, 'keep', <<"empty_fail">>) -> | ||
| lager:debug("resource ~s has empty rules, dropping", [Id]), | ||
| 'false'; | ||
| evaluate_rules(Id, [], _Data, 'keep', <<"empty_ok">>) -> | ||
| lager:debug("resource ~s has empty rules, keeping", [Id]), | ||
| 'true'; | ||
| evaluate_rules(Id, Rules, Data, 'keep', _EmptyMode) -> | ||
| case do_evaluate_rules(Rules, Data) of | ||
| {'error', 'no_match'} -> | ||
| lager:debug("resource ~s does not match request, dropping", [Id]), | ||
| 'false'; | ||
| {'ok', Match} -> | ||
| lager:debug("resource ~s does match (~p) request, keeping", [Id, Match]), | ||
| 'true' | ||
| end; | ||
| evaluate_rules(Id, [], _Data, 'drop', <<"empty_fail">>) -> | ||
| lager:debug("resource ~s has empty rules, keeping", [Id]), | ||
| 'false'; | ||
| evaluate_rules(Id, [], _Data, 'drop', <<"empty_ok">>) -> | ||
| lager:debug("resource ~s has empty rules, dropping", [Id]), | ||
| 'true'; | ||
| evaluate_rules(Id, Rules, Data, 'drop', _EmptyMode) -> | ||
| case do_evaluate_rules(Rules, Data) of | ||
| {'error', 'no_match'} -> | ||
| lager:debug("resource ~s does not match request, keeping", [Id]), | ||
| 'true'; | ||
| {'ok', Match} -> | ||
| lager:debug("resource ~s does match (~p) request, dropping", [Id, Match]), | ||
| 'false' | ||
| end. | ||
|
|
||
| -spec do_evaluate_rules(re:mp(), ne_binary()) -> | ||
| {'ok', ne_binary()} | | ||
| {'error', 'no_match'}. | ||
| do_evaluate_rules([], _) -> {'error', 'no_match'}; | ||
| do_evaluate_rules([Rule|Rules], Data) -> | ||
| case re:run(Data, Rule) of | ||
| {'match', [{Start,End}]} -> | ||
| {'ok', binary:part(Data, Start, End)}; | ||
| {'match', CaptureGroups} -> | ||
| %% find the largest matching group if present by sorting the position of the | ||
| %% matching groups by list, reverse so head is largest, then take the head of the list | ||
| {Start, End} = hd(lists:reverse(lists:keysort(2, tl(CaptureGroups)))), | ||
| {'ok', binary:part(Data, Start, End)}; | ||
| _ -> do_evaluate_rules(Rules, Data) | ||
| end. |
| @@ -0,0 +1,48 @@ | ||
| %%%------------------------------------------------------------------- | ||
| %%% @copyright | ||
| %%% @doc | ||
| %%% | ||
| %%% @end | ||
| %%% @contributors | ||
| %%%------------------------------------------------------------------- | ||
| -module(kz_srs_get_resources). | ||
|
|
||
| -export([handle_req/5]). | ||
|
|
||
| -include("stepswitch.hrl"). | ||
|
|
||
| -spec handle_req(stepswitch_resources:resources(), ne_binary(), kapi_offnet_resource:req(), ne_binary(), kz_proplist()) -> | ||
| stepswitch_resources:resources(). | ||
| handle_req(Resources, _Number, OffnetJObj, _DB, _Params) -> | ||
| NewResources = case kapi_offnet_resource:hunt_account_id(OffnetJObj) of | ||
| 'undefined' -> get_resources('undefined'); | ||
| HuntAccount -> | ||
| AccountId = kapi_offnet_resource:account_id(OffnetJObj), | ||
| maybe_get_local_resources(HuntAccount, AccountId) | ||
| end, | ||
| lists:append(Resources, NewResources). | ||
|
|
||
| -spec maybe_get_local_resources(ne_binary(), ne_binary()) -> kz_json:objects(). | ||
| maybe_get_local_resources(HuntAccount, AccountId) -> | ||
| case kz_util:is_in_account_hierarchy(HuntAccount, AccountId, 'true') of | ||
| 'false' -> | ||
| lager:info("account ~s attempted to use local resources of ~s, but it is not allowed" | ||
| ,[AccountId, HuntAccount] | ||
| ), | ||
| []; | ||
| 'true' -> | ||
| lager:info("account ~s is using the local resources of ~s", [AccountId, HuntAccount]), | ||
| get_resources(HuntAccount) | ||
| end. | ||
|
|
||
| -spec get_resources(api_binary()) -> stepswitch_resources:resources(). | ||
| get_resources('undefined') -> | ||
| case kz_cache:fetch_local(?CACHE_NAME, 'global_resources') of | ||
| {'ok', Resources} -> Resources; | ||
| {'error', 'not_found'} -> stepswitch_resources:fetch_global_resources() | ||
| end; | ||
| get_resources(AccountId) -> | ||
| case kz_cache:fetch_local(?CACHE_NAME, {'local_resources', AccountId}) of | ||
| {'ok', Resources} -> Resources; | ||
| {'error', 'not_found'} -> stepswitch_resources:fetch_local_resources(AccountId) | ||
| end. |
| @@ -0,0 +1,17 @@ | ||
| %%%------------------------------------------------------------------- | ||
| %%% @copyright | ||
| %%% @doc | ||
| %%% | ||
| %%% @end | ||
| %%% @contributors | ||
| %%%------------------------------------------------------------------- | ||
| -module(kz_srs_null). | ||
|
|
||
| -export([handle_req/5]). | ||
|
|
||
| -include("stepswitch.hrl"). | ||
|
|
||
| -spec handle_req(stepswitch_resources:resources(), ne_binary(), kapi_offnet_resource:req(), ne_binary(), kz_json:object()) -> | ||
| stepswitch_resources:resources(). | ||
| handle_req(_Resources, _Number, _OffnetJObj, _Db, _Params) -> | ||
| []. |
| @@ -0,0 +1,60 @@ | ||
|
|
||
| %%%------------------------------------------------------------------- | ||
| %%% @copyright | ||
| %%% @doc | ||
| %%% | ||
| %%% @end | ||
| %%% @contributors | ||
| %%%------------------------------------------------------------------- | ||
| -module(kz_srs_order). | ||
|
|
||
| -export([handle_req/5]). | ||
|
|
||
| -include("stepswitch.hrl"). | ||
|
|
||
| -define(MOD_NAME, <<"order_by">>). | ||
| -define(DEFAULT_SORT_ORDER, <<"ascend">>). | ||
| -define(DEFAULT_DESC_WEIGHT, 0). | ||
| -define(DEFAULT_ASC_WEIGHT, 9999). | ||
|
|
||
| -spec handle_req(stepswitch_resources:resources(), ne_binary(), kapi_offnet_resource:req(), ne_binary(), kz_json:object()) -> | ||
| stepswitch_resources:resources(). | ||
| handle_req([], _Number, _OffnetJObj, _DB, _Params) -> | ||
| lager:warning("empty resource list", []), | ||
| []; | ||
| handle_req([Resource], _Number, _OffnetJObj, _DB, _Params) -> | ||
| Id = stepswitch_resources:get_resrc_id(Resource), | ||
| lager:debug("resource list contains only one resource (~p), skip sorting", [Id]), | ||
| [Resource]; | ||
| handle_req(Resources, Number, OffnetJObj, DB, Params) -> | ||
| Source = kz_srs_util:get_source(kz_json:get_value(<<"value">>, Params)), | ||
| 'ok' = check_source(Source), | ||
| Values = kz_srs_util:get_value(Source, Resources, Number, OffnetJObj, DB, 1), | ||
| SortOrder = kz_json:get_ne_value(<<"direction">>, Params, ?DEFAULT_SORT_ORDER), | ||
| order_by(Resources, Values, SortOrder). | ||
|
|
||
| -spec order_by(stepswitch_resources:resources(), kz_json:object(), ne_binary()) -> | ||
| stepswitch_resources:resources(). | ||
| order_by(Resources, Values, SortOrder) -> | ||
| lists:sort(fun(R1, R2) -> | ||
| Id1 = stepswitch_resources:get_resrc_id(R1), | ||
| Id2 = stepswitch_resources:get_resrc_id(R2), | ||
| Weight1 = kz_json:get_value(Id1, Values, default_weight(SortOrder)), | ||
| Weight2 = kz_json:get_value(Id2, Values, default_weight(SortOrder)), | ||
| sort(Weight1, Weight2, SortOrder) | ||
| end | ||
| ,Resources | ||
| ). | ||
|
|
||
| -spec default_weight(ne_binary()) -> integer(). | ||
| default_weight(<<"ascend">>) -> ?DEFAULT_ASC_WEIGHT; | ||
| default_weight(<<"descend">>) -> ?DEFAULT_DESC_WEIGHT. | ||
|
|
||
| -spec check_source(tuple() | any()) -> 'ok'. | ||
| check_source({'database', _}) -> 'ok'; | ||
| check_source({'resource', _}) -> 'ok'; | ||
| check_source(Source) -> throw({invalid_source, Source}). | ||
|
|
||
| -spec sort(integer(), integer(), ne_binary()) -> boolean(). | ||
| sort(Lesser, Greater, <<"ascend">>) -> Lesser =< Greater; | ||
| sort(Greater, Lesser, <<"descend">>) -> Lesser =< Greater. |
| @@ -0,0 +1,124 @@ | ||
| %%%------------------------------------------------------------------- | ||
| %%% @copyright | ||
| %%% @doc | ||
| %%% | ||
| %%% @end | ||
| %%% @contributors | ||
| %%%------------------------------------------------------------------- | ||
| -module(stepswitch_resource_selectors). | ||
|
|
||
| -export([endpoints/2]). | ||
|
|
||
| -include("stepswitch_resource_selectors.hrl"). | ||
|
|
||
| -define(MOD_NAME, <<"resource_selectors">>). | ||
| -define(SRS_CONFIG_CAT, <<?SS_CONFIG_CAT/binary, ".", ?MOD_NAME/binary>>). | ||
| -define(MOD_PREFIX, "kz_srs_"). | ||
| -define(SRS_RULES_DOC, <<"resource_selector_rules">>). | ||
| -define(DEFAULT_SRS_RULES, [{[{<<"get_resources">> | ||
| ,{[]} | ||
| }]} | ||
| ,{[{<<"filter_list">> | ||
| ,{[{<<"value_a">>,<<"request:Flags">>} | ||
| ,{<<"value_b">>,<<"resource:flags">>} | ||
| ,{<<"action">>,<<"keep">>} | ||
| ]} | ||
| }]} | ||
| ,{[{<<"filter_regex">> | ||
| ,{[{<<"value_a">>,<<"number">>} | ||
| ,{<<"value_b">>,<<"resource:rules">>} | ||
| ,{<<"action">>,<<"keep">>} | ||
| ,{<<"mode">>,<<"empty_fail">>} | ||
| ]} | ||
| }]} | ||
| ,{[{<<"filter_regex">> | ||
| ,{[{<<"value_a">>,<<"cid_number">>} | ||
| ,{<<"value_b">>,<<"resource:cid_rules">>} | ||
| ,{<<"action">>,<<"keep">>} | ||
| ,{<<"mode">>,<<"empty_ok">>} | ||
| ]} | ||
| }]} | ||
| ,{[{<<"order">> | ||
| ,{[{<<"value">>, <<"resource:weight_cost">>} | ||
| ,{<<"direction">>, <<"ascend">>} | ||
| ]} | ||
| }]} | ||
| ] | ||
| ). | ||
|
|
||
| -spec endpoints(ne_binary(), kapi_offnet_resource:req()) -> kz_json:objects(). | ||
| endpoints(Number, OffnetJObj) -> | ||
| HuntAccountId = maybe_get_hunt_account(OffnetJObj), | ||
| SelectorsDb = kz_util:format_resource_selectors_db(HuntAccountId), | ||
| case get_selector_rules(HuntAccountId) of | ||
| {'ok', SelectorRules} -> | ||
| Resources = foldl_modules(Number, OffnetJObj, SelectorsDb, SelectorRules), | ||
| stepswitch_util:resources_to_endpoints(Resources, Number, OffnetJObj); | ||
| {'error', _E} -> [] | ||
| end. | ||
|
|
||
| -spec foldl_modules(ne_binary(), kapi_offnet_resource:req(), ne_binary(), kz_json:objects()) -> stepswitch_resources:resources(). | ||
| foldl_modules(Number, OffnetJObj, SelectorsDb, SelectorRules) -> | ||
| lists:foldl(fun(JObj, Resources) -> | ||
| [Module|_] = kz_json:get_keys(JObj), | ||
| ModuleName = real_module_name(Module), | ||
| ModuleParams = kz_json:get_value(Module, JObj), | ||
| try Res = ModuleName:handle_req(Resources | ||
| ,Number | ||
| ,OffnetJObj | ||
| ,SelectorsDb | ||
| ,ModuleParams | ||
| ), | ||
| lager:info("module ~p return resources: ~p" | ||
| ,[Module, [ stepswitch_resources:get_resrc_id(R) || | ||
| R <- Res ] | ||
| ]), | ||
| Res | ||
| catch | ||
| 'error':R -> | ||
| ST = erlang:get_stacktrace(), | ||
| lager:error("failed to run module: ~p, error: ~p",[Module, R]), | ||
| kz_util:log_stacktrace(ST), | ||
| []; | ||
| 'throw':T -> | ||
| lager:error("module ~p (~p) throw exception: ~p",[Module, ModuleName, T]), | ||
| [] | ||
| end | ||
| end | ||
| ,[] | ||
| ,SelectorRules | ||
| ). | ||
|
|
||
| -spec maybe_get_hunt_account(kapi_offnet_resource:req()) -> api_binary(). | ||
| maybe_get_hunt_account(OffnetJObj) -> | ||
| HuntAccountId = kapi_offnet_resource:hunt_account_id(OffnetJObj), | ||
| AccountId = kapi_offnet_resource:account_id(OffnetJObj), | ||
| {'ok', MasterAccountId} = kapps_util:get_master_account_id(), | ||
| case kz_util:is_not_empty(HuntAccountId) | ||
| andalso kz_util:is_in_account_hierarchy(HuntAccountId, AccountId, 'true') | ||
| of | ||
| 'true' -> HuntAccountId; | ||
| 'false' -> MasterAccountId | ||
| end. | ||
|
|
||
| -spec get_selector_rules(api_binary()) -> {'ok', kz_json:object()} | {'error', any()}. | ||
| get_selector_rules(HuntAccountId) -> | ||
| Db = kz_util:format_account_db(HuntAccountId), | ||
| case kz_datamgr:open_doc(Db, ?SRS_RULES_DOC) of | ||
| {'ok', Doc} -> | ||
| Rules = kz_json:get_value(<<"rules">>, Doc, ?DEFAULT_SRS_RULES), | ||
| {'ok', Rules}; | ||
| {'error', 'not_found'} -> | ||
| Doc = {[{<<"_id">>, ?SRS_RULES_DOC} | ||
| ,{<<"rules">>, ?DEFAULT_SRS_RULES} | ||
| ]}, | ||
| _ = kz_datamgr:save_doc(Db, Doc), | ||
| {'ok', ?DEFAULT_SRS_RULES}; | ||
| {'error', E} -> | ||
| lager:error("failed to get resource selector rules from ~s: ~p", [Db, E]), | ||
| {'error', E} | ||
| end. | ||
|
|
||
| -spec real_module_name(binary()) -> atom(). | ||
| real_module_name(Module) when is_binary(Module) -> | ||
| kz_util:to_atom(<<?MOD_PREFIX, Module/binary>>, 'true'). |
| @@ -0,0 +1,11 @@ | ||
| -ifndef(STEPSWITCH_RESOURCE_SELECTORS_HRL). | ||
| -include("stepswitch.hrl"). | ||
|
|
||
| -define(ALLOWED_RESOURCE_FIELDS,[{<<"weight_cost">>, 'get_resrc_weight'} | ||
| ,{<<"rules">>, 'get_resrc_rules'} | ||
| ,{<<"cid_rules">>, 'get_resrc_cid_rules'} | ||
| ,{<<"flags">>, 'get_resrc_flags'} | ||
| ]). | ||
|
|
||
| -define(STEPSWITCH_RESOURCE_SELECTORS_HRL, 'true'). | ||
| -endif. |
| @@ -48,6 +48,7 @@ | ||
| ,{<<"Event-Name">>, [?DOC_EDITED | ||
| ,?DOC_CREATED | ||
| ,?DOC_DELETED | ||
| ,?DB_EDITED | ||
| ,?DB_CREATED | ||
| ,?DB_DELETED | ||
| ]} | ||