ops-jrz1/scripts/dev-remove.sh
Dan bc81b4ec15 Rename learner to dev across codebase
- scripts/learner-*.sh → scripts/dev-*.sh
- docs/learner-*.md → docs/dev-*.md
- tests/test-learner-env.sh → tests/test-dev-env.sh
- Update all internal references

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 10:42:34 -08:00

196 lines
4.6 KiB
Bash
Executable file

#!/usr/bin/env bash
# dev-remove.sh - Remove a dev account
# Usage: dev-remove.sh <username> [--archive]
#
# Removes:
# - Unix user account
# - Home directory (or archives if --archive flag)
# - Maubot plugin symlinks
set -euo pipefail
MAUBOT_PLUGINS_DIR="/var/lib/maubot/plugins"
ARCHIVE_DIR="/var/backups/devs"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1" >&2; }
usage() {
echo "Usage: $0 <username> [--archive]"
echo ""
echo "Arguments:"
echo " username - Dev's username to remove"
echo " --archive - Archive home directory instead of deleting"
echo ""
echo "Example:"
echo " $0 alice # Delete user and home directory"
echo " $0 alice --archive # Archive home directory before deleting"
exit 1
}
validate_username() {
local username="$1"
# Check if user exists
if ! id "$username" &>/dev/null; then
log_error "User '$username' does not exist"
exit 1
fi
# Safety check - don't delete system users
local uid
uid=$(id -u "$username")
if [[ $uid -lt 1000 ]]; then
log_error "Refusing to delete system user '$username' (UID $uid < 1000)"
exit 1
fi
# Safety check - don't delete important users
case "$username" in
root|dan|admin|maubot|postgres|nginx)
log_error "Refusing to delete protected user '$username'"
exit 1
;;
esac
}
remove_maubot_symlinks() {
local username="$1"
log_info "Removing maubot plugin symlinks for '$username'..."
# Remove any symlinks that point to user's home directory
local count=0
for symlink in "$MAUBOT_PLUGINS_DIR"/*; do
if [[ -L "$symlink" ]]; then
local target
target=$(readlink "$symlink")
if [[ "$target" == "/home/$username/"* ]]; then
rm "$symlink"
log_info "Removed symlink: $symlink"
((count++)) || true
fi
fi
done
# Also remove any plugins named after user
for symlink in "$MAUBOT_PLUGINS_DIR/${username}-"*; do
if [[ -e "$symlink" || -L "$symlink" ]]; then
rm -f "$symlink"
log_info "Removed: $symlink"
((count++)) || true
fi
done
if [[ $count -eq 0 ]]; then
log_info "No maubot symlinks found for '$username'"
fi
}
archive_home() {
local username="$1"
local home_dir="/home/$username"
if [[ ! -d "$home_dir" ]]; then
log_warn "Home directory does not exist: $home_dir"
return
fi
log_info "Archiving home directory..."
mkdir -p "$ARCHIVE_DIR"
local archive_name
archive_name="${username}_$(date +%Y%m%d_%H%M%S).tar.gz"
local archive_path="$ARCHIVE_DIR/$archive_name"
tar -czf "$archive_path" -C /home "$username"
chmod 600 "$archive_path"
log_info "Archived to: $archive_path"
}
remove_user() {
local username="$1"
log_info "Removing user '$username'..."
# Kill any running processes
pkill -u "$username" 2>/dev/null || true
sleep 1
# Remove user and home directory
userdel -r "$username" 2>/dev/null || {
# If userdel -r fails, try without -r and manually remove home
userdel "$username" 2>/dev/null || true
rm -rf "/home/${username:?}"
}
log_info "User removed"
}
main() {
if [[ $# -lt 1 ]]; then
usage
fi
local username="$1"
local archive=false
# Parse flags
shift
while [[ $# -gt 0 ]]; do
case "$1" in
--archive)
archive=true
shift
;;
*)
log_error "Unknown option: $1"
usage
;;
esac
done
# Must run as root
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root"
exit 1
fi
validate_username "$username"
# Confirm deletion
echo ""
log_warn "This will remove user '$username' and all their data!"
if [[ "$archive" == true ]]; then
echo "Home directory will be archived to $ARCHIVE_DIR"
else
echo "Home directory will be PERMANENTLY DELETED"
fi
echo ""
read -rp "Are you sure? (yes/no): " confirm
if [[ "$confirm" != "yes" ]]; then
log_info "Aborted"
exit 0
fi
remove_maubot_symlinks "$username"
if [[ "$archive" == true ]]; then
archive_home "$username"
fi
remove_user "$username"
log_info "Dev '$username' removed successfully"
}
main "$@"