1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-04 15:04:42 +00:00

Support one-click activation of touchid

This commit is contained in:
Tw93
2025-10-11 22:43:50 +08:00
parent 55f6bd352f
commit 7e42516260
3 changed files with 280 additions and 66 deletions

View File

@@ -51,6 +51,7 @@ mo clean --dry-run # Preview mode
mo clean --whitelist # Manage protected caches mo clean --whitelist # Manage protected caches
mo uninstall # Uninstall apps mo uninstall # Uninstall apps
mo analyze # Disk analyzer mo analyze # Disk analyzer
mo touchid # Configure Touch ID for sudo
mo update # Update Mole mo update # Update Mole
mo remove # Remove Mole from system mo remove # Remove Mole from system
mo --help # Show help mo --help # Show help
@@ -148,16 +149,7 @@ Total: 156.8GB
- **Can I protect specific caches?** Yes. Run `mo clean --whitelist` to select caches to protect. - **Can I protect specific caches?** Yes. Run `mo clean --whitelist` to select caches to protect.
- **Touch ID support?** Mole uses `sudo` for privileges, so you'll get a password prompt unless you've configured Touch ID for sudo. - **Touch ID support?** Yes. Run `mo touchid` to enable Touch ID for sudo and avoid repeated password prompts. This is optional but recommended for better experience.
```bash
sudo nano /etc/pam.d/sudo
# Add this line below the comments at the top:
auth sufficient pam_tid.so
# Save: Ctrl+O, then exit: Ctrl+X
```
## Support ## Support

238
bin/touchid.sh Executable file
View File

@@ -0,0 +1,238 @@
#!/bin/bash
# Mole - Touch ID Configuration Helper
# Automatically configure Touch ID for sudo
set -euo pipefail
# Determine script location and source common functions
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LIB_DIR="$(cd "$SCRIPT_DIR/../lib" && pwd)"
# Source common functions
# shellcheck source=../lib/common.sh
source "$LIB_DIR/common.sh"
readonly PAM_SUDO_FILE="/etc/pam.d/sudo"
readonly PAM_TID_LINE="auth sufficient pam_tid.so"
# Check if Touch ID is already configured
is_touchid_configured() {
if [[ ! -f "$PAM_SUDO_FILE" ]]; then
return 1
fi
grep -q "pam_tid.so" "$PAM_SUDO_FILE" 2>/dev/null
}
# Check if system supports Touch ID
supports_touchid() {
# Check if bioutil exists and has Touch ID capability
if command -v bioutil &>/dev/null; then
bioutil -r 2>/dev/null | grep -q "Touch ID" && return 0
fi
# Fallback: check if running on Apple Silicon or modern Intel Mac
local arch
arch=$(uname -m)
if [[ "$arch" == "arm64" ]]; then
return 0
fi
# For Intel Macs, check if it's 2018 or later (approximation)
local model_year
model_year=$(system_profiler SPHardwareDataType 2>/dev/null | grep "Model Identifier" | grep -o "[0-9]\{4\}" | head -1)
if [[ -n "$model_year" ]] && [[ "$model_year" -ge 2018 ]]; then
return 0
fi
return 1
}
# Show current Touch ID status
show_status() {
if is_touchid_configured; then
echo -e "${GREEN}${ICON_SUCCESS}${NC} Touch ID is enabled for sudo"
else
echo -e "${YELLOW}${NC} Touch ID is not configured for sudo"
fi
}
# Enable Touch ID for sudo
enable_touchid() {
# First check if system supports Touch ID
if ! supports_touchid; then
log_warning "This Mac may not support Touch ID"
read -rp "Continue anyway? [y/N] " confirm
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
echo -e "${YELLOW}Cancelled${NC}"
return 1
fi
echo ""
fi
# Check if already configured
if is_touchid_configured; then
echo -e "${GREEN}${ICON_SUCCESS} Touch ID is already enabled${NC}"
return 0
fi
# Create backup and apply changes
if ! sudo cp "$PAM_SUDO_FILE" "${PAM_SUDO_FILE}.mole-backup" 2>/dev/null; then
log_error "Failed to create backup"
return 1
fi
# Create temp file with the modification
local temp_file
temp_file=$(mktemp)
# Insert pam_tid.so after the first comment block
awk '
BEGIN { inserted = 0 }
/^#/ { print; next }
!inserted && /^[^#]/ {
print "'"$PAM_TID_LINE"'"
inserted = 1
}
{ print }
' "$PAM_SUDO_FILE" > "$temp_file"
# Apply the changes
if sudo mv "$temp_file" "$PAM_SUDO_FILE" 2>/dev/null; then
echo -e "${GREEN}${ICON_SUCCESS} Touch ID enabled${NC} ${GRAY}- try: sudo ls${NC}"
echo ""
return 0
else
rm -f "$temp_file" 2>/dev/null || true
log_error "Failed to enable Touch ID"
return 1
fi
}
# Disable Touch ID for sudo
disable_touchid() {
if ! is_touchid_configured; then
echo -e "${YELLOW}Touch ID is not currently enabled${NC}"
return 0
fi
# Create backup and remove configuration
if ! sudo cp "$PAM_SUDO_FILE" "${PAM_SUDO_FILE}.mole-backup" 2>/dev/null; then
log_error "Failed to create backup"
return 1
fi
# Remove pam_tid.so line
local temp_file
temp_file=$(mktemp)
grep -v "pam_tid.so" "$PAM_SUDO_FILE" > "$temp_file"
if sudo mv "$temp_file" "$PAM_SUDO_FILE" 2>/dev/null; then
echo -e "${GREEN}${ICON_SUCCESS} Touch ID disabled${NC}"
echo ""
return 0
else
rm -f "$temp_file" 2>/dev/null || true
log_error "Failed to disable Touch ID"
return 1
fi
}
# Show help
show_help() {
cat << EOF
Usage: mo touchid [command]
Configure Touch ID for sudo to avoid repeated password prompts.
Commands:
enable Enable Touch ID for sudo
disable Disable Touch ID for sudo
status Show current Touch ID configuration
help Show this help message
Examples:
mo touchid # Show status and options
mo touchid enable # Enable Touch ID
mo touchid status # Check current status
Notes:
- Requires macOS with Touch ID sensor
- Changes are applied to /etc/pam.d/sudo
- Automatic backup is created before changes
- You can restore from backup at ${PAM_SUDO_FILE}.mole-backup
EOF
}
# Interactive menu
show_menu() {
echo ""
show_status
if is_touchid_configured; then
echo -ne "${PURPLE}${NC} Press ${GREEN}Enter${NC} to disable, ${GRAY}ESC${NC} to quit: "
IFS= read -r -s -n1 key || key=""
echo ""
case "$key" in
$'\e') # ESC
return 0
;;
""|$'\n'|$'\r') # Enter
printf "\r\033[K" # Clear the prompt line
disable_touchid
;;
*)
echo ""
log_error "Invalid key"
;;
esac
else
echo -ne "${PURPLE}${NC} Press ${GREEN}Enter${NC} to enable, ${GRAY}ESC${NC} to quit: "
IFS= read -r -s -n1 key || key=""
case "$key" in
$'\e') # ESC
return 0
;;
""|$'\n'|$'\r') # Enter
printf "\r\033[K" # Clear the prompt line
enable_touchid
;;
*)
echo ""
log_error "Invalid key"
;;
esac
fi
}
# Main
main() {
local command="${1:-}"
case "$command" in
enable)
enable_touchid
;;
disable)
disable_touchid
;;
status)
show_status
;;
help|--help|-h)
show_help
;;
"")
show_menu
;;
*)
log_error "Unknown command: $command"
echo ""
show_help
exit 1
;;
esac
}
main "$@"

96
mole
View File

@@ -22,7 +22,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/lib/common.sh" source "$SCRIPT_DIR/lib/common.sh"
# Version info # Version info
VERSION="1.7.5" VERSION="1.7.6"
MOLE_TAGLINE="can dig deep to clean your Mac." MOLE_TAGLINE="can dig deep to clean your Mac."
# Get latest version from remote repository # Get latest version from remote repository
@@ -122,7 +122,7 @@ EOF
} }
show_version() { show_version() {
printf 'Mole version %s\n' "$VERSION" printf '\nMole version %s\n\n' "$VERSION"
} }
show_help() { show_help() {
@@ -135,6 +135,7 @@ show_help() {
printf " %s%-28s%s %s\n" "$GREEN" "mo clean --whitelist" "$NC" "Manage protected caches" printf " %s%-28s%s %s\n" "$GREEN" "mo clean --whitelist" "$NC" "Manage protected caches"
printf " %s%-28s%s %s\n" "$GREEN" "mo uninstall" "$NC" "Remove applications completely" printf " %s%-28s%s %s\n" "$GREEN" "mo uninstall" "$NC" "Remove applications completely"
printf " %s%-28s%s %s\n" "$GREEN" "mo analyze" "$NC" "Interactive disk space explorer" printf " %s%-28s%s %s\n" "$GREEN" "mo analyze" "$NC" "Interactive disk space explorer"
printf " %s%-28s%s %s\n" "$GREEN" "mo touchid" "$NC" "Configure Touch ID for sudo"
printf " %s%-28s%s %s\n" "$GREEN" "mo update" "$NC" "Update Mole to the latest version" printf " %s%-28s%s %s\n" "$GREEN" "mo update" "$NC" "Update Mole to the latest version"
printf " %s%-28s%s %s\n" "$GREEN" "mo remove" "$NC" "Remove Mole from the system" printf " %s%-28s%s %s\n" "$GREEN" "mo remove" "$NC" "Remove Mole from the system"
printf " %s%-28s%s %s\n" "$GREEN" "mo --version" "$NC" "Show installed version" printf " %s%-28s%s %s\n" "$GREEN" "mo --version" "$NC" "Show installed version"
@@ -161,7 +162,9 @@ update_mole() {
fi fi
if [[ "$VERSION" == "$latest" ]]; then if [[ "$VERSION" == "$latest" ]]; then
echo -e "${GREEN}✓${NC} Mole is already up to date (${VERSION})" echo ""
echo -e "${GREEN}✓${NC} Already on latest version (${VERSION})"
echo ""
exit 0 exit 0
fi fi
@@ -249,11 +252,6 @@ update_mole() {
# Remove Mole from system # Remove Mole from system
remove_mole() { remove_mole() {
clear
echo ""
echo -e "${YELLOW}Remove Mole${NC}"
echo ""
# Detect all installations with loading # Detect all installations with loading
if [[ -t 1 ]]; then if [[ -t 1 ]]; then
start_inline_spinner "Detecting Mole installations..." start_inline_spinner "Detecting Mole installations..."
@@ -302,100 +300,84 @@ remove_mole() {
stop_inline_spinner stop_inline_spinner
fi fi
printf '\n'
# Check if anything to remove # Check if anything to remove
if [[ "$is_homebrew" == "false" && ${#manual_installs[@]:-0} -eq 0 && ${#alias_installs[@]:-0} -eq 0 ]]; then if [[ "$is_homebrew" == "false" && ${#manual_installs[@]:-0} -eq 0 && ${#alias_installs[@]:-0} -eq 0 ]]; then
echo "" printf '%s\n\n' "${YELLOW}No Mole installation detected${NC}"
echo -e "${YELLOW}No Mole installation detected${NC}"
exit 0 exit 0
fi fi
# Show what will be removed # Show what will be removed
echo "Will remove:" echo -e "${YELLOW}Remove Mole${NC} - will delete the following:"
echo ""
if [[ "$is_homebrew" == "true" ]]; then if [[ "$is_homebrew" == "true" ]]; then
echo " - Mole via Homebrew" echo " - Mole via Homebrew"
fi fi
for install in ${manual_installs[@]+"${manual_installs[@]}"} ${alias_installs[@]+"${alias_installs[@]}"}; do for install in ${manual_installs[@]+"${manual_installs[@]}"} ${alias_installs[@]+"${alias_installs[@]}"}; do
echo " - $install" echo " - $install"
done done
echo " - ~/.config/mole" echo " - ~/.config/mole"
echo " - ~/.cache/mole" echo " - ~/.cache/mole"
echo -ne "${PURPLE}☛${NC} Press ${GREEN}Enter${NC} to confirm, ${GRAY}ESC${NC} to cancel: "
echo ""
echo -n "Press Enter to confirm, ESC or q to cancel: "
# Read single key # Read single key
IFS= read -r -s -n1 key || key="" IFS= read -r -s -n1 key || key=""
echo ""
case "$key" in case "$key" in
$'\e'|q|Q) $'\e')
echo "Cancelled" echo -e "${GRAY}Cancelled${NC}"
echo ""
exit 0 exit 0
;; ;;
""|$'\n'|$'\r') ""|$'\n'|$'\r')
printf "\r\033[K" # Clear the prompt line
# Continue with removal # Continue with removal
;; ;;
*) *)
echo "Cancelled" echo -e "${GRAY}Cancelled${NC}"
echo ""
exit 0 exit 0
;; ;;
esac esac
echo "" # Remove Homebrew installation (silent)
local has_error=false
# Remove Homebrew installation
if [[ "$is_homebrew" == "true" ]]; then if [[ "$is_homebrew" == "true" ]]; then
if brew uninstall mole 2>&1 | grep -q "Uninstalling"; then if ! brew uninstall mole >/dev/null 2>&1; then
log_success "Uninstalled via Homebrew" has_error=true
else
log_error "Failed to uninstall via Homebrew"
echo "Try manually: brew uninstall mole"
fi fi
fi fi
# Remove manual installations (silent)
# Remove manual installations
if [[ ${#manual_installs[@]:-0} -gt 0 ]]; then if [[ ${#manual_installs[@]:-0} -gt 0 ]]; then
for install in "${manual_installs[@]}"; do for install in "${manual_installs[@]}"; do
if [[ -f "$install" ]]; then if [[ -f "$install" ]]; then
if rm -f "$install" 2>/dev/null; then rm -f "$install" 2>/dev/null || has_error=true
log_success "Removed: $install"
else
log_error "Failed to remove $install (try with sudo)"
fi
fi fi
done done
fi fi
if [[ ${#alias_installs[@]} -gt 0 ]]; then if [[ ${#alias_installs[@]} -gt 0 ]]; then
for alias in "${alias_installs[@]}"; do for alias in "${alias_installs[@]}"; do
if [[ -f "$alias" ]]; then if [[ -f "$alias" ]]; then
if rm -f "$alias" 2>/dev/null; then rm -f "$alias" 2>/dev/null || true
log_success "Removed alias: $alias"
else
log_warning "Could not remove alias $alias (may need sudo)"
fi
fi fi
done done
fi fi
# Clean up cache first (silent)
# Clean up cache first (logs to config)
if [[ -d "$HOME/.cache/mole" ]]; then if [[ -d "$HOME/.cache/mole" ]]; then
rm -rf "$HOME/.cache/mole" 2>/dev/null && log_success "Removed cache" rm -rf "$HOME/.cache/mole" 2>/dev/null || true
fi fi
# Clean up configuration last (silent)
# Clean up configuration last (contains logs)
if [[ -d "$HOME/.config/mole" ]]; then if [[ -d "$HOME/.config/mole" ]]; then
log_success "Removed configuration" rm -rf "$HOME/.config/mole" 2>/dev/null || true
rm -rf "$HOME/.config/mole" 2>/dev/null
fi fi
echo "" # Show final result
echo -e "${GREEN}Mole has been removed successfully${NC}" local final_message
echo "" if [[ "$has_error" == "true" ]]; then
echo "Thank you for using Mole!" final_message="${YELLOW}⚠ Mole uninstalled with some errors, thank you for using Mole!${NC}"
else
final_message="${GREEN}✓ Mole uninstalled successfully, thank you for using Mole!${NC}"
fi
printf '\n%s\n\n' "$final_message"
exit 0 exit 0
} }
@@ -443,6 +425,7 @@ show_main_menu() {
if [[ -t 0 ]]; then if [[ -t 0 ]]; then
printf '\r\033[2K\n' printf '\r\033[2K\n'
printf '\r\033[2K%s\n' " ${GRAY}↑/↓${NC} Navigate ${GRAY}|${NC} ${GRAY}Enter${NC} Select ${GRAY}|${NC} ${GRAY}Q/ESC${NC} Quit" printf '\r\033[2K%s\n' " ${GRAY}↑/↓${NC} Navigate ${GRAY}|${NC} ${GRAY}Enter${NC} Select ${GRAY}|${NC} ${GRAY}Q/ESC${NC} Quit"
printf '\r\033[2K\n'
fi fi
# Clear any remaining content below without full screen wipe # Clear any remaining content below without full screen wipe
@@ -478,8 +461,6 @@ interactive_main_menu() {
cleanup_and_exit() { cleanup_and_exit() {
show_cursor show_cursor
echo ""
echo "Thank you for using Mole!"
exit 0 exit 0
} }
@@ -541,6 +522,9 @@ main() {
"analyze") "analyze")
exec "$SCRIPT_DIR/bin/analyze.sh" "${@:2}" exec "$SCRIPT_DIR/bin/analyze.sh" "${@:2}"
;; ;;
"touchid")
exec "$SCRIPT_DIR/bin/touchid.sh" "${@:2}"
;;
"update") "update")
update_mole update_mole
exit 0 exit 0