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

Optimize supports setting whitelist

This commit is contained in:
Tw93
2025-12-08 16:51:25 +08:00
parent a1609e633e
commit 51decd1091
4 changed files with 157 additions and 45 deletions

View File

@@ -14,13 +14,13 @@ source "$SCRIPT_DIR/lib/check/health_json.sh"
# Load check modules # Load check modules
source "$SCRIPT_DIR/lib/check/all.sh" source "$SCRIPT_DIR/lib/check/all.sh"
source "$SCRIPT_DIR/lib/manage/whitelist.sh"
# Colors and icons from common.sh # Colors and icons from common.sh
print_header() { print_header() {
printf '\n' printf '\n'
echo -e "${PURPLE_BOLD}Optimize and Check${NC}" echo -e "${PURPLE_BOLD}Optimize and Check${NC}"
echo ""
} }
# System check functions (real-time display) # System check functions (real-time display)
@@ -123,7 +123,6 @@ show_system_health() {
# Compact one-line format with icon # Compact one-line format with icon
printf "${ICON_ADMIN} System %.0f/%.0f GB RAM | %.0f/%.0f GB Disk | Uptime %.0fd\n" \ printf "${ICON_ADMIN} System %.0f/%.0f GB RAM | %.0f/%.0f GB Disk | Uptime %.0fd\n" \
"$mem_used" "$mem_total" "$disk_used" "$disk_total" "$uptime" "$mem_used" "$mem_total" "$disk_used" "$disk_total" "$uptime"
echo ""
} }
parse_optimizations() { parse_optimizations() {
@@ -233,10 +232,14 @@ declare -a SECURITY_FIXES=()
collect_security_fix_actions() { collect_security_fix_actions() {
SECURITY_FIXES=() SECURITY_FIXES=()
if [[ "${FIREWALL_DISABLED:-}" == "true" ]]; then if [[ "${FIREWALL_DISABLED:-}" == "true" ]]; then
SECURITY_FIXES+=("firewall|Enable macOS firewall") if ! is_whitelisted "firewall"; then
SECURITY_FIXES+=("firewall|Enable macOS firewall")
fi
fi fi
if [[ "${GATEKEEPER_DISABLED:-}" == "true" ]]; then if [[ "${GATEKEEPER_DISABLED:-}" == "true" ]]; then
SECURITY_FIXES+=("gatekeeper|Enable Gatekeeper (App download protection)") if ! is_whitelisted "gatekeeper"; then
SECURITY_FIXES+=("gatekeeper|Enable Gatekeeper (App download protection)")
fi
fi fi
((${#SECURITY_FIXES[@]} > 0)) ((${#SECURITY_FIXES[@]} > 0))
@@ -325,12 +328,17 @@ cleanup_all() {
} }
main() { main() {
local health_json # Declare health_json at the top of main scope
# Parse args # Parse args
for arg in "$@"; do for arg in "$@"; do
case "$arg" in case "$arg" in
"--debug") "--debug")
export MO_DEBUG=1 export MO_DEBUG=1
;; ;;
"--whitelist")
manage_whitelist "optimize"
exit 0
;;
esac esac
done done
@@ -340,8 +348,8 @@ main() {
if [[ -t 1 ]]; then if [[ -t 1 ]]; then
clear clear
fi fi
print_header print_header # Outputs "Optimize and Check"
# Check dependencies # Check dependencies
if ! command -v jq > /dev/null 2>&1; then if ! command -v jq > /dev/null 2>&1; then
echo -e "${RED}${ICON_ERROR}${NC} Missing dependency: jq" echo -e "${RED}${ICON_ERROR}${NC} Missing dependency: jq"
@@ -355,28 +363,11 @@ main() {
exit 1 exit 1
fi fi
# Simple confirmation # Collect system health data (doesn't require sudo)
echo -ne "${PURPLE}${ICON_ARROW}${NC} Optimization needs sudo — ${GREEN}Enter${NC} continue, ${GRAY}ESC${NC} cancel: "
local key
if ! key=$(read_key); then
echo -e " ${GRAY}Cancelled${NC}"
exit 0
fi
if [[ "$key" == "ENTER" ]]; then
printf "\r\033[K"
else
echo -e " ${GRAY}Cancelled${NC}"
exit 0
fi
# Collect system health data after confirmation
if [[ -t 1 ]]; then if [[ -t 1 ]]; then
start_inline_spinner "Collecting system info..." start_inline_spinner "Collecting system info..."
fi fi
local health_json
if ! health_json=$(generate_health_json 2> /dev/null); then if ! health_json=$(generate_health_json 2> /dev/null); then
if [[ -t 1 ]]; then if [[ -t 1 ]]; then
stop_inline_spinner stop_inline_spinner
@@ -402,7 +393,40 @@ main() {
fi fi
# Show system health # Show system health
show_system_health "$health_json" show_system_health "$health_json" # Outputs "⚙ System ..."
# Load whitelist patterns for checks
load_whitelist "optimize"
# Display active whitelist patterns
if [[ ${#CURRENT_WHITELIST_PATTERNS[@]} -gt 0 ]]; then
local patterns_list=$(
local IFS=', '
echo "${CURRENT_WHITELIST_PATTERNS[*]}"
)
echo -e "${ICON_ADMIN} Active Whitelist: ${patterns_list}"
fi
echo "" # Empty line before sudo prompt
# Simple confirmation
echo -ne "${PURPLE}${ICON_ARROW}${NC} Optimization needs sudo — ${GREEN}Enter${NC} continue, ${GRAY}ESC${NC} cancel: "
local key
if ! key=$(read_key); then
echo -e " ${GRAY}Cancelled${NC}"
exit 0
fi
if [[ "$key" == "ENTER" ]]; then
printf "\r\033[K"
else
echo -e " ${GRAY}Cancelled${NC}"
exit 0
fi
if [[ -t 1 ]]; then
stop_inline_spinner
fi
# Parse and display optimizations # Parse and display optimizations
local -a safe_items=() local -a safe_items=()

View File

@@ -30,6 +30,8 @@ list_login_items() {
# ============================================================================ # ============================================================================
check_touchid_sudo() { check_touchid_sudo() {
# Check whitelist
if command -v is_whitelisted >/dev/null && is_whitelisted "check_touchid"; then return; fi
# Check if Touch ID is configured for sudo # Check if Touch ID is configured for sudo
local pam_file="/etc/pam.d/sudo" local pam_file="/etc/pam.d/sudo"
if [[ -f "$pam_file" ]] && grep -q "pam_tid.so" "$pam_file" 2> /dev/null; then if [[ -f "$pam_file" ]] && grep -q "pam_tid.so" "$pam_file" 2> /dev/null; then
@@ -53,6 +55,8 @@ check_touchid_sudo() {
} }
check_rosetta() { check_rosetta() {
# Check whitelist
if command -v is_whitelisted >/dev/null && is_whitelisted "check_rosetta"; then return; fi
# Check Rosetta 2 (for Apple Silicon Macs) # Check Rosetta 2 (for Apple Silicon Macs)
if [[ "$(uname -m)" == "arm64" ]]; then if [[ "$(uname -m)" == "arm64" ]]; then
if [[ -f "/Library/Apple/usr/share/rosetta/rosetta" ]]; then if [[ -f "/Library/Apple/usr/share/rosetta/rosetta" ]]; then
@@ -65,6 +69,8 @@ check_rosetta() {
} }
check_git_config() { check_git_config() {
# Check whitelist
if command -v is_whitelisted >/dev/null && is_whitelisted "check_git_config"; then return; fi
# Check basic Git configuration # Check basic Git configuration
if command -v git > /dev/null 2>&1; then if command -v git > /dev/null 2>&1; then
local git_name=$(git config --global user.name 2> /dev/null || echo "") local git_name=$(git config --global user.name 2> /dev/null || echo "")
@@ -89,6 +95,8 @@ check_all_config() {
# ============================================================================ # ============================================================================
check_filevault() { check_filevault() {
# Check whitelist
if command -v is_whitelisted >/dev/null && is_whitelisted "check_filevault"; then return; fi
# Check FileVault encryption status # Check FileVault encryption status
if command -v fdesetup > /dev/null 2>&1; then if command -v fdesetup > /dev/null 2>&1; then
local fv_status=$(fdesetup status 2> /dev/null || echo "") local fv_status=$(fdesetup status 2> /dev/null || echo "")
@@ -102,6 +110,8 @@ check_filevault() {
} }
check_firewall() { check_firewall() {
# Check whitelist
if command -v is_whitelisted >/dev/null && is_whitelisted "firewall"; then return; fi
# Check firewall status # Check firewall status
unset FIREWALL_DISABLED unset FIREWALL_DISABLED
local firewall_status=$(defaults read /Library/Preferences/com.apple.alf globalstate 2> /dev/null || echo "0") local firewall_status=$(defaults read /Library/Preferences/com.apple.alf globalstate 2> /dev/null || echo "0")
@@ -116,6 +126,8 @@ check_firewall() {
} }
check_gatekeeper() { check_gatekeeper() {
# Check whitelist
if command -v is_whitelisted >/dev/null && is_whitelisted "gatekeeper"; then return; fi
# Check Gatekeeper status # Check Gatekeeper status
if command -v spctl > /dev/null 2>&1; then if command -v spctl > /dev/null 2>&1; then
local gk_status=$(spctl --status 2> /dev/null || echo "") local gk_status=$(spctl --status 2> /dev/null || echo "")
@@ -132,6 +144,8 @@ check_gatekeeper() {
} }
check_sip() { check_sip() {
# Check whitelist
if command -v is_whitelisted >/dev/null && is_whitelisted "check_sip"; then return; fi
# Check System Integrity Protection # Check System Integrity Protection
if command -v csrutil > /dev/null 2>&1; then if command -v csrutil > /dev/null 2>&1; then
local sip_status=$(csrutil status 2> /dev/null || echo "") local sip_status=$(csrutil status 2> /dev/null || echo "")
@@ -194,6 +208,8 @@ is_cache_valid() {
} }
check_homebrew_updates() { check_homebrew_updates() {
# Check whitelist
if command -v is_whitelisted >/dev/null && is_whitelisted "check_brew_updates"; then return; fi
if ! command -v brew > /dev/null 2>&1; then if ! command -v brew > /dev/null 2>&1; then
return return
fi fi
@@ -320,6 +336,8 @@ check_appstore_updates() {
} }
check_macos_update() { check_macos_update() {
# Check whitelist
if command -v is_whitelisted >/dev/null && is_whitelisted "check_macos_updates"; then return; fi
local spinner_started=false local spinner_started=false
if [[ -t 1 ]]; then if [[ -t 1 ]]; then
printf " Checking macOS updates...\r" printf " Checking macOS updates...\r"
@@ -523,6 +541,8 @@ check_memory_usage() {
} }
check_login_items() { check_login_items() {
# Check whitelist
if command -v is_whitelisted >/dev/null && is_whitelisted "check_login_items"; then return; fi
local login_items_count=0 local login_items_count=0
local -a login_items_list=() local -a login_items_list=()
@@ -640,6 +660,8 @@ check_swap_usage() {
} }
check_brew_health() { check_brew_health() {
# Check whitelist
if command -v is_whitelisted >/dev/null && is_whitelisted "check_brew_health"; then return; fi
# Check Homebrew doctor # Check Homebrew doctor
if command -v brew > /dev/null 2>&1; then if command -v brew > /dev/null 2>&1; then
# Show spinner while running brew doctor # Show spinner while running brew doctor

View File

@@ -68,6 +68,13 @@ declare -a DEFAULT_WHITELIST_PATTERNS=(
"$FINDER_METADATA_SENTINEL" "$FINDER_METADATA_SENTINEL"
) )
declare -a DEFAULT_OPTIMIZE_WHITELIST_PATTERNS=(
"check_brew_updates"
"check_brew_health"
"check_touchid"
"check_git_config"
)
# ============================================================================ # ============================================================================
# BSD Stat Compatibility # BSD Stat Compatibility
# ============================================================================ # ============================================================================

View File

@@ -9,8 +9,9 @@ _MOLE_MANAGE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$_MOLE_MANAGE_DIR/../core/common.sh" source "$_MOLE_MANAGE_DIR/../core/common.sh"
source "$_MOLE_MANAGE_DIR/../ui/menu_simple.sh" source "$_MOLE_MANAGE_DIR/../ui/menu_simple.sh"
# Config file path # Config file paths
WHITELIST_CONFIG="$HOME/.config/mole/whitelist" readonly WHITELIST_CONFIG_CLEAN="$HOME/.config/mole/whitelist"
readonly WHITELIST_CONFIG_OPTIMIZE="$HOME/.config/mole/whitelist_checks"
# Default whitelist patterns defined in lib/core/common.sh: # Default whitelist patterns defined in lib/core/common.sh:
# - DEFAULT_WHITELIST_PATTERNS # - DEFAULT_WHITELIST_PATTERNS
@@ -18,15 +19,25 @@ WHITELIST_CONFIG="$HOME/.config/mole/whitelist"
# Save whitelist patterns to config # Save whitelist patterns to config
save_whitelist_patterns() { save_whitelist_patterns() {
local mode="$1"
shift
local -a patterns local -a patterns
patterns=("$@") patterns=("$@")
mkdir -p "$(dirname "$WHITELIST_CONFIG")"
local config_file
local header_text
cat > "$WHITELIST_CONFIG" << 'EOF' if [[ "$mode" == "optimize" ]]; then
# Mole Whitelist - Protected paths won't be deleted config_file="$WHITELIST_CONFIG_OPTIMIZE"
# Default protections: Playwright browsers, HuggingFace models, Maven repo, Ollama models, Surge Mac, R renv, Finder metadata header_text="# Mole Optimization Whitelist - These checks will be skipped during optimization"
# Add one pattern per line to keep items safe. else
EOF config_file="$WHITELIST_CONFIG_CLEAN"
header_text="# Mole Whitelist - Protected paths won't be deleted\n# Default protections: Playwright browsers, HuggingFace models, Maven repo, Ollama models, Surge Mac, R renv, Finder metadata\n# Add one pattern per line to keep items safe."
fi
mkdir -p "$(dirname "$config_file")"
echo -e "$header_text" > "$config_file"
if [[ ${#patterns[@]} -gt 0 ]]; then if [[ ${#patterns[@]} -gt 0 ]]; then
local -a unique_patterns=() local -a unique_patterns=()
@@ -45,9 +56,9 @@ EOF
done done
if [[ ${#unique_patterns[@]} -gt 0 ]]; then if [[ ${#unique_patterns[@]} -gt 0 ]]; then
printf '\n' >> "$WHITELIST_CONFIG" printf '\n' >> "$config_file"
for pattern in "${unique_patterns[@]}"; do for pattern in "${unique_patterns[@]}"; do
echo "$pattern" >> "$WHITELIST_CONFIG" echo "$pattern" >> "$config_file"
done done
fi fi
fi fi
@@ -128,6 +139,24 @@ EOF
echo "Finder metadata (.DS_Store)|$FINDER_METADATA_SENTINEL|system_cache" echo "Finder metadata (.DS_Store)|$FINDER_METADATA_SENTINEL|system_cache"
} }
# Get all optimize items with their patterns
get_optimize_whitelist_items() {
# Format: "display_name|pattern|category"
cat << 'EOF'
macOS Firewall check|firewall|security_check
Gatekeeper check|gatekeeper|security_check
Homebrew updates check|check_brew_updates|update_check
macOS system updates check|check_macos_updates|update_check
Homebrew health check (doctor)|check_brew_health|health_check
SIP status check|check_sip|security_check
FileVault status check|check_filevault|security_check
TouchID sudo check|check_touchid|config_check
Rosetta 2 check|check_rosetta|config_check
Git configuration check|check_git_config|config_check
Login items check|check_login_items|config_check
EOF
}
patterns_equivalent() { patterns_equivalent() {
local first="${1/#~/$HOME}" local first="${1/#~/$HOME}"
local second="${2/#~/$HOME}" local second="${2/#~/$HOME}"
@@ -138,9 +167,17 @@ patterns_equivalent() {
} }
load_whitelist() { load_whitelist() {
local mode="${1:-clean}"
local -a patterns=() local -a patterns=()
local config_file
if [[ -f "$WHITELIST_CONFIG" ]]; then if [[ "$mode" == "optimize" ]]; then
config_file="$WHITELIST_CONFIG_OPTIMIZE"
else
config_file="$WHITELIST_CONFIG_CLEAN"
fi
if [[ -f "$config_file" ]]; then
while IFS= read -r line; do while IFS= read -r line; do
# shellcheck disable=SC2295 # shellcheck disable=SC2295
line="${line#"${line%%[![:space:]]*}"}" line="${line#"${line%%[![:space:]]*}"}"
@@ -148,9 +185,13 @@ load_whitelist() {
line="${line%"${line##*[![:space:]]}"}" line="${line%"${line##*[![:space:]]}"}"
[[ -z "$line" || "$line" =~ ^# ]] && continue [[ -z "$line" || "$line" =~ ^# ]] && continue
patterns+=("$line") patterns+=("$line")
done < "$WHITELIST_CONFIG" done < "$config_file"
else else
patterns=("${DEFAULT_WHITELIST_PATTERNS[@]}") if [[ "$mode" == "clean" ]]; then
patterns=("${DEFAULT_WHITELIST_PATTERNS[@]}")
elif [[ "$mode" == "optimize" ]]; then
patterns=("${DEFAULT_OPTIMIZE_WHITELIST_PATTERNS[@]}")
fi
fi fi
if [[ ${#patterns[@]} -gt 0 ]]; then if [[ ${#patterns[@]} -gt 0 ]]; then
@@ -193,12 +234,15 @@ is_whitelisted() {
} }
manage_whitelist() { manage_whitelist() {
manage_whitelist_categories local mode="${1:-clean}"
manage_whitelist_categories "$mode"
} }
manage_whitelist_categories() { manage_whitelist_categories() {
local mode="$1"
# Load currently enabled patterns from both sources # Load currently enabled patterns from both sources
load_whitelist load_whitelist "$mode"
# Build cache items list # Build cache items list
local -a cache_items=() local -a cache_items=()
@@ -206,6 +250,21 @@ manage_whitelist_categories() {
local -a menu_options=() local -a menu_options=()
local index=0 local index=0
# Choose source based on mode
local items_source
local menu_title
local active_config_file
if [[ "$mode" == "optimize" ]]; then
items_source=$(get_optimize_whitelist_items)
menu_title="Whitelist Manager Select system checks to ignore"
active_config_file="$WHITELIST_CONFIG_OPTIMIZE"
else
items_source=$(get_all_cache_items)
menu_title="Whitelist Manager Select caches to protect"
active_config_file="$WHITELIST_CONFIG_CLEAN"
fi
while IFS='|' read -r display_name pattern _; do while IFS='|' read -r display_name pattern _; do
# Expand $HOME in pattern # Expand $HOME in pattern
pattern="${pattern/\$HOME/$HOME}" pattern="${pattern/\$HOME/$HOME}"
@@ -215,7 +274,7 @@ manage_whitelist_categories() {
menu_options+=("$display_name") menu_options+=("$display_name")
((index++)) || true ((index++)) || true
done < <(get_all_cache_items) done <<< "$items_source"
# Identify custom patterns (not in predefined list) # Identify custom patterns (not in predefined list)
local -a custom_patterns=() local -a custom_patterns=()
@@ -280,7 +339,7 @@ manage_whitelist_categories() {
fi fi
MOLE_SELECTION_RESULT="" MOLE_SELECTION_RESULT=""
paginated_multi_select "Whitelist Manager Select caches to protect" "${menu_options[@]}" paginated_multi_select "$menu_title" "${menu_options[@]}"
unset MOLE_PRESELECTED_INDICES unset MOLE_PRESELECTED_INDICES
local exit_code=$? local exit_code=$?
@@ -318,9 +377,9 @@ manage_whitelist_categories() {
# Save to whitelist config (bash 3.2 + set -u safe) # Save to whitelist config (bash 3.2 + set -u safe)
if [[ ${#all_patterns[@]} -gt 0 ]]; then if [[ ${#all_patterns[@]} -gt 0 ]]; then
save_whitelist_patterns "${all_patterns[@]}" save_whitelist_patterns "$mode" "${all_patterns[@]}"
else else
save_whitelist_patterns save_whitelist_patterns "$mode"
fi fi
local total_protected=$((${#selected_patterns[@]} + ${#custom_patterns[@]})) local total_protected=$((${#selected_patterns[@]} + ${#custom_patterns[@]}))
@@ -331,7 +390,7 @@ manage_whitelist_categories() {
else else
summary_lines+=("Protected ${total_protected} cache(s)") summary_lines+=("Protected ${total_protected} cache(s)")
fi fi
summary_lines+=("Saved to ${WHITELIST_CONFIG}") summary_lines+=("Saved to ${active_config_file}")
print_summary_block "${summary_lines[@]}" print_summary_block "${summary_lines[@]}"
printf '\n' printf '\n'