{
"coverage_options": {
- "minimum_coverage": 83
+ "minimum_coverage": 80
},
"skip_files": [
"test/support"
def db_name(name), do: Module.concat([name, KV])
def realms_name(name), do: Module.concat([name, Realms])
- def admin_name(name), do: Module.concat([name, Admin])
defp dispatch(name, authentication_module, authorization_module) do
[
@callback authenticate?(methods :: list(String.t())) :: boolean()
@callback method() :: String.t()
- @callback challenge(realm :: String.t(), authid :: String.t(), session_id :: integer()) :: %{challenge: String.t()}
- @callback parse_challenge(Challenge.t()) :: parse_challenge()
- @callback authenticate(signature :: String.t(), realm :: String.t(), authid :: String.t(), challenge :: Challenge.t()) ::
- boolean()
+ @callback challenge(realm :: String.t(), authid :: String.t(), session_id :: integer()) :: map()
+ @callback parse_challenge(map()) :: parse_challenge()
+ @callback authenticate(
+ signature :: String.t(),
+ realm :: String.t(),
+ authid :: String.t(),
+ challenge :: map()
+ ) :: boolean()
end
end
defp get_prefix({db, {keyspace, key}, acc}) do
- l = ClusterKV.prefix(db, keyspace, key, ".", 2, 500)
- {db, {keyspace, key}, acc ++ Enum.flat_map(l, fn {_, subscribers} -> subscribers end)}
+ case ClusterKV.prefix(db, keyspace, key, ".", 2, 500) do
+ :not_found ->
+ {db, {keyspace, key}, acc}
+
+ l ->
+ {db, {keyspace, key}, acc ++ Enum.flat_map(l, fn {_, subscribers} -> subscribers end)}
+ end
end
defp get_wildcard({db, {keyspace, key}, acc}) do
message =
case Enum.reverse(message) do
[map | t] when map == %{} -> t
- [nil | t] -> t
m -> m
end
[list | t] when list == [] ->
t
- [nil | t] ->
- t
-
m ->
m
end
[
# {:cluster_kv, path: "../cluster_kv"},
{:cluster_kv,
- git: "https://gitlab.com/entropealabs/cluster_kv.git", tag: "4c36b8d68f40711cd167edb9917d32a992f49561"},
+ git: "https://gitlab.com/entropealabs/cluster_kv.git", tag: "801f732c1cb5a9a9125de34ed2bdf88d2723ed00"},
{:cors_plug, "~> 2.0"},
{:credo, "~> 1.2", only: [:dev, :test], runtime: false},
{:dialyxir, "~> 0.5.1", only: [:dev, :test], runtime: false},
%{
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
"certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "805abd97539caf89ec6d4732c91e62ba9da0cda51ac462380bbd28ee697a8c42"},
- "cluster_kv": {:git, "https://gitlab.com/entropealabs/cluster_kv.git", "4c36b8d68f40711cd167edb9917d32a992f49561", [tag: "4c36b8d68f40711cd167edb9917d32a992f49561"]},
+ "cluster_kv": {:git, "https://gitlab.com/entropealabs/cluster_kv.git", "801f732c1cb5a9a9125de34ed2bdf88d2723ed00", [tag: "801f732c1cb5a9a9125de34ed2bdf88d2723ed00"]},
"conv_case": {:hex, :conv_case, "0.2.2", "5a98b74ab8f7ddbad670e5c7bb39ff280e60699aa3b25c7062ceccf48137433c", [:mix], [], "hexpm", "561c550ab6d55b2a4d4c14449e58c9957798613eb26ea182e14a962965377bca"},
"cors_plug": {:hex, :cors_plug, "2.0.2", "2b46083af45e4bc79632bd951550509395935d3e7973275b2b743bd63cc942ce", [:mix], [{:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "f0d0e13f71c51fd4ef8b2c7e051388e4dfb267522a83a22392c856de7e46465f"},
"cowboy": {:hex, :cowboy, "2.7.0", "91ed100138a764355f43316b1d23d7ff6bdb0de4ea618cb5d8677c93a7a2f115", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "04fd8c6a39edc6aaa9c26123009200fc61f92a3a94f3178c527b70b767c6e605"},
--- /dev/null
+defmodule Wampex.Router.AuthenticationImpl do
+ @moduledoc false
+ @behaviour Wampex.Router.Authentication
+ require Logger
+
+ alias Wampex.Crypto
+ alias Wampex.Serializers.JSON
+
+ @wampcra "wampcra"
+ @auth_provider "userdb"
+ @auth_role "user"
+ @auth_password "bnASR5qF9y8k/sHF6S+NneCOhvVI0zFkvoKQpc2F+hA="
+ @salt "test"
+ @keylen 32
+ @iterations 10
+
+ @impl true
+ def authenticate?(methods) do
+ can_auth(methods)
+ end
+
+ @impl true
+ def method, do: @wampcra
+
+ @impl true
+ def challenge(_realm, authid, session_id) do
+ now = DateTime.to_iso8601(DateTime.utc_now())
+
+ %{
+ challenge:
+ JSON.serialize!(%{
+ nonce: Crypto.random_string(@keylen),
+ authprovider: @auth_provider,
+ authid: authid,
+ timestamp: now,
+ authrole: @auth_role,
+ authmethod: @wampcra,
+ session: session_id
+ }),
+ salt: @salt,
+ keylen: @keylen,
+ iterations: @iterations
+ }
+ end
+
+ @impl true
+ def parse_challenge(challenge) do
+ ch = JSON.deserialize!(challenge.challenge)
+
+ {get_in(ch, ["authid"]), get_in(ch, ["authrole"]), get_in(ch, ["authmethod"]), get_in(ch, ["authprovider"])}
+ end
+
+ @impl true
+ def authenticate(signature, realm, authid, %{
+ challenge: challenge
+ }) do
+ authid
+ |> get_secret(realm)
+ |> Crypto.hash_challenge(challenge)
+ |> :pbkdf2.compare_secure(signature)
+ end
+
+ defp get_secret(_authid, _uri), do: Crypto.pbkdf2(@auth_password, @salt, @iterations, @keylen)
+
+ defp can_auth([]), do: false
+ defp can_auth([@wampcra | _]), do: true
+ defp can_auth([_ | t]), do: can_auth(t)
+end
require Logger
alias Wampex.Client
alias Wampex.Roles.{Callee, Dealer}
- alias Callee.{Register, Yield}
+ alias Callee.{Register, Unregister, Yield}
alias Dealer.Invocation
def start_link(test, name, device) do
{:noreply, state}
end
+
+ def terminate(_r, {_test, name, id}) do
+ Client.send_request(
+ name,
+ Callee.unregister(%Unregister{registration_id: id})
+ )
+
+ :ok
+ end
end
alias Wampex.Roles.Peer.Hello
alias Wampex.Roles.Publisher.Publish
alias Wampex.Router
+ alias Wampex.Router.AuthenticationImpl
require Logger
@url "ws://localhost:4000/ws"
topologies: topologies,
replicas: 1,
quorum: 1,
- admin_realm: @realm_uri,
- admin_authid: @authid,
- admin_password: @auth_password
+ authentication_module: AuthenticationImpl,
+ authorization_module: nil
)
]
end
)
end
- @tag :client
- test "admin callee is invoked and responds and caller gets result" do
- caller_name = TestAdminCaller
- Client.start_link(name: caller_name, session: @session)
-
- %Result{arg_list: [id]} =
- Client.send_request(
- caller_name,
- Caller.call(%Call{
- procedure: "admin.create_peer",
- arg_kw: %{authid: "chris", password: "woot!", realm: @realm_uri}
- })
- )
-
- assert is_binary(id)
- end
-
- @tag :client
- test "admin callee is invoked and responds with error" do
- caller_name = TestAdminErrorCaller
- Client.start_link(name: caller_name, session: @session)
-
- assert {:error, 48, "Error registering user", %{}, [], %{}} =
- Client.send_request(
- caller_name,
- Caller.call(%Call{
- procedure: "admin.create_peer",
- arg_kw: %{authid: "chris", password: "woot!", realm: "not.real"}
- })
- )
- end
-
@tag :client
test "callee is invoked and responds and caller gets result" do
callee_name = TestCalleeRespond
Client.start_link(name: TestPublisher, session: @session)
+ Client.cast_send_request(
+ TestPublisher,
+ Publisher.publish(%Publish{
+ topic: "no.subscribers",
+ arg_list: [12.5, 45.6, 87.5],
+ arg_kw: %{loc: "60645"}
+ })
+ )
+
Client.cast_send_request(
TestPublisher,
Publisher.publish(%Publish{