From d3fb68f456f5a1b08a7c2fe1d7fc1f240f1fb5d5 Mon Sep 17 00:00:00 2001 From: Jakub Pisarek <99591440+sgfn@users.noreply.github.com> Date: Thu, 16 May 2024 15:18:00 +0200 Subject: [PATCH] [RTC-526] Add env vars to configure allowed components (#189) * [RTC-526] Add env vars to configure allowed components * lint * Changes after review * Print allowed components at JF startup --- config/runtime.exs | 7 ++- lib/jellyfish/application.ex | 2 + lib/jellyfish/component/recording.ex | 7 --- lib/jellyfish/component/sip.ex | 11 +--- lib/jellyfish/config_reader.ex | 31 ++++++---- lib/jellyfish/peer.ex | 8 +++ lib/jellyfish/peer/webrtc.ex | 6 -- lib/jellyfish/room.ex | 47 ++++++++++---- lib/jellyfish/room/state.ex | 61 +++++++++++++------ .../controllers/component_controller.ex | 48 ++++++++------- .../controllers/peer_controller.ex | 11 ++-- test/jellyfish/config_reader_test.exs | 31 +++++++--- .../component/file_component_test.exs | 7 ++- .../component/hls_component_test.exs | 10 ++- .../component/recording_component_test.exs | 10 ++- .../component/rtsp_component_test.exs | 8 +++ .../component/sip_component_test.exs | 6 +- .../controllers/component_controller_test.exs | 27 ++++++++ .../controllers/dial_controller_test.exs | 10 ++- .../controllers/peer_controller_test.exs | 15 ++++- .../subscription_controller_test.exs | 21 +++++-- .../integration/server_notification_test.exs | 13 +++- 22 files changed, 283 insertions(+), 114 deletions(-) diff --git a/config/runtime.exs b/config/runtime.exs index ca8b3fbf..f00aedca 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -25,6 +25,9 @@ host = other -> other end +components_used = ConfigReader.read_components_used() +sip_used? = Jellyfish.Component.SIP in components_used + config :jellyfish, jwt_max_age: 24 * 3600, media_files_path: @@ -34,8 +37,8 @@ config :jellyfish, metrics_port: ConfigReader.read_port("JF_METRICS_PORT") || 9568, dist_config: ConfigReader.read_dist_config(), webrtc_config: ConfigReader.read_webrtc_config(), - sip_config: ConfigReader.read_sip_config(), - recording_config: ConfigReader.read_recording_config(), + components_used: components_used, + sip_config: ConfigReader.read_sip_config(sip_used?), s3_config: ConfigReader.read_s3_config(), git_commit: ConfigReader.read_git_commit() diff --git a/lib/jellyfish/application.ex b/lib/jellyfish/application.ex index ebf8353f..1beba9d8 100644 --- a/lib/jellyfish/application.ex +++ b/lib/jellyfish/application.ex @@ -20,10 +20,12 @@ defmodule Jellyfish.Application do dist_config = Application.fetch_env!(:jellyfish, :dist_config) webrtc_config = Application.fetch_env!(:jellyfish, :webrtc_config) git_commit = Application.get_env(:jellyfish, :git_commit) + components_used = Application.get_env(:jellyfish, :components_used) Logger.info("Starting Jellyfish v#{Jellyfish.version()} (#{git_commit})") Logger.info("Distribution config: #{inspect(Keyword.delete(dist_config, :cookie))}") Logger.info("WebRTC config: #{inspect(webrtc_config)}") + Logger.info("Allowed components: #{inspect(components_used)}") children = [ diff --git a/lib/jellyfish/component/recording.ex b/lib/jellyfish/component/recording.ex index d6d1a6bc..b8036990 100644 --- a/lib/jellyfish/component/recording.ex +++ b/lib/jellyfish/component/recording.ex @@ -13,15 +13,8 @@ defmodule Jellyfish.Component.Recording do @impl true def config(%{engine_pid: engine} = options) do - recording_config = Application.fetch_env!(:jellyfish, :recording_config) sink_config = Application.fetch_env!(:jellyfish, :s3_config) - unless recording_config[:recording_used?], - do: - raise(""" - Recording components can only be used if JF_RECORDING_USED environmental variable is set to \"true\" - """) - with {:ok, serialized_opts} <- serialize_options(options, Options.schema()), result_opts <- parse_subscribe_mode(serialized_opts), {:ok, credentials} <- get_credentials(serialized_opts, sink_config), diff --git a/lib/jellyfish/component/sip.ex b/lib/jellyfish/component/sip.ex index 589db844..cf90c164 100644 --- a/lib/jellyfish/component/sip.ex +++ b/lib/jellyfish/component/sip.ex @@ -21,16 +21,7 @@ defmodule Jellyfish.Component.SIP do @impl true def config(%{engine_pid: engine} = options) do - sip_config = Application.fetch_env!(:jellyfish, :sip_config) - - external_ip = - if sip_config[:sip_used?] do - Application.fetch_env!(:jellyfish, :sip_config)[:sip_external_ip] - else - raise """ - SIP components can only be used if JF_SIP_USED environmental variable is set to \"true\" - """ - end + external_ip = Application.fetch_env!(:jellyfish, :sip_config)[:sip_external_ip] with {:ok, serialized_opts} <- serialize_options(options, Options.schema()) do endpoint_spec = %SIP{ diff --git a/lib/jellyfish/config_reader.ex b/lib/jellyfish/config_reader.ex index 8b5084b7..572abb5e 100644 --- a/lib/jellyfish/config_reader.ex +++ b/lib/jellyfish/config_reader.ex @@ -128,36 +128,45 @@ defmodule Jellyfish.ConfigReader do end end - def read_sip_config() do - sip_used? = read_boolean("JF_SIP_USED") + def read_components_used() do + components_used = System.get_env("JF_COMPONENTS_USED") || "" + + components_used + |> String.split(" ", trim: true) + |> Enum.map(fn type -> + case Jellyfish.Component.parse_type(type) do + {:ok, component} -> + component + + {:error, :invalid_type} -> + raise( + "Invalid value in JF_COMPONENTS_USED. Expected a lowercase component name, got: #{type}" + ) + end + end) + end + + def read_sip_config(sip_used?) do sip_ip = System.get_env("JF_SIP_IP") || "" cond do sip_used? != true -> [ - sip_used?: false, sip_external_ip: nil ] ip_address?(sip_ip) -> [ - sip_used?: true, sip_external_ip: sip_ip ] true -> raise """ - JF_SIP_USED has been set to true but incorrect IP address was provided as `JF_SIP_IP` + SIP components are allowed, but incorrect IP address was provided as `JF_SIP_IP` """ end end - def read_recording_config() do - [ - recording_used?: read_boolean("JF_RECORDING_USED") != false - ] - end - def read_s3_config() do credentials = [ bucket: System.get_env("JF_S3_BUCKET"), diff --git a/lib/jellyfish/peer.ex b/lib/jellyfish/peer.ex index 78dcad36..ae00ef01 100644 --- a/lib/jellyfish/peer.ex +++ b/lib/jellyfish/peer.ex @@ -51,6 +51,14 @@ defmodule Jellyfish.Peer do end end + @spec to_string!(module()) :: String.t() + def to_string!(peer) do + case peer do + WebRTC -> "webrtc" + _other -> raise "Invalid peer" + end + end + @spec new(peer(), map()) :: {:ok, t()} | {:error, term()} def new(type, options) do id = UUID.uuid4() diff --git a/lib/jellyfish/peer/webrtc.ex b/lib/jellyfish/peer/webrtc.ex index a3a34807..aa34bec3 100644 --- a/lib/jellyfish/peer/webrtc.ex +++ b/lib/jellyfish/peer/webrtc.ex @@ -14,12 +14,6 @@ defmodule Jellyfish.Peer.WebRTC do @impl true def config(options) do - if not Application.fetch_env!(:jellyfish, :webrtc_config)[:webrtc_used?] do - raise( - "WebRTC peers can only be used if JF_WEBRTC_USED environmental variable is not set to \"false\"" - ) - end - with {:ok, valid_opts} <- OpenApiSpex.cast_value(options, ApiSpec.Peer.WebRTC.schema()) do handshake_options = [ client_mode: false, diff --git a/lib/jellyfish/room.ex b/lib/jellyfish/room.ex index 47be9ebf..62de054c 100644 --- a/lib/jellyfish/room.ex +++ b/lib/jellyfish/room.ex @@ -67,7 +67,9 @@ defmodule Jellyfish.Room do end @spec add_peer(id(), Peer.peer(), map()) :: - {:ok, Peer.t()} | :error | {:error, :reached_peers_limit} + {:ok, Peer.t()} + | :error + | {:error, {:peer_disabled_globally, String.t()} | {:reached_peers_limit, String.t()}} def add_peer(room_id, peer_type, options \\ %{}) do GenServer.call(registry_id(room_id), {:add_peer, peer_type, options}) end @@ -92,7 +94,19 @@ defmodule Jellyfish.Room do @spec add_component(id(), Component.component(), map()) :: {:ok, Component.t()} | :error - | {:error, :incompatible_codec | :reached_components_limit_hls} + | {:error, + {:component_disabled_globally, String.t()} + | :incompatible_codec + | {:reached_components_limit, String.t()} + | :file_does_not_exist + | :bad_parameter_framerate_for_audio + | :invalid_framerate + | :invalid_file_path + | :unsupported_file_type + | {:missing_parameter, term()} + | :missing_s3_credentials + | :overriding_credentials + | :overriding_path_prefix} def add_component(room_id, component_type, options \\ %{}) do GenServer.call(registry_id(room_id), {:add_component, component_type, options}) end @@ -142,15 +156,22 @@ defmodule Jellyfish.Room do @impl true def handle_call({:add_peer, peer_type, override_options}, _from, state) do - with false <- State.reached_peers_limit?(state), + with :ok <- State.check_peer_allowed(peer_type, state), options <- State.generate_peer_options(state, override_options), {:ok, peer} <- Peer.new(peer_type, options) do state = State.add_peer(state, peer) {:reply, {:ok, peer}, state} else - true -> - {:reply, {:error, :reached_peers_limit}, state} + {:error, :peer_disabled_globally} -> + type = Peer.to_string!(peer_type) + Logger.warning("Unable to add peer: #{type} peers are disabled globally") + {:reply, {:error, {:peer_disabled_globally, type}}, state} + + {:error, :reached_peers_limit} -> + type = Peer.to_string!(peer_type) + Logger.warning("Unable to add peer: Reached #{type} peers limit") + {:reply, {:error, {:reached_peers_limit, type}}, state} {:error, reason} -> Logger.warning("Unable to add peer: #{inspect(reason)}") @@ -214,7 +235,7 @@ defmodule Jellyfish.Room do options ) - with :ok <- check_component_allowed(component_type, state), + with :ok <- State.check_component_allowed(component_type, state), {:ok, component} <- Component.new(component_type, options) do state = State.put_component(state, component) @@ -226,13 +247,18 @@ defmodule Jellyfish.Room do {:reply, {:ok, component}, state} else + {:error, :component_disabled_globally} -> + type = Component.to_string!(component_type) + Logger.warning("Unable to add component: #{type} components are disabled globally") + {:reply, {:error, {:component_disabled_globally, type}}, state} + {:error, :incompatible_codec} -> Logger.warning("Unable to add component: incompatible codec") {:reply, {:error, :incompatible_codec}, state} {:error, :reached_components_limit} -> type = Component.to_string!(component_type) - Logger.warning("Unable to add component: reached components limit #{type}") + Logger.warning("Unable to add component: reached #{type} components limit") {:reply, {:error, {:reached_components_limit, type}}, state} {:error, :file_does_not_exist} -> @@ -240,13 +266,12 @@ defmodule Jellyfish.Room do {:reply, {:error, :file_does_not_exist}, state} {:error, :bad_parameter_framerate_for_audio} -> - Logger.warning("Attempted to set framerate for audio component which is not supported.") - + Logger.warning("Unable to add component: attempted to set framerate for audio component") {:reply, {:error, :bad_parameter_framerate_for_audio}, state} {:error, {:invalid_framerate, passed_framerate}} -> Logger.warning( - "Invalid framerate value: #{passed_framerate}. It has to be a positivie integer." + "Unable to add component: expected framerate to be a positive integer, got: #{passed_framerate}" ) {:reply, {:error, :invalid_framerate}, state} @@ -256,7 +281,7 @@ defmodule Jellyfish.Room do {:reply, {:error, :invalid_file_path}, state} {:error, :unsupported_file_type} -> - Logger.warning("Unable to add component: unsupported file path") + Logger.warning("Unable to add component: unsupported file type") {:reply, {:error, :unsupported_file_type}, state} {:error, {:missing_parameter, name}} -> diff --git a/lib/jellyfish/room/state.ex b/lib/jellyfish/room/state.ex index 1f239cf6..8cf9fe63 100644 --- a/lib/jellyfish/room/state.ex +++ b/lib/jellyfish/room/state.ex @@ -382,33 +382,33 @@ defmodule Jellyfish.Room.State do ) end - def check_component_allowed(type, %{ - config: %{video_codec: video_codec}, - components: components - }) - when type in [HLS, Recording] do + @spec check_peer_allowed(Peer.peer(), t()) :: + :ok | {:error, :peer_disabled_globally | :reached_peers_limit} + def check_peer_allowed(Peer.WebRTC, state) do cond do - video_codec != :h264 -> - {:error, :incompatible_codec} + not Application.fetch_env!(:jellyfish, :webrtc_config)[:webrtc_used?] -> + {:error, :peer_disabled_globally} - component_already_present?(type, components) -> - {:error, :reached_components_limit} + Enum.count(state.peers) >= state.config.max_peers -> + {:error, :reached_peers_limit} true -> :ok end end - def check_component_allowed(RTSP, %{config: %{video_codec: video_codec}}) do - # Right now, RTSP component can only publish H264, so there's no point adding it - # to a room which allows another video codec, e.g. VP8 - if video_codec == :h264, - do: :ok, - else: {:error, :incompatible_codec} + @spec check_component_allowed(Component.component(), t()) :: + :ok + | {:error, + :component_disabled_globally | :incompatible_codec | :reached_components_limit} + def check_component_allowed(type, state) do + if type in Application.fetch_env!(:jellyfish, :components_used) do + check_component_allowed_in_room(type, state) + else + {:error, :component_disabled_globally} + end end - def check_component_allowed(_component_type, _state), do: :ok - @spec get_endpoint_id_type(state :: t(), endpoint_id :: endpoint_id()) :: :peer_id | :component_id def get_endpoint_id_type(state, endpoint_id) do @@ -435,6 +435,33 @@ defmodule Jellyfish.Room.State do def validate_subscription_mode(%{properties: %{subscribe_mode: :manual}}), do: :ok def validate_subscription_mode(_not_properties), do: {:error, :invalid_component_type} + defp check_component_allowed_in_room(type, %{ + config: %{video_codec: video_codec}, + components: components + }) + when type in [HLS, Recording] do + cond do + video_codec != :h264 -> + {:error, :incompatible_codec} + + component_already_present?(type, components) -> + {:error, :reached_components_limit} + + true -> + :ok + end + end + + defp check_component_allowed_in_room(RTSP, %{config: %{video_codec: video_codec}}) do + # Right now, RTSP component can only publish H264, so there's no point adding it + # to a room which allows another video codec, e.g. VP8 + if video_codec == :h264, + do: :ok, + else: {:error, :incompatible_codec} + end + + defp check_component_allowed_in_room(_component_type, _state), do: :ok + defp component_already_present?(type, components), do: components |> Map.values() |> Enum.any?(&(&1.type == type)) diff --git a/lib/jellyfish_web/controllers/component_controller.ex b/lib/jellyfish_web/controllers/component_controller.ex index efc9fe92..443fdc3b 100644 --- a/lib/jellyfish_web/controllers/component_controller.ex +++ b/lib/jellyfish_web/controllers/component_controller.ex @@ -76,49 +76,51 @@ defmodule JellyfishWeb.ComponentController do :error -> {:error, :bad_request, "Invalid request body structure"} - {:error, {:missing_parameter, name}} -> - {:error, :bad_request, "Required field \"#{Atom.to_string(name)}\" missing"} - - {:error, :missing_s3_credentials} -> - {:error, :bad_request, - "S3 credentials has to be passed either by request or at application startup as envs"} - - {:error, :overridding_credentials} -> - {:error, :bad_request, - "Conflicting S3 credentials supplied via environment variables and the REST API. Overrides on existing values are disallowed"} - - {:error, :overridding_path_prefix} -> - {:error, :bad_request, - "Conflicting S3 path prefix supplied via environment variables and the REST API. Overrides on existing values are disallowed"} + {:error, :room_not_found} -> + {:error, :not_found, "Room #{room_id} does not exist"} {:error, :invalid_type} -> {:error, :bad_request, "Invalid component type"} - {:error, :room_not_found} -> - {:error, :not_found, "Room #{room_id} does not exist"} + {:error, {:component_disabled_globally, type}} -> + {:error, :bad_request, "Components of type #{type} are disabled on this Jellyfish"} {:error, :incompatible_codec} -> {:error, :bad_request, "Incompatible video codec enforced in room #{room_id}"} - {:error, :invalid_framerate} -> - {:error, :bad_request, "Invalid framerate passed"} + {:error, {:reached_components_limit, type}} -> + {:error, :bad_request, "Reached #{type} components limit in room #{room_id}"} + + {:error, :file_does_not_exist} -> + {:error, :not_found, "File not found"} {:error, :bad_parameter_framerate_for_audio} -> {:error, :bad_request, "Attempted to set framerate for audio component which is not supported."} + {:error, :invalid_framerate} -> + {:error, :bad_request, "Invalid framerate passed"} + {:error, :invalid_file_path} -> {:error, :bad_request, "Invalid file path"} - {:error, :file_does_not_exist} -> - {:error, :not_found, "File not found"} - {:error, :unsupported_file_type} -> {:error, :bad_request, "Unsupported file type"} - {:error, {:reached_components_limit, type}} -> + {:error, {:missing_parameter, name}} -> + {:error, :bad_request, "Required field \"#{Atom.to_string(name)}\" missing"} + + {:error, :missing_s3_credentials} -> + {:error, :bad_request, + "S3 credentials has to be passed either by request or at application startup as envs"} + + {:error, :overridding_credentials} -> {:error, :bad_request, - "Reached #{type} components limit for component in room #{room_id}"} + "Conflicting S3 credentials supplied via environment variables and the REST API. Overrides on existing values are disallowed"} + + {:error, :overridding_path_prefix} -> + {:error, :bad_request, + "Conflicting S3 path prefix supplied via environment variables and the REST API. Overrides on existing values are disallowed"} end end diff --git a/lib/jellyfish_web/controllers/peer_controller.ex b/lib/jellyfish_web/controllers/peer_controller.ex index 4be11780..39d846ba 100644 --- a/lib/jellyfish_web/controllers/peer_controller.ex +++ b/lib/jellyfish_web/controllers/peer_controller.ex @@ -88,14 +88,17 @@ defmodule JellyfishWeb.PeerController do :error -> {:error, :bad_request, "Invalid request body structure"} + {:error, :room_not_found} -> + {:error, :not_found, "Room #{room_id} does not exist"} + {:error, :invalid_type} -> {:error, :bad_request, "Invalid peer type"} - {:error, :room_not_found} -> - {:error, :not_found, "Room #{room_id} does not exist"} + {:error, {:peer_disabled_globally, type}} -> + {:error, :bad_request, "Peers of type #{type} are disabled on this Jellyfish"} - {:error, :reached_peers_limit} -> - {:error, :service_unavailable, "Reached peer limit in room #{room_id}"} + {:error, {:reached_peers_limit, type}} -> + {:error, :service_unavailable, "Reached #{type} peers limit in room #{room_id}"} end end diff --git a/test/jellyfish/config_reader_test.exs b/test/jellyfish/config_reader_test.exs index 84c73c27..05c6eb92 100644 --- a/test/jellyfish/config_reader_test.exs +++ b/test/jellyfish/config_reader_test.exs @@ -151,18 +151,35 @@ defmodule Jellyfish.ConfigReaderTest do end end - test "read_sip_config/0" do - with_env ["JF_SIP_USED", "JF_SIP_IP"] do - assert ConfigReader.read_sip_config() == [sip_used?: false, sip_external_ip: nil] + test "read_components_used/0" do + with_env ["JF_COMPONENTS_USED"] do + assert ConfigReader.read_components_used() == [] - System.put_env("JF_SIP_USED", "true") - assert_raise RuntimeError, fn -> ConfigReader.read_sip_config() end + System.put_env("JF_COMPONENTS_USED", "hls") + assert ConfigReader.read_components_used() == [Jellyfish.Component.HLS] + + System.put_env("JF_COMPONENTS_USED", "recording rtsp sip ") + + assert ConfigReader.read_components_used() |> Enum.sort() == + [Jellyfish.Component.Recording, Jellyfish.Component.RTSP, Jellyfish.Component.SIP] + |> Enum.sort() + + System.put_env("JF_COMPONENTS_USED", "file rtsp invalid_component") + assert_raise RuntimeError, fn -> ConfigReader.read_components_used() end + end + end + + test "read_sip_config/1" do + with_env ["JF_SIP_IP"] do + assert ConfigReader.read_sip_config(false) == [sip_external_ip: nil] + + assert_raise RuntimeError, fn -> ConfigReader.read_sip_config(true) end System.put_env("JF_SIP_IP", "abcdefg") - assert_raise RuntimeError, fn -> ConfigReader.read_sip_config() end + assert_raise RuntimeError, fn -> ConfigReader.read_sip_config(true) end System.put_env("JF_SIP_IP", "127.0.0.1") - assert ConfigReader.read_sip_config() == [sip_used?: true, sip_external_ip: "127.0.0.1"] + assert ConfigReader.read_sip_config(true) == [sip_external_ip: "127.0.0.1"] end end diff --git a/test/jellyfish_web/controllers/component/file_component_test.exs b/test/jellyfish_web/controllers/component/file_component_test.exs index 856abd5d..6055a8e2 100644 --- a/test/jellyfish_web/controllers/component/file_component_test.exs +++ b/test/jellyfish_web/controllers/component/file_component_test.exs @@ -21,6 +21,8 @@ defmodule JellyfishWeb.Component.FileComponentTest do @auth_response %Authenticated{} setup_all _tags do + Application.put_env(:jellyfish, :components_used, [Jellyfish.Component.File]) + media_sources_directory = Application.fetch_env!(:jellyfish, :media_files_path) |> Path.join(@file_component_directory) @@ -30,7 +32,10 @@ defmodule JellyfishWeb.Component.FileComponentTest do File.cp_r!(@fixtures_directory, media_sources_directory) - on_exit(fn -> :file.del_dir_r(media_sources_directory) end) + on_exit(fn -> + :file.del_dir_r(media_sources_directory) + Application.put_env(:jellyfish, :components_used, []) + end) {:ok, %{media_sources_directory: media_sources_directory}} end diff --git a/test/jellyfish_web/controllers/component/hls_component_test.exs b/test/jellyfish_web/controllers/component/hls_component_test.exs index 9f3ea738..aafe0f21 100644 --- a/test/jellyfish_web/controllers/component/hls_component_test.exs +++ b/test/jellyfish_web/controllers/component/hls_component_test.exs @@ -21,6 +21,14 @@ defmodule JellyfishWeb.Component.HlsComponentTest do } |> map_keys_to_string() + setup_all do + Application.put_env(:jellyfish, :components_used, [HLS]) + + on_exit(fn -> + Application.put_env(:jellyfish, :components_used, []) + end) + end + describe "create hls component" do setup [:create_h264_room] @@ -46,7 +54,7 @@ defmodule JellyfishWeb.Component.HlsComponentTest do conn = post(conn, ~p"/room/#{room_id}/component", type: "hls") assert model_response(conn, :bad_request, "Error")["errors"] == - "Reached hls components limit for component in room #{room_id}" + "Reached hls components limit in room #{room_id}" conn = delete(conn, ~p"/room/#{room_id}") assert response(conn, :no_content) diff --git a/test/jellyfish_web/controllers/component/recording_component_test.exs b/test/jellyfish_web/controllers/component/recording_component_test.exs index ac1642ee..1dfaa3b0 100644 --- a/test/jellyfish_web/controllers/component/recording_component_test.exs +++ b/test/jellyfish_web/controllers/component/recording_component_test.exs @@ -15,6 +15,14 @@ defmodule JellyfishWeb.Component.RecordingComponentTest do @path_prefix "path_prefix" + setup_all do + Application.put_env(:jellyfish, :components_used, [Jellyfish.Component.Recording]) + + on_exit(fn -> + Application.put_env(:jellyfish, :components_used, []) + end) + end + describe "create recording component" do setup [:create_h264_room] setup :set_mox_from_context @@ -49,7 +57,7 @@ defmodule JellyfishWeb.Component.RecordingComponentTest do conn = post(conn, ~p"/room/#{room_id}/component", type: "recording") assert model_response(conn, :bad_request, "Error")["errors"] == - "Reached recording components limit for component in room #{room_id}" + "Reached recording components limit in room #{room_id}" end setup :set_mox_from_context diff --git a/test/jellyfish_web/controllers/component/rtsp_component_test.exs b/test/jellyfish_web/controllers/component/rtsp_component_test.exs index cc61b56f..9372db6b 100644 --- a/test/jellyfish_web/controllers/component/rtsp_component_test.exs +++ b/test/jellyfish_web/controllers/component/rtsp_component_test.exs @@ -22,6 +22,14 @@ defmodule JellyfishWeb.Component.RTSPComponentTest do } @rtsp_custom_properties @rtsp_custom_options |> map_keys_to_string() + setup_all do + Application.put_env(:jellyfish, :components_used, [Jellyfish.Component.RTSP]) + + on_exit(fn -> + Application.put_env(:jellyfish, :components_used, []) + end) + end + describe "create rtsp component" do setup [:create_h264_room] diff --git a/test/jellyfish_web/controllers/component/sip_component_test.exs b/test/jellyfish_web/controllers/component/sip_component_test.exs index 85994fc3..9a3a4826 100644 --- a/test/jellyfish_web/controllers/component/sip_component_test.exs +++ b/test/jellyfish_web/controllers/component/sip_component_test.exs @@ -14,10 +14,12 @@ defmodule JellyfishWeb.Component.SIPComponentTest do |> map_keys_to_string() setup_all do - Application.put_env(:jellyfish, :sip_config, sip_used?: true, sip_external_ip: "127.0.0.1") + Application.put_env(:jellyfish, :sip_config, sip_external_ip: "127.0.0.1") + Application.put_env(:jellyfish, :components_used, [Jellyfish.Component.SIP]) on_exit(fn -> - Application.put_env(:jellyfish, :sip_config, sip_used?: false, sip_external_ip: nil) + Application.put_env(:jellyfish, :sip_config, sip_external_ip: nil) + Application.put_env(:jellyfish, :components_used, []) end) end diff --git a/test/jellyfish_web/controllers/component_controller_test.exs b/test/jellyfish_web/controllers/component_controller_test.exs index 3d5c3b75..cb73719a 100644 --- a/test/jellyfish_web/controllers/component_controller_test.exs +++ b/test/jellyfish_web/controllers/component_controller_test.exs @@ -4,6 +4,17 @@ defmodule JellyfishWeb.ComponentControllerTest do @source_uri "rtsp://placeholder-19inrifjbsjb.it:12345/afwefae" + setup_all do + Application.put_env(:jellyfish, :components_used, [ + Jellyfish.Component.RTSP, + Jellyfish.Component.HLS + ]) + + on_exit(fn -> + Application.put_env(:jellyfish, :components_used, []) + end) + end + describe "create component" do test "renders errors when component type is invalid", %{conn: conn, room_id: room_id} do conn = post(conn, ~p"/room/#{room_id}/component", type: "invalid_type") @@ -19,6 +30,22 @@ defmodule JellyfishWeb.ComponentControllerTest do response = model_response(conn, :not_found, "Error") assert response["errors"] == "Room #{room_id} does not exist" end + + test "renders errors when component isn't allowed globally", %{conn: conn, room_id: room_id} do + Application.put_env(:jellyfish, :components_used, []) + + on_exit(fn -> + Application.put_env(:jellyfish, :components_used, [ + Jellyfish.Component.RTSP, + Jellyfish.Component.HLS + ]) + end) + + conn = post(conn, ~p"/room/#{room_id}/component", type: "hls") + + response = model_response(conn, :bad_request, "Error") + assert response["errors"] == "Components of type hls are disabled on this Jellyfish" + end end describe "delete component" do diff --git a/test/jellyfish_web/controllers/dial_controller_test.exs b/test/jellyfish_web/controllers/dial_controller_test.exs index 981d6d98..17c4c09f 100644 --- a/test/jellyfish_web/controllers/dial_controller_test.exs +++ b/test/jellyfish_web/controllers/dial_controller_test.exs @@ -10,10 +10,16 @@ defmodule JellyfishWeb.DialControllerTest do } setup_all do - Application.put_env(:jellyfish, :sip_config, sip_used?: true, sip_external_ip: "127.0.0.1") + Application.put_env(:jellyfish, :sip_config, sip_external_ip: "127.0.0.1") + + Application.put_env(:jellyfish, :components_used, [ + Jellyfish.Component.SIP, + Jellyfish.Component.RTSP + ]) on_exit(fn -> - Application.put_env(:jellyfish, :sip_config, sip_used?: false, sip_external_ip: nil) + Application.put_env(:jellyfish, :sip_config, sip_external_ip: nil) + Application.put_env(:jellyfish, :components_used, []) end) end diff --git a/test/jellyfish_web/controllers/peer_controller_test.exs b/test/jellyfish_web/controllers/peer_controller_test.exs index 81d33c7d..646397c5 100644 --- a/test/jellyfish_web/controllers/peer_controller_test.exs +++ b/test/jellyfish_web/controllers/peer_controller_test.exs @@ -76,7 +76,7 @@ defmodule JellyfishWeb.PeerControllerTest do conn = post(conn, ~p"/room/#{room_id}/peer", type: @peer_type) assert json_response(conn, :service_unavailable)["errors"] == - "Reached peer limit in room #{room_id}" + "Reached webrtc peers limit in room #{room_id}" end test "renders errors when room doesn't exist", %{conn: conn} do @@ -89,6 +89,19 @@ defmodule JellyfishWeb.PeerControllerTest do conn = post(conn, ~p"/room/#{room_id}/peer", invalid_param: @peer_type) assert json_response(conn, :bad_request)["errors"] == "Invalid request body structure" end + + test "renders errors when peer isn't allowed globally", %{conn: conn, room_id: room_id} do + Application.put_env(:jellyfish, :webrtc_config, webrtc_used?: false) + + on_exit(fn -> + Application.put_env(:jellyfish, :webrtc_config, webrtc_used?: true) + end) + + conn = post(conn, ~p"/room/#{room_id}/peer", type: @peer_type) + + assert json_response(conn, :bad_request)["errors"] == + "Peers of type webrtc are disabled on this Jellyfish" + end end describe "delete peer" do diff --git a/test/jellyfish_web/controllers/subscription_controller_test.exs b/test/jellyfish_web/controllers/subscription_controller_test.exs index f43ba25e..6fe03d3d 100644 --- a/test/jellyfish_web/controllers/subscription_controller_test.exs +++ b/test/jellyfish_web/controllers/subscription_controller_test.exs @@ -14,6 +14,21 @@ defmodule JellyfishWeb.SubscriptionControllerTest do password: "pass-word" } + setup_all do + Application.put_env(:jellyfish, :sip_config, sip_external_ip: "127.0.0.1") + + Application.put_env(:jellyfish, :components_used, [ + Jellyfish.Component.SIP, + Jellyfish.Component.HLS, + Jellyfish.Component.Recording + ]) + + on_exit(fn -> + Application.put_env(:jellyfish, :sip_config, sip_external_ip: nil) + Application.put_env(:jellyfish, :components_used, []) + end) + end + setup %{conn: conn} do server_api_token = Application.fetch_env!(:jellyfish, :server_api_token) conn = put_req_header(conn, "authorization", "Bearer " <> server_api_token) @@ -54,12 +69,6 @@ defmodule JellyfishWeb.SubscriptionControllerTest do conn: conn, room_id: room_id } do - Application.put_env(:jellyfish, :sip_config, sip_used?: true, sip_external_ip: "127.0.0.1") - - on_exit(fn -> - Application.put_env(:jellyfish, :sip_config, sip_used?: false, sip_external_ip: nil) - end) - conn = post(conn, ~p"/room/#{room_id}/component", type: "sip", diff --git a/test/jellyfish_web/integration/server_notification_test.exs b/test/jellyfish_web/integration/server_notification_test.exs index 9eabe3d6..efdae952 100644 --- a/test/jellyfish_web/integration/server_notification_test.exs +++ b/test/jellyfish_web/integration/server_notification_test.exs @@ -9,6 +9,7 @@ defmodule JellyfishWeb.Integration.ServerNotificationTest do alias Membrane.RTC.Engine + alias Jellyfish.Component alias Jellyfish.Component.HLS alias Jellyfish.Component.HLS.Manager alias Jellyfish.{PeerMessage, Room, RoomService, ServerMessage} @@ -93,10 +94,18 @@ defmodule JellyfishWeb.Integration.ServerNotificationTest do end setup_all do - Application.put_env(:jellyfish, :sip_config, sip_used?: true, sip_external_ip: "127.0.0.1") + Application.put_env(:jellyfish, :sip_config, sip_external_ip: "127.0.0.1") + + Application.put_env(:jellyfish, :components_used, [ + Component.SIP, + Component.HLS, + Component.RTSP, + Component.File + ]) on_exit(fn -> - Application.put_env(:jellyfish, :sip_config, sip_used?: false, sip_external_ip: nil) + Application.put_env(:jellyfish, :sip_config, sip_external_ip: nil) + Application.put_env(:jellyfish, :components_used, []) end) assert {:ok, _pid} = Endpoint.start_link()