• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

esl / MongooseIM / 5076995463

25 May 2023 07:04AM UTC coverage: 15.93% (-66.0%) from 81.94%
5076995463

push

github

GitHub
Merge pull request #4027 from esl/docker-script

5388 of 33824 relevant lines covered (15.93%)

1117.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/pubsub/node_push.erl
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

23
based_on() ->  node_flat.
×
24

25
init(Host, ServerHost, Opts) ->
26
    node_flat:init(Host, ServerHost, Opts),
×
27
    ok.
×
28

29
terminate(Host, ServerHost) ->
30
    node_flat:terminate(Host, ServerHost),
×
31
    ok.
×
32

33
options() ->
34
    [{deliver_payloads, true},
×
35
     {notify_config, false},
36
     {notify_delete, false},
37
     {notify_retract, false},
38
     {purge_offline, false},
39
     {persist_items, false},
40
     {max_items, 1},
41
     {subscribe, true},
42
     {access_model, whitelist},
43
     {roster_groups_allowed, []},
44
     {publish_model, open},
45
     {notification_type, headline},
46
     {max_payload_size, ?MAX_PAYLOAD_SIZE},
47
     {send_last_published_item, on_sub_and_presence},
48
     {deliver_notifications, true},
49
     {presence_based_delivery, true}].
50

51
features() ->
52
    [
×
53
        <<"create-nodes">>,
54
        <<"delete-nodes">>,
55
        <<"modify-affiliations">>,
56
        <<"publish">>,
57
        <<"publish-options">>,
58
        <<"publish-only-affiliation">>,
59
        <<"purge-nodes">>,
60
        <<"retrieve-affiliations">>
61
    ].
62

63
publish_item(ServerHost, Nidx, Publisher, Model, _MaxItems, _ItemId, _ItemPublisher, Payload,
64
             PublishOptions) ->
65
    {ok, Affiliation} = mod_pubsub_db_backend:get_affiliation(Nidx, jid:to_lower(Publisher)),
×
66
    ElPayload = [El || #xmlel{} = El <- Payload],
×
67

68
    case is_allowed_to_publish(Model, Affiliation) of
×
69
        true ->
70
            do_publish_item(ServerHost, PublishOptions, ElPayload);
×
71
        false ->
72
            {error, mongoose_xmpp_errors:forbidden()}
×
73
    end.
74

75
do_publish_item(ServerHost, PublishOptions,
76
                [#xmlel{name = <<"notification">>} | _] = Notifications) ->
77
    case catch parse_form(PublishOptions) of
×
78
        #{<<"device_id">> := _, <<"service">> := _} = OptionMap ->
79
            NotificationRawForms = [exml_query:subelement(El, <<"x">>) || El <- Notifications],
×
80
            NotificationForms = [parse_form(Form) || Form <- NotificationRawForms],
×
81
            Result = mongoose_hooks:push_notifications(ServerHost, ok,
×
82
                                                       NotificationForms, OptionMap),
83
            handle_push_hook_result(Result);
×
84
        _ ->
85
            {error, mod_pubsub:extended_error(mongoose_xmpp_errors:conflict(), <<"precondition-not-met">>)}
×
86
    end;
87
do_publish_item(_ServerHost, _PublishOptions, _Payload) ->
88
    {error, mongoose_xmpp_errors:bad_request()}.
×
89

90
handle_push_hook_result(ok) ->
91
    {result, default};
×
92
handle_push_hook_result({error, device_not_registered}) ->
93
    {error, mod_pubsub:extended_error(mongoose_xmpp_errors:not_acceptable_cancel(), <<"device-not-registered">>)};
×
94
handle_push_hook_result({error, _}) ->
95
    {error, mod_pubsub:extended_error(mongoose_xmpp_errors:bad_request(), <<"faild-to-submit-push-notification">>)}.
×
96

97
node_to_path(Node) ->
98
    node_flat:node_to_path(Node).
×
99

100
should_delete_when_owner_removed() -> true.
×
101

102
%%%
103
%%% Internal
104
%%%
105

106
is_allowed_to_publish(PublishModel, Affiliation) ->
107
    (PublishModel == open)
108
    or (PublishModel == publishers)
×
109
        and ((Affiliation == owner)
110
              or (Affiliation == publisher)
111
              or (Affiliation == publish_only)).
112

113

114
-spec parse_form(undefined | exml:element()) -> invalid_form | #{atom() => binary()}.
115
parse_form(undefined) ->
116
    #{};
×
117
parse_form(Form) ->
118
    IsForm = ?NS_XDATA == exml_query:attr(Form, <<"xmlns">>),
×
119
    IsSubmit = <<"submit">> == exml_query:attr(Form, <<"type">>, <<"submit">>),
×
120

121
    FieldsXML = exml_query:subelements(Form, <<"field">>),
×
122
    Fields = [{exml_query:attr(Field, <<"var">>),
×
123
               exml_query:path(Field, [{element, <<"value">>}, cdata])} || Field <- FieldsXML],
×
124
    {_, CustomFields} = lists:partition(
×
125
        fun({Name, _}) ->
126
            Name == <<"FORM_TYPE">>
×
127
        end, Fields),
128

129
    case IsForm andalso IsSubmit of
×
130
        true ->
131
            maps:from_list(CustomFields);
×
132
        false ->
133
            invalid_form
×
134
    end.
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc