./ct_report/coverage/mod_vcard_mnesia.COVER.html

1 -module(mod_vcard_mnesia).
2
3 -behaviour(mod_vcard_backend).
4
5 %% mod_vcards callbacks
6 -export([init/2,
7 remove_user/3,
8 get_vcard/3,
9 set_vcard/5,
10 search/3,
11 search_fields/2,
12 search_reported_fields/3]).
13
14 -include("mongoose.hrl").
15 -include("jlib.hrl").
16 -include("mod_vcard.hrl").
17
18 init(_HostType, _Options) ->
19
:-(
prepare_db(),
20
:-(
ok.
21
22 remove_user(_HostType, LUser, LServer) ->
23
:-(
US = {LUser, LServer},
24
:-(
F = fun() ->
25
:-(
mnesia:delete({vcard, US}),
26
:-(
mnesia:delete({vcard_search, US})
27 end,
28
:-(
mnesia:transaction(F).
29
30 get_vcard(_HostType, LUser, LServer) ->
31
:-(
US = {LUser, LServer},
32
:-(
F = fun() ->
33
:-(
mnesia:read({vcard, US})
34 end,
35
:-(
case mnesia:transaction(F) of
36 {atomic, []} ->
37
:-(
{error, mongoose_xmpp_errors:item_not_found()};
38 {atomic, Rs} ->
39
:-(
Els = lists:map(fun(R) ->
40
:-(
R#vcard.vcard
41 end, Rs),
42
:-(
{ok, Els};
43 {aborted, Reason} ->
44
:-(
?LOG_ERROR(#{what => process_sm_iq_vcard_lookup_failed,
45
:-(
reason => Reason, user => LUser, server => LServer}),
46
:-(
{error, mongoose_xmpp_errors:internal_server_error()}
47 end.
48
49 set_vcard(HostType, User, LServer, VCard, VCardSearch) ->
50
:-(
LUser = jid:nodeprep(User),
51
:-(
VCardSearch2 = stringify_search_fields(VCardSearch),
52
:-(
F = fun() ->
53
:-(
mnesia:write(#vcard{us ={LUser, LServer}, vcard = VCard}),
54
:-(
mnesia:write(VCardSearch2)
55 end,
56
:-(
{atomic, _} = mnesia:transaction(F),
57
:-(
mongoose_hooks:vcard_set(HostType, LServer, LUser, VCard),
58
:-(
ok.
59
60 -spec search(mongooseim:host_type(), jid:lserver(), term()) -> [[mongoose_data_forms:field()]].
61 search(HostType, LServer, Data) ->
62
:-(
MatchHead = make_matchhead(LServer, Data),
63
:-(
R = do_search(HostType, LServer, MatchHead),
64
:-(
lists:map(fun record_to_item/1, R).
65
66 do_search(_, _, #vcard_search{_ = '_'}) ->
67
:-(
[];
68 do_search(HostType, LServer, MatchHeadIn) ->
69
:-(
MatchHead = MatchHeadIn#vcard_search{us = {'_', LServer}},
70
:-(
case catch mnesia:dirty_select(vcard_search,
71 [{MatchHead, [], ['$_']}]) of
72 {'EXIT', Reason} ->
73
:-(
?LOG_ERROR(#{what => vcard_search_failed, server => LServer, host_type => HostType,
74
:-(
reason => Reason}),
75
:-(
[];
76 Rs ->
77
:-(
case mod_vcard:get_results_limit(HostType) of
78 infinity ->
79
:-(
Rs;
80 Val ->
81
:-(
lists:sublist(Rs, Val)
82 end
83 end.
84
85 search_fields(_HostType, _LServer) ->
86
:-(
mod_vcard:default_search_fields().
87
88 -spec search_reported_fields(mongooseim:host_type(), jid:lserver(), ejabberd:lang()) ->
89 [mongoose_data_forms:field()].
90 search_reported_fields(_HostType, _LServer, Lang) ->
91
:-(
mod_vcard:get_default_reported_fields(Lang).
92
93 %%--------------------------------------------------------------------
94 %% internal
95 %%--------------------------------------------------------------------
96
97 prepare_db() ->
98
:-(
create_tables(),
99
:-(
set_indexes(),
100
:-(
add_table_copies().
101
102 create_tables() ->
103
:-(
mongoose_mnesia:create_table(vcard,
104 [{disc_only_copies, [node()]},
105 {attributes, record_info(fields, vcard)}]),
106
:-(
mongoose_mnesia:create_table(vcard_search,
107 [{disc_copies, [node()]},
108 {attributes, record_info(fields, vcard_search)}]).
109
110 add_table_copies() ->
111
:-(
mnesia:add_table_copy(vcard, node(), disc_only_copies),
112
:-(
mnesia:add_table_copy(vcard_search, node(), disc_copies).
113
114 set_indexes() ->
115
:-(
mnesia:add_table_index(vcard_search, luser),
116
:-(
mnesia:add_table_index(vcard_search, lfn),
117
:-(
mnesia:add_table_index(vcard_search, lfamily),
118
:-(
mnesia:add_table_index(vcard_search, lgiven),
119
:-(
mnesia:add_table_index(vcard_search, lmiddle),
120
:-(
mnesia:add_table_index(vcard_search, lnickname),
121
:-(
mnesia:add_table_index(vcard_search, lbday),
122
:-(
mnesia:add_table_index(vcard_search, lctry),
123
:-(
mnesia:add_table_index(vcard_search, llocality),
124
:-(
mnesia:add_table_index(vcard_search, lemail),
125
:-(
mnesia:add_table_index(vcard_search, lorgname),
126
:-(
mnesia:add_table_index(vcard_search, lorgunit).
127
128 make_matchhead(LServer, Data) ->
129
:-(
GlobMatch = #vcard_search{_ = '_'},
130
:-(
Match = filter_fields(Data, GlobMatch, LServer),
131
:-(
Match.
132
133 filter_fields([], Match, _LServer) ->
134
:-(
Match;
135 filter_fields([{SVar, [Val]} | Ds], Match, LServer)
136 when is_binary(Val) and (Val /= <<"">>) ->
137
:-(
LVal = jid:str_tolower(Val),
138
:-(
NewMatch =
139 case SVar of
140
:-(
<<"user">> -> Match#vcard_search{luser = make_val(LVal)};
141
:-(
<<"fn">> -> Match#vcard_search{lfn = make_val(LVal)};
142
:-(
<<"last">> -> Match#vcard_search{lfamily = make_val(LVal)};
143
:-(
<<"first">> -> Match#vcard_search{lgiven = make_val(LVal)};
144
:-(
<<"middle">> -> Match#vcard_search{lmiddle = make_val(LVal)};
145
:-(
<<"nick">> -> Match#vcard_search{lnickname = make_val(LVal)};
146
:-(
<<"bday">> -> Match#vcard_search{lbday = make_val(LVal)};
147
:-(
<<"ctry">> -> Match#vcard_search{lctry = make_val(LVal)};
148
:-(
<<"locality">> -> Match#vcard_search{llocality = make_val(LVal)};
149
:-(
<<"email">> -> Match#vcard_search{lemail = make_val(LVal)};
150
:-(
<<"orgname">> -> Match#vcard_search{lorgname = make_val(LVal)};
151
:-(
<<"orgunit">> -> Match#vcard_search{lorgunit = make_val(LVal)};
152
:-(
_ -> Match
153 end,
154
:-(
filter_fields(Ds, NewMatch, LServer);
155 filter_fields([_ | Ds], Match, LServer) ->
156
:-(
filter_fields(Ds, Match, LServer).
157
158 %% Fulltext search is mnesia is something that is really-really wrong
159 stringify_search_fields(#vcard_search{} = S) ->
160
:-(
S#vcard_search{
161 lfn = binary_to_list(S#vcard_search.lfn),
162 lfamily = binary_to_list(S#vcard_search.lfamily),
163 luser = binary_to_list(S#vcard_search.luser),
164 lgiven = binary_to_list(S#vcard_search.lgiven),
165 lmiddle = binary_to_list(S#vcard_search.lmiddle),
166 lnickname = binary_to_list(S#vcard_search.lnickname),
167 lbday = binary_to_list(S#vcard_search.lbday),
168 lctry = binary_to_list(S#vcard_search.lctry),
169 llocality = binary_to_list(S#vcard_search.llocality),
170 lemail = binary_to_list(S#vcard_search.lemail),
171 lorgname = binary_to_list(S#vcard_search.lorgname),
172 lorgunit = binary_to_list(S#vcard_search.lorgunit)
173 }.
174
175 %% returns value as list to match substrings using match spec.
176 %% See vcard_search definition.
177 make_val(ValBin) ->
178
:-(
Val = binary_to_list(ValBin),
179
:-(
case lists:suffix("*", Val) of
180 true ->
181
:-(
lists:sublist(Val, length(Val) - 1) ++ '_';
182 _ ->
183
:-(
Val
184 end.
185
186 record_to_item(R) ->
187
:-(
{User, Server} = R#vcard_search.user,
188
:-(
[
189 ?FIELD(<<"jid">>, <<User/binary, $@, Server/binary>>),
190 ?FIELD(<<"fn">>, (R#vcard_search.fn)),
191 ?FIELD(<<"last">>, (R#vcard_search.family)),
192 ?FIELD(<<"first">>, (R#vcard_search.given)),
193 ?FIELD(<<"middle">>, (R#vcard_search.middle)),
194 ?FIELD(<<"nick">>, (R#vcard_search.nickname)),
195 ?FIELD(<<"bday">>, (R#vcard_search.bday)),
196 ?FIELD(<<"ctry">>, (R#vcard_search.ctry)),
197 ?FIELD(<<"locality">>, (R#vcard_search.locality)),
198 ?FIELD(<<"email">>, (R#vcard_search.email)),
199 ?FIELD(<<"orgname">>, (R#vcard_search.orgname)),
200 ?FIELD(<<"orgunit">>, (R#vcard_search.orgunit))
201 ].
Line Hits Source