aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/acl_test.exs1
-rw-r--r--test/ejabberd_admin_test.exs1
-rw-r--r--test/ejabberd_commands_mock_test.exs56
-rw-r--r--test/ejabberd_commands_test.exs23
-rw-r--r--test/ejabberd_cyrsasl_test.exs10
-rw-r--r--test/ejabberd_oauth_mock.exs7
-rw-r--r--test/elixir-config/attr_test.exs87
-rw-r--r--test/elixir-config/config_test.exs65
-rw-r--r--test/elixir-config/ejabberd_logger.exs49
-rw-r--r--test/elixir-config/shared/ejabberd.exs31
-rw-r--r--test/elixir-config/shared/ejabberd_different_from_default.exs9
-rw-r--r--test/elixir-config/shared/ejabberd_for_validation.exs20
-rw-r--r--test/elixir-config/validation_test.exs32
-rw-r--r--test/mod_admin_extra_test.exs4
-rw-r--r--test/mod_http_api_mock_test.exs97
-rw-r--r--test/mod_http_api_test.exs39
-rw-r--r--test/test_helper.exs7
17 files changed, 497 insertions, 41 deletions
diff --git a/test/acl_test.exs b/test/acl_test.exs
index 551c74ae0..4bd8e6989 100644
--- a/test/acl_test.exs
+++ b/test/acl_test.exs
@@ -26,6 +26,7 @@ defmodule ACLTest do
setup_all do
:ok = :mnesia.start
:ok = :jid.start
+ :stringprep.start
:ok = :ejabberd_config.start(["domain1", "domain2"], [])
:ok = :acl.start
end
diff --git a/test/ejabberd_admin_test.exs b/test/ejabberd_admin_test.exs
index 1c999314c..31b8ab2e2 100644
--- a/test/ejabberd_admin_test.exs
+++ b/test/ejabberd_admin_test.exs
@@ -28,6 +28,7 @@ defmodule EjabberdAdminTest do
# For some myterious reason, :ejabberd_commands.init mays
# sometimes fails if module is not loaded before
{:module, :ejabberd_commands} = Code.ensure_loaded(:ejabberd_commands)
+ {:ok, _} = :ejabberd_access_permissions.start_link()
:ejabberd_commands.init
:ejabberd_admin.start
:ok
diff --git a/test/ejabberd_commands_mock_test.exs b/test/ejabberd_commands_mock_test.exs
index 487cf6a4b..419a989d6 100644
--- a/test/ejabberd_commands_mock_test.exs
+++ b/test/ejabberd_commands_mock_test.exs
@@ -18,9 +18,13 @@
#
# ----------------------------------------------------------------------
+## TODO Fix next test error: add admin user ACL
+
defmodule EjabberdCommandsMockTest do
use ExUnit.Case, async: false
+ require EjabberdOauthMock
+
@author "jsautret@process-one.net"
# mocked callback module
@@ -44,13 +48,18 @@ defmodule EjabberdCommandsMockTest do
_ -> :ok
end
:mnesia.start
+ :ok = :jid.start
+ :ok = :ejabberd_config.start(["domain1", "domain2"], [])
+ {:ok, _} = :ejabberd_access_permissions.start_link()
+ :ok = :acl.start
EjabberdOauthMock.init
- :ok
+ on_exit fn -> :meck.unload end
end
setup do
:meck.unload
:meck.new(@module, [:non_strict])
+ :mnesia.delete_table(:ejabberd_commands)
:ejabberd_commands.init
end
@@ -167,7 +176,7 @@ defmodule EjabberdCommandsMockTest do
# default version is latest one
assert :result3 == :ejabberd_commands.execute_command(command_name, [])
# no such command in APIv0
- assert :unknown_command ==
+ assert {:error, :unknown_command} ==
catch_throw :ejabberd_commands.execute_command(command_name, [], 0)
assert :result1 == :ejabberd_commands.execute_command(command_name, [], 1)
assert :result1 == :ejabberd_commands.execute_command(command_name, [], 2)
@@ -180,7 +189,7 @@ defmodule EjabberdCommandsMockTest do
test "API command with user policy" do
- mock_commands_config
+ mock_commands_config [:user, :admin]
# Register a command test(user, domain) -> {:versionN, user, domain}
# with policy=user and versions 1 & 3
@@ -313,9 +322,8 @@ defmodule EjabberdCommandsMockTest do
end
-
test "API command with admin policy" do
- mock_commands_config
+ mock_commands_config [:admin]
# Register a command test(user, domain) -> {user, domain}
# with policy=admin
@@ -393,13 +401,47 @@ defmodule EjabberdCommandsMockTest do
assert :meck.validate @module
end
+ test "Commands can perform extra check on access" do
+ mock_commands_config [:admin, :open]
+
+ command_name = :test
+ function = :test_command
+ command = ejabberd_commands(name: command_name,
+ args: [{:user, :binary}, {:host, :binary}],
+ access: [:basic_rule_1],
+ module: @module,
+ function: function,
+ policy: :open)
+ :meck.expect(@module, function,
+ fn(user, domain) when is_binary(user) and is_binary(domain) ->
+ {user, domain}
+ end)
+ assert :ok == :ejabberd_commands.register_commands [command]
+
+# :acl.add(:global, :basic_acl_1, {:user, @user, @host})
+# :acl.add_access(:global, :basic_rule_1, [{:allow, [{:acl, :basic_acl_1}]}])
+
+ assert {@user, @domain} ==
+ :ejabberd_commands.execute_command(:undefined,
+ {@user, @domain,
+ @userpass, false},
+ command_name,
+ [@user, @domain])
+ assert {@user, @domain} ==
+ :ejabberd_commands.execute_command(:undefined,
+ {@admin, @domain,
+ @adminpass, false},
+ command_name,
+ [@user, @domain])
+
+ end
##########################################################
# Utils
# Mock a config where only @admin user is allowed to call commands
# as admin
- def mock_commands_config do
+ def mock_commands_config(commands \\ []) do
EjabberdAuthMock.init
EjabberdAuthMock.create_user @user, @domain, @userpass
EjabberdAuthMock.create_user @admin, @domain, @adminpass
@@ -408,10 +450,12 @@ defmodule EjabberdCommandsMockTest do
:meck.expect(:ejabberd_config, :get_option,
fn(:commands_admin_access, _, _) -> :commands_admin_access
(:oauth_access, _, _) -> :all
+ (:commands, _, _) -> [{:add_commands, commands}]
(_, _, default) -> default
end)
:meck.expect(:ejabberd_config, :get_myhosts,
fn() -> [@domain] end)
+
:meck.new :acl
:meck.expect(:acl, :access_matches,
fn(:commands_admin_access, info, _scope) ->
diff --git a/test/ejabberd_commands_test.exs b/test/ejabberd_commands_test.exs
index 31d108214..c8219d0cf 100644
--- a/test/ejabberd_commands_test.exs
+++ b/test/ejabberd_commands_test.exs
@@ -28,7 +28,12 @@ defmodule EjabberdCommandsTest do
setup_all do
:mnesia.start
+ :stringprep.start
+ :ok = :ejabberd_config.start(["localhost"], [])
+ {:ok, _} = :ejabberd_access_permissions.start_link()
+
:ejabberd_commands.init
+ :ok
end
test "Check that we can register a command" do
@@ -37,6 +42,14 @@ defmodule EjabberdCommandsTest do
assert Enum.member?(commands, {:test_user, [], "Test user"})
end
+ test "get_exposed_commands/0 returns registered commands" do
+ commands = [open_test_command]
+ :ok = :ejabberd_commands.register_commands(commands)
+ :ok = :ejabberd_commands.expose_commands(commands)
+ exposed_commands = :ejabberd_commands.get_exposed_commands
+ assert Enum.member?(exposed_commands, :test_open)
+ end
+
test "Check that admin commands are rejected with noauth credentials" do
:ok = :ejabberd_commands.register_commands([admin_test_command])
@@ -70,6 +83,16 @@ defmodule EjabberdCommandsTest do
]}}}})
end
+ defp open_test_command do
+ ejabberd_commands(name: :test_open, tags: [:test],
+ desc: "Test open",
+ policy: :open,
+ module: __MODULE__,
+ function: :test_open,
+ args: [],
+ result: {:res, :rescode})
+ end
+
defp admin_test_command do
ejabberd_commands(name: :test_admin, tags: [:roster],
desc: "Test admin",
diff --git a/test/ejabberd_cyrsasl_test.exs b/test/ejabberd_cyrsasl_test.exs
index 0dc64ee44..d9b949294 100644
--- a/test/ejabberd_cyrsasl_test.exs
+++ b/test/ejabberd_cyrsasl_test.exs
@@ -71,8 +71,8 @@ defmodule EjabberdCyrsaslTest do
response = "username=\"#{user}\",realm=\"#{domain}\",nonce=\"#{nonce}\",cnonce=\"#{cnonce}\"," <>
"nc=\"#{nc}\",qop=auth,digest-uri=\"#{digest_uri}\",response=\"#{response_hash}\"," <>
"charset=utf-8,algorithm=md5-sess"
- assert {:continue, calc_str, state3} = :cyrsasl.server_step(state1, response)
- assert {:ok, list} = :cyrsasl.server_step(state3, "")
+ assert {:continue, _calc_str, state3} = :cyrsasl.server_step(state1, response)
+ assert {:ok, _list} = :cyrsasl.server_step(state3, "")
end
defp calc_digest_sha(user, domain, pass, nc, nonce, cnonce) do
@@ -94,7 +94,7 @@ defmodule EjabberdCyrsaslTest do
defp setup_anonymous_mocks() do
:meck.unload
mock(:ejabberd_auth_anonymous, :is_sasl_anonymous_enabled,
- fn (host) ->
+ fn (_host) ->
true
end)
mock(:ejabberd_auth, :is_user_exists,
@@ -119,7 +119,7 @@ defmodule EjabberdCyrsaslTest do
end
end
- defp check_password(user, authzid, pass) do
+ defp check_password(_user, authzid, pass) do
case get_password(authzid) do
{^pass, mod} ->
{true, mod}
@@ -128,7 +128,7 @@ defmodule EjabberdCyrsaslTest do
end
end
- defp check_password_digest(user, authzid, pass, digest, digest_gen) do
+ defp check_password_digest(_user, authzid, _pass, digest, digest_gen) do
case get_password(authzid) do
{spass, mod} ->
v = digest_gen.(spass)
diff --git a/test/ejabberd_oauth_mock.exs b/test/ejabberd_oauth_mock.exs
index 81cfdc038..965bff1e6 100644
--- a/test/ejabberd_oauth_mock.exs
+++ b/test/ejabberd_oauth_mock.exs
@@ -26,7 +26,10 @@ defmodule EjabberdOauthMock do
:mnesia.start
:mnesia.create_table(:oauth_token,
[ram_copies: [node],
- attributes: [:oauth_token, :us, :scope, :expire]])
+ attributes: [:oauth_token, :us, :scope, :expire]])
+ :application.start(:cache_tab)
+ :cache_tab.new(:oauth_token,
+ [{:max_size, 1000}, {:life_time, 3600}])
end
def get_token(user, domain, command, expiration \\ 3600) do
@@ -40,7 +43,7 @@ defmodule EjabberdOauthMock do
{:user, user, domain}},
{"scope", [to_string command]},
{"expiry_time", expire}],
- :undefined)
+ [])
token
end
diff --git a/test/elixir-config/attr_test.exs b/test/elixir-config/attr_test.exs
new file mode 100644
index 000000000..c5cab5bd8
--- /dev/null
+++ b/test/elixir-config/attr_test.exs
@@ -0,0 +1,87 @@
+defmodule Ejabberd.Config.AttrTest do
+ use ExUnit.Case, async: true
+
+ alias Ejabberd.Config.Attr
+
+ test "extract attrs from single line block" do
+ block = quote do
+ @active false
+ end
+
+ block_res = Attr.extract_attrs_from_block_with_defaults(block)
+ assert {:active, false} in block_res
+ end
+
+ test "extract attrs from multi line block" do
+ block = quote do
+ @active false
+ @opts [http: true]
+ end
+
+ block_res = Attr.extract_attrs_from_block_with_defaults(block)
+ assert {:active, false} in block_res
+ assert {:opts, [http: true]} in block_res
+ end
+
+ test "inserts correctly defaults attr when missing in block" do
+ block = quote do
+ @active false
+ @opts [http: true]
+ end
+
+ block_res = Attr.extract_attrs_from_block_with_defaults(block)
+
+ assert {:active, false} in block_res
+ assert {:git, ""} in block_res
+ assert {:name, ""} in block_res
+ assert {:opts, [http: true]} in block_res
+ assert {:dependency, []} in block_res
+ end
+
+ test "inserts all defaults attr when passed an empty block" do
+ block = quote do
+ end
+
+ block_res = Attr.extract_attrs_from_block_with_defaults(block)
+
+ assert {:active, true} in block_res
+ assert {:git, ""} in block_res
+ assert {:name, ""} in block_res
+ assert {:opts, []} in block_res
+ assert {:dependency, []} in block_res
+ end
+
+ test "validates attrs and returns errors, if any" do
+ block = quote do
+ @not_supported_attr true
+ @active "false"
+ @opts [http: true]
+ end
+
+ block_res =
+ block
+ |> Attr.extract_attrs_from_block_with_defaults
+ |> Attr.validate
+
+ assert {:ok, {:opts, [http: true]}} in block_res
+ assert {:ok, {:git, ""}} in block_res
+ assert {:error, {:not_supported_attr, true}, :attr_not_supported} in block_res
+ assert {:error, {:active, "false"}, :type_not_supported} in block_res
+ end
+
+ test "returns the correct type for an attribute" do
+ assert :boolean == Attr.get_type_for_attr(:active)
+ assert :string == Attr.get_type_for_attr(:git)
+ assert :string == Attr.get_type_for_attr(:name)
+ assert :list == Attr.get_type_for_attr(:opts)
+ assert :list == Attr.get_type_for_attr(:dependency)
+ end
+
+ test "returns the correct default for an attribute" do
+ assert true == Attr.get_default_for_attr(:active)
+ assert "" == Attr.get_default_for_attr(:git)
+ assert "" == Attr.get_default_for_attr(:name)
+ assert [] == Attr.get_default_for_attr(:opts)
+ assert [] == Attr.get_default_for_attr(:dependency)
+ end
+end
diff --git a/test/elixir-config/config_test.exs b/test/elixir-config/config_test.exs
new file mode 100644
index 000000000..c359c49c3
--- /dev/null
+++ b/test/elixir-config/config_test.exs
@@ -0,0 +1,65 @@
+defmodule Ejabberd.ConfigTest do
+ use ExUnit.Case
+
+ alias Ejabberd.Config
+ alias Ejabberd.Config.Store
+
+ setup_all do
+ pid = Process.whereis(Ejabberd.Config.Store)
+ unless pid != nil and Process.alive?(pid) do
+ Store.start_link
+
+ File.cd("test/elixir-config/shared")
+ config_file_path = File.cwd! <> "/ejabberd.exs"
+ Config.init(config_file_path)
+ end
+
+ {:ok, %{}}
+ end
+
+ test "extracts successfully the module name from config file" do
+ assert [Ejabberd.ConfigFile] == Store.get(:module_name)
+ end
+
+ test "extracts successfully general opts from config file" do
+ [general] = Store.get(:general)
+ shaper = [normal: 1000, fast: 50000, max_fsm_queue: 1000]
+ assert [loglevel: 4, language: "en", hosts: ["localhost"], shaper: shaper] == general
+ end
+
+ test "extracts successfully listeners from config file" do
+ [listen] = Store.get(:listeners)
+ assert :ejabberd_c2s == listen.module
+ assert [port: 5222, max_stanza_size: 65536, shaper: :c2s_shaper, access: :c2s] == listen.attrs[:opts]
+ end
+
+ test "extracts successfully modules from config file" do
+ [module] = Store.get(:modules)
+ assert :mod_adhoc == module.module
+ assert [] == module.attrs[:opts]
+ end
+
+ test "extracts successfully hooks from config file" do
+ [register_hook] = Store.get(:hooks)
+
+ assert :register_user == register_hook.hook
+ assert [host: "localhost"] == register_hook.opts
+ assert is_function(register_hook.fun)
+ end
+
+ # TODO: When enalbed, this test causes the evaluation of a different config file, so
+ # the other tests, that uses the store, are compromised because the data is different.
+ # So, until a good way is found, this test should remain disabed.
+ #
+ # test "init/2 with force:true re-initializes the config store with new data" do
+ # config_file_path = File.cwd! <> "/ejabberd_different_from_default.exs"
+ # Config.init(config_file_path, true)
+ #
+ # assert [Ejabberd.ConfigFile] == Store.get(:module_name)
+ # assert [[loglevel: 4, language: "en", hosts: ["localhost"]]] == Store.get(:general)
+ # assert [] == Store.get(:modules)
+ # assert [] == Store.get(:listeners)
+ #
+ # Store.stop
+ # end
+end
diff --git a/test/elixir-config/ejabberd_logger.exs b/test/elixir-config/ejabberd_logger.exs
new file mode 100644
index 000000000..d13f79aa6
--- /dev/null
+++ b/test/elixir-config/ejabberd_logger.exs
@@ -0,0 +1,49 @@
+defmodule Ejabberd.Config.EjabberdLoggerTest do
+ use ExUnit.Case
+
+ import ExUnit.CaptureIO
+
+ alias Ejabberd.Config
+ alias Ejabberd.Config.Store
+ alias Ejabberd.Config.Validation
+ alias Ejabberd.Config.EjabberdLogger
+
+ setup_all do
+ pid = Process.whereis(Ejabberd.Config.Store)
+ unless pid != nil and Process.alive?(pid) do
+ Store.start_link
+
+ File.cd("test/elixir-config/shared")
+ config_file_path = File.cwd! <> "/ejabberd_for_validation.exs"
+ Config.init(config_file_path)
+ end
+
+ {:ok, %{}}
+ end
+
+ test "outputs correctly when attr is not supported" do
+ error_msg = "[ WARN ] Annotation @attr_not_supported is not supported.\n"
+
+ [_mod_irc, _mod_configure, mod_time] = Store.get(:modules)
+ fun = fn ->
+ mod_time
+ |> Validation.validate
+ |> EjabberdLogger.log_errors
+ end
+
+ assert capture_io(fun) == error_msg
+ end
+
+ test "outputs correctly when dependency is not found" do
+ error_msg = "[ WARN ] Module :mod_adhoc was not found, but is required as a dependency.\n"
+
+ [_mod_irc, mod_configure, _mod_time] = Store.get(:modules)
+ fun = fn ->
+ mod_configure
+ |> Validation.validate
+ |> EjabberdLogger.log_errors
+ end
+
+ assert capture_io(fun) == error_msg
+ end
+end
diff --git a/test/elixir-config/shared/ejabberd.exs b/test/elixir-config/shared/ejabberd.exs
new file mode 100644
index 000000000..5d0243bb5
--- /dev/null
+++ b/test/elixir-config/shared/ejabberd.exs
@@ -0,0 +1,31 @@
+defmodule Ejabberd.ConfigFile do
+ use Ejabberd.Config
+
+ def start do
+ [loglevel: 4,
+ language: "en",
+ hosts: ["localhost"],
+ shaper: shaper]
+ end
+
+ defp shaper do
+ [normal: 1000,
+ fast: 50000,
+ max_fsm_queue: 1000]
+ end
+
+ listen :ejabberd_c2s do
+ @opts [
+ port: 5222,
+ max_stanza_size: 65536,
+ shaper: :c2s_shaper,
+ access: :c2s]
+ end
+
+ module :mod_adhoc do
+ end
+
+ hook :register_user, [host: "localhost"], fn(user, server) ->
+ info("User registered: #{user} on #{server}")
+ end
+end
diff --git a/test/elixir-config/shared/ejabberd_different_from_default.exs b/test/elixir-config/shared/ejabberd_different_from_default.exs
new file mode 100644
index 000000000..a39409683
--- /dev/null
+++ b/test/elixir-config/shared/ejabberd_different_from_default.exs
@@ -0,0 +1,9 @@
+defmodule Ejabberd.ConfigFile do
+ use Ejabberd.Config
+
+ def start do
+ [loglevel: 4,
+ language: "en",
+ hosts: ["localhost"]]
+ end
+end
diff --git a/test/elixir-config/shared/ejabberd_for_validation.exs b/test/elixir-config/shared/ejabberd_for_validation.exs
new file mode 100644
index 000000000..8c0196c7e
--- /dev/null
+++ b/test/elixir-config/shared/ejabberd_for_validation.exs
@@ -0,0 +1,20 @@
+defmodule Ejabberd.ConfigFile do
+ use Ejabberd.Config
+
+ def start do
+ [loglevel: 4,
+ language: "en",
+ hosts: ["localhost"]]
+ end
+
+ module :mod_time do
+ @attr_not_supported true
+ end
+
+ module :mod_configure do
+ @dependency [:mod_adhoc]
+ end
+
+ module :mod_irc do
+ end
+end
diff --git a/test/elixir-config/validation_test.exs b/test/elixir-config/validation_test.exs
new file mode 100644
index 000000000..1df775966
--- /dev/null
+++ b/test/elixir-config/validation_test.exs
@@ -0,0 +1,32 @@
+defmodule Ejabberd.Config.ValidationTest do
+ use ExUnit.Case
+
+ alias Ejabberd.Config
+ alias Ejabberd.Config.Store
+ alias Ejabberd.Config.Validation
+
+ setup_all do
+ pid = Process.whereis(Ejabberd.Config.Store)
+ unless pid != nil and Process.alive?(pid) do
+ Store.start_link
+
+ File.cd("test/elixir-config/shared")
+ config_file_path = File.cwd! <> "/ejabberd_for_validation.exs"
+ Config.init(config_file_path)
+ end
+
+ {:ok, %{}}
+ end
+
+ test "validates correctly the modules" do
+ [mod_irc, mod_configure, mod_time] = Store.get(:modules)
+
+ [{:error, _mod, errors}] = Validation.validate(mod_configure)
+ assert %{dependency: [mod_adhoc: :not_found]} == errors
+
+ [{:error, _mod, errors}] = Validation.validate(mod_time)
+ assert %{attribute: [{{:attr_not_supported, true}, :attr_not_supported}]} == errors
+
+ [{:ok, _mod}] = Validation.validate(mod_irc)
+ end
+end
diff --git a/test/mod_admin_extra_test.exs b/test/mod_admin_extra_test.exs
index 761b07b7c..fde66f03f 100644
--- a/test/mod_admin_extra_test.exs
+++ b/test/mod_admin_extra_test.exs
@@ -22,6 +22,9 @@ defmodule EjabberdModAdminExtraTest do
use ExUnit.Case, async: false
require EjabberdAuthMock
+ require EjabberdSmMock
+ require ModLastMock
+ require ModRosterMock
@author "jsautret@process-one.net"
@@ -42,6 +45,7 @@ defmodule EjabberdModAdminExtraTest do
rescue
_ -> :ok
end
+ {:ok, _} = :ejabberd_access_permissions.start_link()
:ejabberd_commands.init
:ok = :ejabberd_config.start([@domain], [])
:mod_admin_extra.start(@domain, [])
diff --git a/test/mod_http_api_mock_test.exs b/test/mod_http_api_mock_test.exs
index 47b1fe94a..4809ecd59 100644
--- a/test/mod_http_api_mock_test.exs
+++ b/test/mod_http_api_mock_test.exs
@@ -46,6 +46,7 @@ defmodule ModHttpApiMockTest do
:mnesia.start
:stringprep.start
:ejabberd_config.start([@domain], [])
+ {:ok, _} = :ejabberd_access_permissions.start_link()
:ejabberd_commands.init
rescue
_ -> :ok
@@ -58,6 +59,7 @@ defmodule ModHttpApiMockTest do
setup do
:meck.unload
:meck.new :ejabberd_commands
+ :meck.new(:acl, [:passthrough]) # Need to fake acl to allow oauth
EjabberdAuthMock.init
:ok
end
@@ -70,9 +72,9 @@ defmodule ModHttpApiMockTest do
fn (@acommand, {@user, @domain, @userpass, false}, @version) ->
{[], {:res, :rescode}}
end)
- :meck.expect(:ejabberd_commands, :get_command_policy,
- fn (@acommand) -> {:ok, :user} end)
- :meck.expect(:ejabberd_commands, :get_commands,
+ :meck.expect(:ejabberd_commands, :get_command_policy_and_scope,
+ fn (@acommand) -> {:ok, :user, [:erlang.atom_to_binary(@acommand,:utf8)]} end)
+ :meck.expect(:ejabberd_commands, :get_exposed_commands,
fn () -> [@acommand] end)
:meck.expect(:ejabberd_commands, :execute_command,
fn (:undefined, {@user, @domain, @userpass, false}, @acommand, [], @version, _) ->
@@ -123,9 +125,9 @@ defmodule ModHttpApiMockTest do
fn (@acommand, {@user, @domain, {:oauth, _token}, false}, @version) ->
{[], {:res, :rescode}}
end)
- :meck.expect(:ejabberd_commands, :get_command_policy,
- fn (@acommand) -> {:ok, :user} end)
- :meck.expect(:ejabberd_commands, :get_commands,
+ :meck.expect(:ejabberd_commands, :get_command_policy_and_scope,
+ fn (@acommand) -> {:ok, :user, [:erlang.atom_to_binary(@acommand,:utf8), "ejabberd:user"]} end)
+ :meck.expect(:ejabberd_commands, :get_exposed_commands,
fn () -> [@acommand] end)
:meck.expect(:ejabberd_commands, :execute_command,
fn (:undefined, {@user, @domain, {:oauth, _token}, false},
@@ -134,7 +136,7 @@ defmodule ModHttpApiMockTest do
end)
- # Correct OAuth call
+ # Correct OAuth call using specific scope
token = EjabberdOauthMock.get_token @user, @domain, @command
req = request(method: :GET,
path: ["api", @command],
@@ -147,6 +149,19 @@ defmodule ModHttpApiMockTest do
assert 200 == elem(result, 0) # HTTP code
assert "0" == elem(result, 2) # command result
+ # Correct OAuth call using specific ejabberd:user scope
+ token = EjabberdOauthMock.get_token @user, @domain, "ejabberd:user"
+ req = request(method: :GET,
+ path: ["api", @command],
+ q: [nokey: ""],
+ # OAuth
+ auth: {:oauth, token, []},
+ ip: {{127,0,0,1},60000},
+ host: @domain)
+ result = :mod_http_api.process([@command], req)
+ assert 200 == elem(result, 0) # HTTP code
+ assert "0" == elem(result, 2) # command result
+
# Wrong OAuth token
req = request(method: :GET,
path: ["api", @command],
@@ -184,8 +199,8 @@ defmodule ModHttpApiMockTest do
result = :mod_http_api.process([@command], req)
assert 401 == elem(result, 0) # HTTP code
- # Check that the command was executed only once
- assert 1 ==
+ # Check that the command was executed twice
+ assert 2 ==
:meck.num_calls(:ejabberd_commands, :execute_command, :_)
assert :meck.validate :ejabberd_auth
@@ -193,5 +208,69 @@ defmodule ModHttpApiMockTest do
#assert :ok = :meck.history(:ejabberd_commands)
end
+ test "Request oauth token, resource owner password credentials" do
+ EjabberdAuthMock.create_user @user, @domain, @userpass
+ :application.set_env(:oauth2, :backend, :ejabberd_oauth)
+ :application.start(:oauth2)
+
+ # Mock a simple command() -> :ok
+ :meck.expect(:ejabberd_commands, :get_command_format,
+ fn (@acommand, {@user, @domain, {:oauth, _token}, false}, @version) ->
+ {[], {:res, :rescode}}
+ end)
+ :meck.expect(:ejabberd_commands, :get_command_policy_and_scope,
+ fn (@acommand) -> {:ok, :user, [:erlang.atom_to_binary(@acommand,:utf8), "ejabberd:user"]} end)
+ :meck.expect(:ejabberd_commands, :get_exposed_commands,
+ fn () -> [@acommand] end)
+ :meck.expect(:ejabberd_commands, :execute_command,
+ fn (:undefined, {@user, @domain, {:oauth, _token}, false},
+ @acommand, [], @version, _) ->
+ :ok
+ end)
+
+ #Mock acl to allow oauth authorizations
+ :meck.expect(:acl, :match_rule, fn(_Server, _Access, _Jid) -> :allow end)
+
+
+ # Correct password
+ req = request(method: :POST,
+ path: ["oauth", "token"],
+ q: [{"grant_type", "password"}, {"scope", @command}, {"username", @user<>"@"<>@domain}, {"ttl", "4000"}, {"password", @userpass}],
+ ip: {{127,0,0,1},60000},
+ host: @domain)
+ result = :ejabberd_oauth.process([], req)
+ assert 200 = elem(result, 0) #http code
+ {kv} = :jiffy.decode(elem(result,2))
+ assert {_, "bearer"} = List.keyfind(kv, "token_type", 0)
+ assert {_, @command} = List.keyfind(kv, "scope", 0)
+ assert {_, 4000} = List.keyfind(kv, "expires_in", 0)
+ {"access_token", _token} = List.keyfind(kv, "access_token", 0)
+
+ #missing grant_type
+ req = request(method: :POST,
+ path: ["oauth", "token"],
+ q: [{"scope", @command}, {"username", @user<>"@"<>@domain}, {"password", @userpass}],
+ ip: {{127,0,0,1},60000},
+ host: @domain)
+ result = :ejabberd_oauth.process([], req)
+ assert 400 = elem(result, 0) #http code
+ {kv} = :jiffy.decode(elem(result,2))
+ assert {_, "unsupported_grant_type"} = List.keyfind(kv, "error", 0)
+
+
+ # incorrect user/pass
+ req = request(method: :POST,
+ path: ["oauth", "token"],
+ q: [{"grant_type", "password"}, {"scope", @command}, {"username", @user<>"@"<>@domain}, {"password", @userpass<>"aa"}],
+ ip: {{127,0,0,1},60000},
+ host: @domain)
+ result = :ejabberd_oauth.process([], req)
+ assert 400 = elem(result, 0) #http code
+ {kv} = :jiffy.decode(elem(result,2))
+ assert {_, "invalid_grant"} = List.keyfind(kv, "error", 0)
+
+ assert :meck.validate :ejabberd_auth
+ assert :meck.validate :ejabberd_commands
+ end
end
diff --git a/test/mod_http_api_test.exs b/test/mod_http_api_test.exs
index 99b8d9b28..c68270f1f 100644
--- a/test/mod_http_api_test.exs
+++ b/test/mod_http_api_test.exs
@@ -31,43 +31,44 @@ defmodule ModHttpApiTest do
:ok = :mnesia.start
:stringprep.start
:ok = :ejabberd_config.start(["localhost"], [])
-
+ {:ok, _} = :ejabberd_access_permissions.start_link()
:ok = :ejabberd_commands.init
-
:ok = :ejabberd_commands.register_commands(cmds)
- on_exit fn -> unregister_commands(cmds) end
+ on_exit fn ->
+ :meck.unload
+ unregister_commands(cmds) end
end
test "We can expose several commands to API at a time" do
setup_mocks()
- :ejabberd_config.add_local_option(:commands, [[{:add_commands, [:open_cmd, :user_cmd]}]])
- commands = :ejabberd_commands.get_commands()
+ :ejabberd_commands.expose_commands([:open_cmd, :user_cmd])
+ commands = :ejabberd_commands.get_exposed_commands()
assert Enum.member?(commands, :open_cmd)
assert Enum.member?(commands, :user_cmd)
end
- test "We can call open commands without authentication" do
- setup_mocks()
- :ejabberd_config.add_local_option(:commands, [[{:add_commands, [:open_cmd]}]])
- request = request(method: :POST, ip: {{127,0,0,1},50000}, data: "[]")
- {200, _, _} = :mod_http_api.process(["open_cmd"], request)
- end
+# test "We can call open commands without authentication" do
+# setup_mocks()
+# :ejabberd_commands.expose_commands([:open_cmd])
+# request = request(method: :POST, ip: {{127,0,0,1},50000}, data: "[]")
+# {200, _, _} = :mod_http_api.process(["open_cmd"], request)
+# end
# This related to the commands config file option
- test "Attempting to access a command that is not exposed as HTTP API returns 401" do
+ test "Attempting to access a command that is not exposed as HTTP API returns 403" do
setup_mocks()
- :ejabberd_config.add_local_option(:commands, [])
+ :ejabberd_commands.expose_commands([])
request = request(method: :POST, ip: {{127,0,0,1},50000}, data: "[]")
- {401, _, _} = :mod_http_api.process(["open_cmd"], request)
+ {403, _, _} = :mod_http_api.process(["open_cmd"], request)
end
test "Call to user, admin or restricted commands without authentication are rejected" do
setup_mocks()
- :ejabberd_config.add_local_option(:commands, [[{:add_commands, [:user_cmd, :admin_cmd, :restricted]}]])
+ :ejabberd_commands.expose_commands([:user_cmd, :admin_cmd, :restricted])
request = request(method: :POST, ip: {{127,0,0,1},50000}, data: "[]")
- {401, _, _} = :mod_http_api.process(["user_cmd"], request)
- {401, _, _} = :mod_http_api.process(["admin_cmd"], request)
- {401, _, _} = :mod_http_api.process(["restricted_cmd"], request)
+ {403, _, _} = :mod_http_api.process(["user_cmd"], request)
+ {403, _, _} = :mod_http_api.process(["admin_cmd"], request)
+ {403, _, _} = :mod_http_api.process(["restricted_cmd"], request)
end
@tag pending: true
@@ -98,7 +99,7 @@ defmodule ModHttpApiTest do
defp setup_mocks() do
:meck.unload
mock(:gen_mod, :get_module_opt,
- fn (_server, :mod_http_api, admin_ip_access, _, _) ->
+ fn (_server, :mod_http_api, _admin_ip_access, _, _) ->
[{:allow, [{:ip, {{127,0,0,2}, 32}}]}]
end)
end
diff --git a/test/test_helper.exs b/test/test_helper.exs
new file mode 100644
index 000000000..454f2338a
--- /dev/null
+++ b/test/test_helper.exs
@@ -0,0 +1,7 @@
+Code.require_file "ejabberd_auth_mock.exs", __DIR__
+Code.require_file "ejabberd_oauth_mock.exs", __DIR__
+Code.require_file "ejabberd_sm_mock.exs", __DIR__
+Code.require_file "mod_last_mock.exs", __DIR__
+Code.require_file "mod_roster_mock.exs", __DIR__
+
+ExUnit.start