new script vor encryption manager and add combobox fo encrypt profiles part two
This commit is contained in:
@@ -158,6 +158,24 @@ do_resize() {
|
||||
log "Resize and remount complete."
|
||||
}
|
||||
|
||||
do_unmount_all() {
|
||||
log "Unmounting all provided pairs."
|
||||
for pair in "$@"; do
|
||||
# Split the pair 'mapper:mount_point'
|
||||
MAPPER_NAME="${pair%%:*}"
|
||||
MOUNT_POINT="${pair#*:}"
|
||||
log "Unmounting $MOUNT_POINT ($MAPPER_NAME)"
|
||||
if mountpoint -q "$MOUNT_POINT"; then
|
||||
chown root:root "$MOUNT_POINT"
|
||||
umount "$MOUNT_POINT"
|
||||
fi
|
||||
if [ -e "/dev/mapper/$MAPPER_NAME" ]; then
|
||||
cryptsetup luksClose "$MAPPER_NAME"
|
||||
fi
|
||||
done
|
||||
log "Bulk unmount complete."
|
||||
}
|
||||
|
||||
|
||||
# --- Main Command Dispatcher ---
|
||||
case "$COMMAND" in
|
||||
@@ -173,6 +191,9 @@ case "$COMMAND" in
|
||||
resize)
|
||||
do_resize "$@"
|
||||
;;
|
||||
unmount_all)
|
||||
do_unmount_all "$@"
|
||||
;;
|
||||
*)
|
||||
log "Unknown command: $COMMAND"
|
||||
exit 1
|
||||
|
@@ -310,14 +310,42 @@ class EncryptionManager:
|
||||
return success
|
||||
|
||||
def unmount_all(self) -> bool:
|
||||
self.logger.log(f"Unmounting all: {self.mounted_destinations}")
|
||||
all_unmounted_successfully = True
|
||||
# Create a copy of the set to avoid issues with modifying it while iterating
|
||||
if not self.mounted_destinations:
|
||||
return True
|
||||
|
||||
self.logger.log(f"Bulk unmounting: {self.mounted_destinations}")
|
||||
|
||||
pairs_to_unmount = []
|
||||
for base_path, profile_name in list(self.mounted_destinations):
|
||||
if not self.unmount_and_reset_owner(
|
||||
base_path, profile_name, force_unmap=True):
|
||||
all_unmounted_successfully = False
|
||||
return all_unmounted_successfully
|
||||
username = os.path.basename(base_path.rstrip('/'))
|
||||
mapper_name = f"pybackup_luks_{username}_{profile_name}"
|
||||
mount_point = self.get_mount_point(base_path, profile_name)
|
||||
pairs_to_unmount.append(f'{mapper_name}:{mount_point}')
|
||||
|
||||
helper_path = os.path.join(os.path.dirname(__file__), 'encryption_helper.sh')
|
||||
|
||||
# This command doesn't need a LUKS password, but pkexec might need the user's password.
|
||||
password = None
|
||||
|
||||
# Build the command string with quoted arguments
|
||||
script = f'"{helper_path}" unmount_all {" ".join(f"\"{pair}\"" for pair in pairs_to_unmount)}'
|
||||
|
||||
success = self._execute_as_root(script, password)
|
||||
|
||||
if success:
|
||||
# Clear all locks and destinations on success
|
||||
for base_path, profile_name in list(self.mounted_destinations):
|
||||
username = os.path.basename(base_path.rstrip('/'))
|
||||
mapper_name = f"pybackup_luks_{username}_{profile_name}"
|
||||
self.remove_from_lock_file(mapper_name)
|
||||
self.mounted_destinations.clear()
|
||||
self.logger.log("Successfully unmounted all profiles.")
|
||||
if self.app and hasattr(self.app, 'header_frame'):
|
||||
self.app.header_frame.refresh_status()
|
||||
else:
|
||||
self.logger.log("Failed to unmount all profiles.")
|
||||
|
||||
return success
|
||||
|
||||
def _get_chown_ids(self, is_system: bool) -> Tuple[Optional[int], Optional[int]]:
|
||||
if not is_system:
|
||||
|
@@ -15,21 +15,18 @@ class HeaderFrame(tk.Frame):
|
||||
|
||||
# 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)
|
||||
left_frame.grid(row=0, column=0, rowspan=2, sticky="ns")
|
||||
|
||||
icon_label = tk.Label(
|
||||
left_frame,
|
||||
image=self.image_manager.get_icon(
|
||||
"backup_extralarge"), # Using a generic backup icon
|
||||
"backup_extralarge"),
|
||||
bg="#455A64",
|
||||
)
|
||||
icon_label.grid(row=0, column=0, sticky="e", padx=10, pady=5)
|
||||
icon_label.pack(side=tk.LEFT, padx=10, pady=5)
|
||||
|
||||
title_label = tk.Label(
|
||||
self,
|
||||
@@ -48,58 +45,81 @@ class HeaderFrame(tk.Frame):
|
||||
fg="#bdc3c7",
|
||||
bg="#455A64",
|
||||
)
|
||||
subtitle_label.grid(row=1, column=1, sticky="w",
|
||||
subtitle_label.grid(row=1, column=1, sticky="nw",
|
||||
padx=(5, 20), pady=(0, 10))
|
||||
|
||||
# Right side: Keyring status
|
||||
# Right side: Status labels
|
||||
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)
|
||||
right_frame.grid(row=0, column=2, rowspan=2, sticky="nse", padx=10, pady=5)
|
||||
|
||||
self.keyring_status_label = tk.Label(
|
||||
self.key_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.key_status_label.pack(anchor="e")
|
||||
|
||||
self.mount_status_label = tk.Label(
|
||||
right_frame,
|
||||
text="",
|
||||
font=("Helvetica", 10, "bold"),
|
||||
bg="#455A64",
|
||||
)
|
||||
self.mount_status_label.pack(anchor="e")
|
||||
|
||||
self.refresh_status()
|
||||
|
||||
def refresh_status(self):
|
||||
"""Checks the mount status of all encrypted profiles and updates the label."""
|
||||
"""Checks key and mount status of all encrypted profiles and updates the labels."""
|
||||
app_logger.log("HeaderFrame: Refreshing status...")
|
||||
dest_path = self.app.destination_path
|
||||
if not dest_path or not os.path.isdir(dest_path):
|
||||
self.keyring_status_label.config(text="")
|
||||
self.key_status_label.config(text="")
|
||||
self.mount_status_label.config(text="")
|
||||
return
|
||||
|
||||
# Get all profile info without triggering a mount
|
||||
# --- Key Status Logic ---
|
||||
# This checks the key for the destination's root user, as a general indicator.
|
||||
username = os.path.basename(dest_path.rstrip('/'))
|
||||
key_in_keyring = self.encryption_manager.is_key_in_keyring(username)
|
||||
# A keyfile for a specific profile is not checked here, we check the general one.
|
||||
key_file_exists = os.path.exists(
|
||||
self.encryption_manager.get_key_file_path(dest_path, username))
|
||||
|
||||
key_status_text = ""
|
||||
if key_in_keyring:
|
||||
key_status_text = "Key: In Keyring"
|
||||
elif key_file_exists:
|
||||
key_status_text = "Key: File Available"
|
||||
else:
|
||||
key_status_text = "Key: Not Available"
|
||||
self.key_status_label.config(text=key_status_text, fg="#bdc3c7")
|
||||
|
||||
# --- Mount Status Logic ---
|
||||
backup_data = self.app.backup_manager.list_all_backups(dest_path)
|
||||
encrypted_profiles = backup_data.get("encrypted_profiles", {})
|
||||
|
||||
if not encrypted_profiles:
|
||||
self.keyring_status_label.config(text="")
|
||||
self.mount_status_label.config(text="")
|
||||
return
|
||||
|
||||
total_count = len(encrypted_profiles)
|
||||
mounted_count = sum(
|
||||
1 for profile in encrypted_profiles.values() if profile['is_mounted'])
|
||||
|
||||
status_text = f"Encrypted: {mounted_count}/{total_count} Mounted"
|
||||
mount_status_text = f"Mounted: {mounted_count}/{total_count}"
|
||||
|
||||
fg_color = ""
|
||||
if mounted_count == total_count:
|
||||
fg_color = "#6bbbff" # LightBlue (All Mounted)
|
||||
fg_color = "#6bbbff" # Bright Blue (All Mounted)
|
||||
elif mounted_count > 0:
|
||||
fg_color = "#eb7f11" # Orange (Partially Mounted)
|
||||
fg_color = "#FFA500" # Bright Orange (Partially Mounted)
|
||||
else:
|
||||
fg_color = "#E8740C" # A different Orange/Red for None Mounted
|
||||
fg_color = "#FF4500" # Bright OrangeRed (None Mounted)
|
||||
|
||||
self.keyring_status_label.config(
|
||||
text=status_text,
|
||||
self.mount_status_label.config(
|
||||
text=mount_status_text,
|
||||
fg=fg_color
|
||||
)
|
||||
app_logger.log("HeaderFrame: Status refresh complete.")
|
||||
app_logger.log("HeaderFrame: Status refresh complete.")
|
Reference in New Issue
Block a user