aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Weth <mail@jonathanweth.de>2021-07-01 11:01:23 +0000
committerJonathan Weth <mail@jonathanweth.de>2021-07-01 11:01:23 +0000
commitf2b1dc8e53f5dbe353a9c35c37550d00ba206bdb (patch)
tree355540ca58a3cef6622c312e06c646c25a3394db
parent807200788a336d309909cb92ec03da0d5627acb5 (diff)
parent0d4fa0b19f3ff02cea3c01c9119767d9d27cceef (diff)
downloadRWA.Support.SessionService-f2b1dc8e53f5dbe353a9c35c37550d00ba206bdb.tar.gz
RWA.Support.SessionService-f2b1dc8e53f5dbe353a9c35c37550d00ba206bdb.tar.bz2
RWA.Support.SessionService-f2b1dc8e53f5dbe353a9c35c37550d00ba206bdb.zip
Merge branch 'feature/api-handshake' into 'master'
Implement API handshake See merge request remotewebapp/rwa.support.sessionservice!8
-rw-r--r--rwa/support/sessionservice/config.py4
-rwxr-xr-xrwa/support/sessionservice/service.py101
-rw-r--r--rwa/support/sessionservice/session.py3
3 files changed, 95 insertions, 13 deletions
diff --git a/rwa/support/sessionservice/config.py b/rwa/support/sessionservice/config.py
index f334e81..a9f75e6 100644
--- a/rwa/support/sessionservice/config.py
+++ b/rwa/support/sessionservice/config.py
@@ -22,3 +22,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+SUPPORTED_API_VERSIONS = [1]
+API_PATH = "/app/rwasupport/api/"
+ALLOW_ONLY_ONE_SESSION = True
diff --git a/rwa/support/sessionservice/service.py b/rwa/support/sessionservice/service.py
index d205056..bb9a1e1 100755
--- a/rwa/support/sessionservice/service.py
+++ b/rwa/support/sessionservice/service.py
@@ -29,23 +29,23 @@ import json
import signal
import time
from threading import Thread
-from typing import Union
+from typing import Dict, Union
import click
import dbus
import dbus.mainloop.glib
import dbus.service
+import requests
import usersettings
import validators
from gi.repository import GLib
+from .config import ALLOW_ONLY_ONE_SESSION, API_PATH, SUPPORTED_API_VERSIONS
from .lock import is_locked, lock, unlock
from .log import logging
from .session import Session
from .trigger import TriggerServerThread
-ALLOW_ONLY_ONE_SESSION = True
-
class RWASupportSessionService(dbus.service.Object):
"""D-Bus Session Service for RWA.Support.
@@ -118,6 +118,55 @@ class RWASupportSessionService(dbus.service.Object):
logging.debug('Return to D-Bus caller: "%s"', self._get_web_app_hosts())
return self._get_web_app_hosts()
+ def _do_api_handshake(self, host: str) -> Dict[str, str]:
+ """Contact a RWA.Support.WebApp host and find out API version.
+
+ :param host: The full hostname.
+ :return: Status information as dictionary.
+
+ **Structure of returned JSON (success):**
+
+ ::
+
+ {"status": "success", "type": "valid_host"}
+
+ **Structure of returned JSON (error):**
+
+ ::
+
+ {"status": "error", "type": "<type>"}
+
+ **Possible choices for error types:**
+
+ * ``connection``
+ * ``permission_denied``
+ * ``unsupported_server``
+ """
+ url = host + API_PATH + "handshake/"
+ logging.info(f"API handshake with {url} ...")
+ try:
+ r = requests.post(url)
+
+ except requests.exceptions.ConnectionError:
+ logging.warning(" resulted in a connection error.")
+ return {"status": "error", "type": "connection"}
+
+ if not r.ok:
+ logging.warning(" resulted in a connection error.")
+ return {"status": "error", "type": "connection"}
+
+ if not r.json()["allowed"]:
+ logging.warning(" was not permitted.")
+ return {"status": "error", "type": "permission_denied"}
+
+ if r.json().get("api_version") not in SUPPORTED_API_VERSIONS:
+ logging.warning(" resulted in a incompatible API version.")
+ return {"status": "error", "type": "unsupported_server"}
+
+ logging.info(" was successful.")
+
+ return {"status": "success", "type": "valid_host"}
+
@dbus.service.method(
"org.ArcticaProject.RWASupportSessionService", in_signature="s", out_signature="s"
)
@@ -127,23 +176,42 @@ class RWASupportSessionService(dbus.service.Object):
:param host: Exact hostname of the RWA.Support.WebApp host (D-Bus string)
:return: All registered hosts as JSON array (D-Bus string)
- **Structure of returned JSON:**
+ **Structure of returned JSON (success):**
::
["https://example.org", "http://127.0.0.1:8000"]
+
+ **Structure of returned JSON (error):**
+
+ ::
+
+ {"status": "error", "type": "<type>"}
+
+ **Possible choices for error types:**
+
+ * ``connection``
+ * ``permission_denied``
+ * ``unsupported_server``
+ * ``invalid_url``
"""
host = str(host)
logging.info('D-Bus method call: %s("%s")', "add_web_app_host", host)
- if self._is_url(host):
- self.settings.save_settings()
- self.settings.web_app_hosts.append(host)
- logging.debug('Added "%s" to "web_app_hosts" in user_settings', host)
- else:
+ if not self._is_url(host):
logging.warning("Given URL is not valid!")
logging.debug('Did not add "%s" to "web_app_hosts" in user_settings', host)
+ return json.dumps({"status": "error", "type": "invalid_url"})
+
+ res = self._do_api_handshake(host)
+ if res["status"] == "error":
+ return json.dumps(res)
+
+ self.settings.web_app_hosts.append(host)
+ self.settings.save_settings()
+ logging.debug('Added "%s" to "web_app_hosts" in user_settings', host)
+
return self._get_web_app_hosts()
@dbus.service.method(
@@ -197,9 +265,13 @@ class RWASupportSessionService(dbus.service.Object):
{"status": "error", "type": "<type>"}
- **Possible choices for error types:** ``multiple``,
- ``connection``,
- ``host_not_found``
+ **Possible choices for error types:**
+
+ * ``multiple``
+ * ``connection``
+ * ``host_not_found``
+ * ``permission_denied``
+ * ``unsupported_server``
"""
logging.info("D-Bus method call: %s(%d)", "start", host_idx)
@@ -222,6 +294,11 @@ class RWASupportSessionService(dbus.service.Object):
logging.debug("The response to the D-Bus caller: '%s'", response)
return response
+ # Check host by doing a handshake
+ res = self._do_api_handshake(host)
+ if res["status"] == "error":
+ return json.dumps(res)
+
# Start session
try:
session = Session(host, self.trigger_service.port, self.mockup_mode)
diff --git a/rwa/support/sessionservice/session.py b/rwa/support/sessionservice/session.py
index 0126800..aa97086 100644
--- a/rwa/support/sessionservice/session.py
+++ b/rwa/support/sessionservice/session.py
@@ -35,6 +35,7 @@ import port_for
import psutil
import requests
+from .config import API_PATH
from .lock import TEMP_DIR_PATH
from .log import logging
from .vnc import run_vnc, save_password
@@ -59,7 +60,7 @@ class Session:
def __init__(self, host: str, trigger_port: int, mockup_session: bool = False):
self.host = host
- self.BASE_URL = self.host + "/app/rwasupport/api/"
+ self.BASE_URL = self.host + API_PATH
self.REGISTER_URL = self.BASE_URL + "register/"
self.STOP_URL = self.BASE_URL + "stop/"
self.STATUS_URL = self.BASE_URL + "status/"