./ct_report/coverage/mod_private.COVER.html

1 %%%----------------------------------------------------------------------
2 %%% File : mod_private.erl
3 %%% Author : Alexey Shchepin <alexey@process-one.net>
4 %%% Purpose : Support for private storage.
5 %%% Created : 16 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
6 %%%
7 %%%
8 %%% ejabberd, Copyright (C) 2002-2011 ProcessOne
9 %%%
10 %%% This program is free software; you can redistribute it and/or
11 %%% modify it under the terms of the GNU General Public License as
12 %%% published by the Free Software Foundation; either version 2 of the
13 %%% License, or (at your option) any later version.
14 %%%
15 %%% This program is distributed in the hope that it will be useful,
16 %%% but WITHOUT ANY WARRANTY; without even the implied warranty of
17 %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 %%% General Public License for more details.
19 %%%
20 %%% You should have received a copy of the GNU General Public License
21 %%% along with this program; if not, write to the Free Software
22 %%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 %%%
24 %%%----------------------------------------------------------------------
25
26 -module(mod_private).
27 -author('alexey@process-one.net').
28
29 -behaviour(gen_mod).
30 -behaviour(mongoose_module_metrics).
31
32 -export([start/2,
33 stop/1,
34 supported_features/0,
35 config_spec/0,
36 process_iq/5,
37 remove_user/3,
38 remove_domain/3]).
39
40 -export([get_personal_data/3]).
41
42 -export([config_metrics/1]).
43
44 -ignore_xref([
45 behaviour_info/1, get_personal_data/3, remove_user/3, remove_domain/3
46 ]).
47
48 -include("mongoose.hrl").
49 -include("jlib.hrl").
50 -include("mongoose_config_spec.hrl").
51 -xep([{xep, 49}, {version, "1.2"}]).
52
53 %%--------------------------------------------------------------------
54 %% gdpr callback
55 %%--------------------------------------------------------------------
56
57 -spec get_personal_data(gdpr:personal_data(), mongooseim:host_type(), jid:jid()) -> gdpr:personal_data().
58 get_personal_data(Acc, HostType, #jid{ luser = LUser, lserver = LServer }) ->
59 19 Schema = ["ns", "xml"],
60 19 NSs = mod_private_backend:get_all_nss(HostType, LUser, LServer),
61 19 Entries = lists:map(
62 fun(NS) ->
63 12 Data = mod_private_backend:multi_get_data(
64 HostType, LUser, LServer, [{NS, default}]),
65 12 { NS, exml:to_binary(Data) }
66 end, NSs),
67 19 [{private, Schema, Entries} | Acc].
68
69 %% ------------------------------------------------------------------
70 %% gen_mod callbacks
71
72 start(HostType, Opts) ->
73 3 mod_private_backend:init(HostType, Opts),
74 3 IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
75 3 ejabberd_hooks:add(hooks(HostType)),
76 3 gen_iq_handler:add_iq_handler_for_domain(HostType, ?NS_PRIVATE, ejabberd_sm,
77 fun ?MODULE:process_iq/5, #{}, IQDisc).
78
79 stop(HostType) ->
80 3 ejabberd_hooks:delete(hooks(HostType)),
81 3 gen_iq_handler:remove_iq_handler_for_domain(HostType, ?NS_PRIVATE, ejabberd_sm).
82
83
:-(
supported_features() -> [dynamic_domains].
84
85 hooks(HostType) ->
86 6 [{remove_user, HostType, ?MODULE, remove_user, 50},
87 {remove_domain, HostType, ?MODULE, remove_domain, 50},
88 {anonymous_purge_hook, HostType, ?MODULE, remove_user, 50},
89 {get_personal_data, HostType, ?MODULE, get_personal_data, 50}].
90
91 config_spec() ->
92 160 #section{
93 items = #{<<"iqdisc">> => mongoose_config_spec:iqdisc(),
94 <<"backend">> => #option{type = atom,
95 validate = {module, mod_private}},
96 <<"riak">> => riak_config_spec()}
97 }.
98
99 riak_config_spec() ->
100 160 #section{
101 items = #{<<"bucket_type">> => #option{type = binary,
102 validate = non_empty}
103 },
104 wrap = none
105 }.
106
107 %% ------------------------------------------------------------------
108 %% Handlers
109
110 remove_user(Acc, User, Server) ->
111 27 HostType = mongoose_acc:host_type(Acc),
112 27 LUser = jid:nodeprep(User),
113 27 LServer = jid:nameprep(Server),
114 27 R = mod_private_backend:remove_user(HostType, LUser, LServer),
115 27 mongoose_lib:log_if_backend_error(R, ?MODULE, ?LINE, {Acc, User, Server}),
116 27 Acc.
117
118 -spec remove_domain(mongoose_hooks:simple_acc(),
119 mongooseim:host_type(), jid:lserver()) ->
120 mongoose_hooks:simple_acc().
121 remove_domain(Acc, HostType, Domain) ->
122
:-(
mod_private_backend:remove_domain(HostType, Domain),
123
:-(
Acc.
124
125 process_iq(Acc,
126 From = #jid{lserver = LServer, luser = LUser},
127 To = #jid{lserver = LServer, luser = LUser},
128 IQ = #iq{type = Type, sub_el = SubElem = #xmlel{children = Elems}},
129 _Extra) ->
130 20 HostType = mongoose_acc:host_type(Acc),
131 20 IsEqual = compare_bare_jids(From, To),
132 20 Strategy = choose_strategy(IsEqual, Type),
133 20 Res = case Strategy of
134 get ->
135 3 NS2XML = to_map(Elems),
136 3 XMLs = mod_private_backend:multi_get_data(HostType, LUser, LServer, NS2XML),
137 3 IQ#iq{type = result, sub_el = [SubElem#xmlel{children = XMLs}]};
138 set ->
139 17 NS2XML = to_map(Elems),
140 17 Result = mod_private_backend:multi_set_data(HostType, LUser, LServer, NS2XML),
141 17 case Result of
142 ok ->
143 17 IQ#iq{type = result, sub_el = [SubElem]};
144 {error, Reason} ->
145
:-(
?LOG_ERROR(#{what => multi_set_data_failed, reason => Reason,
146
:-(
user => LUser, server => LServer}),
147
:-(
error_iq(IQ, mongoose_xmpp_errors:internal_server_error());
148 {aborted, Reason} ->
149
:-(
?LOG_ERROR(#{what => multi_set_data_aborted, reason => Reason,
150
:-(
user => LUser, server => LServer}),
151
:-(
error_iq(IQ, mongoose_xmpp_errors:internal_server_error())
152 end;
153 forbidden ->
154
:-(
error_iq(IQ, mongoose_xmpp_errors:forbidden())
155 end,
156 20 {Acc, Res};
157 process_iq(Acc, _From, _To, IQ, _Extra) ->
158 2 Txt = <<"Only requests from/to your JID are allowed">>,
159 2 Err = mongoose_xmpp_errors:forbidden(<<"en">>, Txt),
160 2 Res = error_iq(IQ, Err),
161 2 {Acc, Res}.
162
163 %% ------------------------------------------------------------------
164 %% Helpers
165
166 3 choose_strategy(true, get) -> get;
167 17 choose_strategy(true, set) -> set;
168
:-(
choose_strategy(_, _ ) -> forbidden.
169
170 compare_bare_jids(#jid{luser = LUser, lserver = LServer},
171 20 #jid{luser = LUser, lserver = LServer}) -> true;
172
:-(
compare_bare_jids(_, _) -> false.
173
174 element_to_namespace(#xmlel{attrs = Attrs}) ->
175 20 xml:get_attr_s(<<"xmlns">>, Attrs);
176 element_to_namespace(_) ->
177
:-(
<<>>.
178
179 %% Skip invalid elements.
180 to_map(Elems) ->
181 20 [{NS, Elem} || Elem <- Elems, is_valid_namespace(NS = element_to_namespace(Elem))].
182
183 20 is_valid_namespace(Namespace) -> Namespace =/= <<>>.
184
185 error_iq(IQ=#iq{sub_el=SubElem}, ErrorStanza) ->
186 2 IQ#iq{type = error, sub_el = [SubElem, ErrorStanza]}.
187
188 config_metrics(Host) ->
189
:-(
OptsToReport = [{backend, mnesia}], %list of tuples {option, defualt_value}
190
:-(
mongoose_module_metrics:opts_for_module(Host, ?MODULE, OptsToReport).
Line Hits Source