]>
Commit | Line | Data |
---|---|---|
52421ab2 | 1 | diff --git a/doc/guide.tex b/doc/guide.tex |
2 | index 5de409d..ac3dba8 100644 | |
3 | --- a/doc/guide.tex | |
4 | +++ b/doc/guide.tex | |
5 | @@ -4052,6 +4052,17 @@ Options: | |
6 | \begin{description} | |
7 | \hostitem{vjud} | |
8 | \iqdiscitem{\ns{vcard-temp}} | |
9 | +\titem{access\_get}\ind{options!accessget} Access rule that defines | |
10 | + who is allowed to see vCard of local users. | |
11 | + If a rule returns `deny' on the requester | |
12 | + user name, that user cannot see vCards of local users. | |
13 | + By default anybody can see the vCards of local users. | |
14 | +\titem{access\_set}\ind{options!accessset} Access rule that defines | |
15 | + who is allowed to modify his vCard. | |
16 | + If a rule returns `deny' on the requester | |
17 | + user name, that user cannot modify his vCard. | |
18 | + By default each local account can modify his own local vCard. | |
19 | + Notice that vCard of a user can only be edited by the user himself. | |
20 | \titem{\{search, true|false\}}\ind{options!search}This option specifies whether the search | |
21 | functionality is enabled or not | |
22 | If disabled, the option \term{host} will be ignored and the | |
0d78319d AM |
23 | @@ -4128,6 +4142,11 @@ consists of the following \modvcardldap{}-specific options: |
24 | \begin{description} | |
25 | \hostitem{vjud} | |
26 | \iqdiscitem{\ns{vcard-temp}} | |
27 | +\titem{access\_get}\ind{options!accessget} Access rule that defines | |
28 | + who is allowed to see vCard of local users. | |
29 | + If a rule returns `deny' on the requester | |
30 | + user name, that user cannot see vCards of local users. | |
31 | + By default anybody can see the vCards of local users. | |
32 | \titem{\{search, true|false\}}\ind{options!search}This option specifies whether the search | |
33 | functionality is enabled (value: \term{true}) or disabled (value: | |
34 | \term{false}). If disabled, the option \term{host} will be ignored and the | |
35 | @@ -4651,14 +4651,17 @@ Examples: | |
52421ab2 | 36 | ]}. |
37 | \end{verbatim} | |
38 | \item The second situation differs in a way that search results are not limited, | |
39 | - and that all virtual hosts will be searched instead of only the current one: | |
40 | + and that all virtual hosts will be searched instead of only the current one. | |
41 | + Also, vCards of local users can only be seen by Local users. | |
42 | \begin{verbatim} | |
43 | +{access, vcard_get, [{allow, local}]}. | |
44 | {modules, | |
45 | [ | |
46 | ... | |
47 | {mod_vcard, [{search, true}, | |
48 | {matches, infinity}, | |
49 | - {allow_return_all, true}]}, | |
50 | + {allow_return_all, true}, | |
51 | + {access_get, vcard_get}]}, | |
52 | ... | |
53 | ]}. | |
54 | \end{verbatim} | |
52421ab2 | 55 | diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl |
56 | index 4384087..c54e8ea 100644 | |
57 | --- a/src/mod_vcard.erl | |
58 | +++ b/src/mod_vcard.erl | |
59 | @@ -174,7 +174,9 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) -> | |
60 | case Type of | |
61 | set -> | |
62 | #jid{user = User, lserver = LServer} = From, | |
63 | - case lists:member(LServer, ?MYHOSTS) of | |
64 | + Access = gen_mod:get_module_opt(LServer, ?MODULE, access_set, all), | |
65 | + case lists:member(LServer, ?MYHOSTS) andalso | |
66 | + (acl:match_rule(LServer, Access, From) == allow) of | |
67 | true -> | |
68 | set_vcard(User, LServer, SubEl), | |
69 | IQ#iq{type = result, sub_el = []}; | |
70 | @@ -183,19 +185,28 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) -> | |
71 | end; | |
72 | get -> | |
73 | #jid{luser = LUser, lserver = LServer} = To, | |
74 | - US = {LUser, LServer}, | |
75 | - F = fun() -> | |
76 | - mnesia:read({vcard, US}) | |
77 | - end, | |
78 | - Els = case mnesia:transaction(F) of | |
79 | - {atomic, Rs} -> | |
80 | - lists:map(fun(R) -> | |
81 | - R#vcard.vcard | |
82 | - end, Rs); | |
83 | - {aborted, _Reason} -> | |
84 | - [] | |
85 | - end, | |
86 | - IQ#iq{type = result, sub_el = Els} | |
87 | + Access = gen_mod:get_module_opt(LServer, ?MODULE, access_get, all), | |
88 | + case acl:match_rule(LServer, Access, From) of | |
89 | + allow -> | |
90 | + Els = get_vcard(LUser, LServer), | |
91 | + IQ#iq{type = result, sub_el = Els}; | |
92 | + deny -> | |
93 | + IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]} | |
94 | + end | |
95 | + end. | |
96 | + | |
97 | +get_vcard(LUser, LServer) -> | |
98 | + US = {LUser, LServer}, | |
99 | + F = fun() -> | |
100 | + mnesia:read({vcard, US}) | |
101 | + end, | |
102 | + case mnesia:transaction(F) of | |
103 | + {atomic, Rs} -> | |
104 | + lists:map(fun(R) -> | |
105 | + R#vcard.vcard | |
106 | + end, Rs); | |
107 | + {aborted, _Reason} -> | |
108 | + [] | |
109 | end. | |
110 | ||
111 | set_vcard(User, LServer, VCARD) -> | |
112 | diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl | |
d803d5e7 | 113 | index f4078df..074bdf7 100644 |
52421ab2 | 114 | --- a/src/mod_vcard_ldap.erl |
115 | +++ b/src/mod_vcard_ldap.erl | |
116 | @@ -241,38 +241,47 @@ process_local_iq(_From, _To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) | |
117 | ]}]} | |
118 | end. | |
119 | ||
120 | -process_sm_iq(_From, #jid{lserver=LServer} = To, #iq{sub_el = SubEl} = IQ) -> | |
121 | - case catch process_vcard_ldap(To, IQ, LServer) of | |
122 | +process_sm_iq(From, #jid{lserver=LServer} = To, #iq{sub_el = SubEl} = IQ) -> | |
123 | + case catch process_vcard_ldap(From, To, IQ, LServer) of | |
124 | {'EXIT', _} -> | |
125 | IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]}; | |
126 | Other -> | |
127 | Other | |
128 | end. | |
129 | ||
130 | -process_vcard_ldap(To, IQ, Server) -> | |
131 | +process_vcard_ldap(From, To, IQ, Server) -> | |
132 | {ok, State} = eldap_utils:get_state(Server, ?PROCNAME), | |
133 | #iq{type = Type, sub_el = SubEl} = IQ, | |
134 | case Type of | |
135 | set -> | |
136 | IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; | |
137 | get -> | |
138 | - #jid{luser = LUser} = To, | |
139 | - LServer = State#state.serverhost, | |
140 | - case ejabberd_auth:is_user_exists(LUser, LServer) of | |
141 | - true -> | |
142 | - VCardMap = State#state.vcard_map, | |
143 | - case find_ldap_user(LUser, State) of | |
144 | - #eldap_entry{attributes = Attributes} -> | |
145 | - Vcard = ldap_attributes_to_vcard(Attributes, VCardMap, {LUser, LServer}), | |
146 | - IQ#iq{type = result, sub_el = Vcard}; | |
147 | - _ -> | |
148 | - IQ#iq{type = result, sub_el = []} | |
149 | - end; | |
150 | - _ -> | |
151 | - IQ#iq{type = result, sub_el = []} | |
152 | - end | |
153 | + process_vcard_ldap_get_maybe(From, To, IQ, State) | |
154 | end. | |
155 | ||
156 | +process_vcard_ldap_get_maybe(From, To, IQ, State) -> | |
157 | + #jid{luser = LUser} = To, | |
158 | + #jid{lserver = FromLServer} = From, | |
159 | + LServer = State#state.serverhost, | |
160 | + Access = gen_mod:get_module_opt(LServer, ?MODULE, access_get, all), | |
d803d5e7 | 161 | + case ejabberd_auth:is_user_exists(LUser, LServer) andalso |
162 | + (acl:match_rule(FromLServer, Access, From) == allow) of | |
52421ab2 | 163 | + true -> |
164 | + process_vcard_ldap_get(LUser, LServer, IQ, State); | |
165 | + _ -> | |
166 | + IQ#iq{type = result, sub_el = []} | |
167 | + end. | |
168 | + | |
169 | +process_vcard_ldap_get(LUser, LServer, IQ, State) -> | |
170 | + VCardMap = State#state.vcard_map, | |
171 | + case find_ldap_user(LUser, State) of | |
172 | + #eldap_entry{attributes = Attributes} -> | |
173 | + Vcard = ldap_attributes_to_vcard(Attributes, VCardMap, {LUser, LServer}), | |
174 | + IQ#iq{type = result, sub_el = Vcard}; | |
175 | + _ -> | |
176 | + IQ#iq{type = result, sub_el = []} | |
177 | + end. | |
178 | + | |
179 | handle_call(get_state, _From, State) -> | |
180 | {reply, {ok, State}, State}; | |
181 | handle_call(stop, _From, State) -> | |
182 | diff --git a/src/mod_vcard_odbc.erl b/src/mod_vcard_odbc.erl | |
183 | index 30c2888..d239823 100644 | |
184 | --- a/src/mod_vcard_odbc.erl | |
185 | +++ b/src/mod_vcard_odbc.erl | |
186 | @@ -138,7 +138,9 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) -> | |
187 | case Type of | |
188 | set -> | |
189 | #jid{user = User, lserver = LServer} = From, | |
190 | - case lists:member(LServer, ?MYHOSTS) of | |
191 | + Access = gen_mod:get_module_opt(LServer, ?MODULE, access_set, all), | |
192 | + case lists:member(LServer, ?MYHOSTS) andalso | |
193 | + (acl:match_rule(LServer, Access, From) == allow) of | |
194 | true -> | |
195 | set_vcard(User, LServer, SubEl), | |
196 | IQ#iq{type = result, sub_el = []}; | |
197 | @@ -147,24 +149,34 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) -> | |
198 | end; | |
199 | get -> | |
200 | #jid{luser = LUser, lserver = LServer} = To, | |
201 | - Username = ejabberd_odbc:escape(LUser), | |
202 | - case catch odbc_queries:get_vcard(LServer, Username) of | |
203 | - {selected, ["vcard"], [{SVCARD}]} -> | |
204 | - case xml_stream:parse_element(SVCARD) of | |
205 | - {error, _Reason} -> | |
206 | - IQ#iq{type = error, | |
207 | - sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}; | |
208 | - VCARD -> | |
209 | - IQ#iq{type = result, sub_el = [VCARD]} | |
210 | - end; | |
211 | - {selected, ["vcard"], []} -> | |
212 | - IQ#iq{type = result, sub_el = []}; | |
213 | - _ -> | |
214 | - IQ#iq{type = error, | |
215 | - sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} | |
216 | + Access = gen_mod:get_module_opt(LServer, ?MODULE, access_get, all), | |
217 | + case acl:match_rule(LServer, Access, From) of | |
218 | + allow -> | |
219 | + get_vcard(LUser, LServer, SubEl, IQ); | |
220 | + deny -> | |
221 | + IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]} | |
222 | end | |
223 | end. | |
224 | ||
225 | +get_vcard(LUser, LServer, SubEl, IQ) -> | |
226 | + Username = ejabberd_odbc:escape(LUser), | |
227 | + case catch odbc_queries:get_vcard(LServer, Username) of | |
228 | + {selected, ["vcard"], [{SVCARD}]} -> | |
229 | + case xml_stream:parse_element(SVCARD) of | |
230 | + {error, _Reason} -> | |
231 | + IQ#iq{type = error, | |
232 | + sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}; | |
233 | + VCARD -> | |
234 | + IQ#iq{type = result, sub_el = [VCARD]} | |
235 | + end; | |
236 | + {selected, ["vcard"], []} -> | |
237 | + IQ#iq{type = result, sub_el = []}; | |
238 | + _ -> | |
239 | + IQ#iq{type = error, | |
240 | + sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} | |
241 | + end. | |
242 | + | |
243 | + | |
244 | set_vcard(User, LServer, VCARD) -> | |
245 | FN = xml:get_path_s(VCARD, [{elem, "FN"}, cdata]), | |
246 | Family = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "FAMILY"}, cdata]), |