comparison mod_external_services/mod_external_services.lua @ 4668:ede9682c2022

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
parents 1990611691cf
children
comparison
equal deleted inserted replaced
4667:1990611691cf 4668:ede9682c2022
122 setmetatable(services, services_mt); 122 setmetatable(services, services_mt);
123 123
124 return services; 124 return services;
125 end 125 end
126 126
127 local function handle_services(event) 127 function services_xml(services, name, namespace)
128 local origin, stanza = event.origin, event.stanza; 128 local reply = st.stanza(name or "services", { xmlns = namespace or "urn:xmpp:extdisco:2" });
129 local action = stanza.tags[1];
130
131 local user_bare = jid.bare(stanza.attr.from);
132 local user_host = jid.host(user_bare);
133 if not ((access:empty() and origin.type == "c2s") or access:contains(user_bare) or access:contains(user_host)) then
134 origin.send(st.error_reply(stanza, "auth", "forbidden"));
135 return true;
136 end
137
138 local reply = st.reply(stanza):tag("services", { xmlns = action.attr.xmlns });
139 local services = get_services();
140
141 local requested_type = action.attr.type;
142 if requested_type then
143 services:filter(function(item)
144 return item.type == requested_type;
145 end);
146 end
147
148 module:fire_event("external_service/services", {
149 origin = origin;
150 stanza = stanza;
151 reply = reply;
152 requested_type = requested_type;
153 services = services;
154 });
155 129
156 for _, srv in ipairs(services) do 130 for _, srv in ipairs(services) do
157 reply:tag("service", { 131 reply:tag("service", {
158 type = srv.type; 132 type = srv.type;
159 transport = srv.transport; 133 transport = srv.transport;
164 expires = srv.expires and dt.datetime(srv.expires) or nil; 138 expires = srv.expires and dt.datetime(srv.expires) or nil;
165 restricted = srv.restricted and "1" or nil; 139 restricted = srv.restricted and "1" or nil;
166 }):up(); 140 }):up();
167 end 141 end
168 142
143 return reply;
144 end
145
146 local function handle_services(event)
147 local origin, stanza = event.origin, event.stanza;
148 local action = stanza.tags[1];
149
150 local user_bare = jid.bare(stanza.attr.from);
151 local user_host = jid.host(user_bare);
152 if not ((access:empty() and origin.type == "c2s") or access:contains(user_bare) or access:contains(user_host)) then
153 origin.send(st.error_reply(stanza, "auth", "forbidden"));
154 return true;
155 end
156
157 local services = get_services();
158
159 local requested_type = action.attr.type;
160 if requested_type then
161 services:filter(function(item)
162 return item.type == requested_type;
163 end);
164 end
165
166 module:fire_event("external_service/services", {
167 origin = origin;
168 stanza = stanza;
169 requested_type = requested_type;
170 services = services;
171 });
172
173 local reply = st.reply(stanza):add_child(services_xml(services, action.name, action.attr.xmlns));
174
169 origin.send(reply); 175 origin.send(reply);
170 return true; 176 return true;
171 end 177 end
172 178
173 local function handle_credentials(event) 179 local function handle_credentials(event)
177 if origin.type ~= "c2s" then 183 if origin.type ~= "c2s" then
178 origin.send(st.error_reply(stanza, "auth", "forbidden", "The 'port' and 'type' attributes are required.")); 184 origin.send(st.error_reply(stanza, "auth", "forbidden", "The 'port' and 'type' attributes are required."));
179 return true; 185 return true;
180 end 186 end
181 187
182 local reply = st.reply(stanza):tag("credentials", { xmlns = action.attr.xmlns });
183 local services = get_services(); 188 local services = get_services();
184 services:filter(function (item) 189 services:filter(function (item)
185 return item.restricted; 190 return item.restricted;
186 end) 191 end)
187 192
197 end 202 end
198 203
199 module:fire_event("external_service/credentials", { 204 module:fire_event("external_service/credentials", {
200 origin = origin; 205 origin = origin;
201 stanza = stanza; 206 stanza = stanza;
202 reply = reply;
203 requested_credentials = requested_credentials; 207 requested_credentials = requested_credentials;
204 services = services; 208 services = services;
205 }); 209 });
206 210
207 services:filter(function (srv) 211 services:filter(function (srv)
208 local port_key = string.format("%s:%s:%d", srv.type, srv.host, srv.port or 0); 212 local port_key = string.format("%s:%s:%d", srv.type, srv.host, srv.port or 0);
209 local portless_key = string.format("%s:%s:%d", srv.type, srv.host, 0); 213 local portless_key = string.format("%s:%s:%d", srv.type, srv.host, 0);
210 return requested_credentials:contains(port_key) or requested_credentials:contains(portless_key); 214 return requested_credentials:contains(port_key) or requested_credentials:contains(portless_key);
211 end); 215 end);
212 216
213 for _, srv in ipairs(services) do 217 local reply = st.reply(stanza):add_child(services_xml(services, action.name, action.attr.xmlns));
214 reply:tag("service", {
215 type = srv.type;
216 transport = srv.transport;
217 host = srv.host;
218 port = srv.port and string.format("%d", srv.port) or nil;
219 username = srv.username;
220 password = srv.password;
221 expires = srv.expires and dt.datetime(srv.expires) or nil;
222 restricted = srv.restricted and "1" or nil;
223 }):up();
224 end
225 218
226 origin.send(reply); 219 origin.send(reply);
227 return true; 220 return true;
228 end 221 end
229 222