Mercurial > prosody-modules
view mod_log_messages_sql/mod_log_messages_sql.lua @ 6082:1a6cd0bbb7ab
mod_compliance_2023: Add 2023 Version of the compliance module, basis is the 2021 Version.
diff --git a/mod_compliance_2023/README.md b/mod_compliance_2023/README.md
new file mode 100644
--- /dev/null
+++ b/mod_compliance_2023/README.md
@@ -0,0 +1,22 @@
+---
+summary: XMPP Compliance Suites 2023 self-test
+labels:
+- Stage-Beta
+rockspec:
+ dependencies:
+ - mod_cloud_notify
+
+...
+
+Compare the list of enabled modules with
+[XEP-0479: XMPP Compliance Suites 2023] and produce basic report to the
+Prosody log file.
+
+If installed with the Prosody plugin installer then all modules needed for a green checkmark should be included. (With prosody 0.12 only [mod_cloud_notify] is not included with prosody and we need the community module)
+
+# Compatibility
+
+ Prosody-Version Status
+ --------------- ----------------------
+ trunk Works as of 2024-12-21
+ 0.12 Works
diff --git a/mod_compliance_2023/mod_compliance_2023.lua b/mod_compliance_2023/mod_compliance_2023.lua
new file mode 100644
--- /dev/null
+++ b/mod_compliance_2023/mod_compliance_2023.lua
@@ -0,0 +1,79 @@
+-- Copyright (c) 2021 Kim Alvefur
+--
+-- This module is MIT licensed.
+
+local hostmanager = require "core.hostmanager";
+
+local array = require "util.array";
+local set = require "util.set";
+
+local modules_enabled = module:get_option_inherited_set("modules_enabled");
+
+for host in pairs(hostmanager.get_children(module.host)) do
+ local component = module:context(host):get_option_string("component_module");
+ if component then
+ modules_enabled:add(component);
+ modules_enabled:include(module:context(host):get_option_set("modules_enabled", {}));
+ end
+end
+
+local function check(suggested, alternate, ...)
+ if set.intersection(modules_enabled, set.new({suggested; alternate; ...})):empty() then return suggested; end
+ return false;
+end
+
+local compliance = {
+ array {"Server"; check("tls"); check("disco")};
+
+ array {"Advanced Server"; check("pep", "pep_simple")};
+
+ array {"Web"; check("bosh"); check("websocket")};
+
+ -- No Server requirements for Advanced Web
+
+ array {"IM"; check("vcard_legacy", "vcard"); check("carbons"); check("http_file_share", "http_upload")};
+
+ array {
+ "Advanced IM";
+ check("vcard_legacy", "vcard");
+ check("blocklist");
+ check("muc");
+ check("private");
+ check("smacks");
+ check("mam");
+ check("bookmarks");
+ };
+
+ array {"Mobile"; check("smacks"); check("csi_simple", "csi_battery_saver")};
+
+ array {"Advanced Mobile"; check("cloud_notify")};
+
+ array {"A/V Calling"; check("turn_external", "external_services", "turncredentials", "extdisco")};
+
+};
+
+function check_compliance()
+ local compliant = true;
+ for _, suite in ipairs(compliance) do
+ local section = suite:pop(1);
+ if module:get_option_boolean("compliance_" .. section:lower():gsub("%A", "_"), true) then
+ local missing = set.new(suite:filter(function(m) return type(m) == "string" end):map(function(m) return "mod_" .. m end));
+ if suite[1] then
+ if compliant then
+ compliant = false;
+ module:log("warn", "Missing some modules for XMPP Compliance 2023");
+ end
+ module:log("info", "%s Compliance: %s", section, missing);
+ end
+ end
+ end
+
+ if compliant then module:log("info", "XMPP Compliance 2023: Compliant ✔️"); end
+end
+
+if prosody.start_time then
+ check_compliance()
+else
+ module:hook_global("server-started", check_compliance);
+end
+
| author | Menel <menel@snikket.de> |
|---|---|
| date | Sun, 22 Dec 2024 16:06:28 +0100 |
| parents | 9d132153d786 |
| children |
line wrap: on
line source
-- Based on mod_mam_sql -- Copyright (C) 2011-2012 Kim Alvefur -- -- This file is MIT/X11 licensed. local st = require "util.stanza"; local jid_bare = require "util.jid".bare; local jid_split = require "util.jid".split; local serialize = require"util.json".encode, require"util.json".decode; local tostring = tostring; local time_now = os.time; local table_name = module:get_option("message_log_sql_table", pcall(require, "util.cache") and "messages" or "prosodyarchive"); local sql, setsql, getsql = {}; do -- SQL stuff local connection; local resolve_relative_path = require "core.configmanager".resolve_relative_path; local params = module:get_option("message_log_sql", module:get_option("sql")); local function test_connection() if not connection then return nil; end if connection:ping() then return true; else module:log("debug", "Database connection closed"); connection = nil; end end local function connect() if not test_connection() then prosody.unlock_globals(); local dbh, err = DBI.Connect( params.driver, params.database, params.username, params.password, params.host, params.port ); prosody.lock_globals(); if not dbh then module:log("debug", "Database connection failed: %s", tostring(err)); return nil, err; end module:log("debug", "Successfully connected to database"); dbh:autocommit(false); -- don't commit automatically connection = dbh; end return connection; end do -- process options to get a db connection local ok; prosody.unlock_globals(); ok, DBI = pcall(require, "DBI"); if not ok then package.loaded["DBI"] = {}; module:log("error", "Failed to load the LuaDBI library for accessing SQL databases: %s", DBI); module:log("error", "More information on installing LuaDBI can be found at http://prosody.im/doc/depends#luadbi"); end prosody.lock_globals(); if not ok or not DBI.Connect then return; -- Halt loading of this module end params = params or { driver = "SQLite3" }; if params.driver == "SQLite3" then params.database = resolve_relative_path(prosody.paths.data or ".", params.database or "prosody.sqlite"); end assert(params.driver and params.database, "Both the SQL driver and the database need to be specified"); assert(connect()); end function getsql(sql, ...) if params.driver == "PostgreSQL" then sql = sql:gsub("`", "\""); end -- do prepared statement stuff local stmt, err = connection:prepare(sql); if not stmt and not test_connection() then error("connection failed"); end if not stmt then module:log("error", "QUERY FAILED: %s %s", err, debug.traceback()); return nil, err; end -- run query local ok, err = stmt:execute(...); if not ok and not test_connection() then error("connection failed"); end if not ok then return nil, err; end return stmt; end function setsql(sql, ...) local stmt, err = getsql(sql, ...); if not stmt then return stmt, err; end return stmt:affected(); end function sql.rollback(...) if connection then connection:rollback(); end -- FIXME check for rollback error? return ...; end function sql.commit(...) local ok, err = connection:commit(); if not ok then module:log("error", "SQL commit failed: %s", tostring(err)); return nil, "SQL commit failed: "..tostring(err); end return ...; end end -- Handle messages local function message_handler(event, c2s) local origin, stanza = event.origin, event.stanza; local orig_type = stanza.attr.type or "normal"; local orig_to = stanza.attr.to; local orig_from = stanza.attr.from; if not orig_from and c2s then orig_from = origin.full_jid; end orig_to = orig_to or orig_from; -- Weird corner cases -- Don't store messages of these types if orig_type == "error" or orig_type == "headline" or orig_type == "groupchat" or not stanza:get_child("body") then return; -- TODO Maybe headlines should be configurable? end local store_user, store_host = jid_split(c2s and orig_from or orig_to); local target_jid = c2s and orig_to or orig_from; local target_bare = jid_bare(target_jid); local _, _, target_resource = jid_split(target_jid); --local id = uuid(); local when = time_now(); -- And stash it local ok, err = setsql([[ INSERT INTO `]]..table_name..[[` (`host`, `user`, `store`, `when`, `with`, `resource`, `stanza`) VALUES (?, ?, ?, ?, ?, ?, ?); ]], store_host, store_user, "message_log", when, target_bare, target_resource, serialize(st.preserialize(stanza))) if ok then sql.commit(); else module:log("error", "SQL error: %s", err); sql.rollback(); end end local function c2s_message_handler(event) return message_handler(event, true); end -- Stanzas sent by local clients module:hook("pre-message/bare", c2s_message_handler, 2); module:hook("pre-message/full", c2s_message_handler, 2); -- Stanszas to local clients module:hook("message/bare", message_handler, 2); module:hook("message/full", message_handler, 2); -- In the telnet console, run: -- >hosts["this host"].modules.mam_sql.environment.create_sql() function create_sql() local stm = assert(getsql([[ CREATE TABLE `]]..table_name..[[` ( `host` TEXT, `user` TEXT, `store` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT, `when` INTEGER, `with` TEXT, `resource` TEXT, `stanza` TEXT ); CREATE INDEX `hus` ON `]]..table_name..[[` (`host`, `user`, `store`); CREATE INDEX `with` ON `]]..table_name..[[` (`with`); CREATE INDEX `thetime` ON `]]..table_name..[[` (`when`); ]])); stm:execute(); sql.commit(); end
