plugins/mod_external_services.lua
author Matthew Wild <mwild1@gmail.com>
Wed, 27 Mar 2024 15:35:15 +0000
branch0.12
changeset 13469 54a936345aaa
parent 12435 95f33a006c03
child 12689 4d75663d1552
permissions -rw-r--r--
prosodyctl check: Warn about invalid domain names in the config file This ensures that domain names of virtual hosts and components are valid in XMPP, and that they are encoded correctly.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     1
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     2
local dt = require "util.datetime";
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     3
local base64 = require "util.encodings".base64;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     4
local hashes = require "util.hashes";
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     5
local st = require "util.stanza";
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     6
local jid = require "util.jid";
11044
c560531d9a6e mod_external_services: Validate services added via events
Kim Alvefur <zash@zash.se>
parents: 11043
diff changeset
     7
local array = require "util.array";
11758
21a9b3f2a728 mod_external_services: Filter services by requested credentials using a Set
Kim Alvefur <zash@zash.se>
parents: 11757
diff changeset
     8
local set = require "util.set";
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     9
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    10
local default_host = module:get_option_string("external_service_host", module.host);
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    11
local default_port = module:get_option_number("external_service_port");
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    12
local default_secret = module:get_option_string("external_service_secret");
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    13
local default_ttl = module:get_option_number("external_service_ttl", 86400);
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    14
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    15
local configured_services = module:get_option_array("external_services", {});
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    16
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    17
local access = module:get_option_set("external_service_access", {});
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    18
11042
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    19
-- https://tools.ietf.org/html/draft-uberti-behave-turn-rest-00
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    20
local function behave_turn_rest_credentials(srv, item, secret)
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    21
	local ttl = default_ttl;
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    22
	if type(item.ttl) == "number" then
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    23
		ttl = item.ttl;
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    24
	end
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    25
	local expires = srv.expires or os.time() + ttl;
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    26
	local username;
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    27
	if type(item.username) == "string" then
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    28
		username = string.format("%d:%s", expires, item.username);
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    29
	else
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    30
		username = string.format("%d", expires);
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    31
	end
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    32
	srv.username = username;
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    33
	srv.password = base64.encode(hashes.hmac_sha1(secret, srv.username));
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    34
end
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    35
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    36
local algorithms = {
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    37
	turn = behave_turn_rest_credentials;
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    38
}
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    39
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    40
-- filter config into well-defined service records
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    41
local function prepare(item)
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    42
	if type(item) ~= "table" then
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    43
		module:log("error", "Service definition is not a table: %q", item);
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    44
		return nil;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    45
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    46
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    47
	local srv = {
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    48
		type = nil;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    49
		transport = nil;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    50
		host = default_host;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    51
		port = default_port;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    52
		username = nil;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    53
		password = nil;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    54
		restricted = nil;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    55
		expires = nil;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    56
	};
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    57
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    58
	if type(item.type) == "string" then
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    59
		srv.type = item.type;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    60
	else
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    61
		module:log("error", "Service missing mandatory 'type' field: %q", item);
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    62
		return nil;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    63
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    64
	if type(item.transport) == "string" then
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    65
		srv.transport = item.transport;
11937
f752427a5214 mod_external_services: Warn about missing recommended fields
Kim Alvefur <zash@zash.se>
parents: 11760
diff changeset
    66
	else
f752427a5214 mod_external_services: Warn about missing recommended fields
Kim Alvefur <zash@zash.se>
parents: 11760
diff changeset
    67
		module:log("warn", "Service missing recommended 'transport' field: %q", item);
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    68
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    69
	if type(item.host) == "string" then
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    70
		srv.host = item.host;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    71
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    72
	if type(item.port) == "number" then
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    73
		srv.port = item.port;
11937
f752427a5214 mod_external_services: Warn about missing recommended fields
Kim Alvefur <zash@zash.se>
parents: 11760
diff changeset
    74
	elseif not srv.port then
f752427a5214 mod_external_services: Warn about missing recommended fields
Kim Alvefur <zash@zash.se>
parents: 11760
diff changeset
    75
		module:log("warn", "Service missing recommended 'port' field: %q", item);
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    76
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    77
	if type(item.username) == "string" then
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    78
		srv.username = item.username;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    79
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    80
	if type(item.password) == "string" then
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    81
		srv.password = item.password;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    82
		srv.restricted = true;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    83
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    84
	if item.restricted == true then
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    85
		srv.restricted = true;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    86
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    87
	if type(item.expires) == "number" then
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    88
		srv.expires = item.expires;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    89
	elseif type(item.ttl) == "number" then
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    90
		srv.expires = os.time() + item.ttl;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    91
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    92
	if (item.secret == true and default_secret) or type(item.secret) == "string" then
11043
ec6919401790 mod_external_services: Allow specifying a credential generation callback
Kim Alvefur <zash@zash.se>
parents: 11042
diff changeset
    93
		local secret_cb = item.credentials_cb or algorithms[item.algorithm] or algorithms[srv.type];
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    94
		local secret = item.secret;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    95
		if secret == true then
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    96
			secret = default_secret;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    97
		end
11042
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    98
		if secret_cb then
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
    99
			secret_cb(srv, item, secret);
efefdf71373b mod_external_services: Prepare to allow more credential algorithms
Kim Alvefur <zash@zash.se>
parents: 11041
diff changeset
   100
			srv.restricted = true;
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   101
		end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   102
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   103
	return srv;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   104
end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   105
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   106
function module.load()
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   107
	-- Trigger errors on startup
11630
ef62d29c8fdc mod_external_services: Also validate services added by other modules
Kim Alvefur <zash@zash.se>
parents: 11044
diff changeset
   108
	local extras = module:get_host_items("external_service");
ef62d29c8fdc mod_external_services: Also validate services added by other modules
Kim Alvefur <zash@zash.se>
parents: 11044
diff changeset
   109
	local services = ( configured_services + extras ) / prepare;
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   110
	if #services == 0 then
11632
0807e835d3b5 mod_external_services: Report overall status as a module status
Kim Alvefur <zash@zash.se>
parents: 11631
diff changeset
   111
		module:set_status("warn", "No services configured or all had errors");
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   112
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   113
end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   114
11631
3a5212fd7e8e mod_external_services: Validate items as they are added
Kim Alvefur <zash@zash.se>
parents: 11630
diff changeset
   115
module:handle_items("external_service", function(added)
11632
0807e835d3b5 mod_external_services: Report overall status as a module status
Kim Alvefur <zash@zash.se>
parents: 11631
diff changeset
   116
	if prepare(added.item) then
0807e835d3b5 mod_external_services: Report overall status as a module status
Kim Alvefur <zash@zash.se>
parents: 11631
diff changeset
   117
		module:set_status("core", "OK");
0807e835d3b5 mod_external_services: Report overall status as a module status
Kim Alvefur <zash@zash.se>
parents: 11631
diff changeset
   118
	end
11631
3a5212fd7e8e mod_external_services: Validate items as they are added
Kim Alvefur <zash@zash.se>
parents: 11630
diff changeset
   119
end, module.load);
3a5212fd7e8e mod_external_services: Validate items as they are added
Kim Alvefur <zash@zash.se>
parents: 11630
diff changeset
   120
11044
c560531d9a6e mod_external_services: Validate services added via events
Kim Alvefur <zash@zash.se>
parents: 11043
diff changeset
   121
-- Ensure only valid items are added in events
c560531d9a6e mod_external_services: Validate services added via events
Kim Alvefur <zash@zash.se>
parents: 11043
diff changeset
   122
local services_mt = {
c560531d9a6e mod_external_services: Validate services added via events
Kim Alvefur <zash@zash.se>
parents: 11043
diff changeset
   123
	__index = getmetatable(array()).__index;
c560531d9a6e mod_external_services: Validate services added via events
Kim Alvefur <zash@zash.se>
parents: 11043
diff changeset
   124
	__newindex = function (self, i, v)
c560531d9a6e mod_external_services: Validate services added via events
Kim Alvefur <zash@zash.se>
parents: 11043
diff changeset
   125
		rawset(self, i, assert(prepare(v), "Invalid service entry added"));
c560531d9a6e mod_external_services: Validate services added via events
Kim Alvefur <zash@zash.se>
parents: 11043
diff changeset
   126
	end;
c560531d9a6e mod_external_services: Validate services added via events
Kim Alvefur <zash@zash.se>
parents: 11043
diff changeset
   127
}
c560531d9a6e mod_external_services: Validate services added via events
Kim Alvefur <zash@zash.se>
parents: 11043
diff changeset
   128
11759
ae565e49289a mod_external_services: Factor out public function returning current services
Kim Alvefur <zash@zash.se>
parents: 11758
diff changeset
   129
function get_services()
ae565e49289a mod_external_services: Factor out public function returning current services
Kim Alvefur <zash@zash.se>
parents: 11758
diff changeset
   130
	local extras = module:get_host_items("external_service");
ae565e49289a mod_external_services: Factor out public function returning current services
Kim Alvefur <zash@zash.se>
parents: 11758
diff changeset
   131
	local services = ( configured_services + extras ) / prepare;
ae565e49289a mod_external_services: Factor out public function returning current services
Kim Alvefur <zash@zash.se>
parents: 11758
diff changeset
   132
ae565e49289a mod_external_services: Factor out public function returning current services
Kim Alvefur <zash@zash.se>
parents: 11758
diff changeset
   133
	setmetatable(services, services_mt);
ae565e49289a mod_external_services: Factor out public function returning current services
Kim Alvefur <zash@zash.se>
parents: 11758
diff changeset
   134
ae565e49289a mod_external_services: Factor out public function returning current services
Kim Alvefur <zash@zash.se>
parents: 11758
diff changeset
   135
	return services;
ae565e49289a mod_external_services: Factor out public function returning current services
Kim Alvefur <zash@zash.se>
parents: 11758
diff changeset
   136
end
ae565e49289a mod_external_services: Factor out public function returning current services
Kim Alvefur <zash@zash.se>
parents: 11758
diff changeset
   137
11760
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   138
function services_xml(services, name, namespace)
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   139
	local reply = st.stanza(name or "services", { xmlns = namespace or "urn:xmpp:extdisco:2" });
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   140
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   141
	for _, srv in ipairs(services) do
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   142
		reply:tag("service", {
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   143
				type = srv.type;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   144
				transport = srv.transport;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   145
				host = srv.host;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   146
				port = srv.port and string.format("%d", srv.port) or nil;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   147
				username = srv.username;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   148
				password = srv.password;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   149
				expires = srv.expires and dt.datetime(srv.expires) or nil;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   150
				restricted = srv.restricted and "1" or nil;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   151
			}):up();
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   152
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   153
11760
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   154
	return reply;
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   155
end
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   156
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   157
local function handle_services(event)
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   158
	local origin, stanza = event.origin, event.stanza;
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   159
	local action = stanza.tags[1];
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   160
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   161
	local user_bare = jid.bare(stanza.attr.from);
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   162
	local user_host = jid.host(user_bare);
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   163
	if not ((access:empty() and origin.type == "c2s") or access:contains(user_bare) or access:contains(user_host)) then
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   164
		origin.send(st.error_reply(stanza, "auth", "forbidden"));
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   165
		return true;
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   166
	end
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   167
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   168
	local services = get_services();
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   169
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   170
	local requested_type = action.attr.type;
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   171
	if requested_type then
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   172
		services:filter(function(item)
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   173
			return item.type == requested_type;
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   174
		end);
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   175
	end
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   176
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   177
	module:fire_event("external_service/services", {
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   178
			origin = origin;
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   179
			stanza = stanza;
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   180
			requested_type = requested_type;
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   181
			services = services;
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   182
		});
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   183
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   184
	local reply = st.reply(stanza):add_child(services_xml(services, action.name, action.attr.xmlns));
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   185
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   186
	origin.send(reply);
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   187
	return true;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   188
end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   189
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   190
local function handle_credentials(event)
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   191
	local origin, stanza = event.origin, event.stanza;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   192
	local action = stanza.tags[1];
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   193
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   194
	if origin.type ~= "c2s" then
12435
95f33a006c03 mod_external_services: Move error message to correct place (fix #1725)
Kim Alvefur <zash@zash.se>
parents: 11937
diff changeset
   195
		origin.send(st.error_reply(stanza, "auth", "forbidden"));
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   196
		return true;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   197
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   198
11759
ae565e49289a mod_external_services: Factor out public function returning current services
Kim Alvefur <zash@zash.se>
parents: 11758
diff changeset
   199
	local services = get_services();
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   200
	services:filter(function (item)
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   201
		return item.restricted;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   202
	end)
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   203
11758
21a9b3f2a728 mod_external_services: Filter services by requested credentials using a Set
Kim Alvefur <zash@zash.se>
parents: 11757
diff changeset
   204
	local requested_credentials = set.new();
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   205
	for service in action:childtags("service") do
11757
c4599a7c534c mod_external_services: Validate required attributes on credentials requests
Kim Alvefur <zash@zash.se>
parents: 11632
diff changeset
   206
		if not service.attr.type or not service.attr.host then
12435
95f33a006c03 mod_external_services: Move error message to correct place (fix #1725)
Kim Alvefur <zash@zash.se>
parents: 11937
diff changeset
   207
			origin.send(st.error_reply(stanza, "modify", "bad-request", "The 'port' and 'type' attributes are required."));
11757
c4599a7c534c mod_external_services: Validate required attributes on credentials requests
Kim Alvefur <zash@zash.se>
parents: 11632
diff changeset
   208
			return true;
c4599a7c534c mod_external_services: Validate required attributes on credentials requests
Kim Alvefur <zash@zash.se>
parents: 11632
diff changeset
   209
		end
c4599a7c534c mod_external_services: Validate required attributes on credentials requests
Kim Alvefur <zash@zash.se>
parents: 11632
diff changeset
   210
11758
21a9b3f2a728 mod_external_services: Filter services by requested credentials using a Set
Kim Alvefur <zash@zash.se>
parents: 11757
diff changeset
   211
		requested_credentials:add(string.format("%s:%s:%d", service.attr.type, service.attr.host,
21a9b3f2a728 mod_external_services: Filter services by requested credentials using a Set
Kim Alvefur <zash@zash.se>
parents: 11757
diff changeset
   212
			tonumber(service.attr.port) or 0));
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   213
	end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   214
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   215
	module:fire_event("external_service/credentials", {
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   216
			origin = origin;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   217
			stanza = stanza;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   218
			requested_credentials = requested_credentials;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   219
			services = services;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   220
		});
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   221
11758
21a9b3f2a728 mod_external_services: Filter services by requested credentials using a Set
Kim Alvefur <zash@zash.se>
parents: 11757
diff changeset
   222
	services:filter(function (srv)
21a9b3f2a728 mod_external_services: Filter services by requested credentials using a Set
Kim Alvefur <zash@zash.se>
parents: 11757
diff changeset
   223
		local port_key = string.format("%s:%s:%d", srv.type, srv.host, srv.port or 0);
21a9b3f2a728 mod_external_services: Filter services by requested credentials using a Set
Kim Alvefur <zash@zash.se>
parents: 11757
diff changeset
   224
		local portless_key = string.format("%s:%s:%d", srv.type, srv.host, 0);
21a9b3f2a728 mod_external_services: Filter services by requested credentials using a Set
Kim Alvefur <zash@zash.se>
parents: 11757
diff changeset
   225
		return requested_credentials:contains(port_key) or requested_credentials:contains(portless_key);
21a9b3f2a728 mod_external_services: Filter services by requested credentials using a Set
Kim Alvefur <zash@zash.se>
parents: 11757
diff changeset
   226
	end);
21a9b3f2a728 mod_external_services: Filter services by requested credentials using a Set
Kim Alvefur <zash@zash.se>
parents: 11757
diff changeset
   227
11760
a0e17b7c8b05 mod_external_services: Factor out public function for converting to XML
Kim Alvefur <zash@zash.se>
parents: 11759
diff changeset
   228
	local reply = st.reply(stanza):add_child(services_xml(services, action.name, action.attr.xmlns));
11040
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   229
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   230
	origin.send(reply);
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   231
	return true;
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   232
end
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   233
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   234
-- XEP-0215 v0.7
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   235
module:add_feature("urn:xmpp:extdisco:2");
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   236
module:hook("iq-get/host/urn:xmpp:extdisco:2:services", handle_services);
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   237
module:hook("iq-get/host/urn:xmpp:extdisco:2:credentials", handle_credentials);
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   238
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   239
-- COMPAT XEP-0215 v0.6
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   240
-- Those still on the old version gets to deal with undefined attributes until they upgrade.
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   241
module:add_feature("urn:xmpp:extdisco:1");
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   242
module:hook("iq-get/host/urn:xmpp:extdisco:1:services", handle_services);
79e410cd7f6e mod_external_services: XEP-0215: External Service Discovery
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   243
module:hook("iq-get/host/urn:xmpp:extdisco:1:credentials", handle_credentials);