./ct_report/coverage/node_push.COVER.html

1 %%%-------------------------------------------------------------------
2 %%% @author Rafal Slota
3 %%% @copyright (C) 2017 Erlang Solutions Ltd.
4 %%% This software is released under the Apache License, Version 2.0
5 %%% cited in 'LICENSE.txt'.
6 %%% @end
7 %%%-------------------------------------------------------------------
8 %%% @doc
9 %%% Node implementation that proxies all published items to `push_notification' hook.
10 %%% @end
11 %%%-------------------------------------------------------------------
12 -module(node_push).
13 -author('rafal.slota@erlang-solutions.com').
14 -behaviour(gen_pubsub_node).
15
16 -include("mongoose.hrl").
17 -include("jlib.hrl").
18 -include("pubsub.hrl").
19
20 -export([based_on/0, init/3, terminate/2, options/0, features/0,
21 publish_item/9, node_to_path/1, should_delete_when_owner_removed/0,
22 check_publish_options/2]).
23
24 -ignore_xref([check_publish_options/2]).
25
26 292 based_on() -> node_flat.
27
28 init(Host, ServerHost, Opts) ->
29 11 node_flat:init(Host, ServerHost, Opts),
30 11 ok.
31
32 terminate(Host, ServerHost) ->
33 11 node_flat:terminate(Host, ServerHost),
34 11 ok.
35
36 options() ->
37 41 [{deliver_payloads, true},
38 {notify_config, false},
39 {notify_delete, false},
40 {notify_retract, false},
41 {purge_offline, false},
42 {persist_items, false},
43 {max_items, 1},
44 {subscribe, true},
45 {access_model, whitelist},
46 {roster_groups_allowed, []},
47 {publish_model, open},
48 {notification_type, headline},
49 {max_payload_size, ?MAX_PAYLOAD_SIZE},
50 {send_last_published_item, on_sub_and_presence},
51 {deliver_notifications, true},
52 {presence_based_delivery, true}].
53
54 features() ->
55 210 [
56 <<"create-nodes">>,
57 <<"delete-nodes">>,
58 <<"modify-affiliations">>,
59 <<"publish">>,
60 <<"publish-options">>,
61 <<"publish-only-affiliation">>,
62 <<"purge-nodes">>,
63 <<"retrieve-affiliations">>
64 ].
65
66 publish_item(ServerHost, Nidx, Publisher, Model, _MaxItems, _ItemId, _ItemPublisher, Payload,
67 PublishOptions) ->
68 41 {ok, Affiliation} = mod_pubsub_db_backend:get_affiliation(Nidx, jid:to_lower(Publisher)),
69 41 ElPayload = [El || #xmlel{} = El <- Payload],
70
71 41 case is_allowed_to_publish(Model, Affiliation) of
72 true ->
73 40 do_publish_item(ServerHost, PublishOptions, ElPayload);
74 false ->
75 1 {error, mongoose_xmpp_errors:forbidden()}
76 end.
77
78 -spec check_publish_options(#{binary() => [binary()]} | invalid_form, #{binary() => [binary()]}) ->
79 boolean().
80 check_publish_options(#{<<"device_id">> := _, <<"service">> := _}, _) ->
81 41 false;
82 check_publish_options(_, _) ->
83 1 true.
84
85 do_publish_item(ServerHost, PublishOptions,
86 [#xmlel{name = <<"notification">>} | _] = Notifications) ->
87 39 NotificationForms = [parse_form(El) || El <- Notifications],
88 39 OptionMap = parse_form(PublishOptions),
89 39 Result = mongoose_hooks:push_notifications(ServerHost, ok, NotificationForms, OptionMap),
90 39 handle_push_hook_result(Result);
91 do_publish_item(_ServerHost, _PublishOptions, _Payload) ->
92 1 {error, mongoose_xmpp_errors:bad_request()}.
93
94 handle_push_hook_result(ok) ->
95 35 {result, default};
96 handle_push_hook_result({error, device_not_registered}) ->
97 1 {error, mod_pubsub:extended_error(mongoose_xmpp_errors:not_acceptable_cancel(), <<"device-not-registered">>)};
98 handle_push_hook_result({error, _}) ->
99 3 {error, mod_pubsub:extended_error(mongoose_xmpp_errors:bad_request(), <<"faild-to-submit-push-notification">>)}.
100
101 node_to_path(Node) ->
102 41 node_flat:node_to_path(Node).
103
104 2 should_delete_when_owner_removed() -> true.
105
106 %%%
107 %%% Internal
108 %%%
109
110 is_allowed_to_publish(PublishModel, Affiliation) ->
111 (PublishModel == open)
112 41 or (PublishModel == publishers)
113 and ((Affiliation == owner)
114 or (Affiliation == publisher)
115 or (Affiliation == publish_only)).
116
117 -spec parse_form(undefined | exml:element()) -> invalid_form | #{binary() => binary()}.
118 parse_form(undefined) ->
119
:-(
#{};
120 parse_form(Parent) ->
121 78 case mongoose_data_forms:find_and_parse_form(Parent) of
122 #{type := <<"submit">>, kvs := KVs} ->
123 78 maps:filtermap(fun(_, [V]) -> {true, V};
124
:-(
(_, _) -> false
125 end, KVs);
126 _ ->
127
:-(
invalid_form
128 end.
Line Hits Source