diff options
-rw-r--r-- | rwa/support/sessionservice/config.py | 4 | ||||
-rwxr-xr-x | rwa/support/sessionservice/service.py | 101 | ||||
-rw-r--r-- | rwa/support/sessionservice/session.py | 3 |
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/" |