./ct_report/coverage/mod_vcard_riak.COVER.html

1 %%==============================================================================
2 %% Copyright 2015 Erlang Solutions Ltd.
3 %%
4 %% Licensed under the Apache License, Version 2.0 (the "License");
5 %% you may not use this file except in compliance with the License.
6 %% You may obtain a copy of the License at
7 %%
8 %% http://www.apache.org/licenses/LICENSE-2.0
9 %%
10 %% Unless required by applicable law or agreed to in writing, software
11 %% distributed under the License is distributed on an "AS IS" BASIS,
12 %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 %% See the License for the specific language governing permissions and
14 %% limitations under the License.
15 %%==============================================================================
16 -module(mod_vcard_riak).
17 -behaviour(mod_vcard_backend).
18
19 %% API
20 -export([init/2,
21 remove_user/3,
22 set_vcard/5,
23 get_vcard/3,
24 search/3,
25 search_fields/2,
26 search_reported_fields/3]).
27
28 -include("mongoose.hrl").
29 -include("jlib.hrl").
30 -include("mod_vcard.hrl").
31 -include_lib("riakc/include/riakc.hrl").
32
33 init(_HostType, _Opts) ->
34
:-(
ok.
35
36 remove_user(HostType, LUser, LServer) ->
37
:-(
mongoose_riak:delete(bucket_type(HostType, LServer), LUser, [{dw, 2}]).
38
39 set_vcard(HostType, User, LServer, VCard, _VCardSearch) ->
40
:-(
BucketType = bucket_type(HostType, LServer),
41
:-(
VCardEncoded = exml:to_binary(VCard),
42
:-(
LUser = jid:nodeprep(User),
43
:-(
Obj = riakc_obj:new(BucketType, LUser, VCardEncoded, "application/xml"),
44
:-(
mongoose_riak:put(Obj).
45
46 get_vcard(HostType, LUser, LServer) ->
47
:-(
BucketType = bucket_type(HostType, LServer),
48
:-(
case mongoose_riak:get(BucketType, LUser) of
49 {ok, Obj} ->
50
:-(
XMLBin = riakc_obj:get_value(Obj),
51
:-(
case exml:parse(XMLBin) of
52 {ok, XMLEl} ->
53
:-(
{ok, [XMLEl]};
54 {error, Reason} ->
55
:-(
?LOG_WARNING(#{what => vcard_lookup_failed, reason => Reason,
56
:-(
packet => XMLBin}),
57
:-(
{error, mongoose_xmpp_errors:service_unavailable()}
58 end;
59 {error, notfound} ->
60
:-(
{error, mongoose_xmpp_errors:item_not_found()};
61 Other ->
62
:-(
Other
63 end.
64
65 search(HostType, LServer, Data) ->
66
:-(
YZQuery = make_yz_query(Data, []),
67
:-(
do_search(YZQuery, HostType, LServer).
68
69 do_search([], _HostType, _) ->
70
:-(
[];
71 do_search(YZQueryIn, HostType, LServer) ->
72
:-(
{_BucketType, BucketName} = bucket_type(HostType, LServer),
73
:-(
YZQuery = [<<"_yz_rb:", BucketName/binary>> | YZQueryIn],
74
:-(
Limit = mod_vcard:get_results_limit(HostType),
75
:-(
YZQueryBin = mongoose_bin:join(YZQuery, <<" AND ">>),
76
:-(
case mongoose_riak:search(yz_vcard_index(HostType), YZQueryBin, [{rows, Limit}]) of
77 {ok, #search_results{docs=R, num_found = _N}} ->
78
:-(
lists:map(fun({_Index, Props}) -> doc2item(HostType, LServer, Props) end, R);
79 Err ->
80
:-(
?LOG_ERROR(#{what => vcard_search_failed, index => yz_vcard_index(HostType),
81
:-(
riak_query => YZQueryBin, reason => Err}),
82
:-(
[]
83 end.
84
85 search_fields(_HostType, _LServer) ->
86
:-(
mod_vcard:default_search_fields().
87
88 search_reported_fields(_HostType, _LServer, Lang) ->
89
:-(
mod_vcard:get_default_reported_fields(Lang).
90
91
:-(
make_yz_query([], Acc) -> Acc;
92 make_yz_query([{Var, [Val]} | Rest], Acc) ->
93
:-(
Part = [riak_search_mapping(Var), ":", make_val(Val)],
94
:-(
make_yz_query(Rest, [erlang:iolist_to_binary(Part) | Acc]).
95
96
:-(
riak_search_mapping(<<"user">>) -> <<"_yz_rk">>;
97
:-(
riak_search_mapping(<<"fn">>) -> <<"vCard.FN">>;
98
:-(
riak_search_mapping(<<"first">>) -> <<"vCard.N.GIVEN">>;
99
:-(
riak_search_mapping(<<"middle">>) -> <<"vCard.N.MIDDLE">>;
100
:-(
riak_search_mapping(<<"last">>) -> <<"vCard.N.FAMILY">>;
101
:-(
riak_search_mapping(<<"nick">>) -> <<"vCard.NICKNAME">>;
102
:-(
riak_search_mapping(<<"bday">>) -> <<"vCard.BDAY">>;
103
:-(
riak_search_mapping(<<"ctry">>) -> <<"vCard.ADR.CTRY">>;
104
:-(
riak_search_mapping(<<"locality">>) -> <<"vCard.ADR.LOCALITY">>;
105
:-(
riak_search_mapping(<<"email">>) -> <<"vCard.EMAIL.USERID">>;
106
:-(
riak_search_mapping(<<"orgname">>) -> <<"vCard.ORG.ORGNAME">>;
107
:-(
riak_search_mapping(<<"orgunit">>) -> <<"vCard.ORG.ORGUNIT">>.
108
109 make_val(Val) ->
110
:-(
LVal = jid:str_tolower(Val),
111
:-(
case binary:match(LVal, <<" ">>) of
112 nomatch ->
113
:-(
LVal;
114 _ ->
115
:-(
[$", LVal, $"]
116 end.
117
118 doc2item(HostType, LServer, Props) ->
119
:-(
Vals = lists:map(pa:bind(fun extract_field/2, Props), search_fields(HostType, LServer)),
120
:-(
#xmlel{name = <<"item">>,
121 children = Vals}.
122
123 extract_field(Props, {_, <<"user">>}) ->
124
:-(
{_, Username} = lists:keyfind(riak_search_mapping(<<"user">>), 1, Props),
125
:-(
{_, Bucket} = lists:keyfind(<<"_yz_rb">>, 1, Props),
126
:-(
[_, Host] = binary:split(Bucket, <<"_">>),
127
:-(
?FIELD(<<"jid">>, iolist_to_binary([Username, "@", Host]));
128 extract_field(Props, {_, Field}) ->
129
:-(
V = case lists:keyfind(riak_search_mapping(Field), 1, Props) of
130 {_, Val} ->
131
:-(
Val;
132 _ ->
133
:-(
""
134 end,
135
:-(
?FIELD(Field, V).
136
137
138 bucket_type(HostType, LServer) ->
139
:-(
{gen_mod:get_module_opt(HostType, mod_vcard, [riak, bucket_type]), <<"vcard_", LServer/binary>>}.
140
141 yz_vcard_index(HostType) ->
142
:-(
gen_mod:get_module_opt(HostType, mod_vcard, [riak, search_index]).
Line Hits Source