Comparison

plugins/mod_external_services.lua @ 11756:a0e17b7c8b05

mod_external_services: Factor out public function for converting to XML Along with the previous commit, allows building the XML thing yourself, should you wish to send it yourself or use it in a different context than an iq reply. API change: The 'reply' is removed from the event.
author Kim Alvefur <zash@zash.se>
date Mon, 30 Aug 2021 20:19:15 +0200
parent 11755:ae565e49289a
child 11933:f752427a5214
comparison
equal deleted inserted replaced
11755:ae565e49289a 11756:a0e17b7c8b05
129 setmetatable(services, services_mt); 129 setmetatable(services, services_mt);
130 130
131 return services; 131 return services;
132 end 132 end
133 133
134 local function handle_services(event) 134 function services_xml(services, name, namespace)
135 local origin, stanza = event.origin, event.stanza; 135 local reply = st.stanza(name or "services", { xmlns = namespace or "urn:xmpp:extdisco:2" });
136 local action = stanza.tags[1];
137
138 local user_bare = jid.bare(stanza.attr.from);
139 local user_host = jid.host(user_bare);
140 if not ((access:empty() and origin.type == "c2s") or access:contains(user_bare) or access:contains(user_host)) then
141 origin.send(st.error_reply(stanza, "auth", "forbidden"));
142 return true;
143 end
144
145 local reply = st.reply(stanza):tag("services", { xmlns = action.attr.xmlns });
146 local services = get_services();
147
148 local requested_type = action.attr.type;
149 if requested_type then
150 services:filter(function(item)
151 return item.type == requested_type;
152 end);
153 end
154
155 module:fire_event("external_service/services", {
156 origin = origin;
157 stanza = stanza;
158 reply = reply;
159 requested_type = requested_type;
160 services = services;
161 });
162 136
163 for _, srv in ipairs(services) do 137 for _, srv in ipairs(services) do
164 reply:tag("service", { 138 reply:tag("service", {
165 type = srv.type; 139 type = srv.type;
166 transport = srv.transport; 140 transport = srv.transport;
171 expires = srv.expires and dt.datetime(srv.expires) or nil; 145 expires = srv.expires and dt.datetime(srv.expires) or nil;
172 restricted = srv.restricted and "1" or nil; 146 restricted = srv.restricted and "1" or nil;
173 }):up(); 147 }):up();
174 end 148 end
175 149
150 return reply;
151 end
152
153 local function handle_services(event)
154 local origin, stanza = event.origin, event.stanza;
155 local action = stanza.tags[1];
156
157 local user_bare = jid.bare(stanza.attr.from);
158 local user_host = jid.host(user_bare);
159 if not ((access:empty() and origin.type == "c2s") or access:contains(user_bare) or access:contains(user_host)) then
160 origin.send(st.error_reply(stanza, "auth", "forbidden"));
161 return true;
162 end
163
164 local services = get_services();
165
166 local requested_type = action.attr.type;
167 if requested_type then
168 services:filter(function(item)
169 return item.type == requested_type;
170 end);
171 end
172
173 module:fire_event("external_service/services", {
174 origin = origin;
175 stanza = stanza;
176 requested_type = requested_type;
177 services = services;
178 });
179
180 local reply = st.reply(stanza):add_child(services_xml(services, action.name, action.attr.xmlns));
181
176 origin.send(reply); 182 origin.send(reply);
177 return true; 183 return true;
178 end 184 end
179 185
180 local function handle_credentials(event) 186 local function handle_credentials(event)
184 if origin.type ~= "c2s" then 190 if origin.type ~= "c2s" then
185 origin.send(st.error_reply(stanza, "auth", "forbidden", "The 'port' and 'type' attributes are required.")); 191 origin.send(st.error_reply(stanza, "auth", "forbidden", "The 'port' and 'type' attributes are required."));
186 return true; 192 return true;
187 end 193 end
188 194
189 local reply = st.reply(stanza):tag("credentials", { xmlns = action.attr.xmlns });
190 local services = get_services(); 195 local services = get_services();
191 services:filter(function (item) 196 services:filter(function (item)
192 return item.restricted; 197 return item.restricted;
193 end) 198 end)
194 199
204 end 209 end
205 210
206 module:fire_event("external_service/credentials", { 211 module:fire_event("external_service/credentials", {
207 origin = origin; 212 origin = origin;
208 stanza = stanza; 213 stanza = stanza;
209 reply = reply;
210 requested_credentials = requested_credentials; 214 requested_credentials = requested_credentials;
211 services = services; 215 services = services;
212 }); 216 });
213 217
214 services:filter(function (srv) 218 services:filter(function (srv)
215 local port_key = string.format("%s:%s:%d", srv.type, srv.host, srv.port or 0); 219 local port_key = string.format("%s:%s:%d", srv.type, srv.host, srv.port or 0);
216 local portless_key = string.format("%s:%s:%d", srv.type, srv.host, 0); 220 local portless_key = string.format("%s:%s:%d", srv.type, srv.host, 0);
217 return requested_credentials:contains(port_key) or requested_credentials:contains(portless_key); 221 return requested_credentials:contains(port_key) or requested_credentials:contains(portless_key);
218 end); 222 end);
219 223
220 for _, srv in ipairs(services) do 224 local reply = st.reply(stanza):add_child(services_xml(services, action.name, action.attr.xmlns));
221 reply:tag("service", {
222 type = srv.type;
223 transport = srv.transport;
224 host = srv.host;
225 port = srv.port and string.format("%d", srv.port) or nil;
226 username = srv.username;
227 password = srv.password;
228 expires = srv.expires and dt.datetime(srv.expires) or nil;
229 restricted = srv.restricted and "1" or nil;
230 }):up();
231 end
232 225
233 origin.send(reply); 226 origin.send(reply);
234 return true; 227 return true;
235 end 228 end
236 229