This commit introduces significant improvements to how encrypted backups are handled,
focusing on user experience and system integration.
- Persistent Mounts: Encrypted backup containers now remain mounted across UI view changes,
eliminating repeated password prompts when navigating the application. The container is
automatically unmounted when the destination changes or the application closes.
- Key Management Fallback: The mounting process now intelligently falls back from
keyring to keyfile, and finally to a user password prompt if previous methods fail.
- Enhanced UI Status: The header now provides detailed feedback on the encryption key
status, indicating whether a key is available (via keyring or keyfile) and if the
container is currently in use.
- Reduced pkexec Prompts: By keeping containers mounted, the number of system-level
pkexec authentication prompts is drastically reduced, improving workflow.
- Bug Fixes:
- Corrected a SyntaxError in encryption_manager.py related to string escaping.
- Fixed an AttributeError in header_frame.py by restoring the is_key_in_keyring method.
- Addressed a TclError on application shutdown by safely destroying Tkinter widgets.
104 lines
3.7 KiB
Python
104 lines
3.7 KiB
Python
import tkinter as tk
|
|
import os
|
|
|
|
from core.pbp_app_config import Msg
|
|
from shared_libs.common_tools import IconManager
|
|
|
|
class HeaderFrame(tk.Frame):
|
|
def __init__(self, container, image_manager, encryption_manager, app, **kwargs):
|
|
super().__init__(container, bg="#455A64", **kwargs)
|
|
|
|
self.image_manager = image_manager
|
|
self.encryption_manager = encryption_manager
|
|
self.app = app
|
|
|
|
# Configure grid weights for internal layout
|
|
self.columnconfigure(1, weight=1) # Make the middle column expand
|
|
self.rowconfigure(0, weight=1) # Make the top row expand
|
|
|
|
# Left side: Icon and Main Title/Subtitle
|
|
left_frame = tk.Frame(self, bg="#455A64")
|
|
left_frame.grid(row=0, column=0, rowspan=2, sticky="nsew")
|
|
left_frame.columnconfigure(0, weight=1)
|
|
left_frame.rowconfigure(0, weight=1)
|
|
|
|
icon_label = tk.Label(
|
|
left_frame,
|
|
image=self.image_manager.get_icon(
|
|
"backup_extralarge"), # Using a generic backup icon
|
|
bg="#455A64",
|
|
)
|
|
icon_label.grid(row=0, column=0, sticky="e", padx=10, pady=5)
|
|
|
|
title_label = tk.Label(
|
|
self,
|
|
text=Msg.STR["header_title"],
|
|
font=("Helvetica", 16, "bold"),
|
|
fg="#ffffff",
|
|
bg="#455A64",
|
|
)
|
|
title_label.grid(row=0, column=1, sticky="w",
|
|
padx=(5, 20), pady=(15, 5))
|
|
|
|
subtitle_label = tk.Label(
|
|
self,
|
|
text=Msg.STR["header_subtitle"],
|
|
font=("Helvetica", 10),
|
|
fg="#bdc3c7",
|
|
bg="#455A64",
|
|
)
|
|
subtitle_label.grid(row=1, column=1, sticky="w",
|
|
padx=(5, 20), pady=(0, 10))
|
|
|
|
# Right side: Keyring status
|
|
right_frame = tk.Frame(self, bg="#455A64")
|
|
right_frame.grid(row=0, column=2, rowspan=2, sticky="nsew")
|
|
right_frame.columnconfigure(0, weight=1)
|
|
right_frame.rowconfigure(0, weight=1)
|
|
|
|
self.keyring_status_label = tk.Label(
|
|
right_frame,
|
|
text="",
|
|
font=("Helvetica", 10, "bold"),
|
|
bg="#455A64",
|
|
)
|
|
self.keyring_status_label.grid(row=0, column=0, sticky="ne", padx=(10, 10), pady=(10, 0))
|
|
|
|
self.refresh_status()
|
|
|
|
def refresh_status(self):
|
|
"""Checks the keyring status based on the current destination and updates the label."""
|
|
dest_path = self.app.destination_path
|
|
if not dest_path or not self.encryption_manager.is_encrypted(dest_path):
|
|
self.keyring_status_label.config(text="") # Clear status if not encrypted
|
|
return
|
|
|
|
username = os.path.basename(dest_path.rstrip('/'))
|
|
|
|
if self.encryption_manager.is_mounted(dest_path):
|
|
status_text = "Key: In Use"
|
|
auth_method = getattr(self.encryption_manager, 'auth_method', None)
|
|
if auth_method == 'keyring':
|
|
status_text += " (Keyring)"
|
|
elif auth_method == 'keyfile':
|
|
status_text += " (Keyfile)"
|
|
self.keyring_status_label.config(
|
|
text=status_text,
|
|
fg="#2E8B57" # SeaGreen
|
|
)
|
|
elif self.encryption_manager.is_key_in_keyring(username):
|
|
self.keyring_status_label.config(
|
|
text="Key: Available (Keyring)",
|
|
fg="#FFD700" # Gold
|
|
)
|
|
elif os.path.exists(self.encryption_manager.get_key_file_path(dest_path)):
|
|
self.keyring_status_label.config(
|
|
text="Key: Available (Keyfile)",
|
|
fg="#FFD700" # Gold
|
|
)
|
|
else:
|
|
self.keyring_status_label.config(
|
|
text="Key: Not Available",
|
|
fg="#A9A9A9" # DarkGray
|
|
)
|