From 4dbf367ae377ecd81c7e344fa16ed1bd7400b297 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 00:57:38 +0700 Subject: [PATCH 01/20] Fix isAlive compatible in threading --- faraday_client/model/application.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/faraday_client/model/application.py b/faraday_client/model/application.py index f5289d90..85927b22 100644 --- a/faraday_client/model/application.py +++ b/faraday_client/model/application.py @@ -138,7 +138,7 @@ def __exit(self, exit_code=0): faraday_client.model.api.stopAPIServer() restapi.stopServer() self._model_controller.stop() - if self._model_controller.isAlive(): + if self._model_controller.is_alive(): # runs only if thread has started, i.e. self._model_controller.start() is run first self._model_controller.join() faraday_client.model.api.devlog("Waiting for controller threads to end...") From 9a260467435aa92b08541c683b682eb67f5c3488 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 01:11:01 +0700 Subject: [PATCH 02/20] Fix typo --- faraday_client/start_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/faraday_client/start_client.py b/faraday_client/start_client.py index 5a4a152a..3f7cbca3 100755 --- a/faraday_client/start_client.py +++ b/faraday_client/start_client.py @@ -357,7 +357,7 @@ def login(ask_for_credentials, cert_path): server_url = input(f"\nPlease enter the Faraday Server URL (Press enter for last used: {server_url}): ") \ or server_url parsed_url = urlparse(server_url) - if not all([parsed_url.scheme, parsed_url.netloc]): + if not all([parsed_url.scheme, parsed_url.netloc]): logger.error("Invalid URL: %s", server_url) sys.exit(1) try: From 89ff886a69fcc11e1e97cd215e324ab5c4de2d24 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 01:40:55 +0700 Subject: [PATCH 03/20] Add URL entry, allow user to add custom URL --- faraday_client/gui/gtk/dialogs.py | 34 +++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/faraday_client/gui/gtk/dialogs.py b/faraday_client/gui/gtk/dialogs.py index abd2b9c9..0bb23d93 100644 --- a/faraday_client/gui/gtk/dialogs.py +++ b/faraday_client/gui/gtk/dialogs.py @@ -274,7 +274,11 @@ class AuthDialog(Gtk.Dialog): """Faraday auth dialog""" def __init__(self, reload_ws_callback, parent): - super().__init__(title=f"Faraday login for {CONF.getAPIUrl()}", flags=Gtk.DialogFlags.MODAL) + server_url = CONF.getAPIUrl() + if not server_url: + super().__init__(title=f"Faraday login", flags=Gtk.DialogFlags.MODAL) + else: + super().__init__(title=f"Faraday login for {server_url}", flags=Gtk.DialogFlags.MODAL) self.set_default_response(Gtk.ResponseType.OK) self.set_keep_above(True) self.set_transient_for(parent) @@ -289,6 +293,22 @@ def __init__(self, reload_ws_callback, parent): instructions.set_max_width_chars(38) content_area.pack_start(instructions, True, True, 10) + """ + Add extra Entry to let user add custom URL + If url is valid, we set it as text else let it be empty + """ + urlBox = Gtk.Box() + url_label = Gtk.Label() + url_label.set_text("URL:") + self.url_entry = Gtk.Entry() + self.url_entry.set_width_chars(24) + self.url_entry.set_activates_default(True) + if server_url: + self.url_entry.set_text(server_url) + urlBox.pack_start(url_label, True, True, 3) + urlBox.pack_start(self.url_entry, False, False, 5) + content_area.pack_start(urlBox, True, True, 10) + userBox = Gtk.Box() user_label = Gtk.Label() user_label.set_text("User:") @@ -331,6 +351,14 @@ def __init__(self, reload_ws_callback, parent): button_box.pack_end(cancel_button, False, True, 10) self.show_all() + def getUrl(self): + if self.url_entry.get_text() is not None: + res = self.url_entry.get_text() + else: + res = "" + return res + + def getUser(self): if self.user_entry.get_text() is not None: res = self.user_entry.get_text() @@ -361,12 +389,13 @@ def exit(self): self.destroy() def on_click_ok(self, buttons=None): + newUrl = self.getUrl() newUser = self.getUser() newPass = self.getPassword() new2FAToken = self.get2FAToken() if self.attempts_counter < self.max_attempts: try: - session_cookie = login_user(CONF.getAPIUrl(), newUser, newPass, new2FAToken) + session_cookie = login_user(newUrl, newUser, newPass, new2FAToken) except Required2FAError: error_message = f"2FA Token Required" errorDialog(self, (error_message)) @@ -402,6 +431,7 @@ def on_click_cancel(self, button=None): """Override on_click_cancel to make it exit Faraday.""" self.destroy() + class NewWorkspaceDialog(Gtk.Window): """Sets up the New Workspace Dialog, where the user can set a name, a description and a type for a new workspace. Also checks that the From df6f2faddb2ef6b8faa73c99cf6058b04fb20e31 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 02:09:57 +0700 Subject: [PATCH 04/20] Add urlparse.scheme for getUrl --- faraday_client/gui/gtk/dialogs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/faraday_client/gui/gtk/dialogs.py b/faraday_client/gui/gtk/dialogs.py index 0bb23d93..3f19bcb3 100644 --- a/faraday_client/gui/gtk/dialogs.py +++ b/faraday_client/gui/gtk/dialogs.py @@ -353,7 +353,8 @@ def __init__(self, reload_ws_callback, parent): def getUrl(self): if self.url_entry.get_text() is not None: - res = self.url_entry.get_text() + from urllib.parse import urlparse + res = urlparse(self.url_entry.get_text()).scheme else: res = "" return res From 2a5a996afa7139104781fdf5dca5406dba005c91 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 02:30:49 +0700 Subject: [PATCH 05/20] Add hardcoded URL if url is invalid --- faraday_client/gui/gtk/dialogs.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/faraday_client/gui/gtk/dialogs.py b/faraday_client/gui/gtk/dialogs.py index 3f19bcb3..31bf057a 100644 --- a/faraday_client/gui/gtk/dialogs.py +++ b/faraday_client/gui/gtk/dialogs.py @@ -305,6 +305,8 @@ def __init__(self, reload_ws_callback, parent): self.url_entry.set_activates_default(True) if server_url: self.url_entry.set_text(server_url) + else: + self.url_entry.set_text("http://localhost:5985") urlBox.pack_start(url_label, True, True, 3) urlBox.pack_start(self.url_entry, False, False, 5) content_area.pack_start(urlBox, True, True, 10) From 7b03a48b1f2ce89bb67d1f72f7eccbb4ca584916 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 02:35:25 +0700 Subject: [PATCH 06/20] Restore normal get text instead of get scheme --- faraday_client/gui/gtk/dialogs.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/faraday_client/gui/gtk/dialogs.py b/faraday_client/gui/gtk/dialogs.py index 31bf057a..283cefd8 100644 --- a/faraday_client/gui/gtk/dialogs.py +++ b/faraday_client/gui/gtk/dialogs.py @@ -355,8 +355,7 @@ def __init__(self, reload_ws_callback, parent): def getUrl(self): if self.url_entry.get_text() is not None: - from urllib.parse import urlparse - res = urlparse(self.url_entry.get_text()).scheme + res = self.url_entry.get_text() else: res = "" return res @@ -398,6 +397,10 @@ def on_click_ok(self, buttons=None): new2FAToken = self.get2FAToken() if self.attempts_counter < self.max_attempts: try: + print("URL: " + newUrl) + print("User: " + newUser) + print("Pass: " + newPass) + print("Token: " + new2FAToken) session_cookie = login_user(newUrl, newUser, newPass, new2FAToken) except Required2FAError: error_message = f"2FA Token Required" From bcb8ed28a25f590c5c215fae7089d77d2d47fa64 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 02:47:06 +0700 Subject: [PATCH 07/20] Add exception for _get_base_server_url for crash trying login with GUI --- faraday_client/persistence/server/server.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/faraday_client/persistence/server/server.py b/faraday_client/persistence/server/server.py index 834368c4..2629d277 100644 --- a/faraday_client/persistence/server/server.py +++ b/faraday_client/persistence/server/server.py @@ -79,7 +79,6 @@ def _conf(): def _get_base_server_url(): - # Faraday server is running, and this module is used by upload_reports... if FARADAY_UPLOAD_REPORTS_OVERWRITE_SERVER_URL: server_url = FARADAY_UPLOAD_REPORTS_OVERWRITE_SERVER_URL @@ -87,7 +86,13 @@ def _get_base_server_url(): server_url = _conf().getAPIUrl() else: server_url = SERVER_URL - return server_url.rstrip('/') + try: + return server_url.rstrip('/') + except: + # Sometime program crashes (NonType object has no attribute rstrip + # Could be logic bug? + # Try to fix it + return SERVER_URL.rstrip('/') def _create_server_api_url(): """Return the server's api url.""" From c29f0461b71d682a21aa547686483c8be10b8136 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 02:59:39 +0700 Subject: [PATCH 08/20] Remove debug lines --- faraday_client/gui/gtk/dialogs.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/faraday_client/gui/gtk/dialogs.py b/faraday_client/gui/gtk/dialogs.py index 283cefd8..23bf3b54 100644 --- a/faraday_client/gui/gtk/dialogs.py +++ b/faraday_client/gui/gtk/dialogs.py @@ -397,10 +397,6 @@ def on_click_ok(self, buttons=None): new2FAToken = self.get2FAToken() if self.attempts_counter < self.max_attempts: try: - print("URL: " + newUrl) - print("User: " + newUser) - print("Pass: " + newPass) - print("Token: " + new2FAToken) session_cookie = login_user(newUrl, newUser, newPass, new2FAToken) except Required2FAError: error_message = f"2FA Token Required" From b3c2ebc71779eb8ad1e99c9a4d1b0f06b5c4cdc0 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 03:32:50 +0700 Subject: [PATCH 09/20] Add URL entry to force login dialog --- faraday_client/gui/gtk/dialogs.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/faraday_client/gui/gtk/dialogs.py b/faraday_client/gui/gtk/dialogs.py index 23bf3b54..cedbd1cd 100644 --- a/faraday_client/gui/gtk/dialogs.py +++ b/faraday_client/gui/gtk/dialogs.py @@ -168,6 +168,25 @@ def __init__(self, parent): instructions.set_max_width_chars(38) content_area.pack_start(instructions, True, True, 10) + """ + Add extra Entry to let user add custom URL + If url is valid, we set it as text else let it be empty + """ + urlBox = Gtk.Box() + url_label = Gtk.Label() + url_label.set_text("URL:") + self.url_entry = Gtk.Entry() + self.url_entry.set_width_chars(24) + self.url_entry.set_activates_default(True) + server_url = CONF.getServerURI() + if server_url: + self.url_entry.set_text(server_url) + else: + self.url_entry.set_text("http://localhost:5985") + urlBox.pack_start(url_label, True, True, 3) + urlBox.pack_start(self.url_entry, False, False, 5) + content_area.pack_start(urlBox, True, True, 10) + userBox = Gtk.Box() user_label = Gtk.Label() user_label.set_text("User:") @@ -190,6 +209,13 @@ def __init__(self, parent): content_area.pack_start(passwordBox, True, True, 10) self.show_all() + def getUrl(self): + if self.url_entry.get_text() is not None: + res = self.url_entry.get_text() + else: + res = "" + return res + def getUser(self): if self.user_entry.get_text() is not None: res = self.user_entry.get_text() @@ -204,14 +230,15 @@ def getPassword(self): res = "" return res - def run(self, attempts, url, parent): + def run(self, attempts, parent): for attempt in range(attempts): run = Gtk.Dialog.run(self) if run == Gtk.ResponseType.OK: newUser = self.getUser() newPass = self.getPassword() - session_cookie = login_user(url, newUser, newPass) + newUrl = self.getUrl() + session_cookie = login_user(newUrl, newUser, newPass) if not session_cookie: if attempt != attempts-1: From a479e90fedf9bf73bdebbd19ac2d7fe39fc0f83e Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 03:33:08 +0700 Subject: [PATCH 10/20] Fix logic for completely new login session --- faraday_client/gui/gtk/application.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/faraday_client/gui/gtk/application.py b/faraday_client/gui/gtk/application.py index 4a8bb5d7..316f62f0 100644 --- a/faraday_client/gui/gtk/application.py +++ b/faraday_client/gui/gtk/application.py @@ -813,11 +813,17 @@ def do_activate(self): if not should_login: return - - if not is_authenticated(CONF.getServerURI(), CONF.getFaradaySessionCookies()): + server_url = CONF.getServerURI() + need_login = False + if not server_url: + need_login = True + elif not is_authenticated(server_url, CONF.getFaradaySessionCookies()): + need_login = True + + if need_login: loginDialog = ForceLoginDialog(self.window, self.exit_faraday_without_confirm) - loginDialog.run(3, CONF.getServerURI(), self.window) + loginDialog.run(3, self.window) self.reload_workspaces() workspace_argument_set = self.open_workspace_from_args() From 4eaf2976822cd795a5c22bb2d57246d4c1f73451 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 03:33:33 +0700 Subject: [PATCH 11/20] Only use terminal login when user uses --login flag --- faraday_client/start_client.py | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/faraday_client/start_client.py b/faraday_client/start_client.py index 3f7cbca3..a9fb1c4b 100755 --- a/faraday_client/start_client.py +++ b/faraday_client/start_client.py @@ -323,7 +323,6 @@ def printBanner(): logger.info("Starting Faraday IDE.") - def try_login_user(server_uri, api_username, api_password, u2fa_token=None): try: session_cookie = login_user(server_uri, api_username, api_password, u2fa_token) @@ -341,7 +340,7 @@ def try_login_user(server_uri, api_username, api_password, u2fa_token=None): return session_cookie -def login(ask_for_credentials, cert_path): +def login(cert_path): """ Sets the username and passwords from the command line. If --login flag is set then username and password is set @@ -353,9 +352,8 @@ def login(ask_for_credentials, cert_path): server_url = input("\nPlease enter the Faraday Server URL (Press enter for http://localhost:5985): ") \ or "http://localhost:5985" else: - if ask_for_credentials: - server_url = input(f"\nPlease enter the Faraday Server URL (Press enter for last used: {server_url}): ") \ - or server_url + server_url = input(f"\nPlease enter the Faraday Server URL (Press enter for last used: {server_url}): ") \ + or server_url parsed_url = urlparse(server_url) if not all([parsed_url.scheme, parsed_url.netloc]): logger.error("Invalid URL: %s", server_url) @@ -376,16 +374,6 @@ def login(ask_for_credentials, cert_path): logger.error("Connection to Faraday server FAILED: %s - use --login to set a new server", server_url) sys.exit(1) CONF.setAPIUrl(server_url) - if not ask_for_credentials: - session_cookies = CONF.getFaradaySessionCookies() - if session_cookies and server_url: - if is_authenticated(server_url, session_cookies): - logger.debug("Valid Previous session cookie found") - if parsed_url.scheme == "https" and cert_path: - CONF.setCerPath(cert_path) - else: - CONF.setCerPath(None) - return True print(f"""\nPlease provide your valid Faraday credentials for {server_url}\nYou have 3 attempts.""") MAX_ATTEMPTS = 3 for attempt in range(1, MAX_ATTEMPTS + 1): @@ -423,6 +411,7 @@ def login(ask_for_credentials, cert_path): except KeyboardInterrupt: sys.exit(0) + def main(): """ Main function for launcher. @@ -444,7 +433,10 @@ def main(): cert_path = os.path.abspath(args.cert_path) if cert_path: os.environ[REQUESTS_CA_BUNDLE_VAR] = cert_path - login(args.login, cert_path) + + if args.login: + # We only call terminal login when user provides login flag + login(cert_path) start_faraday_client() From 8ce596148d3406d6bcdd3dae9fa3b89c135c4e74 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 03:36:56 +0700 Subject: [PATCH 12/20] Add exception's error as pep8 suggested --- faraday_client/persistence/server/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/faraday_client/persistence/server/server.py b/faraday_client/persistence/server/server.py index 2629d277..7d1bddcc 100644 --- a/faraday_client/persistence/server/server.py +++ b/faraday_client/persistence/server/server.py @@ -88,7 +88,7 @@ def _get_base_server_url(): server_url = SERVER_URL try: return server_url.rstrip('/') - except: + except AttributeError: # Sometime program crashes (NonType object has no attribute rstrip # Could be logic bug? # Try to fix it From 0700ef51b1d387374ab4e83df3c040aec202ca14 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 04:00:17 +0700 Subject: [PATCH 13/20] Add title --- faraday_client/gui/gtk/dialogs.py | 1 + 1 file changed, 1 insertion(+) diff --git a/faraday_client/gui/gtk/dialogs.py b/faraday_client/gui/gtk/dialogs.py index cedbd1cd..cce933de 100644 --- a/faraday_client/gui/gtk/dialogs.py +++ b/faraday_client/gui/gtk/dialogs.py @@ -151,6 +151,7 @@ class LoginDialog(Gtk.Dialog): """A simple login dialog with a user and password""" def __init__(self, parent): Gtk.Dialog.__init__(self, + title=f"Faraday login", flags=Gtk.DialogFlags.MODAL, buttons=("OK", Gtk.ResponseType.OK, "Cancel", Gtk.ResponseType.CANCEL)) From 862696b8037843a643bdffac8e7282c9423c1d84 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 05:24:39 +0700 Subject: [PATCH 14/20] Code improvement using pep8 --- faraday_client/gui/gtk/dialogs.py | 139 ++++++++++++++---------------- 1 file changed, 65 insertions(+), 74 deletions(-) diff --git a/faraday_client/gui/gtk/dialogs.py b/faraday_client/gui/gtk/dialogs.py index cce933de..de2ef9b3 100644 --- a/faraday_client/gui/gtk/dialogs.py +++ b/faraday_client/gui/gtk/dialogs.py @@ -11,15 +11,7 @@ from faraday_client.persistence.server.exceptions import Required2FAError from past.builtins import basestring - -import webbrowser -import gi # pylint: disable=import-error -import os -from faraday_client.start_client import FARADAY_CLIENT_BASE -gi.require_version('Gtk', '3.0') - from faraday_client.persistence.server.server import ResourceDoesNotExist -from gi.repository import Gtk, GdkPixbuf, Gdk # pylint: disable=import-error from faraday_client.config.configuration import getInstanceConfiguration from faraday_client.persistence.server.server import ( is_authenticated, @@ -33,10 +25,20 @@ from faraday_client.gui.gtk.compatibility import CompatibleScrolledWindow as GtkScrolledWindow from faraday_client.plugins import fplugin_utils +import webbrowser +import gi # pylint: disable=import-error +import os +from faraday_client.start_client import FARADAY_CLIENT_BASE + +from gi.repository import Gtk, GdkPixbuf, Gdk # pylint: disable=import-error + +gi.require_version('Gtk', '3.0') + CONF = getInstanceConfiguration() logger = logging.getLogger(__name__) + class PreferenceWindowDialog(Gtk.Dialog): """Sets up a preference dialog with basically nothing more than a label, a text entry to input your Faraday server IP and a couple of buttons. @@ -72,9 +74,9 @@ def __init__(self, reload_ws_callback, connect_to_couch, parent): button_box = Gtk.Box(spacing=6) main_box.pack_end(button_box, False, True, 10) - OK_button = Gtk.Button.new_with_label("OK") - OK_button.connect("clicked", self.on_click_ok) - button_box.pack_start(OK_button, False, True, 10) + ok_button = Gtk.Button.new_with_label("OK") + ok_button.connect("clicked", self.on_click_ok) + button_box.pack_start(ok_button, False, True, 10) cancel_button = Gtk.Button.new_with_label("Cancel") self.connect("key_press_event", key_reactions) @@ -87,20 +89,19 @@ def on_click_ok(self, button=None): """Button is useless, only there because GTK likes it. Takes the repourl (Couch IP) from self.ip_entry and connect to it if possible. """ - repourl = self.ip_entry.get_text() + repo_url = self.ip_entry.get_text() - if not check_server_url(repourl): + if not check_server_url(repo_url): errorDialog(self, "Could not connect to Faraday Server.", - ("Are you sure it is running and that the URL is correct?")) + "Are you sure it is running and that the URL is correct?") return False - - credentials_ok = self.credentialsOK(repourl) - couch_connection_ok = self.connectCouchCallback(repourl, parent=self) + credentials_ok = self.credentials_ok(repo_url) + couch_connection_ok = self.connectCouchCallback(repo_url, parent=self) if credentials_ok and couch_connection_ok: self.destroy() - def credentialsOK(self, repourl): + def credentials_ok(self, repo_url): """Pops up a dialog (if necessary) to set up Faraday credentials. Dialog is a LoginDialog which emits a signal marked by 42 when the user clicks its button. The run method returns 42 @@ -108,12 +109,12 @@ def credentialsOK(self, repourl): It's a boolean function, return True if auth ok, False if not. Number 42 was chosen for obvious reasons :) """ - if is_authenticated(repourl, CONF.getFaradaySessionCookies()): + if is_authenticated(repo_url, CONF.getFaradaySessionCookies()): return True # if that didn't work... - loginDialog = LoginDialog(self) - return loginDialog.run(3, repourl, self) + login_dialog = LoginDialog(self) + return login_dialog.run(3, repo_url) def on_click_cancel(self, button=None): self.destroy() @@ -149,6 +150,7 @@ def on_click_cancel(self, button=None): class LoginDialog(Gtk.Dialog): """A simple login dialog with a user and password""" + def __init__(self, parent): Gtk.Dialog.__init__(self, title=f"Faraday login", @@ -157,9 +159,7 @@ def __init__(self, parent): "Cancel", Gtk.ResponseType.CANCEL)) self.set_default_response(Gtk.ResponseType.OK) - self.set_keep_above(True) - self.set_transient_for(parent) content_area = self.get_content_area() @@ -173,7 +173,7 @@ def __init__(self, parent): Add extra Entry to let user add custom URL If url is valid, we set it as text else let it be empty """ - urlBox = Gtk.Box() + url_box = Gtk.Box() url_label = Gtk.Label() url_label.set_text("URL:") self.url_entry = Gtk.Entry() @@ -184,47 +184,47 @@ def __init__(self, parent): self.url_entry.set_text(server_url) else: self.url_entry.set_text("http://localhost:5985") - urlBox.pack_start(url_label, True, True, 3) - urlBox.pack_start(self.url_entry, False, False, 5) - content_area.pack_start(urlBox, True, True, 10) + url_box.pack_start(url_label, True, True, 3) + url_box.pack_start(self.url_entry, False, False, 5) + content_area.pack_start(url_box, True, True, 10) - userBox = Gtk.Box() + user_box = Gtk.Box() user_label = Gtk.Label() user_label.set_text("User:") self.user_entry = Gtk.Entry() self.user_entry.set_width_chars(24) self.user_entry.set_activates_default(True) - userBox.pack_start(user_label, True, True, 3) - userBox.pack_start(self.user_entry, False, False, 5) - content_area.pack_start(userBox, True, True, 10) + user_box.pack_start(user_label, True, True, 3) + user_box.pack_start(self.user_entry, False, False, 5) + content_area.pack_start(user_box, True, True, 10) - passwordBox = Gtk.Box() + passwd_box = Gtk.Box() password_label = Gtk.Label() password_label.set_text("Password:") self.password_entry = Gtk.Entry() self.password_entry.set_visibility(False) self.password_entry.set_width_chars(24) self.password_entry.set_activates_default(True) - passwordBox.pack_start(password_label, True, True, 3) - passwordBox.pack_start(self.password_entry, False, False, 5) - content_area.pack_start(passwordBox, True, True, 10) + passwd_box.pack_start(password_label, True, True, 3) + passwd_box.pack_start(self.password_entry, False, False, 5) + content_area.pack_start(passwd_box, True, True, 10) self.show_all() - def getUrl(self): + def entry_get_url(self): if self.url_entry.get_text() is not None: res = self.url_entry.get_text() else: res = "" return res - def getUser(self): + def entry_get_user(self): if self.user_entry.get_text() is not None: res = self.user_entry.get_text() else: res = "" return res - def getPassword(self): + def entry_get_password(self): if self.password_entry.get_text() is not None: res = self.password_entry.get_text() else: @@ -236,36 +236,28 @@ def run(self, attempts, parent): run = Gtk.Dialog.run(self) if run == Gtk.ResponseType.OK: - newUser = self.getUser() - newPass = self.getPassword() - newUrl = self.getUrl() - session_cookie = login_user(newUrl, newUser, newPass) + txt_user = self.entry_get_user() + txt_pass = self.entry_get_password() + txt_url = self.entry_get_url() + session_cookie = login_user(txt_url, txt_user, txt_pass) if not session_cookie: - if attempt != attempts-1: - errorDialog(self, ("Invalid credentials!. You " - "have " + - str(attempts-1-attempt) + - " attempt(s) left.")) + if attempt != attempts - 1: + errorDialog(self, f"Invalid credentials!. You have {attempts - 1 - attempt} attempt(s) left.") else: - - CONF.setDBUser(newUser) + CONF.setDBUser(txt_user) CONF.setFaradaySessionCookies(session_cookie) - user_info = get_user_info() try: if 'client' in user_info['userCtx']['roles']: - errorDialog(self, ("You can't login as a client. " - "You have " + - str(attempts - 1 - attempt) + - " attempt(s) left.")) + errorDialog(self, f"You can't login as a client. You have {attempts - 1 - attempt}\ + attempt(s) left.") continue except (TypeError, KeyError): pass self.destroy() - return True if run in [Gtk.ResponseType.CANCEL, -4]: @@ -273,9 +265,7 @@ def run(self, attempts, parent): self.exit() return False else: - errorDialog(self, ("Invalid credentials after " + - str(attempts) + " tries. " + - "Check your credentials and try again.")) + errorDialog(self, f"Invalid credentials after {attempts} tries. Check your credentials and try again.") self.exit() return False @@ -285,11 +275,10 @@ def exit(self): class ForceLoginDialog(LoginDialog): """A simple login dialog with a user and password""" + def __init__(self, parent, exit_faraday_callback): LoginDialog.__init__(self, parent) - self.set_deletable(False) - self.exit_faraday = exit_faraday_callback def exit(self, button=None): @@ -298,7 +287,6 @@ def exit(self, button=None): class AuthDialog(Gtk.Dialog): - """Faraday auth dialog""" def __init__(self, reload_ws_callback, parent): @@ -388,7 +376,6 @@ def getUrl(self): res = "" return res - def getUser(self): if self.user_entry.get_text() is not None: res = self.user_entry.get_text() @@ -454,7 +441,7 @@ def on_click_ok(self, buttons=None): MessageDialog(self, "Faraday Authentication Successful") self.destroy() else: - error_message= "Max login attempts reached" + error_message = "Max login attempts reached" errorDialog(self, (error_message)) def on_click_cancel(self, button=None): @@ -467,7 +454,7 @@ class NewWorkspaceDialog(Gtk.Window): a description and a type for a new workspace. Also checks that the those attributes don't correspond to an existing workspace""" - def __init__(self, create_ws_callback, workspace_manager, sidebar, parent, + def __init__(self, create_ws_callback, workspace_manager, sidebar, parent, title=None): Gtk.Window.__init__(self, title="Create New Workspace") @@ -628,7 +615,7 @@ def __init__(self, plugin_manager, parent): for i in range(3)] self.nameEntry, self.versionEntry, self.pluginVersionEntry = [ - Gtk.Label() for i in range(3)] + Gtk.Label() for i in range(3)] nameLabel.set_text("Name: ") versionLabel.set_text("Version: ") @@ -926,6 +913,7 @@ class HostInfoDialog(Gtk.Window): strings and ints) and the object per se, which are in the model folder and are totally alien to GTK. """ + def __init__(self, parent, active_ws_name, host): """Creates a window with the information about a given hosts. The parent is needed so the window can set transient for @@ -951,13 +939,13 @@ def __init__(self, parent, active_ws_name, host): self.specific_info = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.specific_info_frame = self.create_scroll_frame( - self.specific_info, - "Service Information") + self.specific_info, + "Service Information") self.vuln_info = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.vuln_info_frame = self.create_scroll_frame( - self.vuln_info, - "Vulnerability Information") + self.vuln_info, + "Vulnerability Information") main_tree = self.create_main_tree_view(self.model) vuln_list = self.create_vuln_list() @@ -1210,6 +1198,7 @@ def create_vuln_model(self, obj): """Return the model for the vulnerabilities of the obj object. It will be sorted alphabetically. """ + def params_to_string(params): # XXX """Converts params to a string, in case it gets here as a list. It's pretty anoyting, but needed for backwards compatibility. @@ -1306,6 +1295,7 @@ def get_object(self, selected_object, object_type): """Take a selection as selected_object and an object_type and return the actual object, not the model's selection. """ + def safely(func): def safe_wrapper(*args, **kwargs): try: @@ -1314,7 +1304,8 @@ def safe_wrapper(*args, **kwargs): dialog = errorDialog(self, ("There has been a problem. " "The object you clicked on " "does not exist anymore.")) - self.destroy() # exit + self.destroy() # exit + return safe_wrapper object_id = selected_object[0] @@ -1471,8 +1462,8 @@ def save(self, button, keeper): dialog.run() dialog.destroy() - except ResourceDoesNotExist: # TODO: revert this hack to prevent exception when - # fixing conflict of non existent object + except ResourceDoesNotExist: # TODO: revert this hack to prevent exception when + # fixing conflict of non existent object dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, @@ -1911,8 +1902,8 @@ class aboutDialog(Gtk.AboutDialog): """The simple about dialog displayed when the user clicks on "about" ont the menu. Could be in application.py, but for consistency reasons its here""" - def __init__(self, main_window): + def __init__(self, main_window): Gtk.AboutDialog.__init__(self, transient_for=main_window, modal=True) icons = os.path.join(FARADAY_CLIENT_BASE, "data", "images", "icons") faraday_icon = GdkPixbuf.Pixbuf.new_from_file( @@ -1931,6 +1922,7 @@ def __init__(self, main_window): self.set_website(faraday_website) self.set_website_label("Learn more about Faraday") + class errorDialog(Gtk.MessageDialog): """A simple error dialog to show the user where things went wrong. Takes the parent window, (Gtk.Window or Gtk.Dialog, most probably) @@ -2010,5 +2002,4 @@ def strict_key_reactions(window, event): else: return False - # I'm Py3 From 5ded42a11b7313c19e0ef6e89c26b83ab12589ed Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 13:29:22 +0700 Subject: [PATCH 15/20] More pep8 for application module --- faraday_client/gui/gtk/application.py | 62 +++++++++++++-------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/faraday_client/gui/gtk/application.py b/faraday_client/gui/gtk/application.py index 316f62f0..a58b63c9 100644 --- a/faraday_client/gui/gtk/application.py +++ b/faraday_client/gui/gtk/application.py @@ -20,16 +20,16 @@ try: import gi except ImportError as e: - print ("You are missing Gobject Instrospection. Please install " - "version 3.14 or above (recommended) or 3.12") + print("You are missing Gobject Instrospection. Please install " + "version 3.14 or above (recommended) or 3.12") sys.exit(1) try: gi.require_version('Gtk', '3.0') except ValueError: - print ("WARNING: You don't seem to have installed the recommended version" - " of GTK. You can still use the program, but we recommend you" - " check your install of GTK+3") + print("WARNING: You don't seem to have installed the recommended version" + " of GTK. You can still use the program, but we recommend you" + " check your install of GTK+3") try: gi.require_version('Vte', '2.91') @@ -41,8 +41,8 @@ # modules. this just checks for every dependence when starting the app from gi.repository import Gio, Gtk, GdkPixbuf, Vte, GLib, GObject, Gdk except ImportError as e: - print ("You are missing some of the required dependencies. " - "Check that you have GTK+3 and Vte installed.") + print("You are missing some of the required dependencies. " + "Check that you have GTK+3 and Vte installed.") sys.exit(1) import faraday_client.model.guiapi @@ -87,13 +87,12 @@ from faraday_client.plugins import fplugin_utils - CONF = getInstanceConfiguration() logger = logging.getLogger(__name__) -def checkSSL(uri): +def check_ssl(uri): """ This method checks SSL validation It only returns True if the certificate is valid @@ -201,8 +200,8 @@ def remove_workspace(self, button, ws_name): except Exception as ex: traceback_str = traceback.format_exc() faraday_client.model.api.log("An exception was captured while deleting " - "workspace %s\n%s" % (ws_name, traceback_str), - "ERROR") + "workspace %s\n%s" % (ws_name, traceback_str), + "ERROR") available_workspaces = self.serverIO.get_workspaces_names() if available_workspaces: @@ -311,7 +310,8 @@ def exit(*args, **kwargs): logger.info("Exit because there are no workspaces found, and user is not admin") GObject.idle_add(self.window.destroy) GObject.idle_add(self.on_quit) - error_message = "You don't have permissions or no workspace is available.\n"\ + + error_message = "You don't have permissions or no workspace is available.\n" \ "Please contact faraday admin to create a workspace or to assign permissions." dialog = errorDialog(self.window, error_message) dialog.connect("destroy", exit) @@ -377,7 +377,7 @@ def certs_ok(server_uri): with https but didn't pass the checkSSL test. """ if server_uri.startswith("https://"): - return checkSSL(server_uri) + return check_ssl(server_uri) else: return True @@ -391,7 +391,7 @@ def certs_ok(server_uri): "password are still valid.")) success = False elif server_url.startswith("https://"): - if not checkSSL(server_url): + if not check_ssl(server_url): errorDialog(self.window, "The SSL certificate validation has failed") success = False @@ -768,8 +768,8 @@ def do_startup(self): appmenu.insert_submenu(1, "Faraday Plugin", fmenu) - helpMenu = builder.get_object('Help') - self.set_menubar(helpMenu) + help_menu = builder.get_object('Help') + self.set_menubar(help_menu) def do_activate(self): """If there's no window, create one and present it (show it to user). @@ -792,14 +792,14 @@ def do_activate(self): self.window.set_icon(self.icon) self.window.present() - self.loghandler = GUIHandler() + self.log_handler = GUIHandler() if CONF.getDebugStatus(): - self.loghandler.setLevel(logging.DEBUG) + self.log_handler.setLevel(logging.DEBUG) else: - self.loghandler.setLevel(logging.INFO) + self.log_handler.setLevel(logging.INFO) faraday_client.model.guiapi.setMainApp(self) - add_handler(self.loghandler) - self.loghandler.registerGUIOutput(self.window) + add_handler(self.log_handler) + self.log_handler.registerGUIOutput(self.window) notifier = faraday_client.model.log.getNotifier() notifier.widget = self.window @@ -821,9 +821,9 @@ def do_activate(self): need_login = True if need_login: - loginDialog = ForceLoginDialog(self.window, - self.exit_faraday_without_confirm) - loginDialog.run(3, self.window) + login_dialog = ForceLoginDialog(self.window, + self.exit_faraday_without_confirm) + login_dialog.run(3, self.window) self.reload_workspaces() workspace_argument_set = self.open_workspace_from_args() @@ -835,9 +835,9 @@ def on_quit(self, action=None, param=None): def on_plugin_options(self, action, param): """Defines what happens when you press "Plugins" on the menu""" - pluginsOption_window = PluginOptionsDialog(self.plugin_manager, - self.window) - pluginsOption_window.show_all() + plugins_option_window = PluginOptionsDialog(self.plugin_manager, + self.window) + plugins_option_window.show_all() def on_faraday_plugin(self, action, param): """Defines what happens when you press "Faraday Plugin..." on the menu""" @@ -848,11 +848,10 @@ def on_faraday_plugin(self, action, param): else: name = "" - - pluginsOption_window = FaradayPluginsDialog(self.window.get_current_focused_terminal(), + plugin_option_window = FaradayPluginsDialog(self.window.get_current_focused_terminal(), name, self.window) - pluginsOption_window.show_all() + plugin_option_window.show_all() def on_new_button(self, action=None, params=None, title=None): """Defines what happens when you press the 'new' button on the toolbar @@ -975,7 +974,7 @@ def on_preferences(self, action=None, param=None): changes her Couch URL, the sidebar will reload reflecting the new workspaces available""" - #preference_window = PreferenceWindowDialog(self.reload_workspaces, + # preference_window = PreferenceWindowDialog(self.reload_workspaces, # self.connect_to_couch, # self.window) preference_window = AuthDialog(self.reload_workspaces, self.window) @@ -1017,5 +1016,4 @@ def type_faraday_plugin_command(self, action, param=None): fd = terminal.get_pty().get_fd() os.write(fd, command.encode()) - # I'm Py3 From e59281ab80d3b3ea7b5145d654c26792dafd4275 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 14:34:48 +0700 Subject: [PATCH 16/20] More pep8 Don't clear entries if users login failed --- faraday_client/gui/gtk/dialogs.py | 94 ++++++++++++++++--------------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/faraday_client/gui/gtk/dialogs.py b/faraday_client/gui/gtk/dialogs.py index de2ef9b3..bf9c7a65 100644 --- a/faraday_client/gui/gtk/dialogs.py +++ b/faraday_client/gui/gtk/dialogs.py @@ -34,7 +34,7 @@ gi.require_version('Gtk', '3.0') -CONF = getInstanceConfiguration() +user_config = getInstanceConfiguration() logger = logging.getLogger(__name__) @@ -65,7 +65,7 @@ def __init__(self, reload_ws_callback, connect_to_couch, parent): ip_label.set_text("Faraday Server IP or URL") main_box.pack_start(ip_label, True, False, 10) - couch_uri = CONF.getServerURI() + couch_uri = user_config.getServerURI() self.ip_entry = Gtk.Entry() text = couch_uri if couch_uri else "http://127.0.0.1:5050" self.ip_entry.set_text(text) @@ -109,7 +109,7 @@ def credentials_ok(self, repo_url): It's a boolean function, return True if auth ok, False if not. Number 42 was chosen for obvious reasons :) """ - if is_authenticated(repo_url, CONF.getFaradaySessionCookies()): + if is_authenticated(repo_url, user_config.getFaradaySessionCookies()): return True # if that didn't work... @@ -179,7 +179,7 @@ def __init__(self, parent): self.url_entry = Gtk.Entry() self.url_entry.set_width_chars(24) self.url_entry.set_activates_default(True) - server_url = CONF.getServerURI() + server_url = user_config.getServerURI() if server_url: self.url_entry.set_text(server_url) else: @@ -245,8 +245,8 @@ def run(self, attempts, parent): if attempt != attempts - 1: errorDialog(self, f"Invalid credentials!. You have {attempts - 1 - attempt} attempt(s) left.") else: - CONF.setDBUser(txt_user) - CONF.setFaradaySessionCookies(session_cookie) + user_config.setDBUser(txt_user) + user_config.setFaradaySessionCookies(session_cookie) user_info = get_user_info() try: @@ -254,6 +254,9 @@ def run(self, attempts, parent): errorDialog(self, f"You can't login as a client. You have {attempts - 1 - attempt}\ attempt(s) left.") continue + else: + user_config.saveConfig() + user_config.setAPIUrl(txt_url) except (TypeError, KeyError): pass @@ -290,7 +293,7 @@ class AuthDialog(Gtk.Dialog): """Faraday auth dialog""" def __init__(self, reload_ws_callback, parent): - server_url = CONF.getAPIUrl() + server_url = user_config.getAPIUrl() if not server_url: super().__init__(title=f"Faraday login", flags=Gtk.DialogFlags.MODAL) else: @@ -313,7 +316,7 @@ def __init__(self, reload_ws_callback, parent): Add extra Entry to let user add custom URL If url is valid, we set it as text else let it be empty """ - urlBox = Gtk.Box() + url_box = Gtk.Box() url_label = Gtk.Label() url_label.set_text("URL:") self.url_entry = Gtk.Entry() @@ -323,40 +326,40 @@ def __init__(self, reload_ws_callback, parent): self.url_entry.set_text(server_url) else: self.url_entry.set_text("http://localhost:5985") - urlBox.pack_start(url_label, True, True, 3) - urlBox.pack_start(self.url_entry, False, False, 5) - content_area.pack_start(urlBox, True, True, 10) + url_box.pack_start(url_label, True, True, 3) + url_box.pack_start(self.url_entry, False, False, 5) + content_area.pack_start(url_box, True, True, 10) - userBox = Gtk.Box() + user_box = Gtk.Box() user_label = Gtk.Label() user_label.set_text("User:") self.user_entry = Gtk.Entry() self.user_entry.set_width_chars(24) self.user_entry.set_activates_default(True) - userBox.pack_start(user_label, True, True, 3) - userBox.pack_start(self.user_entry, False, False, 5) - content_area.pack_start(userBox, True, True, 10) + user_box.pack_start(user_label, True, True, 3) + user_box.pack_start(self.user_entry, False, False, 5) + content_area.pack_start(user_box, True, True, 10) - passwordBox = Gtk.Box() + password_box = Gtk.Box() password_label = Gtk.Label() password_label.set_text("Password:") self.password_entry = Gtk.Entry() self.password_entry.set_visibility(False) self.password_entry.set_width_chars(24) self.password_entry.set_activates_default(True) - passwordBox.pack_start(password_label, True, True, 3) - passwordBox.pack_start(self.password_entry, False, False, 5) - content_area.pack_start(passwordBox, True, True, 10) + password_box.pack_start(password_label, True, True, 3) + password_box.pack_start(self.password_entry, False, False, 5) + content_area.pack_start(password_box, True, True, 10) - u2FABox = Gtk.Box() - u2FA_label = Gtk.Label() - u2FA_label.set_text("2FA Token:") + u_2fa_box = Gtk.Box() + u_2fa_label = Gtk.Label() + u_2fa_label.set_text("2FA Token:") self.u2FA_entry = Gtk.Entry() self.u2FA_entry.set_width_chars(24) self.u2FA_entry.set_activates_default(True) - u2FABox.pack_start(u2FA_label, True, True, 3) - u2FABox.pack_start(self.u2FA_entry, False, False, 5) - content_area.pack_start(u2FABox, True, True, 10) + u_2fa_box.pack_start(u_2fa_label, True, True, 3) + u_2fa_box.pack_start(self.u2FA_entry, False, False, 5) + content_area.pack_start(u_2fa_box, True, True, 10) button_box = Gtk.Box(spacing=6) content_area.pack_end(button_box, False, True, 10) @@ -369,28 +372,28 @@ def __init__(self, reload_ws_callback, parent): button_box.pack_end(cancel_button, False, True, 10) self.show_all() - def getUrl(self): + def get_url(self): if self.url_entry.get_text() is not None: res = self.url_entry.get_text() else: res = "" return res - def getUser(self): + def get_user(self): if self.user_entry.get_text() is not None: res = self.user_entry.get_text() else: res = "" return res - def getPassword(self): + def get_password(self): if self.password_entry.get_text() is not None: res = self.password_entry.get_text() else: res = "" return res - def get2FAToken(self): + def get_2fa_token(self): if self.u2FA_entry.get_text() is not None: res = self.u2FA_entry.get_text() else: @@ -406,43 +409,42 @@ def exit(self): self.destroy() def on_click_ok(self, buttons=None): - newUrl = self.getUrl() - newUser = self.getUser() - newPass = self.getPassword() - new2FAToken = self.get2FAToken() + new_url = self.get_url() + new_user = self.get_user() + new_pass = self.get_password() + new_2fa_token = self.get_2fa_token() if self.attempts_counter < self.max_attempts: try: - session_cookie = login_user(newUrl, newUser, newPass, new2FAToken) + session_cookie = login_user(new_url, new_user, new_pass, new_2fa_token) except Required2FAError: error_message = f"2FA Token Required" - errorDialog(self, (error_message)) + errorDialog(self, error_message) else: if not session_cookie: logger.warning("Faraday Auth invalid") - self.clear() self.attempts_counter += 1 error_message = f"Invalid credentials!. You have {self.max_attempts - self.attempts_counter} attempt(s) left." - errorDialog(self, (error_message)) + errorDialog(self, error_message) else: - old_cookies = CONF.getFaradaySessionCookies() - CONF.setFaradaySessionCookies(session_cookie) + old_cookies = user_config.getFaradaySessionCookies() + user_config.setFaradaySessionCookies(session_cookie) user_info = get_user_info() if 'client' in user_info['roles']: - CONF.setFaradaySessionCookies(old_cookies) + user_config.setFaradaySessionCookies(old_cookies) self.clear() self.attempts_counter += 1 error_message = f"You can't login as a client. You have {self.max_attempts - self.attempts_counter} attempt(s) left." - errorDialog(self, (error_message)) + errorDialog(self, error_message) self.show_all() else: logger.info("Faraday Auth Successful") - CONF.saveConfig() + user_config.saveConfig() self.reload_ws_callback() MessageDialog(self, "Faraday Authentication Successful") self.destroy() else: error_message = "Max login attempts reached" - errorDialog(self, (error_message)) + errorDialog(self, error_message) def on_click_cancel(self, button=None): """Override on_click_cancel to make it exit Faraday.""" @@ -931,7 +933,7 @@ def __init__(self, parent, active_ws_name, host): host_info = self.model[0] host_id = self.model[0][0] - couch_url = CONF.getServerURI() + couch_url = user_config.getServerURI() base_url = couch_url + "/_ui/#/host/ws/" self.edit_url = base_url + active_ws_name + "/hid/" + host_id @@ -1911,8 +1913,8 @@ def __init__(self, main_window): self.set_logo(faraday_icon) self.set_program_name("Faraday") - app_name = str(CONF.getAppname()) - version = str(CONF.getVersion()) + app_name = str(user_config.getAppname()) + version = str(user_config.getVersion()) self.set_comments(app_name + " " + version + " " + "\n FaradaySec LLC. All rights reserved." From ff75c909a051aa145cb1ad0511e99961214e9ebf Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 14:41:13 +0700 Subject: [PATCH 17/20] Save cookie and settings for ForceAuthDialog --- faraday_client/gui/gtk/dialogs.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/faraday_client/gui/gtk/dialogs.py b/faraday_client/gui/gtk/dialogs.py index bf9c7a65..f878bff7 100644 --- a/faraday_client/gui/gtk/dialogs.py +++ b/faraday_client/gui/gtk/dialogs.py @@ -254,13 +254,12 @@ def run(self, attempts, parent): errorDialog(self, f"You can't login as a client. You have {attempts - 1 - attempt}\ attempt(s) left.") continue - else: - user_config.saveConfig() - user_config.setAPIUrl(txt_url) except (TypeError, KeyError): pass self.destroy() + user_config.setAPIUrl(txt_url) + user_config.saveConfig() return True if run in [Gtk.ResponseType.CANCEL, -4]: From 599726ecb3c8dbe82178a78918a0a23a8fe59bb3 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Mon, 1 Feb 2021 14:41:48 +0700 Subject: [PATCH 18/20] Pep8 syntax --- faraday_client/persistence/server/server.py | 81 +++++++++++++++++---- faraday_client/start_client.py | 62 ++++++++-------- 2 files changed, 98 insertions(+), 45 deletions(-) diff --git a/faraday_client/persistence/server/server.py b/faraday_client/persistence/server/server.py index 7d1bddcc..7aa4f1a3 100644 --- a/faraday_client/persistence/server/server.py +++ b/faraday_client/persistence/server/server.py @@ -39,10 +39,10 @@ from faraday_client import __version__ as f_version from faraday_client.persistence.server.utils import force_unique from faraday_client.persistence.server.server_io_exceptions import (WrongObjectSignature, - CantCommunicateWithServerError, - ConflictInDatabase, - ResourceDoesNotExist, - Unauthorized) + CantCommunicateWithServerError, + ConflictInDatabase, + ResourceDoesNotExist, + Unauthorized) from faraday_client.persistence.server.changes_stream import ( WebsocketsChangesStream @@ -71,7 +71,6 @@ } - def _conf(): from faraday_client.config.configuration import getInstanceConfiguration # pylint:disable=import-outside-toplevel CONF = getInstanceConfiguration() @@ -94,10 +93,12 @@ def _get_base_server_url(): # Try to fix it return SERVER_URL.rstrip('/') + def _create_server_api_url(): """Return the server's api url.""" return "{0}/_api/v2".format(_get_base_server_url()) + def _create_server_get_url(workspace_name, object_name=None, object_id=None, **params): """Creates a url to get from the server. Takes the workspace name as a string, an object_name paramter which is the object you want to @@ -141,6 +142,7 @@ def _create_server_put_url(workspace_name, obj_type, obj_id, command_id): def _create_server_delete_url(workspace_name, obj_type, object_id, command_id=None): return _create_server_put_url(workspace_name, obj_type, object_id, command_id) + # XXX: COUCH IT! def _create_couch_get_url(workspace_name, object_id): server_url = _get_base_server_url() @@ -169,6 +171,7 @@ def _add_session_cookies(func): """A decorator which wrapps a function dealing with I/O with the server and adds authentication to the parameters. """ + def wrapper(*args, **kwargs): if FARADAY_UPLOAD_REPORTS_WEB_COOKIE: kwargs['cookies'] = FARADAY_UPLOAD_REPORTS_WEB_COOKIE @@ -176,6 +179,7 @@ def wrapper(*args, **kwargs): kwargs['cookies'] = _conf().getFaradaySessionCookies() response = func(*args, **kwargs) return response + return wrapper if FARADAY_UP else func @@ -210,6 +214,7 @@ def _unsafe_io_with_server(server_io_function, server_expected_responses, raise CantCommunicateWithServerError(server_io_function, server_url, payload, answer) return answer + def _parse_json(response_object): """Takes a response object and return its response as a dictionary.""" try: @@ -232,6 +237,7 @@ def _get(request_url, **params): request_url, params=params)) + def _put(post_url, expected_response=201, **params): """Put to the post_url. If update is True, try to get the object revision first so as to update the object in Couch. You can @@ -266,7 +272,7 @@ def _delete(delete_url, database=False): last_rev = _get(delete_url)['_rev'] params = {'rev': last_rev} return _parse_json(_unsafe_io_with_server(requests.delete, - [200,204], + [200, 204], delete_url, params=params)) @@ -318,6 +324,7 @@ def _get_raw_workspace_summary(workspace_name): request_url = _create_server_get_url(workspace_name) return _get(request_url) + def _save_to_server(workspace_name, **params): """ @@ -328,14 +335,17 @@ def _save_to_server(workspace_name, **params): post_url = _create_server_post_url(workspace_name, params['type'], params.get('command_id', None)) return _post(post_url, update=False, expected_response=201, **params) + def _get_raw_report_count_vulns(workspace_name, **params): request_url = _create_server_get_url(workspace_name, 'report/countVulns') return _get(request_url, **params) + def _update_in_server(workspace_name, faraday_object_id, **params): put_url = _create_server_put_url(workspace_name, params['type'], faraday_object_id, params.get('command_id', None)) return _put(put_url, expected_response=200, **params) + def _save_db_to_server(db_name, **params): post_url = _create_server_db_url(db_name) return _post(post_url, expected_response=201, **params) @@ -438,6 +448,7 @@ def get_web_vulns(workspace_name, **params): """ return get_all_vulns(workspace_name, type="VulnerabilityWeb", **params) + def get_interfaces(workspace_name, **params): """Get interfaces from the server. @@ -451,6 +462,7 @@ def get_interfaces(workspace_name, **params): return _get_faraday_ready_dictionaries(workspace_name, 'interfaces', 'interfaces', **params) + def get_services(workspace_name, **params): """Get services from the server. @@ -464,6 +476,7 @@ def get_services(workspace_name, **params): return _get_faraday_ready_dictionaries(workspace_name, 'services', 'services', **params) + def get_credentials(workspace_name, **params): """Get credentials from the server. @@ -477,6 +490,7 @@ def get_credentials(workspace_name, **params): return _get_faraday_ready_dictionaries(workspace_name, 'credentials', 'rows', **params) + def get_notes(workspace_name, **params): """Get notes from the server. @@ -490,6 +504,7 @@ def get_notes(workspace_name, **params): return _get_faraday_ready_dictionaries(workspace_name, 'notes', 'rows', **params) + def get_commands(workspace_name, **params): """Get commands from the server. @@ -514,6 +529,7 @@ def get_report(workspace_name, object_id): request_url = _create_server_post_url(workspace_name, object_id) return _get(request_url) + def get_report_docx(workspace_name, report_object_id): """Get an report docx. @@ -538,6 +554,7 @@ def get_report_docx(workspace_name, report_object_id): return _unsafe_io_with_server(requests.get, 200, request_url) + def get_report_count_vulns(workspace_name, confirmed=False, tags=[]): """ Get vulnerabilities count from the server. @@ -554,7 +571,7 @@ def get_report_count_vulns(workspace_name, confirmed=False, tags=[]): """ return _get_raw_report_count_vulns( - workspace_name, confirmed="true" if confirmed else "false", tags=",".join(tags)) + workspace_name, confirmed="true" if confirmed else "false", tags=",".join(tags)) def get_objects(workspace_name, object_signature, **params): @@ -599,13 +616,15 @@ def get_changes_stream(workspace_name, heartbeat='1000', stream_provider=_websoc stream_provider: A function that returns an instance of a Stream provider """ return stream_provider(workspace_name, feed='continuous', - heartbeat=heartbeat, **extra_params) + heartbeat=heartbeat, **extra_params) + def get_workspaces_names(): """Returns: A dictionary with a list with the workspaces names.""" return _get("{0}/ws".format(_create_server_api_url())) + # XXX: COUCH IT! def _clean_up_stupid_couch_response(response_string): """Couch likes to give invalid jsons as a response :). So nice.""" @@ -615,6 +634,7 @@ def _clean_up_stupid_couch_response(response_string): hopefully_valid_json = "{{{0}}}".format(ok_yeah) return json.loads(hopefully_valid_json) + # XXX: COUCH IT! # COUCH IT LEVEL: REVOLUTIONS def get_object_before_last_revision(workspace_name, object_id): @@ -671,6 +691,7 @@ def get_object(workspace_name, object_signature, object_id): objects = get_objects(workspace_name, object_signature, couchid=object_id) return force_unique(objects) + def get_host(workspace_name, host_id): """Get an unique host. @@ -688,6 +709,7 @@ def get_host(workspace_name, host_id): """ return force_unique(get_hosts(workspace_name, couchid=host_id)) + def get_vuln(workspace_name, vuln_id): """Get an unique vuln. @@ -705,6 +727,7 @@ def get_vuln(workspace_name, vuln_id): """ return force_unique(get_vulns(workspace_name, couchid=vuln_id)) + def get_web_vuln(workspace_name, vuln_id): """Get an unique web vuln. @@ -722,6 +745,7 @@ def get_web_vuln(workspace_name, vuln_id): """ return force_unique(get_web_vulns(workspace_name, couchid=vuln_id)) + def get_interface(workspace_name, interface_id): """Get an unique interface. @@ -739,6 +763,7 @@ def get_interface(workspace_name, interface_id): """ return force_unique(get_interfaces(workspace_name, couchid=interface_id)) + def get_service(workspace_name, service_id): """Get an unique service. @@ -756,6 +781,7 @@ def get_service(workspace_name, service_id): """ return force_unique(get_services(workspace_name, couchid=service_id)) + def get_note(workspace_name, note_id): """Get an unique note. @@ -773,6 +799,7 @@ def get_note(workspace_name, note_id): """ return force_unique(get_notes(workspace_name, couchid=note_id)) + def get_credential(workspace_name, credential_id): """Get an unique credential. @@ -790,6 +817,7 @@ def get_credential(workspace_name, credential_id): """ return force_unique(get_services(workspace_name, couchid=credential_id)) + def get_command(workspace_name, command_id): """Get an unique command. @@ -807,6 +835,7 @@ def get_command(workspace_name, command_id): """ return force_unique(get_commands(workspace_name, couchid=command_id)) + def get_workspace(workspace_name, **params): """Get an unique command. @@ -825,6 +854,7 @@ def get_workspace(workspace_name, **params): request_url = _create_server_get_url(workspace_name) return _get(request_url, **params) + def get_workspace_summary(workspace_name): """Get a collection of data about the workspace. @@ -836,6 +866,7 @@ def get_workspace_summary(workspace_name): """ return _get_raw_workspace_summary(workspace_name)['stats'] + def get_workspace_numbers(workspace_name): """Get the number of hosts, interfaces, services and vulns in the workspace. @@ -848,6 +879,7 @@ def get_workspace_numbers(workspace_name): stats = _get_raw_workspace_summary(workspace_name)['stats'] return stats['hosts'], stats['services'], stats['total_vulns'] + def get_hosts_number(workspace_name, **params): """ Args: @@ -859,6 +891,7 @@ def get_hosts_number(workspace_name, **params): """ return int(get_workspace_summary(workspace_name)['hosts']) + def get_services_number(workspace_name, **params): """ Args: @@ -870,6 +903,7 @@ def get_services_number(workspace_name, **params): """ return int(get_workspace_summary(workspace_name)['services']) + def get_interfaces_number(workspace_name, **params): """ Args: @@ -881,6 +915,7 @@ def get_interfaces_number(workspace_name, **params): """ return int(get_workspace_summary(workspace_name)['interfaces']) + def get_vulns_number(workspace_name, **params): """ Args: @@ -892,6 +927,7 @@ def get_vulns_number(workspace_name, **params): """ return int(get_workspace_summary(workspace_name)['total_vulns']) + def get_notes_number(workspace_name, **params): """ Args: @@ -903,6 +939,7 @@ def get_notes_number(workspace_name, **params): """ return int(get_workspace_summary(workspace_name)['notes']) + def get_credentials_number(workspace_name, **params): """ Args: @@ -914,6 +951,7 @@ def get_credentials_number(workspace_name, **params): """ return int(_get_raw_credentials(workspace_name, **params)) + def get_commands_number(workspace_name, **params): """ Args: @@ -925,6 +963,7 @@ def get_commands_number(workspace_name, **params): """ return int(_get_raw_commands(workspace_name, **params)) + def create_host(workspace_name, command_id, ip, os, default_gateway=None, description="", metadata=None, owned=False, owner="", parent=None, hostnames=None, mac=None): @@ -960,6 +999,7 @@ def create_host(workspace_name, command_id, ip, os, default_gateway=None, mac=mac, type="Host") + def update_host(workspace_name, command_id, id, ip, os, default_gateway="", description="", metadata=None, owned=False, owner="", parent=None, hostnames=None, mac=None): @@ -1033,6 +1073,7 @@ def create_service(workspace_name, command_id, name, description, ports, parent, type="Service", metadata=metadata) + def update_service(workspace_name, command_id, id, name, description, ports, parent, owned=False, owner="", protocol="", status="", version="", metadata=None): @@ -1118,7 +1159,8 @@ def create_vuln(workspace_name, command_id, name, description, parent, parent_ty status=status, metadata=metadata, policyviolations=policyviolations, - external_id=external_id) + external_id=external_id) + def update_vuln(workspace_name, command_id, id, name, description, parent, parent_type, owned=None, owner="", confirmed=False, data="", @@ -1168,7 +1210,8 @@ def update_vuln(workspace_name, command_id, id, name, description, parent, status=status, metadata=metadata, policyviolations=policyviolations, - external_id=external_id) + external_id=external_id) + def create_vuln_web(workspace_name, command_id, name, description, parent, parent_type, owned=None, owner="", confirmed=False, @@ -1238,6 +1281,7 @@ def create_vuln_web(workspace_name, command_id, name, description, parent, policyviolations=policyviolations, tags=tags, external_id=external_id) + def update_vuln_web(workspace_name, command_id, id, name, description, parent, parent_type, owned=None, owner="", confirmed=False, data="", refs=None, severity="info", resolution="", @@ -1308,6 +1352,7 @@ def update_vuln_web(workspace_name, command_id, id, name, description, tags=tags, external_id=external_id) + def create_note(workspace_name, command_id, object_type, object_id, name, text, owned=None, owner="", description="", metadata=None): """Creates a note. @@ -1338,6 +1383,7 @@ def create_note(workspace_name, command_id, object_type, object_id, name, text, type="Note", metadata=metadata) + def update_note(workspace_name, command_id, id, name, text, object_type, object_id, owned=None, owner="", description="", metadata=None): @@ -1404,6 +1450,7 @@ def create_credential(workspace_name, command_id, name, username, password, password=password, type="Cred") + def update_credential(workspace_name, command_id, id, name, username, password, parent, parent_type, owned=None, owner="", description="", metadata=None): @@ -1438,6 +1485,7 @@ def update_credential(workspace_name, command_id, id, name, username, password, password=password, type="Cred") + def create_command(workspace_name, command, tool, import_source, duration=None, hostname=None, ip=None, itime=None, params=None, user=None): """Creates a command. @@ -1468,8 +1516,9 @@ def create_command(workspace_name, command, tool, import_source, duration=None, workspace=workspace_name, type="CommandRunInformation") + def update_command(workspace_name, command_id, command, tool, import_source -,duration=None, hostname=None, + , duration=None, hostname=None, ip=None, itime=None, params=None, user=None): """Updates a command. @@ -1503,7 +1552,8 @@ def update_command(workspace_name, command_id, command, tool, import_source def create_executive_report(workspace_name, id, name, tags=[], title="", enterprise="", scope="", objectives="", - summary="", confirmed=False, template_name="", conclusions="", recommendations="", date=None, + summary="", confirmed=False, template_name="", conclusions="", recommendations="", + date=None, owner="", grouped=False): """Creates a Executive report. @@ -1613,6 +1663,7 @@ def delete_workspace(workspace_name): db_url = _create_server_db_url(workspace_name) return _delete(db_url, database=True) + def server_info(): """Return server info if we can stablish a connection with the server, None otherwise. @@ -1622,6 +1673,7 @@ def server_info(): except: return None + def login_user(uri, uname, upass, u2fa_token=None): auth = {"email": uname, "password": upass} headers = {'User-Agent': f'faraday-client/{f_version}'} @@ -1683,9 +1735,11 @@ def check_server_url(url_to_test): test_okey = False return test_okey + def get_user_info(): try: - resp = requests.get(urlparse.urljoin(_get_base_server_url(), "/_api/session"), cookies=_conf().getFaradaySessionCookies(), timeout=1) + resp = requests.get(urlparse.urljoin(_get_base_server_url(), "/_api/session"), + cookies=_conf().getFaradaySessionCookies(), timeout=1) if (resp.status_code != 401) and (resp.status_code != 403): return resp.json() else: @@ -1695,5 +1749,4 @@ def get_user_info(): except requests.adapters.ReadTimeout: return False - # I'm Py3 diff --git a/faraday_client/start_client.py b/faraday_client/start_client.py index a9fb1c4b..ad137e89 100755 --- a/faraday_client/start_client.py +++ b/faraday_client/start_client.py @@ -19,7 +19,6 @@ import requests.exceptions import logging - from faraday_client.config.configuration import getInstanceConfiguration from faraday_client.config.constant import ( CONST_USER_HOME, @@ -39,11 +38,12 @@ CONST_FARADAY_HOME_PATH = os.path.expanduser('~/.faraday') from faraday_client import __version__ -from faraday_client.persistence.server.server import login_user, get_user_info, is_authenticated +from faraday_client.persistence.server.server import login_user, get_user_info import faraday_client from colorama import init, Fore, Back, Style + init(autoreset=True) from urllib.parse import urlparse, urljoin @@ -77,7 +77,7 @@ logger = logging.getLogger(__name__) -def getParserArgs(): +def get_parser_args(): """ Parser setup for faraday launcher arguments. """ @@ -134,7 +134,7 @@ def getParserArgs(): dest="gui", default="gtk", help="Select interface to start faraday. Supported values are " - "gtk and 'no' (no GUI at all). Defaults to GTK") + "gtk and 'no' (no GUI at all). Defaults to GTK") parser.add_argument('--cli', action="store_true", @@ -162,7 +162,6 @@ def getParserArgs(): default=False, help="Enables debug mode. Default = disabled") - parser.add_argument('--nodeps', action="store_true", help='Skip dependency check') @@ -254,7 +253,7 @@ def setupZSH(): dst.write(src.read()) -def setupXMLConfig(): +def setup_xml_config(): """ Checks user configuration file status. @@ -268,7 +267,7 @@ def setupXMLConfig(): logger.info("Using custom user configuration.") -def checkConfiguration(gui_type): +def check_configuration(gui_type): """ Checks if the environment is ready to run Faraday. @@ -280,20 +279,20 @@ def checkConfiguration(gui_type): logger.info("Setting up ZSH integration.") setupZSH() logger.info("Setting up user configuration.") - setupXMLConfig() + setup_xml_config() -def setupFolders(folderlist): +def setup_folders(folder_list): """ Checks if a list of folders exists and creates them otherwise. """ - for folder in folderlist: + for folder in folder_list: fp_folder = os.path.join(FARADAY_USER_HOME, folder) - checkFolder(fp_folder) + check_folder(fp_folder) -def checkFolder(folder): +def check_folder(folder): """ Checks whether a folder exists and creates it if it doesn't. """ @@ -304,11 +303,11 @@ def checkFolder(folder): os.makedirs(folder) -def printBanner(): +def print_banner(): """ Prints Faraday's ascii banner. """ - print (Fore.RED + """ + print(Fore.RED + """ _____ .___ _/ ____\_____ ____________ __| _/_____ ___.__. \ __\ \__ \ \_ __ \__ \ / __ | \__ \ < | | @@ -327,7 +326,8 @@ def try_login_user(server_uri, api_username, api_password, u2fa_token=None): try: session_cookie = login_user(server_uri, api_username, api_password, u2fa_token) except requests.exceptions.SSLError: - print("SSL certificate validation failed.\nYou can use the --cert option in Faraday to set the path of the cert") + print( + "SSL certificate validation failed.\nYou can use the --cert option in Faraday to set the path of the cert") sys.exit(-1) except requests.exceptions.MissingSchema: print("The Faraday Server URL is incorrect, please try again.") @@ -345,8 +345,8 @@ def login(cert_path): Sets the username and passwords from the command line. If --login flag is set then username and password is set """ - CONF = getInstanceConfiguration() - server_url = CONF.getAPIUrl() + user_config = getInstanceConfiguration() + server_url = user_config.getAPIUrl() try: if not server_url: server_url = input("\nPlease enter the Faraday Server URL (Press enter for http://localhost:5985): ") \ @@ -373,10 +373,10 @@ def login(cert_path): except requests.exceptions.ConnectionError as e: logger.error("Connection to Faraday server FAILED: %s - use --login to set a new server", server_url) sys.exit(1) - CONF.setAPIUrl(server_url) + user_config.setAPIUrl(server_url) print(f"""\nPlease provide your valid Faraday credentials for {server_url}\nYou have 3 attempts.""") - MAX_ATTEMPTS = 3 - for attempt in range(1, MAX_ATTEMPTS + 1): + max_attempts = 3 + for attempt in range(1, max_attempts + 1): api_username = input("Username (press enter for faraday): ") or "faraday" api_password = getpass.getpass('Password: ') try: @@ -388,25 +388,25 @@ def login(cert_path): u2fa_token = input("2FA Token: ") session_cookie = try_login_user(server_url, api_username, api_password, u2fa_token) if session_cookie: - CONF.setFaradaySessionCookies(session_cookie) + user_config.setFaradaySessionCookies(session_cookie) if parsed_url.scheme == "https" and cert_path: - CONF.setCerPath(cert_path) + user_config.setCerPath(cert_path) else: - CONF.setCerPath(None) + user_config.setCerPath(None) user_info = get_user_info() if not user_info: continue else: if 'roles' in user_info: if 'client' in user_info['roles']: - print(f"You can't login as a client. You have {MAX_ATTEMPTS - attempt} attempt(s) left.") + print(f"You can't login as a client. You have {max_attempts - attempt} attempt(s) left.") continue logger.info('Login successful: {0}'.format(api_username)) - CONF.saveConfig() + user_config.saveConfig() break - print(f'Login failed, please try again. You have {MAX_ATTEMPTS - attempt} more attempts') + print(f'Login failed, please try again. You have {max_attempts - attempt} more attempts') else: - logger.fatal(f'Invalid credentials, {MAX_ATTEMPTS} attempts failed. Quitting Faraday...') + logger.fatal(f'Invalid credentials, {max_attempts} attempts failed. Quitting Faraday...') sys.exit(-1) except KeyboardInterrupt: sys.exit(0) @@ -418,11 +418,11 @@ def main(): """ global args - args = getParserArgs() - setupFolders(CONST_FARADAY_FOLDER_LIST) - printBanner() + args = get_parser_args() + setup_folders(CONST_FARADAY_FOLDER_LIST) + print_banner() logger.info("Dependencies met.") - checkConfiguration(args.gui) + check_configuration(args.gui) setConf() CONF = getInstanceConfiguration() cert_path = CONF.getCertPath() From 868b97ff017c9abaa0a18ff86bde1f2f7a85a0f2 Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Wed, 3 Feb 2021 04:30:29 +0700 Subject: [PATCH 19/20] Pep8 syntax for some lines Fix hashlib unicode error --- faraday_client/utils/error_report.py | 29 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/faraday_client/utils/error_report.py b/faraday_client/utils/error_report.py index f5deeea8..018f3df1 100644 --- a/faraday_client/utils/error_report.py +++ b/faraday_client/utils/error_report.py @@ -34,11 +34,12 @@ def get_crash_log(): pass + def get_system_info(): pass -def exception_handler(type, value, tb): +def exception_handler(obj_type, value, tb): """ This is a custom exception handler to replace the python original one. The idea is to show the user a dialog with the information and let him/her @@ -49,13 +50,10 @@ def exception_handler(type, value, tb): """ text = StringIO() - traceback.print_exception(type, value, tb, file=text) + traceback.print_exception(obj_type, value, tb, file=text) error_name = text.getvalue().split('\n')[-2] - excepts = """ - Traceback: %s - """ % (text.getvalue() ) - + excepts = f"Traceback: {text.getvalue()}".encode('utf-8') exception_hash = hashlib.sha256(excepts).hexdigest() os_dist = " ".join(platform.dist()) python_version = platform.python_version() @@ -63,13 +61,12 @@ def exception_handler(type, value, tb): modules_info = "" try: - modules_info = ",".join([ "%s=%s" % (x.key, x.version) - for x in pip.get_installed_distributions()]) + modules_info = ",".join(["%s=%s" % (x.key, x.version) + for x in pip.get_installed_distributions()]) except (ImportError, AttributeError): pass - - python_dist = "Python %s \n Modules: [ %s ]" % (python_version, modules_info) + python_dist = f"Python {python_version} \n Modules: [ {modules_info} ]" description = """ Exception: %s @@ -79,8 +76,6 @@ def exception_handler(type, value, tb): Python Versions: %s """ % (excepts, exception_hash, os_dist, faraday_version, python_dist) - - event = ShowExceptionCustomEvent(description, reportToDevelopers, error_name) faraday_client.model.guiapi.postCustomEvent(event) text.seek(0) @@ -103,8 +98,8 @@ def reportToDevelopers(name=None, *description): params['summary'] = 'autoreport %s' % time.time() resp = requests.post(uri, - headers = headers, - data = params, timeout = 1, verify=True) + headers=headers, + data=params, timeout=1, verify=True) model.api.devlog("Report sent to faraday server") @@ -112,6 +107,7 @@ def reportToDevelopers(name=None, *description): model.api.devlog("Error reporting to developers:") model.api.devlog(e) + def installThreadExcepthook(): """ Workaround for sys.excepthook thread bug from @@ -122,9 +118,11 @@ def installThreadExcepthook(): since this replaces a new-style class method. """ init_old = threading.Thread.__init__ + def init(self, *args, **kwargs): init_old(self, *args, **kwargs) run_old = self.run + def run_with_except_hook(*args, **kw): try: run_old(*args, **kw) @@ -132,8 +130,9 @@ def run_with_except_hook(*args, **kw): if isinstance(e, (KeyboardInterrupt, SystemExit)): raise sys.excepthook(*sys.exc_info()) + self.run = run_with_except_hook - threading.Thread.__init__ = init + threading.Thread.__init__ = init # I'm Py3 From 76848a70ccd69be87d909bd2aff8be7d08a54c2d Mon Sep 17 00:00:00 2001 From: Nong Hoang Tu Date: Wed, 3 Feb 2021 04:37:00 +0700 Subject: [PATCH 20/20] Fix platform remove dist() caused error Now report bug dialog is working --- faraday_client/utils/error_report.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/faraday_client/utils/error_report.py b/faraday_client/utils/error_report.py index 018f3df1..c0e4f800 100644 --- a/faraday_client/utils/error_report.py +++ b/faraday_client/utils/error_report.py @@ -14,8 +14,6 @@ import traceback import threading import requests -import hashlib -import platform import faraday_client.model.guiapi from io import StringIO from faraday_client.gui.customevents import ShowExceptionCustomEvent @@ -48,6 +46,9 @@ def exception_handler(obj_type, value, tb): Since this handler may be called from threads, the dialog must be created using gtk idle_add or signals to avoid issues. """ + import hashlib + import platform + import distro text = StringIO() traceback.print_exception(obj_type, value, tb, file=text) @@ -55,7 +56,7 @@ def exception_handler(obj_type, value, tb): excepts = f"Traceback: {text.getvalue()}".encode('utf-8') exception_hash = hashlib.sha256(excepts).hexdigest() - os_dist = " ".join(platform.dist()) + os_dist = " ".join(distro.linux_distribution()) python_version = platform.python_version() faraday_version = CONF.getVersion()