Mercurial > prosody-modules
diff mod_client_management/mod_client_management.lua @ 5653:62c6e17a5e9d
Merge
author | Stephen Paul Weber <singpolyma@singpolyma.net> |
---|---|
date | Mon, 18 Sep 2023 08:24:19 -0500 |
parents | f16edebb1305 |
children | c69320fc438b |
line wrap: on
line diff
--- a/mod_client_management/mod_client_management.lua Mon Sep 18 08:22:07 2023 -0500 +++ b/mod_client_management/mod_client_management.lua Mon Sep 18 08:24:19 2023 -0500 @@ -10,8 +10,8 @@ local strict = module:get_option_boolean("enforce_client_ids", false); -module:default_permission("prosody:user", ":list-clients"); -module:default_permission("prosody:user", ":manage-clients"); +module:default_permission("prosody:registered", ":list-clients"); +module:default_permission("prosody:registered", ":manage-clients"); local tokenauth = module:depends("tokenauth"); local mod_fast = module:depends("sasl2_fast"); @@ -35,6 +35,8 @@ if not (sasl_agent or token_agent) then return; end return { software = sasl_agent and sasl_agent.software or token_agent and token_agent.name or nil; + software_id = token_agent and token_agent.id or nil; + software_version = token_agent and token_agent.version or nil; uri = token_agent and token_agent.uri or nil; device = sasl_agent and sasl_agent.device or nil; }; @@ -250,6 +252,7 @@ type = "access"; first_seen = grant.created; last_seen = grant.accessed; + expires = grant.expires; active = { grant = grant; }; @@ -276,6 +279,17 @@ return active_clients; end +local function user_agent_tostring(user_agent) + if user_agent then + if user_agent.software then + if user_agent.software_version then + return user_agent.software .. "/" .. user_agent.software_version; + end + return user_agent.software; + end + end +end + function revoke_client_access(username, client_selector) if client_selector then local c_type, c_id = client_selector:match("^(%w+)/(.+)$"); @@ -309,6 +323,13 @@ local ok = tokenauth.revoke_grant(username, c_id); if not ok then return nil, "internal-server-error"; end return true; + elseif c_type == "software" then + local active_clients = get_active_clients(username); + for _, client in ipairs(active_clients) do + if client.user_agent and client.user_agent.software == c_id or user_agent_tostring(client.user_agent) == c_id then + return revoke_client_access(username, client.id); + end + end end end @@ -348,7 +369,7 @@ local user_agent = st.stanza("user-agent"); if client.user_agent then if client.user_agent.software then - user_agent:text_tag("software", client.user_agent.software); + user_agent:text_tag("software", client.user_agent.software, { id = client.user_agent.software_id; version = client.user_agent.software_version }); end if client.user_agent.device then user_agent:text_tag("device", client.user_agent.device); @@ -417,23 +438,40 @@ return true, "No clients associated with this account"; end + local function date_or_time(last_seen) + return last_seen and os.date(math.abs(os.difftime(os.time(), last_seen)) >= 86400 and "%Y-%m-%d" or "%H:%M:%S", last_seen); + end + + local date_or_time_width = math.max(#os.date("%Y-%m-%d"), #os.date("%H:%M:%S")); + local colspec = { + { title = "ID"; key = "id"; width = "1p" }; { title = "Software"; key = "user_agent"; width = "1p"; - mapper = function(user_agent) - return user_agent and user_agent.software; - end; + mapper = user_agent_tostring; + }; + { + title = "First seen"; + key = "first_seen"; + width = date_or_time_width; + align = "right"; + mapper = date_or_time; }; { title = "Last seen"; key = "last_seen"; - width = math.max(#os.date("%Y-%m-%d"), #os.date("%H:%M:%S")); + width = date_or_time_width; align = "right"; - mapper = function(last_seen) - return os.date(os.difftime(os.time(), last_seen) >= 86400 and "%Y-%m-%d" or "%H:%M:%S", last_seen); - end; + mapper = date_or_time; + }; + { + title = "Expires"; + key = "expires"; + width = date_or_time_width; + align = "right"; + mapper = date_or_time; }; { title = "Authentication"; @@ -456,4 +494,18 @@ print(string.rep("-", self.session.width)); return true, ("%d clients"):format(#clients); end + + function console_env.user:revoke_client(user_jid, selector) -- luacheck: ignore 212/self + local username, host = jid.split(user_jid); + local mod = prosody.hosts[host] and prosody.hosts[host].modules.client_management; + if not mod then + return false, ("Host does not exist on this server, or does not have mod_client_management loaded"); + end + + local revoked, err = revocation_errors.coerce(mod.revoke_client_access(username, selector)); + if not revoked then + return false, err.text or err; + end + return true, "Client access revoked"; + end end);