diff --git a/gui/src/gui/settings.py b/gui/src/gui/settings.py index ef16727..ec75031 100644 --- a/gui/src/gui/settings.py +++ b/gui/src/gui/settings.py @@ -5,7 +5,7 @@ gi.require_version('Gtk', '4.0') gi.require_version('Adw', '1') import gc -from gi.repository import Gtk, Adw, GLib, Gdk +from gi.repository import Gtk, Adw, GLib, Gdk, Gio from ..services import goldwarden from threading import Thread import subprocess @@ -16,6 +16,30 @@ root_path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file_ token = sys.stdin.readline() goldwarden.create_authenticated_connection(None) +def quickaccess_button_clicked(): + p = subprocess.Popen(["python3", "-m", "src.gui.quickaccess"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=root_path, start_new_session=True) + p.stdin.write(f"{token}\n".encode()) + p.stdin.flush() + +def shortcuts_button_clicked(): + p = subprocess.Popen(["python3", "-m", "src.gui.shortcuts"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=root_path, start_new_session=True) + p.stdin.write(f"{token}\n".encode()) + p.stdin.flush() + +def ssh_button_clicked(): + p = subprocess.Popen(["python3", "-m", "src.gui.ssh"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=root_path, start_new_session=True) + p.stdin.write(f"{token}\n".encode()) + p.stdin.flush() + +def add_action_row(parent, title, subtitle, icon=None): + row = Adw.ActionRow() + row.set_title(title) + row.set_subtitle(subtitle) + if icon != None: + row.set_icon_name(icon) + parent.add(row) + return row + class SettingsWinvdow(Gtk.ApplicationWindow): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -50,10 +74,7 @@ class SettingsWinvdow(Gtk.ApplicationWindow): self.autotype_button = Gtk.Button() self.autotype_button.set_label("Quick Access") self.autotype_button.set_margin_top(10) - def quickaccess_button_clicked(): - p = subprocess.Popen(["python3", "-m", "src.gui.quickaccess"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=root_path, start_new_session=True) - p.stdin.write(f"{token}\n".encode()) - p.stdin.flush() + self.autotype_button.connect("clicked", lambda button: quickaccess_button_clicked()) self.autotype_button.get_style_context().add_class("suggested-action") self.action_preferences_group.add(self.autotype_button) @@ -98,120 +119,48 @@ class SettingsWinvdow(Gtk.ApplicationWindow): self.wiki_button.set_margin_top(10) self.action_preferences_group.add(self.wiki_button) - self.shortcut_preferences_group = Adw.PreferencesGroup() - self.shortcut_preferences_group.set_title("Shortcuts") - self.preferences_page.add(self.shortcut_preferences_group) - - self.autofill_row = Adw.ActionRow() - self.autofill_row.set_title("Autofill Shortcut") - self.autofill_row.set_subtitle("Unavailable, please set up a shortcut in your desktop environment (README)") - self.shortcut_preferences_group.add(self.autofill_row) - - self.autofill_icon = components.StatusIcon() - self.autofill_icon.set_icon("dialog-warning", "warning") - self.autofill_row.add_prefix(self.autofill_icon) - - self.copy_username_shortcut_row = Adw.ActionRow() - self.copy_username_shortcut_row.set_title("Copy Username Shortcut") - self.copy_username_shortcut_row.set_subtitle("U") - self.shortcut_preferences_group.add(self.copy_username_shortcut_row) - - self.copy_password_shortcut_row = Adw.ActionRow() - self.copy_password_shortcut_row.set_title("Copy Password Shortcut") - self.copy_password_shortcut_row.set_subtitle("P") - self.shortcut_preferences_group.add(self.copy_password_shortcut_row) - - self.copy_totp_shortcut_row = Adw.ActionRow() - self.copy_totp_shortcut_row.set_title("Copy TOTP Shortcut") - self.copy_totp_shortcut_row.set_subtitle("T") - self.shortcut_preferences_group.add(self.copy_totp_shortcut_row) - - self.launch_uri_shortcut_row = Adw.ActionRow() - self.launch_uri_shortcut_row.set_title("Launch URI Shortcut") - self.launch_uri_shortcut_row.set_subtitle("L") - self.shortcut_preferences_group.add(self.launch_uri_shortcut_row) - - self.launch_web_vault_shortcut_row = Adw.ActionRow() - self.launch_web_vault_shortcut_row.set_title("Launch Web Vault Shortcut") - self.launch_web_vault_shortcut_row.set_subtitle("V") - self.shortcut_preferences_group.add(self.launch_web_vault_shortcut_row) - - self.focus_search_shortcut_row = Adw.ActionRow() - self.focus_search_shortcut_row.set_title("Focus Search Shortcut") - self.focus_search_shortcut_row.set_subtitle("F") - self.shortcut_preferences_group.add(self.focus_search_shortcut_row) - - self.quit_shortcut_row = Adw.ActionRow() - self.quit_shortcut_row.set_title("Quit Shortcut") - self.quit_shortcut_row.set_subtitle("Esc") - self.shortcut_preferences_group.add(self.quit_shortcut_row) - self.vault_status_preferences_group = Adw.PreferencesGroup() self.vault_status_preferences_group.set_title("Vault Status") self.preferences_page.add(self.vault_status_preferences_group) - self.status_row = Adw.ActionRow() - self.status_row.set_title("Vault Status") - self.status_row.set_subtitle("Locked") - self.vault_status_preferences_group.add(self.status_row) + self.status_row = add_action_row(self.vault_status_preferences_group, "Vault Status", "Locked") self.vault_status_icon = components.StatusIcon() self.vault_status_icon.set_icon("dialog-error", "error") self.status_row.add_prefix(self.vault_status_icon) - self.last_sync_row = Adw.ActionRow() - self.last_sync_row.set_title("Last Sync") - self.last_sync_row.set_subtitle("Never") - self.last_sync_row.set_icon_name("emblem-synchronizing-symbolic") - self.vault_status_preferences_group.add(self.last_sync_row) - - self.websocket_connected_row = Adw.ActionRow() - self.websocket_connected_row.set_title("Websocket Connected") - self.websocket_connected_row.set_subtitle("False") - self.vault_status_preferences_group.add(self.websocket_connected_row) + self.last_sync_row = add_action_row(self.vault_status_preferences_group, "Last Sync", "Never", "emblem-synchronizing-symbolic") + self.websocket_connected_row = add_action_row(self.vault_status_preferences_group, "Websocket Connected", "False") self.websocket_connected_status_icon = components.StatusIcon() self.websocket_connected_status_icon.set_icon("dialog-error", "error") self.websocket_connected_row.add_prefix(self.websocket_connected_status_icon) + + self.login_row = add_action_row(self.vault_status_preferences_group, "Vault Login Entries", "0", "dialog-password-symbolic") + self.notes_row = add_action_row(self.vault_status_preferences_group, "Vault Notes", "0", "emblem-documents-symbolic") + + self.header = Gtk.HeaderBar() + self.set_titlebar(self.header) + + action = Gio.SimpleAction.new("shortcuts", None) + action.connect("activate", lambda action, parameter: shortcuts_button_clicked()) + self.add_action(action) + menu = Gio.Menu.new() + menu.append("Keyboard Shortcuts", "win.shortcuts") + self.popover = Gtk.PopoverMenu() + self.popover.set_menu_model(menu) + + action = Gio.SimpleAction.new("ssh", None) + action.connect("activate", lambda action, parameter: ssh_button_clicked()) + self.add_action(action) + menu.append("SSH Agent", "win.ssh") - self.login_row = Adw.ActionRow() - self.login_row.set_title("Vault Login Entries") - self.login_row.set_subtitle("0") - self.login_row.set_icon_name("dialog-password-symbolic") - self.vault_status_preferences_group.add(self.login_row) + self.hamburger = Gtk.MenuButton() + self.hamburger.set_popover(self.popover) + self.hamburger.set_icon_name("open-menu-symbolic") + self.header.pack_start(self.hamburger) - self.notes_row = Adw.ActionRow() - self.notes_row.set_title("Vault Notes") - self.notes_row.set_subtitle("0") - self.notes_row.set_icon_name("emblem-documents-symbolic") - self.vault_status_preferences_group.add(self.notes_row) - self.preferences_group = Adw.PreferencesGroup() - self.preferences_group.set_title("Services") - self.preferences_page.add(self.preferences_group) - - self.ssh_row = Adw.ActionRow() - self.ssh_row.set_title("SSH Daemon") - self.ssh_row.set_subtitle("Getting status...") - self.ssh_row.set_icon_name("emblem-default") - self.preferences_group.add(self.ssh_row) - - self.goldwarden_daemon_row = Adw.ActionRow() - self.goldwarden_daemon_row.set_title("Goldwarden Daemon") - self.goldwarden_daemon_row.set_subtitle("Getting status...") - self.goldwarden_daemon_row.set_icon_name("emblem-default") - self.preferences_group.add(self.goldwarden_daemon_row) - - self.login_with_device = Adw.ActionRow() - self.login_with_device.set_title("Login with device") - self.login_with_device.set_subtitle("Waiting for requests...") - self.preferences_group.add(self.login_with_device) - - self.status_row = Adw.ActionRow() - self.status_row.set_title("DBUS Service") - self.status_row.set_subtitle("Listening") - self.preferences_group.add(self.status_row) - def update_labels(): pin_set = goldwarden.is_pin_enabled() status = goldwarden.get_vault_status() @@ -276,16 +225,10 @@ class SettingsWinvdow(Gtk.ApplicationWindow): GLib.timeout_add(5000, update_labels) - GLib.timeout_add(1000, update_labels) self.set_default_size(400, 700) self.set_title("Goldwarden") - - #add title buttons - self.title_bar = Gtk.HeaderBar() - self.set_titlebar(self.title_bar) - class MyApp(Adw.Application): def __init__(self, **kwargs): super().__init__(**kwargs) @@ -372,6 +315,5 @@ Gtk.StyleContext.add_provider_for_display( Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) - app = MyApp(application_id="com.quexten.Goldwarden.settings") app.run(sys.argv) \ No newline at end of file diff --git a/gui/src/gui/shortcuts.py b/gui/src/gui/shortcuts.py new file mode 100644 index 0000000..1cf4e6a --- /dev/null +++ b/gui/src/gui/shortcuts.py @@ -0,0 +1,80 @@ +import gi +gi.require_version('Gtk', '4.0') +gi.require_version('Adw', '1') +import gc +import time +from gi.repository import Gtk, Adw, GLib, Notify, Gdk +from threading import Thread +import sys +import os +from . import components + +def add_action_row(parent, title, subtitle, icon=None): + row = Adw.ActionRow() + row.set_title(title) + row.set_subtitle(subtitle) + if icon != None: + row.set_icon_name(icon) + parent.add(row) + return row + +class MyApp(Adw.Application): + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.connect('activate', self.on_activate) + + def on_activate(self, app): + self.pinentry_window = MainWindow(application=app) + self.pinentry_window.present() + self.app = app + +class MainWindow(Gtk.ApplicationWindow): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # vertical box + self.box = Gtk.Box() + self.box.set_orientation(Gtk.Orientation.VERTICAL) + self.set_child(self.box) + + self.stack = Gtk.Stack() + self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT) + self.box.append(self.stack) + + self.preferences_page = Adw.PreferencesPage() + self.preferences_page.set_title("General") + self.stack.add_named(self.preferences_page, "preferences_page") + + self.global_preferences_group = Adw.PreferencesGroup() + self.global_preferences_group.set_title("Global Shortcuts") + self.preferences_page.add(self.global_preferences_group) + + self.autofill_row = Adw.ActionRow() + self.autofill_row.set_title("Autofill Shortcut") + self.autofill_row.set_subtitle("Not implemented - check the wiki for manual setup") + self.global_preferences_group.add(self.autofill_row) + + self.autofill_icon = components.StatusIcon() + self.autofill_icon.set_icon("dialog-warning", "warning") + self.autofill_row.add_prefix(self.autofill_icon) + + self.quickaccess_preferences_group = Adw.PreferencesGroup() + self.quickaccess_preferences_group.set_title("Quick Access Shortcuts") + self.preferences_page.add(self.quickaccess_preferences_group) + + add_action_row(self.quickaccess_preferences_group, "Copy Username Shortcut", "CTRL + U") + add_action_row(self.quickaccess_preferences_group, "Autotype Username Shortcut", "CTRL + ALT + U") + add_action_row(self.quickaccess_preferences_group, "Copy Password Shortcut", "CTRL + P") + add_action_row(self.quickaccess_preferences_group, "Autotype Password Shortcut", "CTRL + ALT + P") + add_action_row(self.quickaccess_preferences_group, "Copy TOTP Shortcut", "CTRL + T") + add_action_row(self.quickaccess_preferences_group, "Autotype TOTP Shortcut", "CTRL + ALT + T") + add_action_row(self.quickaccess_preferences_group, "Launch URI Shortcut", "CTRL+L") + add_action_row(self.quickaccess_preferences_group, "Launch Web Vault Shortcut", "CTRL+V") + add_action_row(self.quickaccess_preferences_group, "Focus Search Shortcut", "F") + add_action_row(self.quickaccess_preferences_group, "Quit Shortcut", "Esc") + + self.set_default_size(700, 700) + self.set_title("Goldwarden Shortcuts") + +app = MyApp(application_id="com.quexten.Goldwarden.shortcuts") +app.run(sys.argv) \ No newline at end of file diff --git a/gui/src/gui/ssh.py b/gui/src/gui/ssh.py new file mode 100644 index 0000000..1f1eafd --- /dev/null +++ b/gui/src/gui/ssh.py @@ -0,0 +1,67 @@ +import gi +gi.require_version('Gtk', '4.0') +gi.require_version('Adw', '1') +import gc +import time +from gi.repository import Gtk, Adw, GLib, Notify, Gdk +from threading import Thread +import sys +import os +from . import components + +class MyApp(Adw.Application): + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.connect('activate', self.on_activate) + + def on_activate(self, app): + self.pinentry_window = MainWindow(application=app) + self.pinentry_window.present() + self.app = app + +class MainWindow(Gtk.ApplicationWindow): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # vertical box + self.box = Gtk.Box() + self.box.set_orientation(Gtk.Orientation.VERTICAL) + self.set_child(self.box) + + self.stack = Gtk.Stack() + self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT) + self.box.append(self.stack) + + self.preferences_page = Adw.PreferencesPage() + self.preferences_page.set_title("General") + self.stack.add_named(self.preferences_page, "preferences_page") + + self.add_ssh_key_group = Adw.PreferencesGroup() + self.add_ssh_key_group.set_title("Add an SSH Key") + self.preferences_page.add(self.add_ssh_key_group) + + self.add_ssh_key_row = Adw.ActionRow() + self.add_ssh_key_row.set_subtitle("flatpak run --command=goldwarden com.quexten.Goldwarden ssh add --name MY_KEY_NAME") + self.add_ssh_key_row.set_subtitle_selectable(True) + self.add_ssh_key_group.add(self.add_ssh_key_row) + + self.ssh_socket_path_group = Adw.PreferencesGroup() + self.ssh_socket_path_group.set_title("SSH Socket Path") + self.ssh_socket_path_group.set_description("Add this to your your enviorment variables") + self.preferences_page.add(self.ssh_socket_path_group) + + self.ssh_socket_path_row = Adw.ActionRow() + self.ssh_socket_path_row.set_subtitle("export SSH_AUTH_SOCK=/home/$USER/.var/app/com.quexten.Goldwarden/data/ssh-auth-sock") + self.ssh_socket_path_row.set_subtitle_selectable(True) + self.ssh_socket_path_group.add(self.ssh_socket_path_row) + + self.git_signing_group = Adw.PreferencesGroup() + self.git_signing_group.set_title("Git Signing") + self.git_signing_group.set_description("Check the wiki for more information") + self.preferences_page.add(self.git_signing_group) + + self.set_default_size(400, 700) + self.set_title("Goldwarden SSH Setup") + +app = MyApp(application_id="com.quexten.Goldwarden.sshsetup") +app.run(sys.argv) \ No newline at end of file