aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Weth <git@jonathanweth.de>2021-06-30 11:01:04 +0200
committerJonathan Weth <git@jonathanweth.de>2021-06-30 11:01:04 +0200
commit125b78b43f24dcbbe9d75879660a056920c72ea5 (patch)
tree51dac44a3ab55d8e24756024c68cf57ff63ac322
parenteb1ee8aae329d83166028ef0496724f30ecce032 (diff)
parent78e14ca8043814c5816a10756fed31e075f87b03 (diff)
downloadRWA.Support.SessionService-125b78b43f24dcbbe9d75879660a056920c72ea5.tar.gz
RWA.Support.SessionService-125b78b43f24dcbbe9d75879660a056920c72ea5.tar.bz2
RWA.Support.SessionService-125b78b43f24dcbbe9d75879660a056920c72ea5.zip
Merge branch 'master' into feature/api-handshake
-rw-r--r--.gitlab-ci.yml7
-rw-r--r--poetry.lock35
-rw-r--r--pyproject.toml1
-rwxr-xr-xrwa/support/sessionservice/service.py112
-rwxr-xr-xtest_client.py8
5 files changed, 127 insertions, 36 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..b61d2fd
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,7 @@
+include:
+ - project: "remotewebapp/aleksis"
+ file: /ci/general.yml
+ - project: "remotewebapp/aleksis"
+ file: /ci/test/lint.yml
+ - project: "remotewebapp/aleksis"
+ file: /ci/build/dist.yml
diff --git a/poetry.lock b/poetry.lock
index 0111965..d2145f7 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -219,6 +219,14 @@ optional = false
python-versions = "*"
[[package]]
+name = "decorator"
+version = "5.0.9"
+description = "Decorators for Humans"
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[[package]]
name = "dj-database-url"
version = "0.5.0"
description = "Use Database URLs in your Django Application."
@@ -944,7 +952,7 @@ urllib3 = "*"
name = "six"
version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
-category = "dev"
+category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
@@ -1213,6 +1221,21 @@ python-versions = "*"
appdirs = ">=1.2"
[[package]]
+name = "validators"
+version = "0.18.2"
+description = "Python Data Validation for Humans™."
+category = "main"
+optional = false
+python-versions = ">=3.4"
+
+[package.dependencies]
+decorator = ">=3.4.0"
+six = ">=1.4.0"
+
+[package.extras]
+test = ["pytest (>=2.2.3)", "flake8 (>=2.4.0)", "isort (>=4.2.2)"]
+
+[[package]]
name = "websockify"
version = "0.9.0"
description = "Websockify."
@@ -1249,7 +1272,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pyt
[metadata]
lock-version = "1.1"
python-versions = "^3.7"
-content-hash = "368a8ee38bb0c8659c6ef4c58e51052b6186ac516234b60488abee1aaa09f5c9"
+content-hash = "cfae68fa7ede37cc59acca52ede338921d94bc20378f977431593ea36c358a5c"
[metadata.files]
alabaster = [
@@ -1373,6 +1396,10 @@ curlylint = [
dbus-python = [
{file = "dbus-python-1.2.16.tar.gz", hash = "sha256:11238f1d86c995d8aed2e22f04a1e3779f0d70e587caffeab4857f3c662ed5a4"},
]
+decorator = [
+ {file = "decorator-5.0.9-py3-none-any.whl", hash = "sha256:6e5c199c16f7a9f0e3a61a4a54b3d27e7dad0dbdde92b944426cb20914376323"},
+ {file = "decorator-5.0.9.tar.gz", hash = "sha256:72ecfba4320a893c53f9706bebb2d55c270c1e51a28789361aa93e4a21319ed5"},
+]
dj-database-url = [
{file = "dj-database-url-0.5.0.tar.gz", hash = "sha256:4aeaeb1f573c74835b0686a2b46b85990571159ffc21aa57ecd4d1e1cb334163"},
{file = "dj_database_url-0.5.0-py2.py3-none-any.whl", hash = "sha256:851785365761ebe4994a921b433062309eb882fedd318e1b0fcecc607ed02da9"},
@@ -1924,6 +1951,10 @@ usersettings = [
{file = "usersettings-1.1.5-py3-none-any.whl", hash = "sha256:503be61d30d0cfd98f16bb6c9be86c29e78dc476c794ffae6333ab26f38994bf"},
{file = "usersettings-1.1.5.tar.gz", hash = "sha256:9f84b282982622d8ebfd2d42b482317ae50fb2b3a7fba22e0b0c36cac61ad673"},
]
+validators = [
+ {file = "validators-0.18.2-py3-none-any.whl", hash = "sha256:0143dcca8a386498edaf5780cbd5960da1a4c85e0719f3ee5c9b41249c4fefbd"},
+ {file = "validators-0.18.2.tar.gz", hash = "sha256:37cd9a9213278538ad09b5b9f9134266e7c226ab1fede1d500e29e0a8fbb9ea6"},
+]
websockify = [
{file = "websockify-0.9.0.tar.gz", hash = "sha256:c35b5b79ebc517d3b784dacfb993be413a93cda5222c6f382443ce29c1a6cada"},
]
diff --git a/pyproject.toml b/pyproject.toml
index be6732c..0e99464 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -25,6 +25,7 @@ flask = "^1.1.2"
argparse = "^1.0.10"
usersettings = "^1.1.5"
click = "^8.0.1"
+validators="^0.18.2"
[tool.poetry.dev-dependencies]
aleksis-builddeps = "*"
diff --git a/rwa/support/sessionservice/service.py b/rwa/support/sessionservice/service.py
index 3305223..9f0ad0a 100755
--- a/rwa/support/sessionservice/service.py
+++ b/rwa/support/sessionservice/service.py
@@ -3,7 +3,7 @@
# This file is part of Remote Support Desktop
# https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.sessionservice
# Copyright 2020, 2021 Jonathan Weth <dev@jonathanweth.de>
-# Copyright 2020 Daniel Teichmann <daniel.teichmann@das-netzwerkteam.de>
+# Copyright 2020, 2021 Daniel Teichmann <daniel.teichmann@das-netzwerkteam.de>
# Copyright 2020 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
# SPDX-License-Identifier: GPL-2.0-or-later
#
@@ -26,7 +26,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import json
-import logging
import signal
import time
from threading import Thread
@@ -37,10 +36,12 @@ import dbus
import dbus.mainloop.glib
import dbus.service
import requests
+import validators
from gi.repository import GLib
from .config import ALLOW_ONLY_ONE_SESSION, API_PATH, SUPPORTED_API_VERSIONS, user_settings
from .lock import is_locked, lock, unlock
+from .log import logging
from .session import Session
from .trigger import TriggerServerThread
@@ -76,6 +77,16 @@ class RWASupportSessionService(dbus.service.Object):
logging.info("D-Bus service has been started.")
+ def _is_url(self, url: str) -> bool:
+ """Test if the given string is an url.
+
+ :param url: The string which should be an URL.
+ :return: Whether the string is an URL.
+ """
+ valid = validators.url(url)
+ logging.debug(f"Is {url} an URL: {valid}")
+ return valid
+
def _get_web_app_hosts(self) -> str:
"""Get all registered RWA.Support.WebApp hosts.
@@ -96,6 +107,9 @@ class RWASupportSessionService(dbus.service.Object):
["https://example.org", "http://127.0.0.1:8000"]
"""
+ logging.info("D-Bus method call: %s()", "get_web_app_hosts")
+
+ 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]:
@@ -173,20 +187,31 @@ class RWASupportSessionService(dbus.service.Object):
* ``connection``
* ``permission_denied``
* ``unsupported_server``
+ * ``invalid_url``
"""
- # Check host by doing a handshake
+ host = str(host)
+
+ logging.info('D-Bus method call: %s("%s")', "add_web_app_host", host)
+
+ 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)
- user_settings.web_app_hosts.append(host)
user_settings.save_settings()
+ user_settings.web_app_hosts.append(host)
+ logging.debug('Added "%s" to "web_app_hosts" in user_settings', host)
+
return self._get_web_app_hosts()
@dbus.service.method(
"org.ArcticaProject.RWASupportSessionService", in_signature="i", out_signature="s"
)
- def remove_web_app_host(self, idx: int) -> str:
+ def remove_web_app_host(self, host_idx: int) -> str:
"""Remove a RWA.Support.WebApp host.
:param idx: Index of web app host (D-Bus integer)
@@ -198,8 +223,19 @@ class RWASupportSessionService(dbus.service.Object):
["https://example.org", "http://127.0.0.1:8000"]
"""
- del user_settings.web_app_hosts[idx]
- user_settings.save_settings()
+ logging.info("D-Bus method call: %s(%d)", "remove_web_app_host", host_idx)
+
+ if host_idx >= 0 and host_idx < len(user_settings.web_app_hosts):
+ host = user_settings.web_app_hosts[host_idx]
+ del user_settings.web_app_hosts[host_idx]
+ user_settings.save_settings()
+ logging.debug('Removed web_app_hosts[%d]="%s" in user_settings', host_idx, host)
+ else:
+ logging.warning("Given host index is not valid!")
+ logging.debug(
+ "Did not remove web_app_hosts[%d] (not existent!) in " "user_settings", host_idx
+ )
+
return self._get_web_app_hosts()
@dbus.service.method(
@@ -231,19 +267,26 @@ class RWASupportSessionService(dbus.service.Object):
* ``permission_denied``
* ``unsupported_server``
"""
+ logging.info("D-Bus method call: %s(%d)", "start", host_idx)
+
if ALLOW_ONLY_ONE_SESSION and len(self.sessions.values()) > 0:
logging.warning(
"There is already one session running and the service "
"is configured to allow only one "
"session, so this session won't be started."
)
- return json.dumps({"status": "error", "type": "multiple"})
- print(host_idx, user_settings.web_app_hosts)
+ response = json.dumps({"status": "error", "type": "multiple"})
+ logging.debug("The response to the D-Bus caller: '%s'", response)
+ return response
try:
host = user_settings.web_app_hosts[host_idx]
+ logging.debug('web_app_hosts[%d] is the following host: "%s"', host_idx, host)
except IndexError:
- return json.dumps({"status": "error", "type": "host_not_found"})
+ logging.error("web_app_hosts[%d] does not exist!", host_idx)
+ response = json.dumps({"status": "error", "type": "host_not_found"})
+ 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)
@@ -265,11 +308,18 @@ class RWASupportSessionService(dbus.service.Object):
logging.info(f"New session #{session.pid} was started with meta {return_json}.")
- return json.dumps(return_json)
+ response = json.dumps(return_json)
+ logging.debug("The response to the D-Bus caller: '%s'", response)
+ return response
except ConnectionError:
- logging.error("There was a connection error while trying to reach the server.")
+ logging.error(
+ "There was a connection error while trying to reach "
+ "the RWA.Support.WebApp server."
+ )
- return json.dumps({"status": "error", "type": "connection"})
+ response = json.dumps({"status": "error", "type": "connection"})
+ logging.debug("The response to the D-Bus caller: '%s'", response)
+ return response
@dbus.service.method(
"org.ArcticaProject.RWASupportSessionService", in_signature="i", out_signature="s"
@@ -299,15 +349,22 @@ class RWASupportSessionService(dbus.service.Object):
``dead`` There was a problem, so that the session is dead.
============ ======================
"""
- return self._get_status(pid)
+ logging.info("D-Bus method call: %s(%d)", "status", pid)
+ response = self._get_status(pid)
+ logging.debug("The response to the D-Bus caller: '%s'", response)
+ return response
@dbus.service.method(
"org.ArcticaProject.RWASupportSessionService", in_signature="i", out_signature="s"
)
def refresh_status(self, pid: int) -> str:
"""Update status from WebApp before returning it here like :meth:`status`."""
+ logging.info("D-Bus method call: %s(%d)", "refresh_status", pid)
+
self._update_session(pid)
- return self._get_status(pid)
+ response = self._get_status(pid)
+ logging.debug("The response to the D-Bus caller: '%s'", response)
+ return response
@dbus.service.method(
"org.ArcticaProject.RWASupportSessionService", in_signature="i", out_signature="s"
@@ -324,12 +381,18 @@ class RWASupportSessionService(dbus.service.Object):
{"id": <pid>, "status": "stopped"}
"""
+ logging.info("D-Bus method call: %s(%d)", "stop", pid)
+
try:
session = self.sessions[pid]
except KeyError:
- return json.dumps({"pid": pid, "status": "stopped"}, sort_keys=True)
+ response = json.dumps({"pid": pid, "status": "stopped"}, sort_keys=True)
+ logging.debug("The response to the D-Bus caller: '%s'", response)
+ return response
session.stop()
- return json.dumps({"id": pid, "status": "stopped"}, sort_keys=True)
+ response = json.dumps({"id": pid, "status": "stopped"}, sort_keys=True)
+ logging.debug("The response to the D-Bus caller: '%s'", response)
+ return response
def _get_status(self, pid: int) -> str:
try:
@@ -420,21 +483,6 @@ class RWASupportSessionService(dbus.service.Object):
time.sleep(1)
-def str2bool(v: Union[str, bool, int]) -> bool:
- """Return true or false if the given string can be interpreted as a boolean.
-
- If it fails, raise an exception.
- """
- if isinstance(v, bool):
- return v
- if v.lower() in ("yes", "true", "t", "y", "1", 1):
- return True
- elif v.lower() in ("no", "false", "f", "n", "0", 0):
- return False
- else:
- raise argparse.ArgumentTypeError("Boolean value expected.")
-
-
@click.command()
@click.option(
"-m",
diff --git a/test_client.py b/test_client.py
index ee49bae..72538c1 100755
--- a/test_client.py
+++ b/test_client.py
@@ -29,8 +29,12 @@
import click
import dbus
-bus = dbus.SessionBus()
-req = bus.get_object("org.ArcticaProject.RWASupportSessionService", "/RWASupportSessionService")
+try:
+ bus = dbus.SessionBus()
+ req = bus.get_object("org.ArcticaProject.RWASupportSessionService", "/RWASupportSessionService")
+except dbus.exceptions.DBusException:
+ click.echo("The D-Bus service isn't responding! Is it even started? Aborting ...")
+ exit(1)
@click.group()