forked from edgehog-device-manager/edgehog
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add GraphQL query to retrieve the status of a forwarder session
Define a `forwarderSession` GraphQL query that can be used by clients to inspect the status of a device → Forwarder session, and know whether the session is ready to be accessed and it is closed. Closes edgehog-device-manager#446 Signed-off-by: Davide Briani <davide.briani@secomind.com>
- Loading branch information
1 parent
ff109af
commit 51a3a72
Showing
5 changed files
with
235 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# | ||
# This file is part of Edgehog. | ||
# | ||
# Copyright 2024 SECO Mind Srl | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
# | ||
|
||
defmodule EdgehogWeb.Resolvers.ForwarderSessions do | ||
alias Edgehog.Astarte | ||
alias Edgehog.Devices | ||
alias Edgehog.Devices.Device | ||
|
||
@doc """ | ||
Fetches a forwarder session by its token and the device ID | ||
""" | ||
def find_forwarder_session(%{device_id: device_id, session_token: session_token}, _resolution) do | ||
device = | ||
device_id | ||
|> Devices.get_device!() | ||
|> Devices.preload_astarte_resources_for_device() | ||
|
||
with :ok <- validate_device_connected(device), | ||
{:ok, appengine_client} <- Devices.appengine_client_from_device(device) do | ||
Astarte.fetch_forwarder_session(appengine_client, device.device_id, session_token) | ||
end | ||
end | ||
|
||
defp validate_device_connected(%Device{online: true}), do: :ok | ||
defp validate_device_connected(%Device{online: false}), do: {:error, :device_disconnected} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# | ||
# This file is part of Edgehog. | ||
# | ||
# Copyright 2024 SECO Mind Srl | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
# | ||
|
||
defmodule EdgehogWeb.Schema.ForwarderSessionsTypes do | ||
use Absinthe.Schema.Notation | ||
use Absinthe.Relay.Schema.Notation, :modern | ||
|
||
alias EdgehogWeb.Resolvers | ||
|
||
@desc """ | ||
The status of a forwarder session | ||
""" | ||
enum :forwarder_session_status do | ||
@desc "The device is connected to the forwarder." | ||
value :connected | ||
@desc "The device is connecting to the forwarder." | ||
value :connecting | ||
@desc "The device is not connected to the forwarder." | ||
value :disconnected | ||
end | ||
|
||
@desc """ | ||
The details of a forwarder session | ||
""" | ||
object :forwarder_session do | ||
@desc "The token that identifies the session." | ||
field :token, non_null(:string) | ||
@desc "The status of the session." | ||
field :status, non_null(:forwarder_session_status) | ||
@desc "Indicates if TLS is used when the device connects to the forwarder." | ||
field :secure, non_null(:boolean) | ||
@desc "The hostname of the forwarder instance." | ||
field :forwarder_hostname, non_null(:string) | ||
@desc "The port of the forwarder instance." | ||
field :forwarder_port, non_null(:integer) | ||
end | ||
|
||
object :forwarder_sessions_queries do | ||
@desc "Fetches a forwarder session by its token and the device ID." | ||
field :forwarder_session, :forwarder_session do | ||
@desc "The GraphQL ID of the device corresponding to the session." | ||
arg :device_id, non_null(:id) | ||
@desc "The token that identifies the session." | ||
arg :session_token, non_null(:string) | ||
|
||
middleware Absinthe.Relay.Node.ParseIDs, device_id: :device | ||
resolve &Resolvers.ForwarderSessions.find_forwarder_session/2 | ||
end | ||
end | ||
end |
121 changes: 121 additions & 0 deletions
121
backend/test/edgehog_web/schema/query/forwarder_session_test.exs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
# | ||
# This file is part of Edgehog. | ||
# | ||
# Copyright 2024 SECO Mind Srl | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
# | ||
|
||
defmodule EdgehogWeb.Schema.Query.ForwarderSessionTest do | ||
use EdgehogWeb.ConnCase, async: true | ||
use Edgehog.AstarteMockCase | ||
|
||
alias Edgehog.Astarte.Device.ForwarderSession | ||
|
||
import Edgehog.AstarteFixtures | ||
import Edgehog.DevicesFixtures | ||
|
||
describe "forwarderSession query" do | ||
setup do | ||
cluster = cluster_fixture() | ||
realm = realm_fixture(cluster) | ||
|
||
{:ok, realm: realm} | ||
end | ||
|
||
@query """ | ||
query ($device_id: ID!, $session_token: String!) { | ||
forwarderSession(deviceId: $device_id, sessionToken: $session_token) { | ||
token | ||
status | ||
forwarderHostname | ||
forwarderPort | ||
} | ||
} | ||
""" | ||
|
||
test "returns the forwarder session", %{conn: conn, api_path: api_path, realm: realm} do | ||
device = device_fixture(realm, %{online: true}) | ||
|
||
mock_forwarder_session(device, %ForwarderSession{ | ||
token: "session_token", | ||
status: :disconnected, | ||
secure: false, | ||
forwarder_hostname: "localhost", | ||
forwarder_port: 4001 | ||
}) | ||
|
||
variables = %{ | ||
device_id: Absinthe.Relay.Node.to_global_id(:device, device.id, EdgehogWeb.Schema), | ||
session_token: "session_token" | ||
} | ||
|
||
result = run_query(conn, api_path, variables) | ||
|
||
assert %{ | ||
"data" => %{ | ||
"forwarderSession" => %{ | ||
"token" => "session_token", | ||
"status" => "DISCONNECTED", | ||
"forwarderHostname" => "localhost", | ||
"forwarderPort" => 4001 | ||
} | ||
} | ||
} = result | ||
end | ||
|
||
test "returns error if the device is disconnected", %{ | ||
conn: conn, | ||
api_path: api_path, | ||
realm: realm | ||
} do | ||
device = device_fixture(realm, %{online: false}) | ||
|
||
variables = %{ | ||
device_id: Absinthe.Relay.Node.to_global_id(:device, device.id, EdgehogWeb.Schema), | ||
session_token: "session_token" | ||
} | ||
|
||
result = run_query(conn, api_path, variables) | ||
|
||
assert %{ | ||
"data" => %{"forwarderSession" => nil}, | ||
"errors" => [ | ||
%{ | ||
"code" => "device_disconnected", | ||
"message" => "The device is not connected", | ||
"status_code" => 409 | ||
} | ||
] | ||
} = result | ||
end | ||
end | ||
|
||
defp mock_forwarder_session(device, forwarder_session) do | ||
device_id = device.device_id | ||
session_token = forwarder_session.token | ||
|
||
Edgehog.Astarte.Device.ForwarderSessionMock | ||
|> expect(:fetch_session, fn _appengine_client, ^device_id, ^session_token -> | ||
{:ok, forwarder_session} | ||
end) | ||
end | ||
|
||
defp run_query(conn, api_path, variables) do | ||
conn | ||
|> get(api_path, query: @query, variables: variables) | ||
|> json_response(200) | ||
end | ||
end |