Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 633b362577 | |||
| 150b7e7219 | |||
| e6065bf08f | |||
| c2aa5f77bf | |||
| 7caec56e96 | |||
| 97354426cf | |||
| 63e3fb92d1 | |||
| a2d1ffffe6 | |||
| f17d4c0adc | |||
| 92a09fdb71 | |||
| 039d786e1f | |||
| 2d707cc0d2 | |||
| 0a88d03dc9 | |||
| f12ee28660 | |||
| 260c289d34 | |||
| d8899ca9ac | |||
| 1e456065f6 | |||
| 82074190fb | |||
| 6fe7c5cac5 | |||
| e9d1201ea8 | |||
| 9a89b360c0 | |||
| b39a1e2d74 | |||
| 151b818af4 | |||
| df47e2a93f | |||
| d0e93f9219 | |||
| 47c5aba1e5 | |||
| 00abf5d42c | |||
| 9c25d1024a | |||
| 8eccbade56 |
@@ -1,3 +1,23 @@
|
||||
# Version 20.03
|
||||
|
||||
* Changes in this version
|
||||
- Add support of ssl connection when connection to mysql
|
||||
database (configured with `sql_ssl: true` option)
|
||||
- Experimental support for cockroachdb when configured
|
||||
with postgres connector
|
||||
- Add cache and optimize queries issued by `mod_shared_roster`,
|
||||
this should greatly improve performance of this module when
|
||||
used with `sql` backend
|
||||
- Fix problem with accessing webadmin
|
||||
- Make webadmin work even when url is missing trailing slash
|
||||
- When compiling external modules with ext_mod, use flags
|
||||
that were detected during compilation of ejabberd
|
||||
- Make config changed to ldap options be updated when issued
|
||||
`reload_config` command
|
||||
- Fix `room_empty_destory` command
|
||||
- Fix reporting errors in `send_stanza` command when xml
|
||||
passed to it couldn't be passed correctly
|
||||
|
||||
# Version 20.02
|
||||
|
||||
* Changes in this version
|
||||
|
||||
@@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do
|
||||
|
||||
def project do
|
||||
[app: :ejabberd,
|
||||
version: "20.2.0",
|
||||
version: "20.3.0",
|
||||
description: description(),
|
||||
elixir: "~> 1.4",
|
||||
elixirc_paths: ["lib"],
|
||||
@@ -51,12 +51,25 @@ defmodule Ejabberd.Mixfile do
|
||||
end
|
||||
end
|
||||
|
||||
defp if_version_below(ver, okResult) do
|
||||
if :erlang.system_info(:otp_release) < ver do
|
||||
okResult
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
defp erlc_options do
|
||||
# Use our own includes + includes from all dependencies
|
||||
includes = ["include"] ++ deps_include(["fast_xml", "xmpp", "p1_utils"])
|
||||
[:debug_info, {:d, :ELIXIR_ENABLED}] ++ cond_options() ++ Enum.map(includes, fn(path) -> {:i, path} end) ++
|
||||
if_version_above('20', [{:d, :DEPRECATED_GET_STACKTRACE}]) ++
|
||||
if_function_exported(:erl_error, :format_exception, 6, [{:d, :HAVE_ERL_ERROR}])
|
||||
result = [:debug_info, {:d, :ELIXIR_ENABLED}] ++
|
||||
cond_options() ++
|
||||
Enum.map(includes, fn (path) -> {:i, path} end) ++
|
||||
if_version_above('20', [{:d, :DEPRECATED_GET_STACKTRACE}]) ++
|
||||
if_version_below('22', [{:d, :LAGER}]) ++
|
||||
if_function_exported(:erl_error, :format_exception, 6, [{:d, :HAVE_ERL_ERROR}])
|
||||
defines = for {:d, value} <- result, do: {:d, value}
|
||||
result ++ [{:d, :ALL_DEFS, defines}]
|
||||
end
|
||||
|
||||
defp cond_options do
|
||||
@@ -120,6 +133,7 @@ defmodule Ejabberd.Mixfile do
|
||||
defp cond_apps do
|
||||
for {:true, app} <- [{config(:redis), :eredis},
|
||||
{config(:mysql), :p1_mysql},
|
||||
{config(:odbc), :odbc},
|
||||
{config(:pgsql), :p1_pgsql},
|
||||
{config(:sqlite), :sqlite3},
|
||||
{config(:zlib), :ezlib}], do:
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
%{
|
||||
"artificery": {:hex, :artificery, "0.4.2", "3ded6e29e13113af52811c72f414d1e88f711410cac1b619ab3a2666bbd7efd4", [:mix], [], "hexpm"},
|
||||
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm"},
|
||||
"cache_tab": {:hex, :cache_tab, "1.0.22", "ad16577e7f26709cacdcb86e6a4960c8d158cab9d189cdf49cc1e2dc33106a70", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"distillery": {:hex, :distillery, "2.1.1", "f9332afc2eec8a1a2b86f22429e068ef35f84a93ea1718265e740d90dd367814", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm"},
|
||||
"eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"artificery": {:hex, :artificery, "0.4.2", "3ded6e29e13113af52811c72f414d1e88f711410cac1b619ab3a2666bbd7efd4", [:mix], [], "hexpm", "514586f4312ef3709a3ccbd8e55f69455add235c1729656687bb781d10d0afdb"},
|
||||
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm", "fab09b20e3f5db886725544cbcf875b8e73ec93363954eb8a1a9ed834aa8c1f9"},
|
||||
"cache_tab": {:hex, :cache_tab, "1.0.22", "ad16577e7f26709cacdcb86e6a4960c8d158cab9d189cdf49cc1e2dc33106a70", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "53ed75e7c289434953a4407eb0a40b8675c5046b057313f97cf10e196efd8d79"},
|
||||
"distillery": {:hex, :distillery, "2.1.1", "f9332afc2eec8a1a2b86f22429e068ef35f84a93ea1718265e740d90dd367814", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm", "bbc7008b0161a6f130d8d903b5b3232351fccc9c31a991f8fcbf2a12ace22995"},
|
||||
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"},
|
||||
"eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "501133f3112079b92d9e22da8b88bf4f0e13d4d67ae9c15c42c30bd25ceb83b6"},
|
||||
"epam": {:hex, :epam, "1.0.6", "6e57e1f5a330fa02a08ee0d4b16d9161f95177351e48c6dfede2f89b7e2f589f", [:rebar3], [], "hexpm"},
|
||||
"eredis": {:hex, :eredis, "1.2.0", "0b8e9cfc2c00fa1374cd107ea63b49be08d933df2cf175e6a89b73dd9c380de4", [:rebar3], [], "hexpm"},
|
||||
"esip": {:hex, :esip, "1.0.32", "b6d5d9eb8342b86509de02ac79e6a9a772dab011e936092441d4e92a7986ca29", [:rebar3], [{:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.0.31", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.21.3", "857ec876b35a587c5d9148a2512e952e24c24345552259464b98bfbb883c7b42", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"ezlib": {:hex, :ezlib, "1.0.7", "c8adffd32e66831df77955d163d705cdcf0a3d66762e6f68f8123012e714bf05", [:rebar3], [], "hexpm"},
|
||||
"fast_tls": {:hex, :fast_tls, "1.1.4", "a0320baf14be72fc9f99211543e411bb98077bf72c42e2d86fc4e2c10d60c258", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"fast_xml": {:hex, :fast_xml, "1.1.39", "687080c0190a8c45d564a3576201f1a89f31ae413dd700a2def0821736f98d4d", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"fast_yaml": {:hex, :fast_yaml, "1.0.23", "0c74d6274c232609467bf55563066840c265e70081ee0c23215d1f3ca2624dfc", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"goldrush": {:hex, :goldrush, "0.1.9", "f06e5d5f1277da5c413e84d5a2924174182fb108dabb39d5ec548b27424cd106", [:rebar3], [], "hexpm"},
|
||||
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"jiffy": {:hex, :jiffy, "1.0.1", "4f25639772ca41202f41ba9c8f6ca0933554283dd4742c90651e03471c55e341", [:rebar3], [], "hexpm"},
|
||||
"jose": {:hex, :jose, "1.9.0", "4167c5f6d06ffaebffd15cdb8da61a108445ef5e85ab8f5a7ad926fdf3ada154", [:mix, :rebar3], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"lager": {:hex, :lager, "3.6.10", "6172b43ab720ac33914ccd0aeb21fdbdf88213847707d4b91e6af57b2ae5c4d2", [:rebar3], [{:goldrush, "0.1.9", [hex: :goldrush, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"esip": {:hex, :esip, "1.0.32", "b6d5d9eb8342b86509de02ac79e6a9a772dab011e936092441d4e92a7986ca29", [:rebar3], [{:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stun, "1.0.31", [hex: :stun, repo: "hexpm", optional: false]}], "hexpm", "ab083aaa144c718d5f1c06b3034947cf6a9f73aedca04015813c983478ad94ed"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.21.3", "857ec876b35a587c5d9148a2512e952e24c24345552259464b98bfbb883c7b42", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "0db1ee8d1547ab4877c5b5dffc6604ef9454e189928d5ba8967d4a58a801f161"},
|
||||
"ezlib": {:hex, :ezlib, "1.0.7", "c8adffd32e66831df77955d163d705cdcf0a3d66762e6f68f8123012e714bf05", [:rebar3], [], "hexpm", "5634b9f7112837f9338a61da1993601f4ab81615de84ff0baddcdc5a3fe940dc"},
|
||||
"fast_tls": {:hex, :fast_tls, "1.1.4", "a0320baf14be72fc9f99211543e411bb98077bf72c42e2d86fc4e2c10d60c258", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "027fc2a726d6f3ad36c7fa230780000e8d3fc72dc8b397c9bff2018d3f5ff06a"},
|
||||
"fast_xml": {:hex, :fast_xml, "1.1.39", "687080c0190a8c45d564a3576201f1a89f31ae413dd700a2def0821736f98d4d", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "2521816ed30b9c76befd85e477b5173c0329bd08fc8429f970b668c14bddb3f9"},
|
||||
"fast_yaml": {:hex, :fast_yaml, "1.0.24", "d304799e6b961a21a509449830193154870b2b526cfc2e7046e9953ad413765f", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "71f4d5f868a2cfd4794e6bbd89495c4e4c54c45c6cb65b7f12d96271d6c02c84"},
|
||||
"goldrush": {:hex, :goldrush, "0.1.9", "f06e5d5f1277da5c413e84d5a2924174182fb108dabb39d5ec548b27424cd106", [:rebar3], [], "hexpm", "99cb4128cffcb3227581e5d4d803d5413fa643f4eb96523f77d9e6937d994ceb"},
|
||||
"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.0.1", "4f25639772ca41202f41ba9c8f6ca0933554283dd4742c90651e03471c55e341", [:rebar3], [], "hexpm", "2568927f6f5e383cb775f6fd87bc6e80ea5f7d813418de450aa644b02c7f7112"},
|
||||
"jose": {:hex, :jose, "1.9.0", "4167c5f6d06ffaebffd15cdb8da61a108445ef5e85ab8f5a7ad926fdf3ada154", [:mix, :rebar3], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}], "hexpm", "6429c4fee52b2dda7861ee19a4f09c8c1ffa213bee3a1ec187828fde95d447ed"},
|
||||
"lager": {:hex, :lager, "3.6.10", "6172b43ab720ac33914ccd0aeb21fdbdf88213847707d4b91e6af57b2ae5c4d2", [:rebar3], [{:goldrush, "0.1.9", [hex: :goldrush, repo: "hexpm", optional: false]}], "hexpm", "5d10499461826b79c5abee18bb594b3949cbdf76d9d9fd7e66d0a558137c21c9"},
|
||||
"luerl": {:hex, :luerl, "0.3.1", "5412807630aac1aaf59ffe5a1bc09259c447b4faeb1d3fe2d4ef41b87676cb04", [:rebar3], [], "hexpm"},
|
||||
"makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"mqtree": {:hex, :mqtree, "1.0.7", "0d8f6101eb2bb6a6e27f0e5a60cfad04b27dd552e75f30294e565605ce7cd0d2", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm"},
|
||||
"p1_acme": {:hex, :p1_acme, "1.0.4", "2d118dbc38e7bc8eda34f4c5bf7afa6bce1345affc022bba514f42e194818820", [:rebar3], [{:idna, "~>6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jiffy, "~>1.0.1", [hex: :jiffy, repo: "hexpm", optional: false]}, {:jose, "~>1.9.0", [hex: :jose, repo: "hexpm", optional: false]}, {:yconf, "~>1.0.3", [hex: :yconf, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"p1_mysql": {:hex, :p1_mysql, "1.0.13", "6a17bfd7a33d035673d633572e93370bdd2fcf4077362ed13b1a8fd8176a1643", [:rebar3], [], "hexpm"},
|
||||
"p1_oauth2": {:hex, :p1_oauth2, "0.6.6", "b17053bd7a34621f9a1a7327285a3e37abd38eb1d176afccc8cfc39882ff0a44", [:rebar3], [], "hexpm"},
|
||||
"p1_pgsql": {:hex, :p1_pgsql, "1.1.9", "07ff9b037954dec06b4e30e33a82ac69a5a513e2860d2e59b7f6f4af23493c45", [:rebar3], [], "hexpm"},
|
||||
"p1_utils": {:hex, :p1_utils, "1.0.18", "3fe224de5b2e190d730a3c5da9d6e8540c96484cf4b4692921d1e28f0c32b01c", [:rebar3], [], "hexpm"},
|
||||
"pkix": {:hex, :pkix, "1.0.5", "407c02c70191d0791cd9b422ac2380df5f7f8304ec26a6d3b06e0e02be688fca", [:rebar3], [], "hexpm"},
|
||||
"makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "a10c6eb62cca416019663129699769f0c2ccf39428b3bb3c0cb38c718a0c186d"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "d4b316c7222a85bbaa2fd7c6e90e37e953257ad196dc229505137c5e505e9eff"},
|
||||
"mqtree": {:hex, :mqtree, "1.0.7", "0d8f6101eb2bb6a6e27f0e5a60cfad04b27dd552e75f30294e565605ce7cd0d2", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "317db0349a8d9695bc89ef7062e9654e93347cd9576f827739650e26482825bb"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"},
|
||||
"p1_acme": {:hex, :p1_acme, "1.0.5", "de54353100ed82d0c820fbc011b7a7ad54f65af052eb8112922ad8be8eadf8f1", [:rebar3], [{:idna, "~>6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jiffy, "~>1.0.1", [hex: :jiffy, repo: "hexpm", optional: false]}, {:jose, "~>1.9.0", [hex: :jose, repo: "hexpm", optional: false]}, {:yconf, "~>1.0.4", [hex: :yconf, repo: "hexpm", optional: false]}], "hexpm", "cbecfc70ce11d37d679875117c685aa2a7bc2502bfa51722c8e619602c92a0c0"},
|
||||
"p1_mysql": {:hex, :p1_mysql, "1.0.14", "ea2d58d0551d62fce9882f65fc7e0273ae6d683ab277aad657a661f514411198", [:rebar3], [], "hexpm", "70df0680b71118ace166e59fbf8be19058be3c3918bc3b7ede6e1f297a4a9dbe"},
|
||||
"p1_oauth2": {:hex, :p1_oauth2, "0.6.6", "b17053bd7a34621f9a1a7327285a3e37abd38eb1d176afccc8cfc39882ff0a44", [:rebar3], [], "hexpm", "8a5fd16fc581a50e62176ab8b78b83b6e7cc6f76f7f59f75f58d713b7c1ca7b2"},
|
||||
"p1_pgsql": {:hex, :p1_pgsql, "1.1.9", "07ff9b037954dec06b4e30e33a82ac69a5a513e2860d2e59b7f6f4af23493c45", [:rebar3], [], "hexpm", "81aab8cff0203250dd3d9cc77a0232dc9f8e56c99fd742abbaedc51a0fd633a7"},
|
||||
"p1_utils": {:hex, :p1_utils, "1.0.18", "3fe224de5b2e190d730a3c5da9d6e8540c96484cf4b4692921d1e28f0c32b01c", [:rebar3], [], "hexpm", "1fc8773a71a15553b179c986b22fbeead19b28fe486c332d4929700ffeb71f88"},
|
||||
"pkix": {:hex, :pkix, "1.0.5", "407c02c70191d0791cd9b422ac2380df5f7f8304ec26a6d3b06e0e02be688fca", [:rebar3], [], "hexpm", "b86aed212afaf019ac97bf56857366e5f01c3003f38ee050af8ba16455e13719"},
|
||||
"sqlite3": {:hex, :sqlite3, "1.1.6", "4ea71af0b45908b5f02c9b09e4c87177039ef404f20accb35049cd8924cc417c", [:rebar3], [], "hexpm"},
|
||||
"stringprep": {:hex, :stringprep, "1.0.19", "79761de42960a625fb0cd6d31686f6118aef30540a7abb884b92f72861b6adde", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"stun": {:hex, :stun, "1.0.31", "577d845d4b77b155bad234598c2056f6e182f178468727de083bedf275dc83a1", [:rebar3], [{:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
|
||||
"xmpp": {:hex, :xmpp, "1.4.5", "b226baa9ad960e8de041289b94bbcb6148a7980acc0c1ec58dfc8f24acded3ad", [:rebar3], [{:ezlib, "1.0.7", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "1.1.39", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.19", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"yconf": {:hex, :yconf, "1.0.3", "7f71d0fe0e95ecb0f4004acee7b7db46c13e38c216d0bd03ef2a595a898d21a3", [:rebar3], [{:fast_yaml, "1.0.23", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"stringprep": {:hex, :stringprep, "1.0.19", "79761de42960a625fb0cd6d31686f6118aef30540a7abb884b92f72861b6adde", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "3f77edbcb530899faffe95d57b6e2bac704a5a6ea1ead5957387f9e4ed8c5f07"},
|
||||
"stun": {:hex, :stun, "1.0.31", "577d845d4b77b155bad234598c2056f6e182f178468727de083bedf275dc83a1", [:rebar3], [{:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "c7edd93d823c0e1438bfe70adf99c39cf4cbca73cbd3c086c6e461ad00c6f8d4"},
|
||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm", "1d1848c40487cdb0b30e8ed975e34e025860c02e419cb615d255849f3427439d"},
|
||||
"xmpp": {:hex, :xmpp, "1.4.5", "b226baa9ad960e8de041289b94bbcb6148a7980acc0c1ec58dfc8f24acded3ad", [:rebar3], [{:ezlib, "1.0.7", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "1.1.4", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "1.1.39", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "1.0.19", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm", "7bd21dd10ff3369f65128fcf730595073f1b6288a8b563d165874aecb2220317"},
|
||||
"yconf": {:hex, :yconf, "1.0.4", "f08dcc2ad041f68580e98753f70453976d256f2c1a40a29a985465ab16d489a6", [:rebar3], [{:fast_yaml, "1.0.24", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm", "44570111ad224ee4eec6e2bffa1e7223ef4b76f91f9dd2f768eee214d2dcabe2"},
|
||||
}
|
||||
|
||||
+4
-4
@@ -26,20 +26,20 @@
|
||||
{fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.39"}}},
|
||||
{idna, ".*", {git, "https://github.com/benoitc/erlang-idna", {tag, "6.0.0"}}},
|
||||
{xmpp, ".*", {git, "https://github.com/processone/xmpp", {tag, "1.4.5"}}},
|
||||
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.23"}}},
|
||||
{yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.3"}}},
|
||||
{fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.24"}}},
|
||||
{yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.4"}}},
|
||||
{jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "1.0.1"}}},
|
||||
{p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.6"}}},
|
||||
{pkix, ".*", {git, "https://github.com/processone/pkix", {tag, "1.0.5"}}},
|
||||
{jose, ".*", {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.9.0"}}},
|
||||
{eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.14"}}},
|
||||
{mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.7"}}},
|
||||
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme.git", {tag, "1.0.4"}}},
|
||||
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme.git", {tag, "1.0.5"}}},
|
||||
{base64url, ".*", {git, "https://github.com/dvv/base64url.git", {tag, "v1.0"}}},
|
||||
{if_var_true, stun, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.31"}}}},
|
||||
{if_var_true, sip, {esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.32"}}}},
|
||||
{if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql",
|
||||
{tag, "1.0.13"}}}},
|
||||
{tag, "1.0.14"}}}},
|
||||
{if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql",
|
||||
{tag, "1.1.9"}}}},
|
||||
{if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3",
|
||||
|
||||
+4
-2
@@ -304,12 +304,14 @@ fun(Hooks) ->
|
||||
end,
|
||||
|
||||
ProcessErlOpt = fun(Vals) ->
|
||||
lists:map(
|
||||
R = lists:map(
|
||||
fun({i, Path}) ->
|
||||
{i, ResolveDepPath(Path)};
|
||||
(ErlOpt) ->
|
||||
ErlOpt
|
||||
end, Vals)
|
||||
end, Vals),
|
||||
M = lists:filter(fun({d, M}) -> true; (_) -> false end, R),
|
||||
[{d, 'ALL_DEFS', M} | R]
|
||||
end,
|
||||
|
||||
ProcssXrefExclusions = fun(Items) ->
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
-export([start/1, stop/1, start_link/1, set_password/3,
|
||||
check_password/4, user_exists/2,
|
||||
get_users/2, count_users/2,
|
||||
store_type/1, plain_password_required/1]).
|
||||
store_type/1, plain_password_required/1,
|
||||
reload/1]).
|
||||
|
||||
-include("logger.hrl").
|
||||
|
||||
@@ -109,6 +110,10 @@ init(Host) ->
|
||||
State#state.password, State#state.tls_options),
|
||||
{ok, State}.
|
||||
|
||||
reload(Host) ->
|
||||
stop(Host),
|
||||
start(Host).
|
||||
|
||||
plain_password_required(_) -> true.
|
||||
|
||||
store_type(_) -> external.
|
||||
|
||||
@@ -902,7 +902,7 @@ bounce_message_queue({_, Pid} = SID, JID) ->
|
||||
receive {route, Pkt} ->
|
||||
ejabberd_router:route(Pkt),
|
||||
bounce_message_queue(SID, JID)
|
||||
after 0 ->
|
||||
after 100 ->
|
||||
ok
|
||||
end
|
||||
end.
|
||||
|
||||
@@ -857,9 +857,13 @@ parse_urlencoded(<<>>, Last, Cur, _State) ->
|
||||
parse_urlencoded(undefined, _, _, _) -> [].
|
||||
|
||||
apply_custom_headers(Headers, CustomHeaders) ->
|
||||
M = maps:merge(maps:from_list(Headers),
|
||||
{Doctype, Headers2} = case Headers -- [html] of
|
||||
Headers -> {[], Headers};
|
||||
Other -> {[html], Other}
|
||||
end,
|
||||
M = maps:merge(maps:from_list(Headers2),
|
||||
maps:from_list(CustomHeaders)),
|
||||
maps:to_list(M).
|
||||
Doctype ++ maps:to_list(M).
|
||||
|
||||
% The following code is mostly taken from yaws_ssl.erl
|
||||
|
||||
|
||||
+21
-11
@@ -253,7 +253,7 @@ to_list(EscapeFun, Val) ->
|
||||
|
||||
to_array(EscapeFun, Val) ->
|
||||
Escaped = lists:join(<<",">>, lists:map(EscapeFun, Val)),
|
||||
[<<"{">>, Escaped, <<"}">>].
|
||||
lists:flatten([<<"{">>, Escaped, <<"}">>]).
|
||||
|
||||
to_string_literal(odbc, S) ->
|
||||
<<"'", (escape(S))/binary, "'">>;
|
||||
@@ -736,11 +736,11 @@ pgsql_sql_query_format(SQLQuery) ->
|
||||
pgsql_escape() ->
|
||||
#sql_escape{string = fun(X) -> <<"E'", (escape(X))/binary, "'">> end,
|
||||
integer = fun(X) -> misc:i2l(X) end,
|
||||
boolean = fun(true) -> <<"1">>;
|
||||
(false) -> <<"0">>
|
||||
boolean = fun(true) -> <<"'t'">>;
|
||||
(false) -> <<"'f'">>
|
||||
end,
|
||||
in_array_string = fun(X) -> <<"E'", (escape(X))/binary, "'">> end,
|
||||
like_escape = fun() -> <<"">> end
|
||||
like_escape = fun() -> <<"ESCAPE E'\\\\'">> end
|
||||
}.
|
||||
|
||||
sqlite_sql_query(SQLQuery) ->
|
||||
@@ -776,11 +776,13 @@ pgsql_prepare(SQLQuery, State) ->
|
||||
like_escape = fun() -> escape end},
|
||||
{RArgs, _} =
|
||||
lists:foldl(
|
||||
fun(arg, {Acc, I}) ->
|
||||
{[<<$$, (integer_to_binary(I))/binary>> | Acc], I + 1};
|
||||
(escape, {Acc, I}) ->
|
||||
{[<<"">> | Acc], I}
|
||||
end, {[], 1}, (SQLQuery#sql_query.args)(Escape)),
|
||||
fun(arg, {Acc, I}) ->
|
||||
{[<<$$, (integer_to_binary(I))/binary>> | Acc], I + 1};
|
||||
(escape, {Acc, I}) ->
|
||||
{[<<"ESCAPE E'\\\\'">> | Acc], I};
|
||||
(List, {Acc, I}) when is_list(List) ->
|
||||
{[<<$$, (integer_to_binary(I))/binary>> | Acc], I + 1}
|
||||
end, {[], 1}, (SQLQuery#sql_query.args)(Escape)),
|
||||
Args = lists:reverse(RArgs),
|
||||
%N = length((SQLQuery#sql_query.args)(Escape)),
|
||||
%Args = [<<$$, (integer_to_binary(I))/binary>> || I <- lists:seq(1, N)],
|
||||
@@ -1001,12 +1003,18 @@ pgsql_execute_to_odbc(_) -> {updated, undefined}.
|
||||
|
||||
%% part of init/1
|
||||
%% Open a database connection to MySQL
|
||||
mysql_connect(Server, Port, DB, Username, Password, ConnectTimeout, _, _) ->
|
||||
mysql_connect(Server, Port, DB, Username, Password, ConnectTimeout, Transport, _) ->
|
||||
SSLOpts = case Transport of
|
||||
ssl ->
|
||||
[ssl_required];
|
||||
_ ->
|
||||
[]
|
||||
end,
|
||||
case p1_mysql_conn:start(binary_to_list(Server), Port,
|
||||
binary_to_list(Username),
|
||||
binary_to_list(Password),
|
||||
binary_to_list(DB),
|
||||
ConnectTimeout, fun log/3)
|
||||
ConnectTimeout, fun log/3, SSLOpts)
|
||||
of
|
||||
{ok, Ref} ->
|
||||
p1_mysql_conn:fetch(
|
||||
@@ -1112,6 +1120,8 @@ warn_if_ssl_unsupported(tcp, _) ->
|
||||
ok;
|
||||
warn_if_ssl_unsupported(ssl, pgsql) ->
|
||||
ok;
|
||||
warn_if_ssl_unsupported(ssl, mysql) ->
|
||||
ok;
|
||||
warn_if_ssl_unsupported(ssl, Type) ->
|
||||
?WARNING_MSG("SSL connection is not supported for ~ts", [Type]).
|
||||
|
||||
|
||||
@@ -648,7 +648,11 @@ make_sql_upsert_insert(Table, ParseRes) ->
|
||||
]),
|
||||
State.
|
||||
|
||||
make_sql_upsert_pgsql901(Table, ParseRes) ->
|
||||
make_sql_upsert_pgsql901(Table, ParseRes0) ->
|
||||
ParseRes = lists:map(
|
||||
fun({"family", A2, A3}) -> {"\"family\"", A2, A3};
|
||||
(Other) -> Other
|
||||
end, ParseRes0),
|
||||
Update = make_sql_upsert_update(Table, ParseRes),
|
||||
Vals =
|
||||
lists:map(
|
||||
|
||||
+107
-124
@@ -29,8 +29,8 @@
|
||||
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-export([process/2, list_users/4,
|
||||
list_users_in_diapason/4, pretty_print_xml/1,
|
||||
-export([process/2, list_users/5,
|
||||
list_users_in_diapason/5, pretty_print_xml/1,
|
||||
term_to_id/1]).
|
||||
|
||||
-include("logger.hrl").
|
||||
@@ -95,20 +95,20 @@ get_jid(Auth, HostHTTP, Method) ->
|
||||
throw({unauthorized, Auth})
|
||||
end.
|
||||
|
||||
get_menu_items(global, cluster, Lang, JID, Level) ->
|
||||
{_Base, _, Items} = make_server_menu([], [], Lang, JID, Level),
|
||||
get_menu_items(global, cluster, Lang, JID, Base) ->
|
||||
{_BaseURL, _, Items} = make_server_menu([], [], Lang, JID, Base),
|
||||
lists:map(fun ({URI, Name}) ->
|
||||
{<<URI/binary, "/">>, Name};
|
||||
{<<Base/binary, URI/binary, "/">>, Name};
|
||||
({URI, Name, _SubMenu}) ->
|
||||
{<<URI/binary, "/">>, Name}
|
||||
{<<Base/binary, URI/binary, "/">>, Name}
|
||||
end,
|
||||
Items);
|
||||
get_menu_items(Host, cluster, Lang, JID, Level) ->
|
||||
{_Base, _, Items} = make_host_menu(Host, [], Lang, JID, Level),
|
||||
get_menu_items(Host, cluster, Lang, JID, Base) ->
|
||||
{_BaseURL, _, Items} = make_host_menu(Host, [], Lang, JID, Base),
|
||||
lists:map(fun ({URI, Name}) ->
|
||||
{<<URI/binary, "/">>, Name};
|
||||
{<<Base/binary, URI/binary, "/">>, Name};
|
||||
({URI, Name, _SubMenu}) ->
|
||||
{<<URI/binary, "/">>, Name}
|
||||
{<<Base/binary, URI/binary, "/">>, Name}
|
||||
end,
|
||||
Items).
|
||||
|
||||
@@ -123,10 +123,10 @@ get_menu_items(Host, cluster, Lang, JID, Level) ->
|
||||
%% Items
|
||||
%% ).
|
||||
|
||||
is_allowed_path(BasePath, {Path, _}, JID) ->
|
||||
is_allowed_path(BasePath ++ [Path], JID);
|
||||
is_allowed_path(BasePath, {Path, _, _}, JID) ->
|
||||
is_allowed_path(BasePath ++ [Path], JID).
|
||||
is_allowed_path(Base, {Path, _}, JID) ->
|
||||
is_allowed_path(Base ++ [Path], JID);
|
||||
is_allowed_path(Base, {Path, _, _}, JID) ->
|
||||
is_allowed_path(Base ++ [Path], JID).
|
||||
|
||||
is_allowed_path([<<"admin">> | Path], JID) ->
|
||||
is_allowed_path(Path, JID);
|
||||
@@ -152,7 +152,7 @@ url_to_path(URL) -> str:tokens(URL, <<"/">>).
|
||||
|
||||
process([<<"server">>, SHost | RPath] = Path,
|
||||
#request{auth = Auth, lang = Lang, host = HostHTTP,
|
||||
method = Method} =
|
||||
path = RequestPath, method = Method} =
|
||||
Request) ->
|
||||
Host = jid:nameprep(SHost),
|
||||
case ejabberd_router:is_my_host(Host) of
|
||||
@@ -160,7 +160,8 @@ process([<<"server">>, SHost | RPath] = Path,
|
||||
case get_auth_admin(Auth, HostHTTP, Path, Method) of
|
||||
{ok, {User, Server}} ->
|
||||
AJID = get_jid(Auth, HostHTTP, Method),
|
||||
process_admin(Host,
|
||||
Base = extract_base_path(RequestPath, Path),
|
||||
process_admin(Base, Host,
|
||||
Request#request{path = RPath,
|
||||
us = {User, Server}},
|
||||
AJID);
|
||||
@@ -187,12 +188,13 @@ process([<<"server">>, SHost | RPath] = Path,
|
||||
end;
|
||||
process(RPath,
|
||||
#request{auth = Auth, lang = Lang, host = HostHTTP,
|
||||
method = Method} =
|
||||
path = Path, method = Method} =
|
||||
Request) ->
|
||||
Base = extract_base_path(Path, RPath),
|
||||
case get_auth_admin(Auth, HostHTTP, RPath, Method) of
|
||||
{ok, {User, Server}} ->
|
||||
AJID = get_jid(Auth, HostHTTP, Method),
|
||||
process_admin(global,
|
||||
process_admin(Base, global,
|
||||
Request#request{path = RPath,
|
||||
us = {User, Server}},
|
||||
AJID);
|
||||
@@ -266,16 +268,15 @@ get_auth_account2(HostOfRule, AccessRule, User, Server,
|
||||
%%%==================================
|
||||
%%%% make_xhtml
|
||||
|
||||
make_xhtml(Els, Host, Lang, JID, Level) ->
|
||||
make_xhtml(Els, Host, cluster, Lang, JID, Level).
|
||||
make_xhtml(Els, Host, Lang, JID, Base) ->
|
||||
make_xhtml(Els, Host, cluster, Lang, JID, Base).
|
||||
|
||||
%% @spec (Els, Host, Node, Lang, JID) -> {200, [html], xmlelement()}
|
||||
%% where Host = global | string()
|
||||
%% Node = cluster | atom()
|
||||
%% JID = jid()
|
||||
make_xhtml(Els, Host, Node, Lang, JID, Level) ->
|
||||
Base = get_base_path_sum(0, 0, Level),
|
||||
MenuItems = make_navigation(Host, Node, Lang, JID, Level),
|
||||
make_xhtml(Els, Host, Node, Lang, JID, Base) ->
|
||||
MenuItems = make_navigation(Host, Node, Lang, JID, Base),
|
||||
{200, [html],
|
||||
#xmlel{name = <<"html">>,
|
||||
attrs =
|
||||
@@ -333,19 +334,19 @@ make_xhtml(Els, Host, Node, Lang, JID, Level) ->
|
||||
direction(<<"he">>) -> [{<<"dir">>, <<"rtl">>}];
|
||||
direction(_) -> [].
|
||||
|
||||
get_base_path(Host, Node, Level) ->
|
||||
SumHost = case Host of
|
||||
global -> 0;
|
||||
_ -> -2
|
||||
end,
|
||||
SumNode = case Node of
|
||||
cluster -> 0;
|
||||
_ -> -2
|
||||
end,
|
||||
get_base_path_sum(SumHost, SumNode, Level).
|
||||
extract_base_path(Path, RPath) ->
|
||||
Base = lists:sublist(Path, length(Path)-length(RPath)),
|
||||
iolist_to_binary("/" ++ lists:join("/", Base) ++ "/").
|
||||
|
||||
get_base_path_sum(SumHost, SumNode, Level) ->
|
||||
iolist_to_binary(lists:duplicate(Level + SumHost + SumNode, "../")).
|
||||
get_base_path(global, cluster, Base) -> Base;
|
||||
get_base_path(Host, cluster, Base) ->
|
||||
<<Base/binary, "/server/", Host/binary, "/">>;
|
||||
get_base_path(global, Node, Base) ->
|
||||
<<Base/binary, "/node/",
|
||||
(iolist_to_binary(atom_to_list(Node)))/binary, "/">>;
|
||||
get_base_path(Host, Node, Base) ->
|
||||
<<Base/binary, "/server/", Host/binary, "/node/",
|
||||
(iolist_to_binary(atom_to_list(Node)))/binary, "/">>.
|
||||
|
||||
%%%==================================
|
||||
%%%% css & images
|
||||
@@ -356,11 +357,11 @@ additions_js() ->
|
||||
{error, _} -> <<>>
|
||||
end.
|
||||
|
||||
css(Host) ->
|
||||
css(Base, Host) ->
|
||||
case misc:read_css("admin.css") of
|
||||
{ok, CSS} ->
|
||||
Base = get_base_path(Host, cluster, 0),
|
||||
re:replace(CSS, <<"@BASE@">>, Base, [{return, binary}]);
|
||||
BP = get_base_path(Host, cluster, Base),
|
||||
re:replace(CSS, <<"@BASE@">>, BP, [{return, binary}]);
|
||||
{error, _} ->
|
||||
<<>>
|
||||
end.
|
||||
@@ -386,73 +387,73 @@ logo_fill() ->
|
||||
%%%==================================
|
||||
%%%% process_admin
|
||||
|
||||
process_admin(global, #request{path = [], lang = Lang}, AJID) ->
|
||||
process_admin(Base, global, #request{path = [], lang = Lang}, AJID) ->
|
||||
make_xhtml((?H1GL((translate:translate(Lang, ?T("Administration"))), <<"">>,
|
||||
<<"Contents">>))
|
||||
++
|
||||
[?XE(<<"ul">>,
|
||||
[?LI([?ACT(MIU, MIN)])
|
||||
|| {MIU, MIN}
|
||||
<- get_menu_items(global, cluster, Lang, AJID, 0)])],
|
||||
global, Lang, AJID, 0);
|
||||
process_admin(Host, #request{path = [], lang = Lang}, AJID) ->
|
||||
<- get_menu_items(global, cluster, Lang, AJID, Base)])],
|
||||
global, Lang, AJID, Base);
|
||||
process_admin(Base, Host, #request{path = [], lang = Lang}, AJID) ->
|
||||
make_xhtml([?XCT(<<"h1">>, ?T("Administration")),
|
||||
?XE(<<"ul">>,
|
||||
[?LI([?ACT(MIU, MIN)])
|
||||
|| {MIU, MIN}
|
||||
<- get_menu_items(Host, cluster, Lang, AJID, 2)])],
|
||||
Host, Lang, AJID, 2);
|
||||
process_admin(Host, #request{path = [<<"style.css">>]}, _) ->
|
||||
<- get_menu_items(Host, cluster, Lang, AJID, Base)])],
|
||||
Host, Lang, AJID, Base);
|
||||
process_admin(Base, Host, #request{path = [<<"style.css">>]}, _) ->
|
||||
{200,
|
||||
[{<<"Content-Type">>, <<"text/css">>}, last_modified(),
|
||||
cache_control_public()],
|
||||
css(Host)};
|
||||
process_admin(_Host, #request{path = [<<"favicon.ico">>]}, _) ->
|
||||
css(Base, Host)};
|
||||
process_admin(_Base, _Host, #request{path = [<<"favicon.ico">>]}, _) ->
|
||||
{200,
|
||||
[{<<"Content-Type">>, <<"image/x-icon">>},
|
||||
last_modified(), cache_control_public()],
|
||||
favicon()};
|
||||
process_admin(_Host, #request{path = [<<"logo.png">>]}, _) ->
|
||||
process_admin(_Base, _Host, #request{path = [<<"logo.png">>]}, _) ->
|
||||
{200,
|
||||
[{<<"Content-Type">>, <<"image/png">>}, last_modified(),
|
||||
cache_control_public()],
|
||||
logo()};
|
||||
process_admin(_Host, #request{path = [<<"logo-fill.png">>]}, _) ->
|
||||
process_admin(_Base, _Host, #request{path = [<<"logo-fill.png">>]}, _) ->
|
||||
{200,
|
||||
[{<<"Content-Type">>, <<"image/png">>}, last_modified(),
|
||||
cache_control_public()],
|
||||
logo_fill()};
|
||||
process_admin(_Host, #request{path = [<<"additions.js">>]}, _) ->
|
||||
process_admin(_Base, _Host, #request{path = [<<"additions.js">>]}, _) ->
|
||||
{200,
|
||||
[{<<"Content-Type">>, <<"text/javascript">>},
|
||||
last_modified(), cache_control_public()],
|
||||
additions_js()};
|
||||
process_admin(global, #request{path = [<<"vhosts">>], lang = Lang}, AJID) ->
|
||||
process_admin(Base, global, #request{path = [<<"vhosts">>], lang = Lang}, AJID) ->
|
||||
Res = list_vhosts(Lang, AJID),
|
||||
make_xhtml((?H1GL((translate:translate(Lang, ?T("Virtual Hosts"))),
|
||||
<<"virtual-hosting">>, ?T("Virtual Hosting")))
|
||||
++ Res,
|
||||
global, Lang, AJID, 1);
|
||||
process_admin(Host, #request{path = [<<"users">>], q = Query,
|
||||
global, Lang, AJID, Base);
|
||||
process_admin(Base, Host, #request{path = [<<"users">>], q = Query,
|
||||
lang = Lang}, AJID)
|
||||
when is_binary(Host) ->
|
||||
Res = list_users(Host, Query, Lang, fun url_func/1),
|
||||
Res = list_users(Base, Host, Query, Lang, fun url_func/1),
|
||||
make_xhtml([?XCT(<<"h1">>, ?T("Users"))] ++ Res, Host,
|
||||
Lang, AJID, 3);
|
||||
process_admin(Host, #request{path = [<<"users">>, Diap],
|
||||
Lang, AJID, Base);
|
||||
process_admin(Base, Host, #request{path = [<<"users">>, Diap],
|
||||
lang = Lang}, AJID)
|
||||
when is_binary(Host) ->
|
||||
Res = list_users_in_diapason(Host, Diap, Lang,
|
||||
Res = list_users_in_diapason(Base, Host, Diap, Lang,
|
||||
fun url_func/1),
|
||||
make_xhtml([?XCT(<<"h1">>, ?T("Users"))] ++ Res, Host,
|
||||
Lang, AJID, 4);
|
||||
process_admin(Host, #request{path = [<<"online-users">>],
|
||||
Lang, AJID, Base);
|
||||
process_admin(Base, Host, #request{path = [<<"online-users">>],
|
||||
lang = Lang}, AJID)
|
||||
when is_binary(Host) ->
|
||||
Res = list_online_users(Host, Lang),
|
||||
make_xhtml([?XCT(<<"h1">>, ?T("Online Users"))] ++ Res,
|
||||
Host, Lang, AJID, 3);
|
||||
process_admin(Host, #request{path = [<<"last-activity">>],
|
||||
Host, Lang, AJID, Base);
|
||||
process_admin(Base, Host, #request{path = [<<"last-activity">>],
|
||||
q = Query, lang = Lang}, AJID)
|
||||
when is_binary(Host) ->
|
||||
?DEBUG("Query: ~p", [Query]),
|
||||
@@ -493,49 +494,37 @@ process_admin(Host, #request{path = [<<"last-activity">>],
|
||||
?INPUTT(<<"submit">>, <<"integral">>,
|
||||
?T("Show Integral Table"))])]
|
||||
++ Res,
|
||||
Host, Lang, AJID, 3);
|
||||
process_admin(Host, #request{path = [<<"stats">>], lang = Lang}, AJID) ->
|
||||
Host, Lang, AJID, Base);
|
||||
process_admin(Base, Host, #request{path = [<<"stats">>], lang = Lang}, AJID) ->
|
||||
Res = get_stats(Host, Lang),
|
||||
PageH1 = ?H1GL(translate:translate(Lang, ?T("Statistics")), <<"mod-stats">>, <<"mod_stats">>),
|
||||
Level = case Host of
|
||||
global -> 1;
|
||||
_ -> 3
|
||||
end,
|
||||
make_xhtml(PageH1 ++ Res, Host, Lang, AJID, Level);
|
||||
process_admin(Host, #request{path = [<<"user">>, U],
|
||||
make_xhtml(PageH1 ++ Res, Host, Lang, AJID, Base);
|
||||
process_admin(Base, Host, #request{path = [<<"user">>, U],
|
||||
q = Query, lang = Lang}, AJID) ->
|
||||
case ejabberd_auth:user_exists(U, Host) of
|
||||
true ->
|
||||
Res = user_info(U, Host, Query, Lang),
|
||||
make_xhtml(Res, Host, Lang, AJID, 4);
|
||||
make_xhtml(Res, Host, Lang, AJID, Base);
|
||||
false ->
|
||||
make_xhtml([?XCT(<<"h1">>, ?T("Not Found"))], Host,
|
||||
Lang, AJID, 4)
|
||||
Lang, AJID, Base)
|
||||
end;
|
||||
process_admin(Host, #request{path = [<<"nodes">>], lang = Lang}, AJID) ->
|
||||
process_admin(Base, Host, #request{path = [<<"nodes">>], lang = Lang}, AJID) ->
|
||||
Res = get_nodes(Lang),
|
||||
Level = case Host of
|
||||
global -> 1;
|
||||
_ -> 3
|
||||
end,
|
||||
make_xhtml(Res, Host, Lang, AJID, Level);
|
||||
process_admin(Host, #request{path = [<<"node">>, SNode | NPath],
|
||||
make_xhtml(Res, Host, Lang, AJID, Base);
|
||||
process_admin(Base, Host, #request{path = [<<"node">>, SNode | NPath],
|
||||
q = Query, lang = Lang}, AJID) ->
|
||||
case search_running_node(SNode) of
|
||||
false ->
|
||||
make_xhtml([?XCT(<<"h1">>, ?T("Node not found"))], Host,
|
||||
Lang, AJID, 2);
|
||||
Lang, AJID, Base);
|
||||
Node ->
|
||||
Res = get_node(Host, Node, NPath, Query, Lang),
|
||||
Level = case Host of
|
||||
global -> 2 + length(NPath);
|
||||
_ -> 4 + length(NPath)
|
||||
end,
|
||||
make_xhtml(Res, Host, Node, Lang, AJID, Level)
|
||||
Res = get_node(Base, Host, Node, NPath, Query, Lang),
|
||||
make_xhtml(Res, Host, Node, Lang, AJID, Base)
|
||||
end;
|
||||
%%%==================================
|
||||
%%%% process_admin default case
|
||||
process_admin(Host, #request{lang = Lang} = Request, AJID) ->
|
||||
process_admin(Base, Host, #request{lang = Lang} = Request, AJID) ->
|
||||
Res = case Host of
|
||||
global ->
|
||||
ejabberd_hooks:run_fold(
|
||||
@@ -544,17 +533,13 @@ process_admin(Host, #request{lang = Lang} = Request, AJID) ->
|
||||
ejabberd_hooks:run_fold(
|
||||
webadmin_page_host, Host, [], [Host, Request])
|
||||
end,
|
||||
Level = case Host of
|
||||
global -> length(Request#request.path);
|
||||
_ -> 2 + length(Request#request.path)
|
||||
end,
|
||||
case Res of
|
||||
[] ->
|
||||
setelement(1,
|
||||
make_xhtml([?XC(<<"h1">>, <<"Not Found">>)], Host, Lang,
|
||||
AJID, Level),
|
||||
AJID, Base),
|
||||
404);
|
||||
_ -> make_xhtml(Res, Host, Lang, AJID, Level)
|
||||
_ -> make_xhtml(Res, Host, Lang, AJID, Base)
|
||||
end.
|
||||
|
||||
term_to_id(T) -> base64:encode((term_to_binary(T))).
|
||||
@@ -601,13 +586,13 @@ list_vhosts2(Lang, Hosts) ->
|
||||
%%%==================================
|
||||
%%%% list_users
|
||||
|
||||
list_users(Host, Query, Lang, URLFunc) ->
|
||||
list_users(Base, Host, Query, Lang, URLFunc) ->
|
||||
Res = list_users_parse_query(Query, Host),
|
||||
Users = ejabberd_auth:get_users(Host),
|
||||
SUsers = lists:sort([{S, U} || {U, S} <- Users]),
|
||||
FUsers = case length(SUsers) of
|
||||
N when N =< 100 ->
|
||||
[list_given_users(Host, SUsers, <<"../">>, Lang,
|
||||
[list_given_users(Host, SUsers, Base, Lang,
|
||||
URLFunc)];
|
||||
N ->
|
||||
NParts = trunc(math:sqrt(N * 6.17999999999999993783e-1))
|
||||
@@ -683,17 +668,18 @@ list_users_parse_query(Query, Host) ->
|
||||
false -> nothing
|
||||
end.
|
||||
|
||||
list_users_in_diapason(Host, Diap, Lang, URLFunc) ->
|
||||
list_users_in_diapason(Base, Host, Diap, Lang, URLFunc) ->
|
||||
Users = ejabberd_auth:get_users(Host),
|
||||
SUsers = lists:sort([{S, U} || {U, S} <- Users]),
|
||||
[S1, S2] = ejabberd_regexp:split(Diap, <<"-">>),
|
||||
N1 = binary_to_integer(S1),
|
||||
N2 = binary_to_integer(S2),
|
||||
Sub = lists:sublist(SUsers, N1, N2 - N1 + 1),
|
||||
[list_given_users(Host, Sub, <<"../../">>, Lang,
|
||||
[list_given_users(Host, Sub, Base, Lang,
|
||||
URLFunc)].
|
||||
|
||||
list_given_users(Host, Users, Prefix, Lang, URLFunc) ->
|
||||
list_given_users(Host, Users, Base, Lang, URLFunc) ->
|
||||
Prefix = get_base_path(Host, cluster, Base),
|
||||
ModOffline = get_offlinemsg_module(Host),
|
||||
?XE(<<"table">>,
|
||||
[?XE(<<"thead">>,
|
||||
@@ -1075,10 +1061,10 @@ search_running_node(SNode, [Node | Nodes]) ->
|
||||
_ -> search_running_node(SNode, Nodes)
|
||||
end.
|
||||
|
||||
get_node(global, Node, [], Query, Lang) ->
|
||||
get_node(Base, global, Node, [], Query, Lang) ->
|
||||
Res = node_parse_query(Node, Query),
|
||||
Base = get_base_path(global, Node, 2),
|
||||
MenuItems2 = make_menu_items(global, Node, Base, Lang),
|
||||
BP = get_base_path(global, Node, Base),
|
||||
MenuItems2 = make_menu_items(global, Node, BP, Lang),
|
||||
[?XC(<<"h1">>,
|
||||
(str:format(translate:translate(Lang, ?T("Node ~p")), [Node])))]
|
||||
++
|
||||
@@ -1099,12 +1085,12 @@ get_node(global, Node, [], Query, Lang) ->
|
||||
[?INPUTT(<<"submit">>, <<"restart">>, ?T("Restart")),
|
||||
?C(<<" ">>),
|
||||
?INPUTT(<<"submit">>, <<"stop">>, ?T("Stop"))])];
|
||||
get_node(Host, Node, [], _Query, Lang) ->
|
||||
Base = get_base_path(Host, Node, 4),
|
||||
MenuItems2 = make_menu_items(Host, Node, Base, Lang),
|
||||
get_node(Base, Host, Node, [], _Query, Lang) ->
|
||||
BP = get_base_path(Host, Node, Base),
|
||||
MenuItems2 = make_menu_items(Host, Node, BP, Lang),
|
||||
[?XC(<<"h1">>, (str:format(translate:translate(Lang, ?T("Node ~p")), [Node]))),
|
||||
?XE(<<"ul">>, MenuItems2)];
|
||||
get_node(global, Node, [<<"db">>], Query, Lang) ->
|
||||
get_node(_Base, global, Node, [<<"db">>], Query, Lang) ->
|
||||
case ejabberd_cluster:call(Node, mnesia, system_info, [tables]) of
|
||||
{badrpc, _Reason} ->
|
||||
[?XCT(<<"h1">>, ?T("RPC Call Error"))];
|
||||
@@ -1182,7 +1168,7 @@ get_node(global, Node, [<<"db">>], Query, Lang) ->
|
||||
<<"submit">>,
|
||||
?T("Submit"))])])]))])])]
|
||||
end;
|
||||
get_node(global, Node, [<<"backup">>], Query, Lang) ->
|
||||
get_node(_Base, global, Node, [<<"backup">>], Query, Lang) ->
|
||||
HomeDirRaw = case {os:getenv("HOME"), os:type()} of
|
||||
{EnvHome, _} when is_list(EnvHome) -> list_to_binary(EnvHome);
|
||||
{false, {win32, _Osname}} -> <<"C:/">>;
|
||||
@@ -1332,7 +1318,7 @@ get_node(global, Node, [<<"backup">>], Query, Lang) ->
|
||||
?XE(<<"td">>,
|
||||
[?INPUTT(<<"submit">>, <<"import_dir">>,
|
||||
?T("OK"))])])])])])];
|
||||
get_node(global, Node, [<<"stats">>], _Query, Lang) ->
|
||||
get_node(_Base, global, Node, [<<"stats">>], _Query, Lang) ->
|
||||
UpTime = ejabberd_cluster:call(Node, erlang, statistics,
|
||||
[wall_clock]),
|
||||
UpTimeS = (str:format("~.3f",
|
||||
@@ -1381,7 +1367,7 @@ get_node(global, Node, [<<"stats">>], _Query, Lang) ->
|
||||
[?XCT(<<"td">>, ?T("Transactions Logged:")),
|
||||
?XAC(<<"td">>, [{<<"class">>, <<"alignright">>}],
|
||||
(pretty_string_int(TransactionsLogged)))])])])];
|
||||
get_node(global, Node, [<<"update">>], Query, Lang) ->
|
||||
get_node(_Base, global, Node, [<<"update">>], Query, Lang) ->
|
||||
ejabberd_cluster:call(Node, code, purge, [ejabberd_update]),
|
||||
Res = node_update_parse_query(Node, Query),
|
||||
ejabberd_cluster:call(Node, code, load_file, [ejabberd_update]),
|
||||
@@ -1437,7 +1423,7 @@ get_node(global, Node, [<<"update">>], Query, Lang) ->
|
||||
?XC(<<"pre">>, (misc:atom_to_binary(Check))),
|
||||
?BR,
|
||||
?INPUTT(<<"submit">>, <<"update">>, ?T("Update"))])];
|
||||
get_node(Host, Node, NPath, Query, Lang) ->
|
||||
get_node(_Base, Host, Node, NPath, Query, Lang) ->
|
||||
Res = case Host of
|
||||
global ->
|
||||
ejabberd_hooks:run_fold(webadmin_page_node, Host, [],
|
||||
@@ -1749,19 +1735,19 @@ make_navigation_menu(Host, Node, Lang, JID, Level) ->
|
||||
make_server_menu(HostMenu, NodeMenu, Lang, JID, Level).
|
||||
|
||||
%% @spec (Host, Node, Base, Lang) -> [LI]
|
||||
make_menu_items(global, cluster, Base, Lang) ->
|
||||
make_menu_items(global, cluster, BP, Lang) ->
|
||||
HookItems = get_menu_items_hook(server, Lang),
|
||||
make_menu_items(Lang, {Base, <<"">>, HookItems});
|
||||
make_menu_items(global, Node, Base, Lang) ->
|
||||
make_menu_items(Lang, {BP, <<"">>, HookItems});
|
||||
make_menu_items(global, Node, BP, Lang) ->
|
||||
HookItems = get_menu_items_hook({node, Node}, Lang),
|
||||
make_menu_items(Lang, {Base, <<"">>, HookItems});
|
||||
make_menu_items(Host, cluster, Base, Lang) ->
|
||||
make_menu_items(Lang, {BP, <<"">>, HookItems});
|
||||
make_menu_items(Host, cluster, BP, Lang) ->
|
||||
HookItems = get_menu_items_hook({host, Host}, Lang),
|
||||
make_menu_items(Lang, {Base, <<"">>, HookItems});
|
||||
make_menu_items(Host, Node, Base, Lang) ->
|
||||
make_menu_items(Lang, {BP, <<"">>, HookItems});
|
||||
make_menu_items(Host, Node, BP, Lang) ->
|
||||
HookItems = get_menu_items_hook({hostnode, Host, Node},
|
||||
Lang),
|
||||
make_menu_items(Lang, {Base, <<"">>, HookItems}).
|
||||
make_menu_items(Lang, {BP, <<"">>, HookItems}).
|
||||
|
||||
make_host_node_menu(global, _, _Lang, _JID, _Level) ->
|
||||
{<<"">>, <<"">>, []};
|
||||
@@ -1803,22 +1789,19 @@ make_node_menu(global, Node, Lang, Level) ->
|
||||
{<<"stats">>, ?T("Statistics")},
|
||||
{<<"update">>, ?T("Update")}]
|
||||
++ get_menu_items_hook({node, Node}, Lang),
|
||||
{NodeBase, iolist_to_binary(atom_to_list(Node)),
|
||||
NodeFixed};
|
||||
make_node_menu(_Host, _Node, _Lang, _Level) ->
|
||||
{<<"">>, <<"">>, []}.
|
||||
{NodeBase, iolist_to_binary(atom_to_list(Node)), NodeFixed}.
|
||||
|
||||
make_server_menu(HostMenu, NodeMenu, Lang, JID, Level) ->
|
||||
Base = get_base_path(global, cluster, Level),
|
||||
BP = get_base_path(global, cluster, Level),
|
||||
Fixed = [{<<"vhosts">>, ?T("Virtual Hosts"), HostMenu},
|
||||
{<<"nodes">>, ?T("Nodes"), NodeMenu},
|
||||
{<<"stats">>, ?T("Statistics")}]
|
||||
++ get_menu_items_hook(server, Lang),
|
||||
BasePath = url_to_path(Base),
|
||||
Base = url_to_path(BP),
|
||||
Fixed2 = [Tuple
|
||||
|| Tuple <- Fixed,
|
||||
is_allowed_path(BasePath, Tuple, JID)],
|
||||
{Base, <<"">>, Fixed2}.
|
||||
is_allowed_path(Base, Tuple, JID)],
|
||||
{BP, <<"">>, Fixed2}.
|
||||
|
||||
get_menu_items_hook({hostnode, Host, Node}, Lang) ->
|
||||
ejabberd_hooks:run_fold(webadmin_menu_hostnode, Host,
|
||||
|
||||
+1
-1
@@ -570,7 +570,7 @@ compile_result(Results) ->
|
||||
end.
|
||||
|
||||
compile_options() ->
|
||||
[verbose, report_errors, report_warnings]
|
||||
[verbose, report_errors, report_warnings, ?ALL_DEFS]
|
||||
++ [{i, filename:join(app_dir(App), "include")}
|
||||
|| App <- [fast_xml, xmpp, p1_utils, ejabberd]]
|
||||
++ [{i, filename:join(mod_dir(Mod), "include")}
|
||||
|
||||
@@ -1513,6 +1513,9 @@ send_stanza(FromString, ToString, Stanza) ->
|
||||
catch _:{xmpp_codec, Why} ->
|
||||
io:format("incorrect stanza: ~ts~n", [xmpp:format_error(Why)]),
|
||||
{error, Why};
|
||||
_:{badmatch, {error, {Code, Why}}} when is_integer(Code) ->
|
||||
io:format("invalid xml: ~p~n", [Why]),
|
||||
{error, Why};
|
||||
_:{badmatch, {error, Why}} ->
|
||||
io:format("invalid xml: ~p~n", [Why]),
|
||||
{error, Why};
|
||||
|
||||
@@ -268,7 +268,7 @@ is_received_muc_invite(Msg, received) ->
|
||||
#muc_user{invites = [_|_]} ->
|
||||
true;
|
||||
_ ->
|
||||
xmpp:has_subtag(Msg, #x_conference{})
|
||||
xmpp:has_subtag(Msg, #x_conference{jid = jid:make(<<"">>)})
|
||||
end.
|
||||
|
||||
-spec is_received_muc_pm(jid(), message(), direction()) -> boolean().
|
||||
|
||||
@@ -55,10 +55,11 @@ get_last(LUser, LServer) ->
|
||||
end.
|
||||
|
||||
store_last_info(LUser, LServer, TimeStamp, Status) ->
|
||||
TS = integer_to_binary(TimeStamp),
|
||||
case ?SQL_UPSERT(LServer, "last",
|
||||
["!username=%(LUser)s",
|
||||
"!server_host=%(LServer)s",
|
||||
"seconds=%(TimeStamp)d",
|
||||
"seconds=%(TS)s",
|
||||
"state=%(Status)s"]) of
|
||||
ok ->
|
||||
ok;
|
||||
@@ -76,11 +77,12 @@ export(_Server) ->
|
||||
fun(Host, #last_activity{us = {LUser, LServer},
|
||||
timestamp = TimeStamp, status = Status})
|
||||
when LServer == Host ->
|
||||
TS = integer_to_binary(TimeStamp),
|
||||
[?SQL("delete from last where username=%(LUser)s and %(LServer)H;"),
|
||||
?SQL_INSERT("last",
|
||||
["username=%(LUser)s",
|
||||
"server_host=%(LServer)s",
|
||||
"seconds=%(TimeStamp)d",
|
||||
"seconds=%(TS)s",
|
||||
"state=%(Status)s"])];
|
||||
(_Host, _R) ->
|
||||
[]
|
||||
|
||||
@@ -805,7 +805,7 @@ get_rooms(ServiceArg) ->
|
||||
Hosts = find_services(ServiceArg),
|
||||
lists:flatmap(
|
||||
fun(Host) ->
|
||||
[{RoomName, RoomHost, Host, Pid}
|
||||
[{RoomName, RoomHost, ejabberd_router:host_of_route(Host), Pid}
|
||||
|| {RoomName, RoomHost, Pid} <- mod_muc:get_online_rooms(Host)]
|
||||
end, Hosts).
|
||||
|
||||
|
||||
@@ -217,6 +217,8 @@ unsubscribe(Pid, JID) ->
|
||||
try p1_fsm:sync_send_all_state_event(Pid, {muc_unsubscribe, JID})
|
||||
catch _:{timeout, {p1_fsm, _, _}} ->
|
||||
{error, ?T("Request has timed out")};
|
||||
exit:{normal, {p1_fsm, _, _}} ->
|
||||
ok;
|
||||
_:{_, {p1_fsm, _, _}} ->
|
||||
{error, ?T("Conference room does not exist")}
|
||||
end.
|
||||
@@ -741,10 +743,13 @@ handle_sync_event({muc_subscribe, From, Nick, Nodes}, _From,
|
||||
{error, Err} ->
|
||||
{reply, {error, get_error_text(Err)}, StateName, StateData}
|
||||
end;
|
||||
handle_sync_event({muc_unsubscribe, From}, _From, StateName, StateData) ->
|
||||
handle_sync_event({muc_unsubscribe, From}, _From, StateName,
|
||||
#state{config = Conf} = StateData) ->
|
||||
IQ = #iq{type = set, id = p1_rand:get_string(),
|
||||
from = From, sub_els = [#muc_unsubscribe{}]},
|
||||
case process_iq_mucsub(From, IQ, StateData) of
|
||||
{result, _, stop} ->
|
||||
{stop, normal, StateData#state{config = Conf#config{persistent = false}}};
|
||||
{result, _, NewState} ->
|
||||
{reply, ok, StateName, NewState};
|
||||
{ignore, NewState} ->
|
||||
@@ -4198,7 +4203,7 @@ process_iq_vcard(From, #iq{type = set, lang = Lang, sub_els = [Pkt]},
|
||||
|
||||
-spec process_iq_mucsub(jid(), iq(), state()) ->
|
||||
{error, stanza_error()} |
|
||||
{result, undefined | muc_subscribe() | muc_subscriptions(), state()} |
|
||||
{result, undefined | muc_subscribe() | muc_subscriptions(), stop | state()} |
|
||||
{ignore, state()}.
|
||||
process_iq_mucsub(_From, #iq{type = set, lang = Lang,
|
||||
sub_els = [#muc_subscribe{}]},
|
||||
|
||||
+11
-22
@@ -93,31 +93,20 @@ process([], #request{method = 'GET', lang = Lang}) ->
|
||||
process([<<"register.css">>],
|
||||
#request{method = 'GET'}) ->
|
||||
serve_css();
|
||||
process([<<"new">>],
|
||||
process([Section],
|
||||
#request{method = 'GET', lang = Lang, host = Host,
|
||||
ip = IP}) ->
|
||||
case ejabberd_router:is_my_host(Host) of
|
||||
ip = {Addr, _Port}}) ->
|
||||
Host2 = case ejabberd_router:is_my_host(Host) of
|
||||
true ->
|
||||
{Addr, _Port} = IP,
|
||||
form_new_get(Host, Lang, Addr);
|
||||
Host;
|
||||
false ->
|
||||
{400, [], <<"Host not served">>}
|
||||
end;
|
||||
process([<<"delete">>],
|
||||
#request{method = 'GET', lang = Lang, host = Host}) ->
|
||||
case ejabberd_router:is_my_host(Host) of
|
||||
true ->
|
||||
form_del_get(Host, Lang);
|
||||
false ->
|
||||
{400, [], <<"Host not served">>}
|
||||
end;
|
||||
process([<<"change_password">>],
|
||||
#request{method = 'GET', lang = Lang, host = Host}) ->
|
||||
case ejabberd_router:is_my_host(Host) of
|
||||
true ->
|
||||
form_changepass_get(Host, Lang);
|
||||
false ->
|
||||
{400, [], <<"Host not served">>}
|
||||
<<"">>
|
||||
end,
|
||||
case Section of
|
||||
<<"new">> -> form_new_get(Host2, Lang, Addr);
|
||||
<<"delete">> -> form_del_get(Host2, Lang);
|
||||
<<"change_password">> -> form_changepass_get(Host2, Lang);
|
||||
_ -> {404, [], "Not Found"}
|
||||
end;
|
||||
process([<<"new">>],
|
||||
#request{method = 'POST', q = Q, ip = {Ip, _Port},
|
||||
|
||||
+242
-76
@@ -71,10 +71,20 @@
|
||||
-callback is_user_in_group({binary(), binary()}, binary(), binary()) -> boolean().
|
||||
-callback add_user_to_group(binary(), {binary(), binary()}, binary()) -> any().
|
||||
-callback remove_user_from_group(binary(), {binary(), binary()}, binary()) -> {atomic, any()}.
|
||||
-callback use_cache(binary()) -> boolean().
|
||||
-callback cache_nodes(binary()) -> [node()].
|
||||
|
||||
-optional_callbacks([use_cache/1, cache_nodes/1]).
|
||||
|
||||
-define(GROUP_OPTS_CACHE, shared_roster_group_opts_cache).
|
||||
-define(USER_GROUPS_CACHE, shared_roster_user_groups_cache).
|
||||
-define(GROUP_EXPLICIT_USERS_CACHE, shared_roster_group_explicit_cache).
|
||||
-define(SPECIAL_GROUPS_CACHE, shared_roster_special_groups_cache).
|
||||
|
||||
start(Host, Opts) ->
|
||||
Mod = gen_mod:db_mod(Opts, ?MODULE),
|
||||
Mod:init(Host, Opts),
|
||||
init_cache(Mod, Host, Opts),
|
||||
ejabberd_hooks:add(webadmin_menu_host, Host, ?MODULE,
|
||||
webadmin_menu, 70),
|
||||
ejabberd_hooks:add(webadmin_page_host, Host, ?MODULE,
|
||||
@@ -136,6 +146,43 @@ reload(Host, NewOpts, OldOpts) ->
|
||||
depends(_Host, _Opts) ->
|
||||
[].
|
||||
|
||||
-spec init_cache(module(), binary(), gen_mod:opts()) -> ok.
|
||||
init_cache(Mod, Host, Opts) ->
|
||||
case use_cache(Mod, Host) of
|
||||
true ->
|
||||
CacheOpts = cache_opts(Opts),
|
||||
ets_cache:new(?GROUP_OPTS_CACHE, CacheOpts),
|
||||
ets_cache:new(?USER_GROUPS_CACHE, CacheOpts),
|
||||
ets_cache:new(?GROUP_EXPLICIT_USERS_CACHE, CacheOpts),
|
||||
ets_cache:new(?SPECIAL_GROUPS_CACHE, CacheOpts);
|
||||
false ->
|
||||
ets_cache:delete(?GROUP_OPTS_CACHE),
|
||||
ets_cache:delete(?USER_GROUPS_CACHE),
|
||||
ets_cache:delete(?GROUP_EXPLICIT_USERS_CACHE),
|
||||
ets_cache:delete(?SPECIAL_GROUPS_CACHE)
|
||||
end.
|
||||
|
||||
-spec cache_opts(gen_mod:opts()) -> [proplists:property()].
|
||||
cache_opts(Opts) ->
|
||||
MaxSize = mod_private_opt:cache_size(Opts),
|
||||
CacheMissed = mod_private_opt:cache_missed(Opts),
|
||||
LifeTime = mod_private_opt:cache_life_time(Opts),
|
||||
[{max_size, MaxSize}, {cache_missed, CacheMissed}, {life_time, LifeTime}].
|
||||
|
||||
-spec use_cache(module(), binary()) -> boolean().
|
||||
use_cache(Mod, Host) ->
|
||||
case erlang:function_exported(Mod, use_cache, 1) of
|
||||
true -> Mod:use_cache(Host);
|
||||
false -> mod_shared_roster_opt:use_cache(Host)
|
||||
end.
|
||||
|
||||
-spec cache_nodes(module(), binary()) -> [node()].
|
||||
cache_nodes(Mod, Host) ->
|
||||
case erlang:function_exported(Mod, cache_nodes, 1) of
|
||||
true -> Mod:cache_nodes(Host);
|
||||
false -> ejabberd_cluster:get_nodes()
|
||||
end.
|
||||
|
||||
-spec get_user_roster([#roster{}], {binary(), binary()}) -> [#roster{}].
|
||||
get_user_roster(Items, US) ->
|
||||
{U, S} = US,
|
||||
@@ -376,24 +423,69 @@ create_group(Host, Group) ->
|
||||
|
||||
create_group(Host, Group, Opts) ->
|
||||
Mod = gen_mod:db_mod(Host, ?MODULE),
|
||||
case use_cache(Mod, Host) of
|
||||
true ->
|
||||
ets_cache:insert(?GROUP_OPTS_CACHE, {Host, Group}, Opts, cache_nodes(Mod, Host)),
|
||||
ets_cache:clear(?SPECIAL_GROUPS_CACHE, cache_nodes(Mod, Host));
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
Mod:create_group(Host, Group, Opts).
|
||||
|
||||
delete_group(Host, Group) ->
|
||||
Mod = gen_mod:db_mod(Host, ?MODULE),
|
||||
case use_cache(Mod, Host) of
|
||||
true ->
|
||||
ets_cache:delete(?GROUP_OPTS_CACHE, {Host, Group}, cache_nodes(Mod, Host)),
|
||||
ets_cache:clear(?USER_GROUPS_CACHE, cache_nodes(Mod, Host)),
|
||||
ets_cache:clear(?GROUP_EXPLICIT_USERS_CACHE, cache_nodes(Mod, Host)),
|
||||
ets_cache:clear(?SPECIAL_GROUPS_CACHE, cache_nodes(Mod, Host));
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
Mod:delete_group(Host, Group).
|
||||
|
||||
get_group_opts(Host, Group) ->
|
||||
Mod = gen_mod:db_mod(Host, ?MODULE),
|
||||
Mod:get_group_opts(Host, Group).
|
||||
case use_cache(Mod, Host) of
|
||||
true ->
|
||||
ets_cache:lookup(
|
||||
?GROUP_OPTS_CACHE, {Host, Group},
|
||||
fun() ->
|
||||
case Mod:get_group_opts(Host, Group) of
|
||||
error -> error;
|
||||
V -> {cache, V}
|
||||
end
|
||||
end);
|
||||
false ->
|
||||
Mod:get_group_opts(Host, Group)
|
||||
end.
|
||||
|
||||
set_group_opts(Host, Group, Opts) ->
|
||||
Mod = gen_mod:db_mod(Host, ?MODULE),
|
||||
case use_cache(Mod, Host) of
|
||||
true ->
|
||||
ets_cache:insert(?GROUP_OPTS_CACHE, {Host, Group}, Opts, cache_nodes(Mod, Host)),
|
||||
ets_cache:clear(?SPECIAL_GROUPS_CACHE, cache_nodes(Mod, Host));
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
Mod:set_group_opts(Host, Group, Opts).
|
||||
|
||||
get_user_groups(US) ->
|
||||
Host = element(2, US),
|
||||
Mod = gen_mod:db_mod(Host, ?MODULE),
|
||||
Mod:get_user_groups(US, Host) ++ get_special_users_groups(Host).
|
||||
UG = case use_cache(Mod, Host) of
|
||||
true ->
|
||||
ets_cache:lookup(
|
||||
?USER_GROUPS_CACHE, {Host, US},
|
||||
fun() ->
|
||||
{cache, Mod:get_user_groups(US, Host)}
|
||||
end);
|
||||
false ->
|
||||
Mod:get_user_groups(US, Host)
|
||||
end,
|
||||
UG ++ get_special_users_groups(Host).
|
||||
|
||||
is_group_enabled(Host1, Group1) ->
|
||||
{Host, Group} = split_grouphost(Host1, Group1),
|
||||
@@ -419,16 +511,7 @@ get_online_users(Host) ->
|
||||
|
||||
get_group_users(Host1, Group1) ->
|
||||
{Host, Group} = split_grouphost(Host1, Group1),
|
||||
case get_group_opt(Host, Group, all_users, false) of
|
||||
true -> ejabberd_auth:get_users(Host);
|
||||
false -> []
|
||||
end
|
||||
++
|
||||
case get_group_opt(Host, Group, online_users, false) of
|
||||
true -> get_online_users(Host);
|
||||
false -> []
|
||||
end
|
||||
++ get_group_explicit_users(Host, Group).
|
||||
get_group_users(Host, Group, get_group_opts(Host, Group)).
|
||||
|
||||
get_group_users(Host, Group, GroupOpts) ->
|
||||
case proplists:get_value(all_users, GroupOpts, false) of
|
||||
@@ -445,7 +528,16 @@ get_group_users(Host, Group, GroupOpts) ->
|
||||
|
||||
get_group_explicit_users(Host, Group) ->
|
||||
Mod = gen_mod:db_mod(Host, ?MODULE),
|
||||
Mod:get_group_explicit_users(Host, Group).
|
||||
case use_cache(Mod, Host) of
|
||||
true ->
|
||||
ets_cache:lookup(
|
||||
?GROUP_EXPLICIT_USERS_CACHE, {Host, Group},
|
||||
fun() ->
|
||||
{cache, Mod:get_group_explicit_users(Host, Group)}
|
||||
end);
|
||||
false ->
|
||||
Mod:get_group_explicit_users(Host, Group)
|
||||
end.
|
||||
|
||||
get_group_name(Host1, Group1) ->
|
||||
{Host, Group} = split_grouphost(Host1, Group1),
|
||||
@@ -453,24 +545,55 @@ get_group_name(Host1, Group1) ->
|
||||
|
||||
%% Get list of names of groups that have @all@/@online@/etc in the memberlist
|
||||
get_special_users_groups(Host) ->
|
||||
lists:filtermap(fun ({Group, Opts}) ->
|
||||
case proplists:get_value(all_users, Opts, false) orelse
|
||||
proplists:get_value(online_users, Opts, false) of
|
||||
true -> {true, Group};
|
||||
false -> false
|
||||
end
|
||||
end,
|
||||
groups_with_opts(Host)).
|
||||
Extract =
|
||||
fun() ->
|
||||
lists:filtermap(
|
||||
fun({Group, Opts}) ->
|
||||
case proplists:get_value(all_users, Opts, false) orelse
|
||||
proplists:get_value(online_users, Opts, false) of
|
||||
true -> {true, Group};
|
||||
false -> false
|
||||
end
|
||||
end,
|
||||
groups_with_opts(Host))
|
||||
end,
|
||||
Mod = gen_mod:db_mod(Host, ?MODULE),
|
||||
case use_cache(Mod, Host) of
|
||||
true ->
|
||||
ets_cache:lookup(
|
||||
?SPECIAL_GROUPS_CACHE, {Host, false},
|
||||
fun() ->
|
||||
{cache, Extract()}
|
||||
end);
|
||||
false ->
|
||||
Extract()
|
||||
end.
|
||||
|
||||
|
||||
%% Get list of names of groups that have @online@ in the memberlist
|
||||
get_special_users_groups_online(Host) ->
|
||||
lists:filtermap(fun ({Group, Opts}) ->
|
||||
case proplists:get_value(online_users, Opts, false) of
|
||||
true -> {true, Group};
|
||||
false -> false
|
||||
end
|
||||
end,
|
||||
groups_with_opts(Host)).
|
||||
Extract =
|
||||
fun() ->
|
||||
lists:filtermap(
|
||||
fun({Group, Opts}) ->
|
||||
case proplists:get_value(online_users, Opts, false) of
|
||||
true -> {true, Group};
|
||||
false -> false
|
||||
end
|
||||
end,
|
||||
groups_with_opts(Host))
|
||||
end,
|
||||
Mod = gen_mod:db_mod(Host, ?MODULE),
|
||||
case use_cache(Mod, Host) of
|
||||
true ->
|
||||
ets_cache:lookup(
|
||||
?SPECIAL_GROUPS_CACHE, {Host, true},
|
||||
fun() ->
|
||||
{cache, Extract()}
|
||||
end);
|
||||
false ->
|
||||
Extract()
|
||||
end.
|
||||
|
||||
%% Given two lists of groupnames and their options,
|
||||
%% return the list of displayed groups to the second list
|
||||
@@ -555,27 +678,32 @@ add_user_to_group2(Host, US, Group) ->
|
||||
{LUser, LServer} = US,
|
||||
case ejabberd_regexp:run(LUser, <<"^@.+@\$">>) of
|
||||
match ->
|
||||
GroupOpts = mod_shared_roster:get_group_opts(Host, Group),
|
||||
GroupOpts = get_group_opts(Host, Group),
|
||||
MoreGroupOpts = case LUser of
|
||||
<<"@all@">> -> [{all_users, true}];
|
||||
<<"@online@">> -> [{online_users, true}];
|
||||
_ -> []
|
||||
end,
|
||||
mod_shared_roster:set_group_opts(Host, Group,
|
||||
GroupOpts ++ MoreGroupOpts);
|
||||
set_group_opts(Host, Group,
|
||||
GroupOpts ++ MoreGroupOpts);
|
||||
nomatch ->
|
||||
DisplayedToGroups = displayed_to_groups(Group, Host),
|
||||
DisplayedGroups = get_displayed_groups(Group, LServer),
|
||||
push_user_to_displayed(LUser, LServer, Group, Host, both, DisplayedToGroups),
|
||||
push_displayed_to_user(LUser, LServer, Host, both, DisplayedGroups),
|
||||
Mod = gen_mod:db_mod(Host, ?MODULE),
|
||||
case use_cache(Mod, Host) of
|
||||
true ->
|
||||
ets_cache:delete(?USER_GROUPS_CACHE, {Host, US}, cache_nodes(Mod, Host)),
|
||||
ets_cache:delete(?GROUP_EXPLICIT_USERS_CACHE, {Host, Group}, cache_nodes(Mod, Host));
|
||||
false ->
|
||||
ok
|
||||
end,
|
||||
Mod:add_user_to_group(Host, US, Group)
|
||||
end.
|
||||
|
||||
get_displayed_groups(Group, LServer) ->
|
||||
GroupsOpts = groups_with_opts(LServer),
|
||||
GroupOpts = proplists:get_value(Group, GroupsOpts, []),
|
||||
proplists:get_value(displayed_groups, GroupOpts, []).
|
||||
get_group_opt(LServer, Group, displayed_groups, []).
|
||||
|
||||
push_displayed_to_user(LUser, LServer, Host, Subscription, DisplayedGroups) ->
|
||||
[push_members_to_user(LUser, LServer, DGroup, Host,
|
||||
@@ -586,7 +714,7 @@ remove_user_from_group(Host, US, Group) ->
|
||||
{LUser, LServer} = US,
|
||||
case ejabberd_regexp:run(LUser, <<"^@.+@\$">>) of
|
||||
match ->
|
||||
GroupOpts = mod_shared_roster:get_group_opts(Host, Group),
|
||||
GroupOpts = get_group_opts(Host, Group),
|
||||
NewGroupOpts = case LUser of
|
||||
<<"@all@">> ->
|
||||
lists:filter(fun (X) -> X /= {all_users, true}
|
||||
@@ -597,9 +725,16 @@ remove_user_from_group(Host, US, Group) ->
|
||||
end,
|
||||
GroupOpts)
|
||||
end,
|
||||
mod_shared_roster:set_group_opts(Host, Group, NewGroupOpts);
|
||||
set_group_opts(Host, Group, NewGroupOpts);
|
||||
nomatch ->
|
||||
Mod = gen_mod:db_mod(Host, ?MODULE),
|
||||
case use_cache(Mod, Host) of
|
||||
true ->
|
||||
ets_cache:delete(?USER_GROUPS_CACHE, {Host, US}, cache_nodes(Mod, Host)),
|
||||
ets_cache:delete(?GROUP_EXPLICIT_USERS_CACHE, {Host, Group}, cache_nodes(Mod, Host));
|
||||
false ->
|
||||
ok
|
||||
end,
|
||||
Result = Mod:remove_user_from_group(Host, US, Group),
|
||||
DisplayedToGroups = displayed_to_groups(Group, Host),
|
||||
DisplayedGroups = get_displayed_groups(Group, LServer),
|
||||
@@ -610,8 +745,7 @@ remove_user_from_group(Host, US, Group) ->
|
||||
|
||||
push_members_to_user(LUser, LServer, Group, Host,
|
||||
Subscription) ->
|
||||
GroupsOpts = groups_with_opts(LServer),
|
||||
GroupOpts = proplists:get_value(Group, GroupsOpts, []),
|
||||
GroupOpts = get_group_opts(LServer, Group),
|
||||
GroupName = proplists:get_value(name, GroupOpts, Group),
|
||||
Members = get_group_users(Host, Group),
|
||||
lists:foreach(fun ({U, S}) ->
|
||||
@@ -659,9 +793,7 @@ push_user_to_members(User, Server, Subscription) ->
|
||||
lists:usort(SpecialGroups ++ UserGroups)).
|
||||
|
||||
push_user_to_displayed(LUser, LServer, Group, Host, Subscription, DisplayedToGroupsOpts) ->
|
||||
GroupsOpts = groups_with_opts(Host),
|
||||
GroupOpts = proplists:get_value(Group, GroupsOpts, []),
|
||||
GroupName = proplists:get_value(name, GroupOpts, Group),
|
||||
GroupName = get_group_opt(Host, Group, name, Group),
|
||||
[push_user_to_group(LUser, LServer, GroupD, Host,
|
||||
GroupName, Subscription)
|
||||
|| GroupD <- DisplayedToGroupsOpts].
|
||||
@@ -722,13 +854,15 @@ unset_presence(LUser, LServer, Resource, Status) ->
|
||||
case length(Resources) of
|
||||
0 ->
|
||||
OnlineGroups = get_special_users_groups_online(LServer),
|
||||
lists:foreach(fun (OG) ->
|
||||
push_user_to_displayed(LUser, LServer, OG,
|
||||
LServer, remove, displayed_to_groups(OG, LServer)),
|
||||
push_displayed_to_user(LUser, LServer,
|
||||
LServer, remove, displayed_to_groups(OG, LServer))
|
||||
end,
|
||||
OnlineGroups);
|
||||
lists:foreach(
|
||||
fun(OG) ->
|
||||
DisplayedToGroups = displayed_to_groups(OG, LServer),
|
||||
push_user_to_displayed(LUser, LServer, OG,
|
||||
LServer, remove, DisplayedToGroups),
|
||||
push_displayed_to_user(LUser, LServer,
|
||||
LServer, remove, DisplayedToGroups)
|
||||
end,
|
||||
OnlineGroups);
|
||||
_ -> ok
|
||||
end.
|
||||
|
||||
@@ -756,7 +890,7 @@ webadmin_page(Acc, _, _) -> Acc.
|
||||
|
||||
list_shared_roster_groups(Host, Query, Lang) ->
|
||||
Res = list_sr_groups_parse_query(Host, Query),
|
||||
SRGroups = mod_shared_roster:list_groups(Host),
|
||||
SRGroups = list_groups(Host),
|
||||
FGroups = (?XAE(<<"table">>, [],
|
||||
[?XE(<<"tbody">>,
|
||||
(lists:map(fun (Group) ->
|
||||
@@ -807,15 +941,17 @@ list_sr_groups_parse_query(Host, Query) ->
|
||||
list_sr_groups_parse_addnew(Host, Query) ->
|
||||
case lists:keysearch(<<"namenew">>, 1, Query) of
|
||||
{value, {_, Group}} when Group /= <<"">> ->
|
||||
mod_shared_roster:create_group(Host, Group), ok;
|
||||
_ -> error
|
||||
create_group(Host, Group),
|
||||
ok;
|
||||
_ ->
|
||||
error
|
||||
end.
|
||||
|
||||
list_sr_groups_parse_delete(Host, Query) ->
|
||||
SRGroups = mod_shared_roster:list_groups(Host),
|
||||
SRGroups = list_groups(Host),
|
||||
lists:foreach(fun (Group) ->
|
||||
case lists:member({<<"selected">>, Group}, Query) of
|
||||
true -> mod_shared_roster:delete_group(Host, Group);
|
||||
true -> delete_group(Host, Group);
|
||||
_ -> ok
|
||||
end
|
||||
end,
|
||||
@@ -825,15 +961,15 @@ list_sr_groups_parse_delete(Host, Query) ->
|
||||
shared_roster_group(Host, Group, Query, Lang) ->
|
||||
Res = shared_roster_group_parse_query(Host, Group,
|
||||
Query),
|
||||
GroupOpts = mod_shared_roster:get_group_opts(Host, Group),
|
||||
GroupOpts = get_group_opts(Host, Group),
|
||||
Name = get_opt(GroupOpts, name, <<"">>),
|
||||
Description = get_opt(GroupOpts, description, <<"">>),
|
||||
AllUsers = get_opt(GroupOpts, all_users, false),
|
||||
OnlineUsers = get_opt(GroupOpts, online_users, false),
|
||||
DisplayedGroups = get_opt(GroupOpts, displayed_groups,
|
||||
[]),
|
||||
Members = mod_shared_roster:get_group_explicit_users(Host,
|
||||
Group),
|
||||
Members = get_group_explicit_users(Host,
|
||||
Group),
|
||||
FMembers = iolist_to_binary(
|
||||
[if AllUsers -> <<"@all@\n">>;
|
||||
true -> <<"">>
|
||||
@@ -915,7 +1051,7 @@ shared_roster_group_parse_query(Host, Group, Query) ->
|
||||
DispGroupsOpt = if DispGroups == [] -> [];
|
||||
true -> [{displayed_groups, DispGroups}]
|
||||
end,
|
||||
OldMembers = mod_shared_roster:get_group_explicit_users(Host,
|
||||
OldMembers = get_group_explicit_users(Host,
|
||||
Group),
|
||||
SJIDs = str:tokens(SMembers, <<", \r\n">>),
|
||||
NewMembers = lists:foldl(fun (_SJID, error) -> error;
|
||||
@@ -950,26 +1086,28 @@ shared_roster_group_parse_query(Host, Group, Query) ->
|
||||
RemovedDisplayedGroups = CurrentDisplayedGroups -- DispGroups,
|
||||
displayed_groups_update(OldMembers, RemovedDisplayedGroups, remove),
|
||||
displayed_groups_update(OldMembers, AddedDisplayedGroups, both),
|
||||
mod_shared_roster:set_group_opts(Host, Group,
|
||||
NameOpt ++
|
||||
DispGroupsOpt ++
|
||||
DescriptionOpt ++
|
||||
AllUsersOpt ++ OnlineUsersOpt),
|
||||
set_group_opts(Host, Group,
|
||||
NameOpt ++
|
||||
DispGroupsOpt ++
|
||||
DescriptionOpt ++
|
||||
AllUsersOpt ++ OnlineUsersOpt),
|
||||
if NewMembers == error -> error;
|
||||
true ->
|
||||
AddedMembers = NewMembers -- OldMembers,
|
||||
RemovedMembers = OldMembers -- NewMembers,
|
||||
lists:foreach(fun (US) ->
|
||||
mod_shared_roster:remove_user_from_group(Host,
|
||||
US,
|
||||
Group)
|
||||
end,
|
||||
RemovedMembers),
|
||||
NonAddedMembers = lists:filter(fun (US) ->
|
||||
error == mod_shared_roster:add_user_to_group(Host, US,
|
||||
Group)
|
||||
end,
|
||||
AddedMembers),
|
||||
lists:foreach(
|
||||
fun(US) ->
|
||||
remove_user_from_group(Host,
|
||||
US,
|
||||
Group)
|
||||
end,
|
||||
RemovedMembers),
|
||||
NonAddedMembers = lists:filter(
|
||||
fun(US) ->
|
||||
error == add_user_to_group(Host, US,
|
||||
Group)
|
||||
end,
|
||||
AddedMembers),
|
||||
case NonAddedMembers of
|
||||
[] -> ok;
|
||||
_ -> {error_jids, NonAddedMembers}
|
||||
@@ -1027,10 +1165,22 @@ import(LServer, {sql, _}, DBType, Tab, L) ->
|
||||
Mod:import(LServer, Tab, L).
|
||||
|
||||
mod_opt_type(db_type) ->
|
||||
econf:db_type(?MODULE).
|
||||
econf:db_type(?MODULE);
|
||||
mod_opt_type(use_cache) ->
|
||||
econf:bool();
|
||||
mod_opt_type(cache_size) ->
|
||||
econf:pos_int(infinity);
|
||||
mod_opt_type(cache_missed) ->
|
||||
econf:bool();
|
||||
mod_opt_type(cache_life_time) ->
|
||||
econf:timeout(second, infinity).
|
||||
|
||||
mod_options(Host) ->
|
||||
[{db_type, ejabberd_config:default_db(Host, ?MODULE)}].
|
||||
[{db_type, ejabberd_config:default_db(Host, ?MODULE)},
|
||||
{use_cache, ejabberd_option:use_cache(Host)},
|
||||
{cache_size, ejabberd_option:cache_size(Host)},
|
||||
{cache_missed, ejabberd_option:cache_missed(Host)},
|
||||
{cache_life_time, ejabberd_option:cache_life_time(Host)}].
|
||||
|
||||
mod_doc() ->
|
||||
#{desc =>
|
||||
@@ -1072,7 +1222,23 @@ mod_doc() ->
|
||||
"the tables and store user information. The default is "
|
||||
"the storage defined by the global option 'default_db', "
|
||||
"or 'mnesia' if omitted. If 'sql' value is defined, "
|
||||
"make sure you have defined the database.")}}],
|
||||
"make sure you have defined the database.")}},
|
||||
{use_cache,
|
||||
#{value => "true | false",
|
||||
desc =>
|
||||
?T("Same as top-level 'use_cache' option, but applied to this module only.")}},
|
||||
{cache_size,
|
||||
#{value => "pos_integer() | infinity",
|
||||
desc =>
|
||||
?T("Same as top-level 'cache_size' option, but applied to this module only.")}},
|
||||
{cache_missed,
|
||||
#{value => "true | false",
|
||||
desc =>
|
||||
?T("Same as top-level 'cache_missed' option, but applied to this module only.")}},
|
||||
{cache_life_time,
|
||||
#{value => "timeout()",
|
||||
desc =>
|
||||
?T("Same as top-level 'cache_life_time' option, but applied to this module only.")}}],
|
||||
example =>
|
||||
[{?T("Take the case of a computer club that wants all its members "
|
||||
"seeing each other in their rosters. To achieve this, they "
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
get_user_groups/2, get_group_explicit_users/2,
|
||||
get_user_displayed_groups/3, is_user_in_group/3,
|
||||
add_user_to_group/3, remove_user_from_group/3, import/3]).
|
||||
-export([need_transform/1, transform/1]).
|
||||
-export([need_transform/1, transform/1, use_cache/1]).
|
||||
|
||||
-include("mod_roster.hrl").
|
||||
-include("mod_shared_roster.hrl").
|
||||
@@ -56,6 +56,10 @@ list_groups(Host) ->
|
||||
[{#sr_group{group_host = {'$1', '$2'}, _ = '_'},
|
||||
[{'==', '$2', Host}], ['$1']}]).
|
||||
|
||||
-spec use_cache(binary()) -> boolean().
|
||||
use_cache(_Host) ->
|
||||
false.
|
||||
|
||||
groups_with_opts(Host) ->
|
||||
Gs = mnesia:dirty_select(sr_group,
|
||||
[{#sr_group{group_host = {'$1', Host}, opts = '$2',
|
||||
|
||||
@@ -3,7 +3,29 @@
|
||||
|
||||
-module(mod_shared_roster_opt).
|
||||
|
||||
-export([cache_life_time/1]).
|
||||
-export([cache_missed/1]).
|
||||
-export([cache_size/1]).
|
||||
-export([db_type/1]).
|
||||
-export([use_cache/1]).
|
||||
|
||||
-spec cache_life_time(gen_mod:opts() | global | binary()) -> 'infinity' | pos_integer().
|
||||
cache_life_time(Opts) when is_map(Opts) ->
|
||||
gen_mod:get_opt(cache_life_time, Opts);
|
||||
cache_life_time(Host) ->
|
||||
gen_mod:get_module_opt(Host, mod_shared_roster, cache_life_time).
|
||||
|
||||
-spec cache_missed(gen_mod:opts() | global | binary()) -> boolean().
|
||||
cache_missed(Opts) when is_map(Opts) ->
|
||||
gen_mod:get_opt(cache_missed, Opts);
|
||||
cache_missed(Host) ->
|
||||
gen_mod:get_module_opt(Host, mod_shared_roster, cache_missed).
|
||||
|
||||
-spec cache_size(gen_mod:opts() | global | binary()) -> 'infinity' | pos_integer().
|
||||
cache_size(Opts) when is_map(Opts) ->
|
||||
gen_mod:get_opt(cache_size, Opts);
|
||||
cache_size(Host) ->
|
||||
gen_mod:get_module_opt(Host, mod_shared_roster, cache_size).
|
||||
|
||||
-spec db_type(gen_mod:opts() | global | binary()) -> atom().
|
||||
db_type(Opts) when is_map(Opts) ->
|
||||
@@ -11,3 +33,9 @@ db_type(Opts) when is_map(Opts) ->
|
||||
db_type(Host) ->
|
||||
gen_mod:get_module_opt(Host, mod_shared_roster, db_type).
|
||||
|
||||
-spec use_cache(gen_mod:opts() | global | binary()) -> boolean().
|
||||
use_cache(Opts) when is_map(Opts) ->
|
||||
gen_mod:get_opt(use_cache, Opts);
|
||||
use_cache(Host) ->
|
||||
gen_mod:get_module_opt(Host, mod_shared_roster, use_cache).
|
||||
|
||||
|
||||
@@ -896,14 +896,13 @@ select_affiliation_subscriptions(Nidx, JID, JID) ->
|
||||
select_affiliation_subscriptions(Nidx, GenKey, SubKey) ->
|
||||
GJ = encode_jid(GenKey),
|
||||
SJ = encode_jid(SubKey),
|
||||
case catch
|
||||
ejabberd_sql:sql_query_t(
|
||||
?SQL("select jid = %(GJ)s as @(G)d, @(affiliation)s, @(subscriptions)s from "
|
||||
" pubsub_state where nodeid=%(Nidx)d and jid in (%(GJ)s, %(SJ)s)"))
|
||||
case catch ejabberd_sql:sql_query_t(
|
||||
?SQL("select jid = %(GJ)s as @(G)b, @(affiliation)s, @(subscriptions)s from "
|
||||
" pubsub_state where nodeid=%(Nidx)d and jid in (%(GJ)s, %(SJ)s)"))
|
||||
of
|
||||
{selected, Res} ->
|
||||
lists:foldr(
|
||||
fun({1, A, S}, {_, Subs}) ->
|
||||
fun({true, A, S}, {_, Subs}) ->
|
||||
{decode_affiliation(A), Subs ++ decode_subscriptions(S)};
|
||||
({_, _, S}, {Aff, Subs}) ->
|
||||
{Aff, Subs ++ decode_subscriptions(S)}
|
||||
|
||||
@@ -259,6 +259,8 @@ init_per_testcase(TestCase, OrigConfig) ->
|
||||
case Test of
|
||||
"test_connect" ++ _ ->
|
||||
Config;
|
||||
"webadmin_" ++ _ ->
|
||||
Config;
|
||||
"test_legacy_auth_feature" ->
|
||||
connect(Config);
|
||||
"test_legacy_auth" ++ _ ->
|
||||
@@ -372,6 +374,7 @@ db_tests(DB) when DB == mnesia; DB == redis ->
|
||||
auth_md5,
|
||||
presence_broadcast,
|
||||
last,
|
||||
webadmin_tests:single_cases(),
|
||||
roster_tests:single_cases(),
|
||||
private_tests:single_cases(),
|
||||
privacy_tests:single_cases(),
|
||||
@@ -401,6 +404,7 @@ db_tests(DB) ->
|
||||
auth_md5,
|
||||
presence_broadcast,
|
||||
last,
|
||||
webadmin_tests:single_cases(),
|
||||
roster_tests:single_cases(),
|
||||
private_tests:single_cases(),
|
||||
privacy_tests:single_cases(),
|
||||
|
||||
@@ -66,6 +66,8 @@ access_rules:
|
||||
acl:
|
||||
local:
|
||||
user_regexp: ""
|
||||
admin:
|
||||
user: "admin"
|
||||
language: en
|
||||
listen:
|
||||
-
|
||||
@@ -84,6 +86,7 @@ listen:
|
||||
port: WEB_PORT
|
||||
module: ejabberd_http
|
||||
request_handlers:
|
||||
"/admin": ejabberd_web_admin
|
||||
"/api": mod_http_api
|
||||
"/upload": mod_http_upload
|
||||
"/captcha": ejabberd_captcha
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% Author : Pawel Chmielowski <pawel@process-one.net>
|
||||
%%% Created : 23 Mar 2020 by Pawel Chmielowski <pawel@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2020 ProcessOne
|
||||
%%%
|
||||
%%% This program is free software; you can redistribute it and/or
|
||||
%%% modify it under the terms of the GNU General Public License as
|
||||
%%% published by the Free Software Foundation; either version 2 of the
|
||||
%%% License, or (at your option) any later version.
|
||||
%%%
|
||||
%%% This program is distributed in the hope that it will be useful,
|
||||
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
%%% General Public License for more details.
|
||||
%%%
|
||||
%%% You should have received a copy of the GNU General Public License along
|
||||
%%% with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
%%%
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(webadmin_tests).
|
||||
|
||||
%% API
|
||||
-compile(export_all).
|
||||
-import(suite, [disconnect/1, is_feature_advertised/3, upload_jid/1,
|
||||
my_jid/1, wait_for_slave/1, wait_for_master/1,
|
||||
send_recv/2, put_event/2, get_event/1]).
|
||||
|
||||
-include("suite.hrl").
|
||||
-include_lib("stdlib/include/assert.hrl").
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
%%%===================================================================
|
||||
%%% Single user tests
|
||||
%%%===================================================================
|
||||
single_cases() ->
|
||||
{webadmin_single, [sequence],
|
||||
[single_test(login_page),
|
||||
single_test(welcome_page)]}.
|
||||
|
||||
login_page(Config) ->
|
||||
Headers = ?match({ok, {{"HTTP/1.1", 401, _}, Headers, _}},
|
||||
httpc:request(get, {page(Config, ""), []}, [],
|
||||
[{body_format, binary}]),
|
||||
Headers),
|
||||
?match("basic realm=\"ejabberd\"", proplists:get_value("www-authenticate", Headers, none)).
|
||||
|
||||
welcome_page(Config) ->
|
||||
Body = ?match({ok, {{"HTTP/1.1", 200, _}, _, Body}},
|
||||
httpc:request(get, {page(Config, ""), [basic_auth_header(Config)]}, [],
|
||||
[{body_format, binary}]),
|
||||
Body),
|
||||
?match({_, _}, binary:match(Body, <<"ejabberd Web Admin">>)).
|
||||
|
||||
%%%===================================================================
|
||||
%%% Internal functions
|
||||
%%%===================================================================
|
||||
single_test(T) ->
|
||||
list_to_atom("webadmin_" ++ atom_to_list(T)).
|
||||
|
||||
basic_auth_header(Config) ->
|
||||
Server = ?config(server, Config),
|
||||
ejabberd_auth:try_register(<<"admin">>, Server, <<"pass">>),
|
||||
{"authorization", "Basic "++base64:encode_to_string(<<"admin@", Server/binary, ":pass">>)}.
|
||||
|
||||
page(Config, Tail) ->
|
||||
Server = ?config(server_host, Config),
|
||||
Port = ct:get_config(web_port, 5280),
|
||||
"http://" ++ Server ++ ":" ++ integer_to_list(Port) ++ "/admin/" ++ Tail.
|
||||
Reference in New Issue
Block a user