Compare commits

...

9 Commits

Author SHA1 Message Date
Paweł Chmielowski 73bcabd2fa Replace muc.example.com with conference.example.com in commands docs
Second form matches what we use by default, and we seen some confusion
between those two when people try to adopt commands from docs to real
usage.
2024-04-23 14:33:34 +02:00
Badlop da8c9f3357 rebar.lock: Track it, now that rebar3 uses loose dependency versioning
This is recommended in Rebar3 documentation:
  [Lock files] should always be checked into source control.
  https://rebar3.org/docs/configuration/dependencies/#lock-files
2024-04-23 13:46:21 +02:00
Badlop 6cfef4f476 mix.lock: Update to latest versions 2024-04-22 18:28:34 +02:00
Badlop e9fbfaf536 Update Luerl to 1.2.0 when OTP>=20, simplifies commit a09f222 2024-04-22 18:28:34 +02:00
Badlop 0407c56605 rebar.config: Update deps version to rebar3's relaxed versioning 2024-04-22 18:28:34 +02:00
Badlop 1a63443e02 rebar.config.script: Support relaxed dependency version (#4192)
Instead of adding another element to the tuple, let's reuse the second
element, which was used only by rebar2, and always has ".*" as value.
2024-04-22 18:28:34 +02:00
Badlop 0345f798bd Update p1_acme to git, to support Jose 1.11.10 and Ipv6 support (#4170) 2024-04-22 18:28:34 +02:00
Badlop ee9d4d56a9 Update Jose to the new 1.11.10 for Erlang/OTP > 23 2024-04-22 18:28:34 +02:00
Badlop 44bafa478e New ban commands use private storage to keep ban information (#4201) 2024-04-22 18:28:15 +02:00
9 changed files with 363 additions and 107 deletions

View File

@ -329,6 +329,11 @@ jobs:
sed -i 's|^{deps, \(.*\)|{deps, \1\n {decimal, ".*", {git, "https://github.com/ericmj/decimal", {branch, "main"}}}, |g' rebar.config
cat rebar.config
- name: Unlock Jose dependency on older Erlang
if: matrix.otp < 24
run: |
mix deps.unlock jose
- name: Compile
run: |
./autogen.sh

1
.gitignore vendored
View File

@ -37,7 +37,6 @@
/_build
/database/
/.rebar
/rebar.lock
/log/
Mnesia.nonode@nohost/
# Binaries created with tools/make-{binaries,installers,packages}:

10
mix.exs
View File

@ -138,9 +138,8 @@ defmodule Ejabberd.MixProject do
{:fast_yaml, "~> 1.0"},
{:idna, "~> 6.0"},
{:jiffy, "~> 1.1.1"},
{:jose, "~> 1.11.5"},
{:mqtree, "~> 1.0"},
{:p1_acme, "~> 1.0"},
{:p1_acme, git: "https://github.com/processone/p1_acme", branch: "master"},
{:p1_oauth2, "~> 0.6"},
{:p1_utils, "~> 1.0"},
{:pkix, "~> 1.0"},
@ -168,11 +167,10 @@ defmodule Ejabberd.MixProject do
{config(:redis), {:eredis, "~> 1.2.0"}},
{config(:sip), {:esip, "~> 1.0"}},
{config(:zlib), {:ezlib, "~> 1.0"}},
{if_version_above(~c"23", true), {:jose, "~> 1.11.10"}},
{if_version_below(~c"24", true), {:jose, "1.11.1"}},
{if_version_below(~c"22", true), {:lager, "~> 3.9.1"}},
{config(:lua) and if_version_below(~c"27", true),
{:luerl, "~> 1.1.1"}},
{config(:lua) and if_version_above(~c"26", true),
{:luerl, git: "https://github.com/processone/luerl", branch: "otp27"}},
{config(:lua), {:luerl, "~> 1.2.0"}},
{config(:mysql), {:p1_mysql, ">= 1.0.23" }},
{config(:pgsql), {:p1_pgsql, "~> 1.1"}},
{config(:sqlite), {:sqlite3, "~> 1.1"}},

View File

@ -8,21 +8,21 @@
"eredis": {:hex, :eredis, "1.2.0", "0b8e9cfc2c00fa1374cd107ea63b49be08d933df2cf175e6a89b73dd9c380de4", [:rebar3], [], "hexpm", "d9b5abef2c2c8aba8f32aa018203e0b3dc8b1157773b254ab1d4c2002317f1e1"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"esip": {:hex, :esip, "1.0.52", "a2840287c493a4280e6fba57a257706843b025c315875e38b03fd07190e22dba", [:rebar3], [{:fast_tls, "1.1.19", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.2.12", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm", "6f00165395900500aa262ce0297162d93931c78c1464d89fd0edc6e3d6bc011f"},
"ex_doc": {:hex, :ex_doc, "0.31.2", "8b06d0a5ac69e1a54df35519c951f1f44a7b7ca9a5bb7a260cd8a174d6322ece", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "317346c14febaba9ca40fd97b5b5919f7751fb85d399cc8e7e8872049f37e0af"},
"ex_doc": {:hex, :ex_doc, "0.32.1", "21e40f939515373bcdc9cffe65f3b3543f05015ac6c3d01d991874129d173420", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "5142c9db521f106d61ff33250f779807ed2a88620e472ac95dc7d59c380113da"},
"ezlib": {:hex, :ezlib, "1.0.12", "ffe906ba10d03aaee7977e1e0e81d9ffc3bb8b47fb9cd8e2e453507a2e56221f", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "30e94355fb42260aab6e12582cb0c56bf233515e655c8aeaf48760e7561e4ebb"},
"fast_tls": {:hex, :fast_tls, "1.1.19", "f52731a4b35259fa06cf23e2a0732920ad9efce7c3d68377f129a474998747bb", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "db34322c8782d4c5139ccb80709d8ec8c38089b44262edd0c2f660ac495bd389"},
"fast_xml": {:hex, :fast_xml, "1.1.51", "a7f8c6942591632309099386d5c339c89997ac2bbdd1216f6c196dee6d7828a9", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "7fce41b7d1a4ba438a2d7a088dabe74a3ca0739f1af2abcb77e62daf43e0409a"},
"fast_yaml": {:hex, :fast_yaml, "1.0.36", "65413a34a570fd4e205a460ba602e4ee7a682f35c22d2e1c839025dbf515105c", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "1abe8f758fc2a86b08edff80bbc687cfd41ebc1412cfec0ef4a0acfcd032052f"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "4bdd305eb64e18b0273864920695cb18d7a2021f31a11b9c5fbcd9a253f936e2"},
"jiffy": {:hex, :jiffy, "1.1.1", "aca10f47aa91697bf24ab9582c74e00e8e95474c7ef9f76d4f1a338d0f5de21b", [:rebar3], [], "hexpm", "62e1f0581c3c19c33a725c781dfa88410d8bff1bbafc3885a2552286b4785c4c"},
"jose": {:hex, :jose, "1.11.5", "3bc2d75ffa5e2c941ca93e5696b54978323191988eb8d225c2e663ddfefd515e", [:mix, :rebar3], [], "hexpm", "dcd3b215bafe02ea7c5b23dafd3eb8062a5cd8f2d904fd9caa323d37034ab384"},
"luerl": {:hex, :luerl, "1.1.1", "083518e437586f6631150d39c4bff242ed2ec80cb14a3299a0c2628f07a2ff7f", [:rebar3], [], "hexpm", "e17ef246a7ff876ec90e68792a39708979416004d4eacfe8a7643206b9470773"},
"jose": {:hex, :jose, "1.11.10", "a903f5227417bd2a08c8a00a0cbcc458118be84480955e8d251297a425723f83", [:mix, :rebar3], [], "hexpm", "0d6cd36ff8ba174db29148fc112b5842186b68a90ce9fc2b3ec3afe76593e614"},
"luerl": {:hex, :luerl, "1.2.0", "60f05f4240f0e7c148ddb79b67b8ff972734aad237aa74c83d0748b8214c8ef0", [:rebar3], [], "hexpm", "9cafd4f6094ff0f5a9d278fd81d60d3e026c820bdfb6cacd4b1bd909f21b525d"},
"makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.5", "e0ff5a7c708dda34311f7522a8758e23bfcd7d8d8068dc312b5eb41c6fd76eba", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "94d2e986428585a21516d7d7149781480013c56e30c6a233534bedf38867a59a"},
"mqtree": {:hex, :mqtree, "1.0.16", "f8f8b4971e4ca94313ba9bcaaa1aa1077daaba5e3fd3468ffb491420a4cc3593", [:rebar3], [{:p1_utils, "1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "c87d1c95575db65af29b795c9daa3bed43f5c1bf84072a74469659bcf53594eb"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
"p1_acme": {:hex, :p1_acme, "1.0.22", "b40a8031ef0f4592e97e6a8e08e53dbd31a2198cb8377b249f0caea4f8025a1d", [:rebar3], [{:base64url, "1.0.1", [hex: :base64url, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jiffy, "1.1.1", [hex: :jiffy, repo: "hexpm", optional: false]}, {:jose, "1.11.5", [hex: :jose, repo: "hexpm", optional: false]}, {:yconf, "1.0.15", [hex: :yconf, repo: "hexpm", optional: false]}], "hexpm", "c2b25a7b295a435dac4f278a73d8417ff2b0020c45e1683504e8692ef03e2057"},
"p1_acme": {:git, "https://github.com/processone/p1_acme", "2d049fa25d66f97a08b58ba8e07a751ed60ff9c4", [branch: "master"]},
"p1_mysql": {:hex, :p1_mysql, "1.0.23", "9b4e98f1f01e2cc4a759f611f0f015365e65c5f61ea453aa4bdfe950d20a5f11", [:rebar3], [], "hexpm", "9cef98265fb287374e7b64bf4022c4df5ec66196ca31cf4bed73c67c45bf824e"},
"p1_oauth2": {:hex, :p1_oauth2, "0.6.14", "1c5f82535574de87e2059695ac4b91f8f9aebacbc1c80287dae6f02552d47aea", [:rebar3], [], "hexpm", "1fd3ac474e43722d9d5a87c6df8d36f698ed87af7bb81cbbb66361451d99ae8f"},
"p1_pgsql": {:hex, :p1_pgsql, "1.1.25", "f59b7faa457fadf0c2713ac335202f41ca1b06b7c4926925b3cb0bc6f0578601", [:rebar3], [{:xmpp, "1.8.1", [hex: :xmpp, repo: "hexpm", optional: false]}], "hexpm", "b654c1e07d3e775b626b407e7696cacfd88d17be83e7168b9d89c3832d913de7"},

View File

@ -24,71 +24,54 @@
{deps, [{if_not_rebar3,
{if_version_below, "24",
{base64url, ".*", {git, "https://github.com/dvv/base64url", {tag, "1.0.1"}}}
{base64url, "~> 1.0", {git, "https://github.com/dvv/base64url", {tag, "1.0.1"}}}
}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.30"}}},
{eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.22"}}},
{cache_tab, "~> 1.0.30", {git, "https://github.com/processone/cache_tab", {tag, "1.0.30"}}},
{eimp, "~> 1.0.22", {git, "https://github.com/processone/eimp", {tag, "1.0.22"}}},
{if_var_true, pam,
{epam, ".*", {git, "https://github.com/processone/epam", {tag, "1.0.14"}}}},
{epam, "~> 1.0.14", {git, "https://github.com/processone/epam", {tag, "1.0.14"}}}},
{if_var_true, redis,
{eredis, ".*", {git, "https://github.com/wooga/eredis", {tag, "v1.2.0"}}}},
{eredis, "~> 1.2.0", {git, "https://github.com/wooga/eredis", {tag, "v1.2.0"}}}},
{if_var_true, sip,
{esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.52"}}}},
{esip, "~> 1.0.52", {git, "https://github.com/processone/esip", {tag, "1.0.52"}}}},
{if_var_true, zlib,
{ezlib, ".*", {git, "https://github.com/processone/ezlib", {tag, "1.0.12"}}}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.1.19"}}},
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.51"}}},
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.36"}}},
{idna, ".*", {git, "https://github.com/benoitc/erlang-idna", {tag, "6.0.0"}}},
{ezlib, "~> 1.0.12", {git, "https://github.com/processone/ezlib", {tag, "1.0.12"}}}},
{fast_tls, "~> 1.1.19", {git, "https://github.com/processone/fast_tls", {tag, "1.1.19"}}},
{fast_xml, "~> 1.1.51", {git, "https://github.com/processone/fast_xml", {tag, "1.1.51"}}},
{fast_yaml, "~> 1.0.36", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.36"}}},
{idna, "~> 6.0", {git, "https://github.com/benoitc/erlang-idna", {tag, "6.0.0"}}},
{if_version_above, "19",
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "1.1.1"}}},
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "1.1.0"}}} % for R19 and below
{jiffy, "~> 1.1.1", {git, "https://github.com/davisp/jiffy", {tag, "1.1.1"}}},
{jiffy, "1.1.0", {git, "https://github.com/davisp/jiffy", {tag, "1.1.0"}}} % for R19 and below
},
{if_version_above, "20",
{jose, ".*", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.11.5"}}},
{jose, ".*", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.11.1"}}}
{if_version_above, "23",
{jose, "~> 1.11.10", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.11.10"}}},
{jose, "1.11.1", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.11.1"}}}
},
{if_version_below, "22",
{lager, ".*", {git, "https://github.com/erlang-lager/lager", {tag, "3.9.1"}}}
{lager, "~> 3.9.1", {git, "https://github.com/erlang-lager/lager", {tag, "3.9.1"}}}
},
%% Lua, rebar, OTP 20: 1.0 git tag
{if_var_true, lua,
{if_not_rebar3,
{if_version_below, "21",
{luerl, ".*", {git, "https://github.com/rvirding/luerl", {tag, "1.0"}}}
}}},
%% Lua, rebar3, OTP 20: 1.0.0 hex package
{if_var_true, lua,
{if_rebar3,
{if_version_below, "21",
{luerl, ".*", {git, "https://github.com/rvirding/luerl", {tag, "1.0.0"}}}
}}},
%% Lua, any rebar, OTP 21-26: 1.1.1 git tag / 1.1.1 hex package
{if_var_true, lua,
{if_version_above, "20", {if_version_below, "27",
{luerl, ".*", {git, "https://github.com/rvirding/luerl", {tag, "1.1.1"}}}
}}},
%% Lua, any rebar, OTP 27: temporary otp27 branch from fork
{if_var_true, lua,
{if_version_above, "26",
{luerl, ".*", {git, "https://github.com/processone/luerl", {branch, "otp27"}}}
{if_version_below, "21",
{luerl, "1.0.0", {git, "https://github.com/rvirding/luerl", {tag, "1.0"}}},
{luerl, "~> 1.2.0", {git, "https://github.com/rvirding/luerl", {tag, "1.2"}}}
}},
{mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.16"}}},
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme", {tag, "1.0.22"}}},
{mqtree, "~> 1.0.16", {git, "https://github.com/processone/mqtree", {tag, "1.0.16"}}},
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme", {branch, "master"}}},
{if_var_true, mysql,
{p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", {tag, "1.0.23"}}}},
{p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.14"}}},
{p1_oauth2, "~> 0.6.14", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.14"}}},
{if_var_true, pgsql,
{p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", {tag, "1.1.25"}}}},
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.25"}}},
{pkix, ".*", {git, "https://github.com/processone/pkix", {tag, "1.0.9"}}},
{p1_pgsql, "~> 1.1.15", {git, "https://github.com/processone/p1_pgsql", {tag, "1.1.25"}}}},
{p1_utils, "~> 1.0.25", {git, "https://github.com/processone/p1_utils", {tag, "1.0.25"}}},
{pkix, "~> 1.0.9", {git, "https://github.com/processone/pkix", {tag, "1.0.9"}}},
{if_var_true, sqlite,
{sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3", {tag, "1.1.14"}}}},
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.29"}}},
{sqlite3, "~> 1.1.14", {git, "https://github.com/processone/erlang-sqlite3", {tag, "1.1.14"}}}},
{stringprep, "~> 1.0.29", {git, "https://github.com/processone/stringprep", {tag, "1.0.29"}}},
{if_var_true, stun,
{stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.2.12"}}}},
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.8.1"}}},
{yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.15"}}}
{stun, "~> 1.2.12", {git, "https://github.com/processone/stun", {tag, "1.2.12"}}}},
{xmpp, "~> 1.8.1", {git, "https://github.com/processone/xmpp", {tag, "1.8.1"}}},
{yconf, "~> 1.0.15", {git, "https://github.com/processone/yconf", {tag, "1.0.15"}}}
]}.
{gitonly_deps, [ejabberd_po]}.

View File

@ -219,20 +219,35 @@ AppendList2 = fun(Append) ->
end
end,
Rebar3DepsFilter =
% Convert our rich deps syntax to rebar2 format:
% https://github.com/rebar/rebar/wiki/Dependency-management
Rebar2DepsFilter =
fun(DepsList, GitOnlyDeps) ->
lists:map(fun({DepName, _, {git, _, {tag, Version}}} = Dep) ->
case lists:member(DepName, GitOnlyDeps) of
true ->
Dep;
_ ->
{DepName, Version}
end;
(Dep) ->
Dep
lists:map(fun({DepName, _HexVersion, Source}) ->
{DepName, ".*", Source}
end, DepsList)
end,
% Convert our rich deps syntax to rebar3 version definition format:
% https://rebar3.org/docs/configuration/dependencies/#dependency-version-handling
% https://hexdocs.pm/elixir/Version.html
Rebar3DepsFilter =
fun(DepsList, GitOnlyDeps) ->
lists:map(fun({DepName, HexVersion, {git, _, {tag, GitVersion}} = Source}) ->
case {lists:member(DepName, GitOnlyDeps), HexVersion == ".*"} of
{true, _} ->
{DepName, ".*", Source};
{false, true} ->
{DepName, GitVersion};
{false, false} ->
{DepName, HexVersion}
end;
({DepName, _HexVersion, Source}) ->
{DepName, ".*", Source}
end, DepsList)
end,
DepAlts = fun("esip") -> ["esip", "p1_sip"];
("xmpp") -> ["xmpp", "p1_xmpp"];
("fast_xml") -> ["fast_xml", "p1_xml"];
@ -423,6 +438,8 @@ Rules = [
ProcessRelx, [], []},
{[deps], [floating_deps], true,
ProcessFloatingDeps, [], []},
{[deps], [gitonly_deps], (not IsRebar3),
Rebar2DepsFilter, [], []},
{[deps], [gitonly_deps], IsRebar3,
Rebar3DepsFilter, [], []},
{[deps], SystemDeps /= false,

87
rebar.lock Normal file
View File

@ -0,0 +1,87 @@
{"1.2.0",
[{<<"base64url">>,{pkg,<<"base64url">>,<<"1.0.1">>},1},
{<<"cache_tab">>,{pkg,<<"cache_tab">>,<<"1.0.30">>},0},
{<<"eimp">>,{pkg,<<"eimp">>,<<"1.0.22">>},0},
{<<"epam">>,{pkg,<<"epam">>,<<"1.0.14">>},0},
{<<"eredis">>,{pkg,<<"eredis">>,<<"1.2.0">>},0},
{<<"esip">>,{pkg,<<"esip">>,<<"1.0.52">>},0},
{<<"ezlib">>,{pkg,<<"ezlib">>,<<"1.0.12">>},0},
{<<"fast_tls">>,{pkg,<<"fast_tls">>,<<"1.1.19">>},0},
{<<"fast_xml">>,{pkg,<<"fast_xml">>,<<"1.1.51">>},0},
{<<"fast_yaml">>,{pkg,<<"fast_yaml">>,<<"1.0.36">>},0},
{<<"idna">>,{pkg,<<"idna">>,<<"6.1.1">>},0},
{<<"jiffy">>,{pkg,<<"jiffy">>,<<"1.1.1">>},0},
{<<"jose">>,{pkg,<<"jose">>,<<"1.11.10">>},0},
{<<"luerl">>,{pkg,<<"luerl">>,<<"1.2.0">>},0},
{<<"mqtree">>,{pkg,<<"mqtree">>,<<"1.0.16">>},0},
{<<"p1_acme">>,
{git,"https://github.com/processone/p1_acme",
{ref,"b4d0900eabb208c493ae3958bc545151bb19b90e"}},
0},
{<<"p1_mysql">>,{pkg,<<"p1_mysql">>,<<"1.0.23">>},0},
{<<"p1_oauth2">>,{pkg,<<"p1_oauth2">>,<<"0.6.14">>},0},
{<<"p1_pgsql">>,{pkg,<<"p1_pgsql">>,<<"1.1.25">>},0},
{<<"p1_utils">>,{pkg,<<"p1_utils">>,<<"1.0.25">>},0},
{<<"pkix">>,{pkg,<<"pkix">>,<<"1.0.9">>},0},
{<<"sqlite3">>,{pkg,<<"sqlite3">>,<<"1.1.14">>},0},
{<<"stringprep">>,{pkg,<<"stringprep">>,<<"1.0.29">>},0},
{<<"stun">>,{pkg,<<"stun">>,<<"1.2.12">>},0},
{<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},1},
{<<"xmpp">>,{pkg,<<"xmpp">>,<<"1.8.1">>},0},
{<<"yconf">>,{pkg,<<"yconf">>,<<"1.0.15">>},0}]}.
[
{pkg_hash,[
{<<"base64url">>, <<"F8C7F2DA04CA9A5D0F5F50258F055E1D699F0E8BF4CFDB30B750865368403CF6">>},
{<<"cache_tab">>, <<"6D35EECFB65FBE5FC85988503A27338D32DE01243F3FC8EA3EE7161AF08725A4">>},
{<<"eimp">>, <<"FA9B376EF0B50E8455DB15C7C11DEA4522C6902E04412288AAB436D26335F6EB">>},
{<<"epam">>, <<"AA0B85D27F4EF3A756AE995179DF952A0721237E83C6B79D644347B75016681A">>},
{<<"eredis">>, <<"0B8E9CFC2C00FA1374CD107EA63B49BE08D933DF2CF175E6A89B73DD9C380DE4">>},
{<<"esip">>, <<"A2840287C493A4280E6FBA57A257706843B025C315875E38B03FD07190E22DBA">>},
{<<"ezlib">>, <<"FFE906BA10D03AAEE7977E1E0E81D9FFC3BB8B47FB9CD8E2E453507A2E56221F">>},
{<<"fast_tls">>, <<"F52731A4B35259FA06CF23E2A0732920AD9EFCE7C3D68377F129A474998747BB">>},
{<<"fast_xml">>, <<"A7F8C6942591632309099386D5C339C89997AC2BBDD1216F6C196DEE6D7828A9">>},
{<<"fast_yaml">>, <<"65413A34A570FD4E205A460BA602E4EE7A682F35C22D2E1C839025DBF515105C">>},
{<<"idna">>, <<"8A63070E9F7D0C62EB9D9FCB360A7DE382448200FBBD1B106CC96D3D8099DF8D">>},
{<<"jiffy">>, <<"ACA10F47AA91697BF24AB9582C74E00E8E95474C7EF9F76D4F1A338D0F5DE21B">>},
{<<"jose">>, <<"A903F5227417BD2A08C8A00A0CBCC458118BE84480955E8D251297A425723F83">>},
{<<"luerl">>, <<"60F05F4240F0E7C148DDB79B67B8FF972734AAD237AA74C83D0748B8214C8EF0">>},
{<<"mqtree">>, <<"F8F8B4971E4CA94313BA9BCAAA1AA1077DAABA5E3FD3468FFB491420A4CC3593">>},
{<<"p1_mysql">>, <<"9B4E98F1F01E2CC4A759F611F0F015365E65C5F61EA453AA4BDFE950D20A5F11">>},
{<<"p1_oauth2">>, <<"1C5F82535574DE87E2059695AC4B91F8F9AEBACBC1C80287DAE6F02552D47AEA">>},
{<<"p1_pgsql">>, <<"F59B7FAA457FADF0C2713AC335202F41CA1B06B7C4926925B3CB0BC6F0578601">>},
{<<"p1_utils">>, <<"2D39B5015A567BBD2CC7033EEB93A7C60D8C84EFE1EF69A3473FAA07FA268187">>},
{<<"pkix">>, <<"EB20B2715D71A23B4FE7E754DAE9281A964B51113D0BBA8ADF9DA72BF9D65AC2">>},
{<<"sqlite3">>, <<"F9EA0CFF8540865FDFDB7E24EEF34DC46677364B1C070896E99B5BF08C8A7FD7">>},
{<<"stringprep">>, <<"02F23E8C3A219A3DFE40A22E908BECE3A2F68AF0FF599EA8A7B714ECB21E62EE">>},
{<<"stun">>, <<"A65DF67A8AAAECB6A94D687977B2E9F161820819910CB97BBE26A3525356525B">>},
{<<"unicode_util_compat">>, <<"BC84380C9AB48177092F43AC89E4DFA2C6D62B40B8BD132B1059ECC7232F9A78">>},
{<<"xmpp">>, <<"134A350DBC6E2E99512FB38669191C1D1C134B3B6836F4C6740801882AFA650A">>},
{<<"yconf">>, <<"E22998B3D7728270BDD06162A9515BD142B14FAE8927CBDBD3EF639C32AA6F7A">>}]},
{pkg_hash_ext,[
{<<"base64url">>, <<"F9B3ADD4731A02A9B0410398B475B33E7566A695365237A6BDEE1BB447719F5C">>},
{<<"cache_tab">>, <<"6D8A5E00D8F84C42627706A6DBEDB02E34D58495F3ED61935C8475CA0531CDA0">>},
{<<"eimp">>, <<"B3B9FFB1D9A5F4A2BA88AC418A819164932D9A9D3A2FC3D32CA338CE855C4392">>},
{<<"epam">>, <<"2F3449E72885A72A6C2A843F561ADD0FC2F70D7A21F61456930A547473D4D989">>},
{<<"eredis">>, <<"D9B5ABEF2C2C8ABA8F32AA018203E0B3DC8B1157773B254AB1D4C2002317F1E1">>},
{<<"esip">>, <<"6F00165395900500AA262CE0297162D93931C78C1464D89FD0EDC6E3D6BC011F">>},
{<<"ezlib">>, <<"30E94355FB42260AAB6E12582CB0C56BF233515E655C8AEAF48760E7561E4EBB">>},
{<<"fast_tls">>, <<"DB34322C8782D4C5139CCB80709D8EC8C38089B44262EDD0C2F660AC495BD389">>},
{<<"fast_xml">>, <<"7FCE41B7D1A4BA438A2D7A088DABE74A3CA0739F1AF2ABCB77E62DAF43E0409A">>},
{<<"fast_yaml">>, <<"1ABE8F758FC2A86B08EDFF80BBC687CFD41EBC1412CFEC0EF4A0ACFCD032052F">>},
{<<"idna">>, <<"92376EB7894412ED19AC475E4A86F7B413C1B9FBB5BD16DCCD57934157944CEA">>},
{<<"jiffy">>, <<"62E1F0581C3C19C33A725C781DFA88410D8BFF1BBAFC3885A2552286B4785C4C">>},
{<<"jose">>, <<"0D6CD36FF8BA174DB29148FC112B5842186B68A90CE9FC2B3EC3AFE76593E614">>},
{<<"luerl">>, <<"9CAFD4F6094FF0F5A9D278FD81D60D3E026C820BDFB6CACD4B1BD909F21B525D">>},
{<<"mqtree">>, <<"C87D1C95575DB65AF29B795C9DAA3BED43F5C1BF84072A74469659BCF53594EB">>},
{<<"p1_mysql">>, <<"9CEF98265FB287374E7B64BF4022C4DF5EC66196CA31CF4BED73C67C45BF824E">>},
{<<"p1_oauth2">>, <<"1FD3AC474E43722D9D5A87C6DF8D36F698ED87AF7BB81CBBB66361451D99AE8F">>},
{<<"p1_pgsql">>, <<"B654C1E07D3E775B626B407E7696CACFD88D17BE83E7168B9D89C3832D913DE7">>},
{<<"p1_utils">>, <<"9219214428F2C6E5D3187FF8EB9A8783695C2427420BE9A259840E07ADA32847">>},
{<<"pkix">>, <<"DAAB2C09CDD4EDA05C9B45A5C00E994A1A5F27634929E1377E2E59B707103E3A">>},
{<<"sqlite3">>, <<"85054B6CA297343C159ED6794A473FF2C8EEABD854B6FE02F711C0BFD373CE86">>},
{<<"stringprep">>, <<"928EBA304C3006EB1512110EBD7B87DB163B00859A09375A1E4466152C6C462A">>},
{<<"stun">>, <<"A2055032B6D338D0454142004BCB12FAFB0C64AB1F273F1D0C6923EBBC8EDE40">>},
{<<"unicode_util_compat">>, <<"25EEE6D67DF61960CF6A794239566599B09E17E668D3700247BC498638152521">>},
{<<"xmpp">>, <<"32D4A308A6613E4E4155FA4E82ECCDC8833096D0FA8D99C8D428C800611E59D3">>},
{<<"yconf">>, <<"7FF2AB24D3C9833842716B9AAAA01A8F96641A7695CBB701B03445C4DEF01117">>}]}
].

View File

@ -49,7 +49,8 @@
% Accounts
set_password/3, check_password_hash/4, delete_old_users/1,
delete_old_users_vhost/2, ban_account/3, check_password/3,
delete_old_users_vhost/2, check_password/3,
ban_account/3, ban_account_v2/3, get_ban_details/2, unban_account/2,
% vCard
set_nickname/3, get_vcard/3,
@ -85,6 +86,7 @@
-include("mod_roster.hrl").
-include("mod_privacy.hrl").
-include("ejabberd_sm.hrl").
-include_lib("xmpp/include/scram.hrl").
-include_lib("xmpp/include/xmpp.hrl").
%%%
@ -236,8 +238,10 @@ get_commands_spec() ->
"New password for user"],
result = {res, rescode},
result_example = ok},
#ejabberd_commands{name = ban_account, tags = [accounts],
desc = "Ban an account: kick sessions and set random password",
longdesc = "This simply sets a random password.",
module = ?MODULE, function = ban_account,
args = [{user, binary}, {host, binary}, {reason, binary}],
args_example = [<<"attacker">>, <<"myserver.com">>, <<"Spaming other users">>],
@ -245,6 +249,53 @@ get_commands_spec() ->
"Reason for banning user"],
result = {res, rescode},
result_example = ok},
#ejabberd_commands{name = ban_account, tags = [accounts],
desc = "Ban an account",
longdesc = "This command kicks the account sessions, "
"sets a random password, and stores ban details in the "
"account private storage. "
"This command requires mod_private to be enabled. "
"Check also _`get_ban_details`_ API "
"and `_unban_account`_ API.",
module = ?MODULE, function = ban_account_v2,
version = 2,
note = "improved in 24.xx",
args = [{user, binary}, {host, binary}, {reason, binary}],
args_example = [<<"attacker">>, <<"myserver.com">>, <<"Spaming other users">>],
args_desc = ["User name to ban", "Server name",
"Reason for banning user"],
result = {res, rescode},
result_example = ok},
#ejabberd_commands{name = get_ban_details, tags = [accounts],
desc = "Get ban details about an account",
longdesc = "Check _`ban_account`_ API.",
module = ?MODULE, function = get_ban_details,
version = 2,
note = "added in 24.xx",
args = [{user, binary}, {host, binary}],
args_example = [<<"attacker">>, <<"myserver.com">>],
args_desc = ["User name to unban", "Server name"],
result = {ban_details, {list,
{detail, {tuple, [{name, string},
{value, string}
]}}
}},
result_example = [{"reason", "Spamming other users"},
{"bandate", "2024-04-22T09:16:47.975312Z"},
{"lastdate", "2024-04-22T08:39:12Z"},
{"lastreason", "Connection reset by peer"}]},
#ejabberd_commands{name = unban_account, tags = [accounts],
desc = "Revert the ban from an account: set back the old password",
longdesc = "Check _`ban_account`_ API.",
module = ?MODULE, function = unban_account,
version = 2,
note = "added in 24.xx",
args = [{user, binary}, {host, binary}],
args_example = [<<"gooduser">>, <<"myserver.com">>],
args_desc = ["User name to unban", "Server name"],
result = {res, rescode},
result_example = ok},
#ejabberd_commands{name = num_resources, tags = [session],
desc = "Get the number of resources of a user",
module = ?MODULE, function = num_resources,
@ -905,7 +956,7 @@ set_password(User, Host, Password) ->
check_password(User, Host, Password) ->
ejabberd_auth:check_password(User, <<>>, Host, Password).
%% Copied some code from ejabberd_commands.erl
%% Copied some code from ejabberd_commands.erln
check_password_hash(User, Host, PasswordHash, HashMethod) ->
AccountPass = ejabberd_auth:get_password_s(User, Host),
Methods = lists:map(fun(A) -> atom_to_binary(A, latin1) end,
@ -978,7 +1029,7 @@ delete_or_not(LUser, LServer, TimeStamp_oldest) ->
end.
%%
%% Ban account
%% Ban account v0
ban_account(User, Host, ReasonText) ->
Reason = prepare_reason(ReasonText),
@ -1014,6 +1065,119 @@ prepare_reason([Reason]) ->
prepare_reason(Reason) when is_binary(Reason) ->
Reason.
%%
%% Ban account v2
ban_account_v2(User, Host, ReasonText) ->
case is_banned(User, Host) of
true ->
account_was_already_banned;
false ->
ban_account_v2_b(User, Host, ReasonText)
end.
ban_account_v2_b(User, Host, ReasonText) ->
Reason = prepare_reason(ReasonText),
Pass = ejabberd_auth:get_password_s(User, Host),
Last = get_last(User, Host),
BanDate = xmpp_util:encode_timestamp(erlang:timestamp()),
BanPrivateXml = build_ban_xmlel(Reason, Pass, Last, BanDate),
ok = private_set2(User, Host, BanPrivateXml),
ok = set_random_password_v2(User, Host),
kick_sessions(User, Host, Reason),
ok.
set_random_password_v2(User, Server) ->
NewPass = p1_rand:get_string(),
ok = ejabberd_auth:set_password(User, Server, NewPass).
build_ban_xmlel(Reason, Pass, {LastDate, LastReason}, BanDate) ->
PassEls = build_pass_els(Pass),
#xmlel{name = <<"banned">>,
attrs = [{<<"xmlns">>, <<"ejabberd:banned">>}],
children = [#xmlel{name = <<"reason">>, attrs = [], children = [{xmlcdata, Reason}]},
#xmlel{name = <<"password">>, attrs = [], children = PassEls},
#xmlel{name = <<"lastdate">>, attrs = [], children = [{xmlcdata, LastDate}]},
#xmlel{name = <<"lastreason">>, attrs = [], children = [{xmlcdata, LastReason}]},
#xmlel{name = <<"bandate">>, attrs = [], children = [{xmlcdata, BanDate}]}
]}.
build_pass_els(Pass) when is_binary(Pass) ->
[{xmlcdata, Pass}];
build_pass_els(#scram{storedkey = StoredKey,
serverkey = ServerKey,
salt = Salt,
hash = Hash,
iterationcount = IterationCount}) ->
[#xmlel{name = <<"storedkey">>, attrs = [], children = [{xmlcdata, StoredKey}]},
#xmlel{name = <<"serverkey">>, attrs = [], children = [{xmlcdata, ServerKey}]},
#xmlel{name = <<"salt">>, attrs = [], children = [{xmlcdata, Salt}]},
#xmlel{name = <<"hash">>, attrs = [], children = [{xmlcdata, misc:atom_to_binary(Hash)}]},
#xmlel{name = <<"iterationcount">>, attrs = [], children = [{xmlcdata, integer_to_binary(IterationCount)}]}
].
%%
%% Get ban details
get_ban_details(User, Host) ->
[El] = private_get2(User, Host, <<"banned">>, <<"ejabberd:banned">>),
Reason = fxml:get_subtag_cdata(El, <<"reason">>),
LastDate = fxml:get_subtag_cdata(El, <<"lastdate">>),
LastReason = fxml:get_subtag_cdata(El, <<"lastreason">>),
BanDate = fxml:get_subtag_cdata(El, <<"bandate">>),
[{"reason", Reason},
{"bandate", BanDate},
{"lastdate", LastDate},
{"lastreason", LastReason}
].
is_banned(User, Host) ->
case lists:keyfind("bandate", 1, get_ban_details(User, Host)) of
{_, BanDate} when BanDate /= <<>> ->
true;
_ ->
false
end.
%%
%% Unban account
unban_account(User, Host) ->
case is_banned(User, Host) of
false ->
account_was_not_banned;
true ->
unban_account2(User, Host)
end.
unban_account2(User, Host) ->
OldPass = get_oldpass(User, Host),
ok = ejabberd_auth:set_password(User, Host, OldPass),
UnBanPrivateXml = build_unban_xmlel(),
private_set2(User, Host, UnBanPrivateXml).
get_oldpass(User, Host) ->
[El] = private_get2(User, Host, <<"banned">>, <<"ejabberd:banned">>),
Pass = fxml:get_subtag(El, <<"password">>),
get_pass(Pass).
get_pass(#xmlel{children = [{xmlcdata, Pass}]}) ->
Pass;
get_pass(#xmlel{children = ScramEls} = Pass) when is_list(ScramEls) ->
StoredKey = fxml:get_subtag_cdata(Pass, <<"storedkey">>),
ServerKey = fxml:get_subtag_cdata(Pass, <<"serverkey">>),
Salt = fxml:get_subtag_cdata(Pass, <<"salt">>),
Hash = fxml:get_subtag_cdata(Pass, <<"hash">>),
IterationCount = fxml:get_subtag_cdata(Pass, <<"iterationcount">>),
#scram{storedkey = StoredKey,
serverkey = ServerKey,
salt = Salt,
hash = binary_to_existing_atom(Hash, latin1),
iterationcount = binary_to_integer(IterationCount)}.
build_unban_xmlel() ->
#xmlel{name = <<"banned">>, attrs = [{<<"xmlns">>, <<"ejabberd:banned">>}]}.
%%%
%%% Sessions
%%%
@ -1515,11 +1679,14 @@ set_last(User, Server, Timestamp, Status) ->
%% <aa xmlns='bb'>Cluth</aa>
private_get(Username, Host, Element, Ns) ->
ElementXml = #xmlel{name = Element, attrs = [{<<"xmlns">>, Ns}]},
Els = mod_private:get_data(jid:nodeprep(Username), jid:nameprep(Host),
[{Ns, ElementXml}]),
Els = private_get2(Username, Host, Element, Ns),
binary_to_list(fxml:element_to_binary(xmpp:encode(#private{sub_els = Els}))).
private_get2(Username, Host, Element, Ns) ->
ElementXml = #xmlel{name = Element, attrs = [{<<"xmlns">>, Ns}]},
mod_private:get_data(jid:nodeprep(Username), jid:nameprep(Host),
[{Ns, ElementXml}]).
private_set(Username, Host, ElementString) ->
case fxml_stream:parse_element(ElementString) of
{error, Error} ->

View File

@ -98,9 +98,9 @@ get_commands_spec() ->
policy = admin,
module = ?MODULE, function = muc_online_rooms,
args_desc = ["MUC service, or `global` for all"],
args_example = ["muc.example.com"],
args_example = ["conference.example.com"],
result_desc = "List of rooms",
result_example = ["room1@muc.example.com", "room2@muc.example.com"],
result_example = ["room1@conference.example.com", "room2@conference.example.com"],
args = [{service, binary}],
args_rename = [{host, service}],
result = {rooms, {list, {room, string}}}},
@ -110,11 +110,11 @@ get_commands_spec() ->
policy = admin,
module = ?MODULE, function = muc_online_rooms_by_regex,
args_desc = ["MUC service, or `global` for all",
"Regex pattern for room name"],
args_example = ["muc.example.com", "^prefix"],
"Regex pattern for room name"],
args_example = ["conference.example.com", "^prefix"],
result_desc = "List of rooms with summary",
result_example = [{"room1@muc.example.com", "true", 10},
{"room2@muc.example.com", "false", 10}],
result_example = [{"room1@conference.example.com", "true", 10},
{"room2@conference.example.com", "false", 10}],
args = [{service, binary}, {regex, binary}],
args_rename = [{host, service}],
result = {rooms, {list, {room, {tuple,
@ -126,7 +126,7 @@ get_commands_spec() ->
desc = "Register a nick to a User JID in a MUC service",
module = ?MODULE, function = muc_register_nick,
args_desc = ["Nick", "User JID", "Service"],
args_example = [<<"Tim">>, <<"tim@example.org">>, <<"muc.example.org">>],
args_example = [<<"Tim">>, <<"tim@example.org">>, <<"conference.example.org">>],
args = [{nick, binary}, {jid, binary}, {service, binary}],
args_rename = [{host, service}],
result = {res, rescode}},
@ -134,7 +134,7 @@ get_commands_spec() ->
desc = "Unregister the nick registered by that account in the MUC service",
module = ?MODULE, function = muc_unregister_nick,
args_desc = ["User JID", "MUC service"],
args_example = [<<"tim@example.org">>, <<"muc.example.org">>],
args_example = [<<"tim@example.org">>, <<"conference.example.org">>],
args = [{jid, binary}, {service, binary}],
args_rename = [{host, service}],
result = {res, rescode}},
@ -143,7 +143,7 @@ get_commands_spec() ->
desc = "Create a MUC room name@service in host",
module = ?MODULE, function = create_room,
args_desc = ["Room name", "MUC service", "Server host"],
args_example = ["room1", "muc.example.com", "example.com"],
args_example = ["room1", "conference.example.com", "example.com"],
args = [{name, binary}, {service, binary},
{host, binary}],
result = {res, rescode}},
@ -151,7 +151,7 @@ get_commands_spec() ->
desc = "Destroy a MUC room",
module = ?MODULE, function = destroy_room,
args_desc = ["Room name", "MUC service"],
args_example = ["room1", "muc.example.com"],
args_example = ["room1", "conference.example.com"],
args = [{name, binary}, {service, binary}],
result = {res, rescode}},
#ejabberd_commands{name = create_rooms_file, tags = [muc],
@ -169,7 +169,7 @@ get_commands_spec() ->
"The syntax of `subscribers` is: `JID:Nick:Node:Node2:Node3,JID:Nick:Node`.",
module = ?MODULE, function = create_room_with_opts,
args_desc = ["Room name", "MUC service", "Server host", "List of options"],
args_example = ["room1", "muc.example.com", "localhost",
args_example = ["room1", "conference.example.com", "localhost",
[{"members_only","true"},
{"affiliations", "owner:bob@example.com,member:peter@example.com"},
{"subscribers", "bob@example.com:Bob:messages:subject,anne@example.com:Anne:messages"}]],
@ -197,9 +197,9 @@ get_commands_spec() ->
" The MUC service argument can be `global` to get all hosts.",
module = ?MODULE, function = rooms_unused_list,
args_desc = ["MUC service, or `global` for all", "Number of days"],
args_example = ["muc.example.com", 31],
args_example = ["conference.example.com", 31],
result_desc = "List of unused rooms",
result_example = ["room1@muc.example.com", "room2@muc.example.com"],
result_example = ["room1@conference.example.com", "room2@conference.example.com"],
args = [{service, binary}, {days, integer}],
args_rename = [{host, service}],
result = {rooms, {list, {room, string}}}},
@ -210,9 +210,9 @@ get_commands_spec() ->
" The MUC service argument can be `global` to get all hosts.",
module = ?MODULE, function = rooms_unused_destroy,
args_desc = ["MUC service, or `global` for all", "Number of days"],
args_example = ["muc.example.com", 31],
args_example = ["conference.example.com", 31],
result_desc = "List of unused rooms that has been destroyed",
result_example = ["room1@muc.example.com", "room2@muc.example.com"],
result_example = ["room1@conference.example.com", "room2@conference.example.com"],
args = [{service, binary}, {days, integer}],
args_rename = [{host, service}],
result = {rooms, {list, {room, string}}}},
@ -222,9 +222,9 @@ get_commands_spec() ->
longdesc = "The MUC service argument can be `global` to get all hosts.",
module = ?MODULE, function = rooms_empty_list,
args_desc = ["MUC service, or `global` for all"],
args_example = ["muc.example.com"],
args_example = ["conference.example.com"],
result_desc = "List of empty rooms",
result_example = ["room1@muc.example.com", "room2@muc.example.com"],
result_example = ["room1@conference.example.com", "room2@conference.example.com"],
args = [{service, binary}],
args_rename = [{host, service}],
result = {rooms, {list, {room, string}}}},
@ -233,9 +233,9 @@ get_commands_spec() ->
longdesc = "The MUC service argument can be `global` to get all hosts.",
module = ?MODULE, function = rooms_empty_destroy,
args_desc = ["MUC service, or `global` for all"],
args_example = ["muc.example.com"],
args_example = ["conference.example.com"],
result_desc = "List of empty rooms that have been destroyed",
result_example = ["room1@muc.example.com", "room2@muc.example.com"],
result_example = ["room1@conference.example.com", "room2@conference.example.com"],
args = [{service, binary}],
args_rename = [{host, service}],
result = {rooms, {list, {room, string}}}},
@ -245,7 +245,7 @@ get_commands_spec() ->
module = ?MODULE, function = get_user_rooms,
args_desc = ["Username", "Server host"],
args_example = ["tom", "example.com"],
result_example = ["room1@muc.example.com", "room2@muc.example.com"],
result_example = ["room1@conference.example.com", "room2@conference.example.com"],
args = [{user, binary}, {host, binary}],
result = {rooms, {list, {room, string}}}},
#ejabberd_commands{name = get_user_subscriptions, tags = [muc, muc_sub],
@ -254,7 +254,7 @@ get_commands_spec() ->
module = ?MODULE, function = get_user_subscriptions,
args_desc = ["Username", "Server host"],
args_example = ["tom", "example.com"],
result_example = [{"room1@muc.example.com", "Tommy", ["mucsub:config"]}],
result_example = [{"room1@conference.example.com", "Tommy", ["mucsub:config"]}],
args = [{user, binary}, {host, binary}],
result = {rooms,
{list,
@ -270,7 +270,7 @@ get_commands_spec() ->
desc = "Get the list of occupants of a MUC room",
module = ?MODULE, function = get_room_occupants,
args_desc = ["Room name", "MUC service"],
args_example = ["room1", "muc.example.com"],
args_example = ["room1", "conference.example.com"],
result_desc = "The list of occupants with JID, nick and affiliation",
result_example = [{"user1@example.com/psi", "User 1", "owner"}],
args = [{name, binary}, {service, binary}],
@ -286,7 +286,7 @@ get_commands_spec() ->
desc = "Get the number of occupants of a MUC room",
module = ?MODULE, function = get_room_occupants_number,
args_desc = ["Room name", "MUC service"],
args_example = ["room1", "muc.example.com"],
args_example = ["room1", "conference.example.com"],
result_desc = "Number of room occupants",
result_example = 7,
args = [{name, binary}, {service, binary}],
@ -302,7 +302,7 @@ get_commands_spec() ->
module = ?MODULE, function = send_direct_invitation,
args_desc = ["Room name", "MUC service", "Password, or `none`",
"Reason text, or `none`", "Users JIDs separated with `:` characters"],
args_example = [<<"room1">>, <<"muc.example.com">>,
args_example = [<<"room1">>, <<"conference.example.com">>,
<<>>, <<"Check this out!">>,
"user2@localhost:user3@example.com"],
args = [{name, binary}, {service, binary}, {password, binary},
@ -319,7 +319,7 @@ get_commands_spec() ->
note = "updated in 24.02",
args_desc = ["Room name", "MUC service", "Password, or `none`",
"Reason text, or `none`", "List of users JIDs"],
args_example = [<<"room1">>, <<"muc.example.com">>,
args_example = [<<"room1">>, <<"conference.example.com">>,
<<>>, <<"Check this out!">>,
["user2@localhost", "user3@example.com"]],
args = [{name, binary}, {service, binary}, {password, binary},
@ -330,7 +330,7 @@ get_commands_spec() ->
desc = "Change an option in a MUC room",
module = ?MODULE, function = change_room_option,
args_desc = ["Room name", "MUC service", "Option name", "Value to assign"],
args_example = ["room1", "muc.example.com", "members_only", "true"],
args_example = ["room1", "conference.example.com", "members_only", "true"],
args = [{name, binary}, {service, binary},
{option, binary}, {value, binary}],
result = {res, rescode}},
@ -338,7 +338,7 @@ get_commands_spec() ->
desc = "Get options from a MUC room",
module = ?MODULE, function = get_room_options,
args_desc = ["Room name", "MUC service"],
args_example = ["room1", "muc.example.com"],
args_example = ["room1", "conference.example.com"],
result_desc = "List of room options tuples with name and value",
result_example = [{"members_only", "true"}],
args = [{name, binary}, {service, binary}],
@ -434,7 +434,7 @@ get_commands_spec() ->
desc = "List subscribers of a MUC conference",
module = ?MODULE, function = get_subscribers,
args_desc = ["Room name", "MUC service"],
args_example = ["room1", "muc.example.com"],
args_example = ["room1", "conference.example.com"],
result_desc = "The list of users that are subscribed to that room",
result_example = ["user2@example.com", "user3@example.com"],
args = [{name, binary}, {service, binary}],
@ -443,7 +443,7 @@ get_commands_spec() ->
desc = "Change an affiliation in a MUC room",
module = ?MODULE, function = set_room_affiliation,
args_desc = ["Room name", "MUC service", "User JID", "Affiliation to set"],
args_example = ["room1", "muc.example.com", "user2@example.com", "member"],
args_example = ["room1", "conference.example.com", "user2@example.com", "member"],
args = [{name, binary}, {service, binary},
{jid, binary}, {affiliation, binary}],
result = {res, rescode}},
@ -451,7 +451,7 @@ get_commands_spec() ->
desc = "Get the list of affiliations of a MUC room",
module = ?MODULE, function = get_room_affiliations,
args_desc = ["Room name", "MUC service"],
args_example = ["room1", "muc.example.com"],
args_example = ["room1", "conference.example.com"],
result_desc = "The list of affiliations with username, domain, affiliation and reason",
result_example = [{"user1", "example.com", member, "member"}],
args = [{name, binary}, {service, binary}],
@ -467,7 +467,7 @@ get_commands_spec() ->
desc = "Get affiliation of a user in MUC room",
module = ?MODULE, function = get_room_affiliation,
args_desc = ["Room name", "MUC service", "User JID"],
args_example = ["room1", "muc.example.com", "user1@example.com"],
args_example = ["room1", "conference.example.com", "user1@example.com"],
result_desc = "Affiliation of the user",
result_example = member,
args = [{name, binary}, {service, binary}, {jid, binary}],
@ -477,7 +477,7 @@ get_commands_spec() ->
note = "added in 23.04",
module = ?MODULE, function = get_room_history,
args_desc = ["Room name", "MUC service"],
args_example = ["room1", "muc.example.com"],
args_example = ["room1", "conference.example.com"],
args = [{name, binary}, {service, binary}],
result = {history, {list,
{entry, {tuple,