Software /
code /
prosody-modules
Changeset
6210:24316a399978 draft
Merge
author | Trần H. Trung <xmpp:trần.h.trung@trung.fun> |
---|---|
date | Tue, 18 Mar 2025 00:19:25 +0700 |
parents | 6209:d611ed13df7e |
children | 6211:750d64c47ec6 |
files | mod_firewall/mod_firewall.lua mod_flags/mod_flags.lua mod_http_altconnect/README.md mod_http_auth_check/README.md mod_http_authentication/README.md mod_http_logging/README.md mod_http_muc_log/README.md mod_http_oauth2/README.md mod_http_upload/README.md mod_idlecompat/README.md mod_ignore_host_chatstates/README.md mod_incidents_handling/README.md |
diffstat | 12 files changed, 784 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/mod_firewall/mod_firewall.lua Tue Mar 18 00:16:25 2025 +0700 +++ b/mod_firewall/mod_firewall.lua Tue Mar 18 00:19:25 2025 +0700 @@ -315,6 +315,10 @@ new_long_id = { global_code = [[local new_long_id = require "util.id".long;]]; }; + + trace = { + global_code = [[local trace_init = module:require("trace").init;]]; + }; }; local function include_dep(dependency, code) @@ -371,9 +375,9 @@ module:require"marks"; end -local function new_rule(ruleset, chain) +local function new_rule(ruleset, chain, line_no) assert(chain, "no chain specified"); - local rule = { conditions = {}, actions = {}, deps = {} }; + local rule = { conditions = {}, actions = {}, deps = {}, line_no = line_no }; table.insert(ruleset[chain], rule); return rule; end @@ -385,6 +389,7 @@ return "Error compiling "..filename.." on line "..line_no..": "..err; end + local metadata = { debug = {} }; local ruleset = { deliver = {}; }; @@ -429,6 +434,12 @@ return nil, errmsg("Only event chains supported at the moment"); end ruleset[chain] = ruleset[chain] or {}; + elseif not(state) and line:sub(1, 2) == "@@" then + local k, v = line:match("^@@%s*([^%s=]+)%s*=%s*(.+)$"); + if not k then + return nil, errmsg("Unable to parse metadata assignment (expected '@@ key = value')"); + end + metadata[k] = v; elseif not(state) and line:sub(1,1) == "%" then -- Definition (zone, limit, etc.) local what, name = line:match("^%%%s*([%w_]+) +([^ :]+)"); if not definition_handlers[what] then @@ -483,12 +494,13 @@ end elseif state == "actions" then -- state is actions but action pattern did not match state = nil; -- Awaiting next rule, etc. - table.insert(ruleset[chain], rule); + table.insert(ruleset[chain], rule); -- FIXME: Is this a bug? Rule should have already been inserted by new_rule()? rule = nil; else - if not state then + -- Condition + if not state then -- Starting a new rule block? state = "rules"; - rule = new_rule(ruleset, chain); + rule = new_rule(ruleset, chain, line_no); end -- Check standard modifiers for the condition (e.g. NOT) local negated; @@ -514,10 +526,10 @@ end end end - return ruleset; + return ruleset, metadata; end -local function process_firewall_rules(ruleset) +local function process_firewall_rules(ruleset, metadata) -- Compile ruleset and return complete code local chain_handlers = {}; @@ -537,8 +549,13 @@ end end + if metadata.trace then + include_dep("trace", code); + table.insert(code, ("local trace = trace_init(%q, %q);"):format(metadata.filename, chain_name)) + end + local condition_cache, n_conditions = {}, 0; - for _, rule in ipairs(rules) do + for rule_n, rule in ipairs(rules) do for _, dep in ipairs(rule.deps) do include_dep(dep, code); end @@ -562,6 +579,17 @@ else rule.conditions[i] = (negated and "not(" or "(")..condition..")"; end + + if metadata.trace then + -- Wrap each condition in a tracer + rule.conditions[i] = ("trace(%d, %d, %s)"):format(rule_n, i, rule.conditions[i]); + end + end + + if metadata.trace then + -- Trace overall action + table.insert(rule.actions, 1, ("trace(%d, nil, true)"):format(rule_n)); + table.insert(rule.actions, ("else trace(%d, nil, false)"):format(rule_n)); end rule_code = "if "..table.concat(rule.conditions, " and ").." then\n\t\t\t" @@ -592,9 +620,9 @@ end local function compile_firewall_rules(filename) - local ruleset, err = parse_firewall_rules(filename); - if not ruleset then return nil, err; end - local chain_handlers = process_firewall_rules(ruleset); + local ruleset, metadata = parse_firewall_rules(filename); + if not ruleset then return nil, metadata; end + local chain_handlers = process_firewall_rules(ruleset, metadata); return chain_handlers; end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_flags/mod_flags.lua Tue Mar 18 00:19:25 2025 +0700 @@ -0,0 +1,194 @@ +-- This module is only for 0.12, later versions have mod_flags bundled +--% conflicts: mod_flags + +local flags_map; +if prosody.process_type ~= "prosodyctl" then + flags_map = module:open_store("account_flags", "map"); +end + +-- API + +function add_flag(username, flag, comment) -- luacheck: ignore 131/add_flag + local flag_data = { + when = os.time(); + comment = comment; + }; + + local ok, err = flags_map:set(username, flag, flag_data); + if not ok then + return nil, err; + end + + module:fire_event("user-flag-added/"..flag, { + user = username; + flag = flag; + data = flag_data; + }); + + return true; +end + +function remove_flag(username, flag) -- luacheck: ignore 131/remove_flag + local ok, err = flags_map:set(username, flag, nil); + if not ok then + return nil, err; + end + + module:fire_event("user-flag-removed/"..flag, { + user = username; + flag = flag; + }); + + return true; +end + +function has_flag(username, flag) -- luacheck: ignore 131/has_flag + local ok, err = flags_map:get(username, flag); + if not ok and err then + error("Failed to check flags for user: "..err); + end + return not not ok; +end + +function get_flag_info(username, flag) -- luacheck: ignore 131/get_flag_info + return flags_map:get(username, flag); +end + + +-- Migration from mod_firewall marks + +local function migrate_marks(host) + local usermanager = require "core.usermanager"; + + local flag_storage = module:open_store("account_flags"); + local mark_storage = module:open_store("firewall_marks"); + + local migration_comment = "Migrated from mod_firewall marks at "..os.date("%Y-%m-%d %R"); + + local migrated, empty, errors = 0, 0, 0; + for username in usermanager.users(host) do + local marks, err = mark_storage:get(username); + if marks then + local flags = {}; + for mark_name, mark_timestamp in pairs(marks) do + flags[mark_name] = { + when = mark_timestamp; + comment = migration_comment; + }; + end + local saved_ok, saved_err = flag_storage:set(username, flags); + if saved_ok then + prosody.log("error", "Failed to save flags for %s: %s", username, saved_err); + migrated = migrated + 1; + else + errors = errors + 1; + end + elseif err then + prosody.log("error", "Failed to load marks for %s: %s", username, err); + errors = errors + 1; + else + empty = empty + 1; + end + end + + print(("Finished - %d migrated, %d users with no marks, %d errors"):format(migrated, empty, errors)); +end + +function module.command(arg) + local storagemanager = require "core.storagemanager"; + local usermanager = require "core.usermanager"; + local jid = require "util.jid"; + local warn = require"util.prosodyctl".show_warning; + + local command = arg[1]; + if not command then + warn("Valid subcommands: migrate_marks"); + return 0; + end + table.remove(arg, 1); + + local node, host = jid.prepped_split(arg[1]); + if not host then + warn("Please specify a host or JID after the command"); + return 1; + elseif not prosody.hosts[host] then + warn("Unknown host: "..host); + return 1; + end + + table.remove(arg, 1); + + module.host = host; -- luacheck: ignore 122 + storagemanager.initialize_host(host); + usermanager.initialize_host(host); + + flags_map = module:open_store("account_flags", "map"); + + if command == "migrate_marks" then + migrate_marks(host); + return 0; + elseif command == "find" then + local flag = assert(arg[1], "expected argument: flag"); + local flags = module:open_store("account_flags", "map"); + local users_with_flag = flags:get_all(flag); + + local c = 0; + for user, flag_data in pairs(users_with_flag) do + print(user, os.date("%Y-%m-%d %R", flag_data.when), flag_data.comment or ""); + c = c + 1; + end + + print(("%d accounts listed"):format(c)); + return 1; + elseif command == "add" then + local username = assert(node, "expected a user JID, got "..host); + local flag = assert(arg[1], "expected argument: flag"); + local comment = arg[2]; + + local ok, err = add_flag(username, flag, comment); + if not ok then + print("Failed to add flag: "..err); + return 1; + end + + print("Flag added"); + return 1; + elseif command == "remove" then + local username = assert(node, "expected a user JID, got "..host); + local flag = assert(arg[1], "expected argument: flag"); + + local ok, err = remove_flag(username, flag); + if not ok then + print("Failed to remove flag: "..err); + return 1; + end + + print("Flag removed"); + return 1; + elseif command == "list" then + local username = assert(node, "expected a user JID, got "..host); + + local c = 0; + + local flags = module:open_store("account_flags"); + local user_flags, err = flags:get(username); + + if not user_flags and err then + print("Unable to list flags: "..err); + return 1; + end + + if user_flags then + for flag_name, flag_data in pairs(user_flags) do + print(flag_name, os.date("%Y-%m-%d %R", flag_data.when), flag_data.comment or ""); + c = c + 1; + end + end + + print(("%d flags listed"):format(c)); + return 0; + else + warn("Unknown command: %s", command); + return 1; + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_http_altconnect/README.md Tue Mar 18 00:19:25 2025 +0700 @@ -0,0 +1,3 @@ +This module helps make BOSH and WebSocket connection endpoints +discoverable via the HTTP method described in +[XEP-0156](https://xmpp.org/extensions/xep-0156.html#http).
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_http_auth_check/README.md Tue Mar 18 00:19:25 2025 +0700 @@ -0,0 +1,31 @@ +--- +labels: +summary: 'Test account credentials using HTTP' +... + +Introduction +------------ + +This module lets you test whether a set of credentials are valid, +using Prosody's configured authentication mechanism. + +This is useful as an easy way to allow other (e.g. non-XMPP) applications +to authenticate users using their XMPP credentials. + +Syntax +------ + +To test credentials, issue a simple GET request with HTTP basic auth: + + GET /auth_check HTTP/1.1 + Authorization: Basic <base64(jid:password)> + +Prosody will return a 2xx code on success (user exists and credentials are +correct), or 401 if the credentials are invalid. Any other code may be returned +if there is a problem handling the request. + +### Example usage + +Here follows some example usage using `curl`. + + curl http://prosody.local:5280/auth_check -u user@example.com:secr1t
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_http_authentication/README.md Tue Mar 18 00:19:25 2025 +0700 @@ -0,0 +1,29 @@ +--- +labels: +- 'Stage-Beta' +summary: Enforces HTTP Basic authentication across all HTTP endpoints served by Prosody +... + +# mod_http_authentication + +This module enforces HTTP Basic authentication across all HTTP endpoints served by Prosody. + +## Configuration + + Name Default Description + ---------------------------------- --------------------------------- -------------------------------------------------------------------------------------------------------------------------------------- + http\_credentials "minddistrict:secretpassword" The credentials that HTTP clients must provide to access the HTTP interface. Should be a string with the syntax "username:password". + unauthenticated\_http\_endpoints { "/http-bind", "/http-bind/" } A list of paths that should be excluded from authentication. + +## Usage + +This is a global module, so should be added to the global `modules_enabled` option in your config file. It applies to all HTTP virtual hosts. + +## Compatibility + +The module use a new API in Prosody 0.10 and will not work with older +versions. + +## Details + +By Kim Alvefur \<zash@zash.se\>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_http_logging/README.md Tue Mar 18 00:19:25 2025 +0700 @@ -0,0 +1,3 @@ +This module produces more detailed HTTP logs for Prosodys built-in HTTP +server. The format is similar to that of Apache and go into Prosodys +normal logs at the `info` level.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_http_muc_log/README.md Tue Mar 18 00:19:25 2025 +0700 @@ -0,0 +1,109 @@ +--- +labels: +- 'Stage-Beta' +summary: Provides a web interface to stored chatroom logs +rockspec: + build: + copy_directories: + - res + - static +... + +Introduction +============ + +This module provides a built-in web interface to view chatroom logs +stored by [mod\_muc\_mam]. + +Installation +============ + +Same as any other module, be sure to include the HTML template +`http_muc_log.html` alongside `mod_http_muc_log.lua`. + +Configuration +============= + +For example: + +``` lua +Component "conference.example.com" "muc" +modules_enabled = { + "muc_mam"; + "http_muc_log"; +} +storage = { + muc_log = "sql"; -- for example +} +``` + +The web interface would then be reachable at the address: + + http://conference.example.com:5280/muc_log/ + +See [the page about Prosodys HTTP server][doc:http] for info about the +address. + +## Styling + +The default HTML template lives in `http_muc_log.html` in the same +directory as the module, but can be changed by setting +`http_muc_log_template` to point to a different file. The same template, +with different input is used for every view. + +The module uses [util.interpolation][doc:developers:util:interpolation] +for rendering templates, with the pattern `"%b{}"` and HTML / XML +escaping enabled. + +## Default view + +To link to the latest day instead of calendar from the room listing +page: + +```lua +http_muc_log_default_view = "latest" +``` + +## Inline images + +Inline images can optionally be shown. This is disabled by default for +privacy reasons. + +``` {.lua} +http_muc_log_show_images = true +``` + +## Calendar optimization + +The calendar view relies on an optional part of the Prosody archive +storage API that provides a list of every valid date. If this is +unavailable then the module queries for the first and the last messages +and assumes that every date between those is valid. This may lead to +many empty pages in case the logs are sparse. + +This optimization can be turned off, to get a more accurate calendar +view, but it will likely be very slow. + +``` {.lua} +http_muc_log_lazy_calendar = false +``` + +## Pinned chatrooms + +The room list page is normally sorted by address, rooms having a +description before those that don't. To override this, or pin certain +rooms to the top: + +``` lua +http_muc_log_list_order = { + "general@channels.example.com", + "support@channels.example.com", +} +``` + +Compatibility +============= + +Requires Prosody 0.11 or later and a storage backend with support for +stanza archives. See [mod\_storage\_muc\_log] for using legacy data from +[mod\_muc\_log].
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_http_oauth2/README.md Tue Mar 18 00:19:25 2025 +0700 @@ -0,0 +1,289 @@ +--- +labels: +- Stage-Alpha +rockspec: + build: + copy_directories: + - html +summary: OAuth 2.0 Authorization Server API +--- + +## Introduction + +This module implements an [OAuth2](https://oauth.net/2/)/[OpenID Connect +(OIDC)](https://openid.net/connect/) Authorization Server on top of +Prosody's usual internal authentication backend. + +OAuth and OIDC are web standards that allow you to provide clients and +third-party applications limited access to your account, without sharing your +password with them. + +With this module deployed, software that supports OAuth can obtain +"access tokens" from Prosody which can then be used to connect to XMPP +accounts using the [OAUTHBEARER SASL mechanism][rfc7628] or via non-XMPP +interfaces such as [mod_rest]. + +Although this module has been around for some time, it has recently been +significantly extended and largely rewritten to support OAuth/OIDC more fully. + +As of April 2023, it should be considered **alpha** stage. It works, we have +tested it, but it has not yet seen wider review, testing and deployment. At +this stage we recommend it for experimental and test deployments only. For +specific information, see the [deployment notes section](#deployment-notes) +below. + +Known client implementations: + +- [example shell script for mod_rest](https://hg.prosody.im/prosody-modules/file/tip/mod_rest/example/rest.sh) +- *(we need you!)* + +Support for [OAUTHBEARER][rfc7628] has been added to the Lua XMPP +library, [verse](https://code.matthewwild.co.uk/verse). If you know of +additional implementations, or are motivated to work on one, please let +us know! We'd be happy to help (e.g. by providing a test server). + +## Standards support + +Notable supported standards: + +- [RFC 6749: The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749) +- [RFC 7009: OAuth 2.0 Token Revocation](https://www.rfc-editor.org/rfc/rfc7009) +- [RFC 7591: OAuth 2.0 Dynamic Client Registration](https://www.rfc-editor.org/rfc/rfc7591.html) +- [RFC 7628: A Set of Simple Authentication and Security Layer (SASL) Mechanisms for OAuth](https://www.rfc-editor.org/rfc/rfc7628) +- [RFC 7636: Proof Key for Code Exchange by OAuth Public Clients](https://www.rfc-editor.org/rfc/rfc7636) +- [RFC 7662: OAuth 2.0 Token Introspection](https://www.rfc-editor.org/rfc/rfc7662) +- [RFC 8628: OAuth 2.0 Device Authorization Grant](https://www.rfc-editor.org/rfc/rfc8628) +- [RFC 9207: OAuth 2.0 Authorization Server Issuer Identification](https://www.rfc-editor.org/rfc/rfc9207.html) +- [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html) +- [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html) (_partial, e.g. missing JWKS_) +- [OpenID Connect Dynamic Client Registration 1.0](https://openid.net/specs/openid-connect-registration-1_0.html) + +## Configuration + +### Interface + +The module presents a web page to users to allow them to authenticate when +a client requests access. Built-in pages are provided, but you may also theme +or entirely override them. + +This module honours the `site_name` configuration option that is also used by +a number of other modules: + +```lua +site_name = "My XMPP Server" +``` + +To provide custom templates, specify the path to the template directory: + +```lua +oauth2_template_path = "/etc/prosody/custom-oauth2-templates" +``` + +If you know what features your templates use use you can adjust the +`Content-Security-Policy` header to only allow what is needed: + +```lua +oauth2_security_policy = "default-src 'self'" -- this is the default +``` + +### Token parameters + +The following options configure the lifetime of tokens issued by the module. +The defaults are recommended. + +```lua +oauth2_access_token_ttl = 3600 -- one hour +oauth2_refresh_token_ttl = 604800 -- one week +``` + +### Dynamic client registration + +To allow users to connect any compatible software, you should enable dynamic +client registration. + +Dynamic client registration can be enabled by configuring a JWT key. Algorithm +defaults to *HS256*, lifetime defaults to forever. + +```lua +oauth2_registration_key = "securely generated JWT key here" +oauth2_registration_algorithm = "HS256" +oauth2_registration_ttl = nil -- unlimited by default +``` + +Registering a client is described in +[RFC7591](https://www.rfc-editor.org/rfc/rfc7591.html). + +In addition to the requirements in the RFC, the following requirements +are enforced: + +`client_name` +: **MUST** be present, is shown to users in consent screen. + +`client_uri` +: **MUST** be present and **MUST** be a `https://` URL. + +`redirect_uris` + +: **MUST** contain at least one valid URI. Different rules apply + depending on the value of `application_type`, see below. + +`application_type` + +: Optional, defaults to `web`. Determines further restrictions for + `redirect_uris`. The following values are supported: + + `web` *(default)* + : For web clients. With this, `redirect_uris` **MUST** be + `https://` URIs and **MUST** use the same hostname part as the + `client_uri`. + + `native` + : For native e.g. desktop clients etc. `redirect_uris` **MUST** + match one of: + + - Loopback HTTP URI, e.g. `http://127.0.0.1/` or + `http://[::1]` + - Application-specific scheme, e.g. `com.example.app:/` + - The special OOB URI `urn:ietf:wg:oauth:2.0:oob` + +`tos_uri`, `policy_uri` +: Informative URLs pointing to Terms of Service and Service Policy + document **MUST** use the same scheme (i.e. `https://`) and hostname + as the `client_uri`. + +#### Registration Examples + +In short registration works by POST-ing a JSON structure describing your +client to an endpoint: + +``` bash +curl -sSf https://xmpp.example.net/oauth2/register \ + -H Content-Type:application/json \ + -H Accept:application/json \ + --data ' +{ + "client_name" : "My Application", + "client_uri" : "https://app.example.com/", + "redirect_uris" : [ + "https://app.example.com/redirect" + ] +} +' +``` + +Another example with more fields: + +``` bash +curl -sSf https://xmpp.example.net/oauth2/register \ + -H Content-Type:application/json \ + -H Accept:application/json \ + --data ' +{ + "application_type" : "native", + "client_name" : "Desktop Chat App", + "client_uri" : "https://app.example.org/", + "contacts" : [ + "support@example.org" + ], + "policy_uri" : "https://app.example.org/about/privacy", + "redirect_uris" : [ + "http://localhost:8080/redirect", + "org.example.app:/redirect" + ], + "scope" : "xmpp", + "software_id" : "32a0a8f3-4016-5478-905a-c373156eca73", + "software_version" : "3.4.1", + "tos_uri" : "https://app.example.org/about/terms" +} +' +``` + +### Supported flows + +- Authorization Code grant, optionally with Proof Key for Code Exchange +- Device Authorization Grant +- Resource owner password grant *(disabled by default)* +- Implicit flow *(disabled by default)* +- Refresh Token grants + +Various flows can be disabled and enabled with +`allowed_oauth2_grant_types` and `allowed_oauth2_response_types`: + +```lua +-- These examples reflect the defaults +allowed_oauth2_grant_types = { + "authorization_code"; -- authorization code grant + "device_code"; + -- "password"; -- resource owner password grant disabled by default +} + +allowed_oauth2_response_types = { + "code"; -- authorization code flow + -- "token"; -- implicit flow disabled by default +} +``` + +The [Proof Key for Code Exchange][RFC 7636] mitigation method is +required by default but can be made optional: + +```lua +oauth2_require_code_challenge = false -- default is true +``` + +Further, individual challenge methods can be enabled or disabled: + +```lua +-- These reflects the default +allowed_oauth2_code_challenge_methods = { + -- "plain"; -- insecure but backwards-compatible + "S256"; +} +``` + +### Policy documents + +Links to Terms of Service and Service Policy documents can be advertised +for use by OAuth clients: + +```lua +oauth2_terms_url = "https://example.com/terms-of-service.html" +oauth2_policy_url = "https://example.com/service-policy.pdf" +-- These are unset by default +``` + +## Deployment notes + +### Access management + +This module does not provide an interface for users to manage what they have +granted access to their account! (e.g. to view and revoke clients they have +previously authorized). It is recommended to join this module with +[mod_client_management] to provide such access. However, at the time of writing, +no XMPP clients currently support the protocol used by that module. We plan to +work on additional interfaces in the future. + +### Scopes + +OAuth supports "scopes" as a way to grant clients limited access. + +There are currently no standard scopes defined for XMPP. This is +something that we intend to change, e.g. by definitions provided in a +future XEP. This means that clients you authorize currently have to +choose between unrestricted access to your account (including the +ability to change your password and lock you out!) and zero access. So, +for now, while using OAuth clients can prevent leaking your password to +them, it is not currently suitable for connecting untrusted clients to +your account. + +As a first step, the `xmpp` scope is supported, and corresponds to +whatever permissions the user would have when logged in over XMPP. + +Further, known Prosody roles can be used as scopes. + +OpenID scopes such as `openid` and `profile` can be used for "Login +with XMPP" without granting access to more than limited profile details. + +## Compatibility + +Requires Prosody trunk (April 2023), **not** compatible with Prosody 0.12 or +earlier.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_http_upload/README.md Tue Mar 18 00:19:25 2025 +0700 @@ -0,0 +1,13 @@ +--- +description: HTTP File Upload +superseded_by: mod_http_file_share +labels: +- Stage-Obsolete +--- + +This module is obsolete and deleted. + +In Prosody 0.12 and later, consider switching to [mod_http_file_share](https://prosody.im/doc/modules/mod_http_file_share) +which is distributed with Prosody. You can migrate existing files using +[mod_migrate_http_upload](https://modules.prosody.im/mod_migrate_http_upload.html). +You will be redirected shortly.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_idlecompat/README.md Tue Mar 18 00:19:25 2025 +0700 @@ -0,0 +1,24 @@ +--- +labels: +- 'Stage-Beta' +summary: 'XEP-0319 compatibility module' +... + +Introduction +============ + +This module adds [XEP-0319](http://xmpp.org/extensions/xep-0319.html) +idle tags to presence stanzas containing [XEP-0012: Last +Activity](http://xmpp.org/extensions/xep-0012.html) tags for idle +indication (e.g. supported by libpurple clients). It works on outgoing +and incoming presence stanzas. + +Install and enable it like any other module. It has no configuration. + +Compatibility +============= + + ------- ------- + trunk Works + 0.9 Works + ------- -------
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_ignore_host_chatstates/README.md Tue Mar 18 00:19:25 2025 +0700 @@ -0,0 +1,3 @@ +This module discards typing notifications sent to a bare host JID, +preventing error replies to be sent. These errors are harmless but can +be annoying sometimes if your client shows them prominently.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_incidents_handling/README.md Tue Mar 18 00:19:25 2025 +0700 @@ -0,0 +1,47 @@ +--- +labels: +- 'Stage-Beta' +summary: Incidents Handling plugin +... + +Introduction +============ + +This module implements +[XEP-268](http://xmpp.org/extensions/xep-0268.html). + +Details +======= + +It will let you manage reports, inquiries, requests and responses +through an Adhoc interface. The following new adhoc admin commands will +be available: + +- List Incidents -- List all available incidents and let's you reply + requests. +- Send Incident Inquiry -- Inquiry a remote server about an incident. +- Send Incident Report -- Send an incident report to a remote server. +- Send Incident Request -- Send an incident request to a remote + server. + +Each Adhoc form provides syntax instructions through `<desc/>` elements +(they may currently be stripped by Prosody), although it's encouraged to +read the [IODEF specifications](https://tools.ietf.org/html/rfc5070). + +Usage +===== + +Copy the module folder into your prosody modules directory. Place the +module between your enabled modules either into the global or a vhost +section. + +Optional configuration directives: + +``` {.lua} +incidents_expire_time = 86400 -- Expiral of "closed" incidents in seconds. +``` + +Info +==== + +- to be 0.9, works.