#!/bin/bash

##################################################################################################################
##################################################################################################################
##													    	##
## ESTE SCRIPT ESTÁ DISEÑADO Y PROBADO CON BASH POR LO QUE PUEDE NO LLEGAR A FUNCIONAR BIEN CON OTRAS SHELLS	##
##														##
## Se ejecutará con correcto funcionamiento con el comando:							##
## $ bash "nombre_script.sh"											##
##														##
##################################################################################################################
##################################################################################################################

# Puede que algunos comandos/partes del scripts no funcionen bien en todas las shells,
# comprueba la compatibilidad con la tuya si fuera necesario.

# Versión del script: 1.0v

# Este script ayudará y facilitará la gestión de usuarios en entornos Linux
# apoyate en este script/menú para añadir, eliminar y modificar usuarios.
#
# Para ejecutar ciertas tareas es posible que se pida la contraseña de sudo.
#
# Sientete libre de modificarlo a tu gusto.


# --- Funciones ---


# Función de crear un usuario, en caso de error de cualquier tipo (como usuario ya existente)
# se repite esa parte de la función para asegurar una creación correcta.
create_user() {
	# Pide nombre de usuario y verifica si ya existe o no.
	while true; do
		clear
		echo
		printf "\e[1;36m--- Crear un usuario ---\e[0m\n\n"
		printf "\e[32mPaso 1 de 4\e[0m\n"
		echo
		read -p "Ingrese el nombre de usuario a crear: " user

		# Verifica si el usuario ya existe.
		if id "$user" >/dev/null 2>&1; then
			printf "\e[1;31mEl usuario '$user' ya existe. Intente con otro nombre.\e[0m\n"
			echo
			echo "Pulse INTRO para continuar."
			read INTRO
		else
			break
		fi
	 done

	# Pide contraseña y confirmación oculta.
	while true; do
		clear
		echo
		printf "\e[1;36m--- Crear un usuario ---\e[0m\n\n"
		printf "\e[32mPaso 2 de 4\e[0m\n"
		echo
		read -s -p "Ingrese la contraseña: " pass1
		echo
		read -s -p "Repita la contraseña: " pass2
		echo
		if [[ "$pass1" == "$pass2" ]]; then
			break
		else
			printf "\e[1;31mLas contraseñas no coinciden. Intente de nuevo.\e[0m\n"
			echo
			echo "Pulse INTRO para continuar."
			read INTRO
		fi
	done

	# Pregunta si quiere que el usuario tenga directorio en home.
	while true; do
		clear
		echo
		printf "\e[1;36m--- Crear un usuario ---\e[0m\n\n"
		printf "\e[32mPaso 3 de 4\e[0m\n"
		echo
		read -n 1 -p "¿Desea que el usuario tenga un directorio en /home?? (y/n): " home_dir
		echo
		case "$home_dir" in
			y)
				create_home="-m"
				break
				;;
			n)
				create_home=""
				break
				;;
			*)
				printf "\e[1;31mRespuesta inválida. Ingrese 'y' o 'n'.\e[0m\n"
				echo
				echo "Pulse INTRO para continuar."
				read INTRO
				;;
		esac
	done

	# Crear el usuario con o sin directorio home
	sudo useradd $create_home "$user"
	echo "$user:$pass1" | sudo chpasswd

	# Preguntar si desea permisos sudo
	while true; do
		clear
		echo
		printf "\e[1;36m--- Crear un usuario ---\e[0m\n\n"
		printf "\e[32mPaso 4 de 4\e[0m\n"
		echo
		read -n 1 -p "¿Desea que el usuario tenga permisos sudo? (y/n): " ans
		echo
		case "$ans" in
			y)
				sudo usermod -aG sudo "$user"
				echo "Se le asignaron permisos sudo a $user."
				break
				;;
			n)
				echo "No se le asignaron permisos sudo."
				break
				;;
			*)
				printf "\e[1;31mRespuesta inválida. Ingrese 'y' o 'n'.\e[0m\n"
				echo
				echo "Pulse INTRO para continuar."
				read INTRO
				;;
		esac
	done

	clear
	echo
	printf "\e[1;36m--- Crear un usuario ---\e[0m\n\n"
	echo "El usuario $user se ha creado correctamente."
	echo
	echo "Pulse INTRO para continuar."
	read INTRO
}


# Función de eliminar usuario.
# Tiene en cuenta factores como si existe el usuario, si el usuario es esencial o no (como root),
# confirmación, si va a ser eliminación recursiva, etc...
delete_user() {
	# Pide el nombre de usuario y verifica si existe y que no sea root ni el usuario actual.
	while true; do
		clear
		echo
		printf "\e[1;36m--- Eliminar un usuario ---\e[0m\n\n"
		printf "\e[32mPaso 1 de 4\e[0m\n"
		echo
		read -p "Ingrese el nombre del usuario a eliminar: " user

		# Verifica si el usuario existe
		if ! id "$user" >/dev/null 2>&1; then
			printf "\e[1;31mEl usuario '%s' no existe. Intente con otro nombre.\e[0m\n" "$user"
			echo
			echo "Pulse INTRO para continuar."
			read INTRO
			continue
		fi

		# Comprueba que no sea el usuario actual ni el root
		current_user=$(whoami)
		if [[ "$user" == "root" || "$user" == "$current_user" ]]; then
			printf "\e[1;31mNo se puede eliminar al usuario '%s' porque es un usuario esencial del sistema actualmente.\e[0m\n" "$user"
			echo
			echo "Pulse INTRO para continuar."
			read INTRO
			continue
		fi
		break
	done

	# Comprueba procesos activos (por si el usuario que se quiere eliminar tiene alguno activo) y pide confirmación
	while true; do
		clear
		echo
		printf "\e[1;36m--- Eliminar un usuario ---\e[0m\n\n"
		printf "\e[32mPaso 2 de 4\e[0m\n"
		echo
		pids=$(pgrep - u "$user")
		if [[ -n "$pids" ]]; then
			printf "\e[1;33mAdvertencia: El usuario '%s' tiene procesos activos:\e[0m\n%s\n" "$user" "$pids"
			echo
			read -n 1 -p "¿Desea continuar con la eliminación? Esto puede interrumpir procesos. (y/n): " confirm_process
			echo
			if [[ "$confirm_process" == "y" ]]; then
				break
			else
				printf "\e[1;31mEliminación cancelada.\e[0m\n"
				echo
				echo "Pulse INTRO para continuar."
				read INTRO
				return
			fi
		else
			break
		fi
	done

	# Confirma la eliminación
	while true; do
		clear
		echo
		printf "\e[1;36m--- Eliminar un usuario ---\e[0m\n\n"
		printf "\e[32mPaso 3 de 4\e[0m\n"
		echo
	    	read -n 1 -p "¿Está seguro que desea eliminar al usuario '$user'? (y/n): " confirm
	    	echo
		if [[ "$confirm" == "y" ]]; then
			break
		else
			printf "\e[1;31mEliminación cancelada.\e[0m\n"
			echo
			echo "Pulse INTRO para continuar."
			read INTRO
			continue
		fi
	done

	# Pregunta si quiere eliminar el directorio home y los archivos asociados
	while true; do
		clear
		echo
		printf "\e[1;36m--- Eliminar un usuario ---\e[0m\n\n"
		printf "\e[32mPaso 4 de 4\e[0m\n"
		echo
		read -n 1 -p "¿Eliminar también el directorio home y archivos asociados? (y/n): " delhome
		echo
		home_dir=$(getent passwd "$user" | cut -d: -f6)
		if [[ "$delhome" == "y" ]]; then
			if [[ -d "$home_dir" ]]; then
				sudo userdel -r "$user"
				break
			else
				sudo userdel "$user"
				break
			fi
		elif [[ "$delhome" == "n" ]]; then
			sudo deluser "$user"
			break
		else
			printf "\e[1;31mOpción inválida.\e[0m\n"
			echo
			echo "Pulse INTRO para continuar."
			read INTRO
			continue
		fi
	done

	# Verificar resultado y mostrar mensaje
	clear
	echo
	printf "\e[1;36m--- Eliminar un usuario ---\e[0m\n\n"
	if [[ $? -eq 0 ]]; then
		printf "\e[1;32mUsuario '%s' eliminado correctamente.\e[0m\n" "$user"
	else
		printf "\e[1;31mError al eliminar al usuario '%s'.\e[0m\n" "$user"
	fi
	echo
	echo "Pulse INTRO para continuar."
	read INTRO
}


# Está función comprueba si un usuario existe en el sistema o no
user_exist() {
	while true; do
		clear
		echo
		printf "\e[1;36m--- Comprobar si un usuario existe ---\e[0m\n\n"
		read -p "Ingrese el nombre de usuario a comprobar: " user

		if id "$user" >/dev/null 2>&1; then
			printf "\e[1;32mEl usuario '%s' existe en el sistema.\e[0m\n" "$user"
		else
			printf "\e[1;31mEl usuario '%s' no existe en el sistema.\e[0m\n" "$user"
		fi
		echo
		echo "Pulse INTRO para continuar."
		read INTRO
		break
	done
}


# Esta función añade a un usuario a un grupo comprobando antes
# que ambos existan, y si el grupo no existe da opción a crearlo
add_user_group() {
	clear
	printf "\e[1;36m--- Añadir a un usuario a un grupo ---\e[0m\n\n"

	# Pide el nombre de usuario y el del grupo
	read -p "Ingrese el nombre de usuario: " user
	if ! id "$user" >/dev/null 2>&1; then
		printf "\e[1;31mEl usuario '%s' no existe. Por favor, use primero la opción 1 del script para crearlo.\e[0m\n" "$user"
		echo
		echo "Pulse INTRO para continuar."
		read INTRO
		return
	fi

	read -p "Ingrese el nombre del grupo: " group
	if ! getent group "$group" >/dev/null 2>&1; then
		printf "\e[1;33mEl grupo '%s' no existe.\e[0m\n" "$group"
		read -n 1 -p "¿Desea crearlo? (y/n): " create
		echo
		if [[ "$create" == "y" ]]; then
			if sudo groupadd "$group"; then
				printf "\e[1;32mGrupo '%s' creado correctamente.\e[0m\n" "$group"
			else
				printf "\e[1;32mError al crear el grupo '%s'.\e[0m\n" "$group"
				echo
				echo "Pulse INTRO para continuar."
				read INTRO
				return
			fi
		else
			printf "\e[1;31mOperación cancelada.\e[0m\n"
			echo
			echo "Pulse INTRO para continuar."
			read INTRO
		fi
	fi

	# Añade el usuario al grupo
	if sudo usermod -aG "$group" "$user"; then
		printf "\e[1;32mUsuario '%s' añadido correctamente al grupo '%s'.\e[0m\n" "$user" "$group"
	else
		printf "\e[1;31mError al añadir el usuario '%s' al grupo '%s'.\e[0m\n" "$user" "$group"
	fi
	echo
	echo "Pulse INTRO para continuar."
	read INTRO
}


# Esta función se encarga de eliminar a un usuario de un grupo.
# Verifica que el usuario y el grupo existan, que el usuario sea miembro del grupo y
# protege usuarios críticos (root y el actual)
remove_user_group() {
	clear
	printf "\e[1;36m--- Eliminar a un usuario de un grupo ---\e[0m\n\n"

	# Pide el nombre de usuario y comprueba que no sea un usuario crítico
	read -p "Ingrese el nombre del usuario: " user

	if ! id "$user" >/dev/null 2>&1; then
		printf "\e[1;31mEl usuario '%s' no existe.\e[0m\n" "$user"
		echo
		echo "Pulse INTRO para continuar."
		read INTRO
		return
	fi

	current_user=$(whoami)
	if [[ "$user" == "root" || "$user" == "current_user" ]]; then
		printf "\e[1;31mNo está permitido modificar a '%s'.\e[0m\n" "$user"
		echo
		echo "Pulse INTRO para continuar."
		read INTRO
		return
	fi

	# Pide el nombre el grupo y verifica que existe
	read -p "Ingrese el nombre del grupo: " group

	if ! getent group "$group" >/dev/null 2>&1; then
		printf "\e[1;31mEl grupo '%s' no existe.\e[0m\n" "$group"
		echo
		echo "Pulse INTRO para continuar."
		read INTRO
		return
	fi

	# Verifica si el usuario es miembro del grupo
	if ! id -nG "$user" | grep -qw "$group"; then
		printf "\e[1;33mEl usuario '%s' no pertenece al grupo '%s'.\e[0m\n" "$user" "$group"
		echo
		echo "Pulse INTRO para continuar."
		read INTRO
		return
	fi

	printf "\e[1;33m¿Estás seguro de eliminar al usuario '%s' del grupo '%s'? (y/n): \e[0m\n" "$user" "$group"
	read ans
	if [[ "$ans" == "y" ]]; then
		# Quita al usuario de la lista y reasigna sus grupos
		new_group=$(id -ng "$user" | tr ' ' '\n' | grep -v "^$group$" | tr '\n' ',' | sed 's/,$//')

		if sudo usermod -G "$new_group" "$user"; then
			printf "\e[1;32mEl grupo '%s' fue eliminado correctamente del usuario '%s'.\e[0m\n" "$group" "$user"
		else
			printf "\e[1;31mError al modificar los grupos del usuario '%s'.\e[0m\n" "$user"
		fi
		echo
		echo "Pulse INTRO para continuar."
		read INTRO
	else
		printf "\e[1;31mEliminación del usuario '%s' del grupo '%s' cancelada.\e[0m\n" "$user" "$group"

	fi
}


# Esta función crea un grupo verificando si ya existe
add_group() {
	while true; do
		clear
		printf "\e[1;36m--- Crear un grupo ---\e[0m\n\n"

		# Pide el nombre del grupo
		read -p "Ingrese el nombre del grupo: " group

		# Verifica si ese grupo ya existe
		if getent group "$group" >/dev/null 2>&1; then
			printf "\e[1;33mEl grupo '%s' ya existe. Intente con otro nombre.\e[0m\n" "$group"
			echo
			echo "Pulse INTRO para continuar."
			read INTRO
			continue
		fi

		# Intenta crear el grupo
		if sudo groupadd "$group"; then
			printf "\e[1;32mGrupo '%s' creado correctamente.\e[0m\n" "$group"
		else
			printf "\e[1;31mError al crear el grupo '%s'.\e[0m\n" "$group"
		fi

		echo
		echo "Pulse INTRO para continuar."
		read INTRO
		break
	done
}


# Esta función elimina a un grupo ya existente.
# Verifica si el grupo existe, advierte si hay usuarios dentro del grupo y
# pide confirmación para eliminar el grupo
remove_group() {
	while true; do
		clear
		printf "\e[1;36m--- Eliminar un grupo ---\e[0m\n\n"

		# Pide el nombre del grupo
		read -p "Ingrese el nombre del grupo a eliminar: " group

		# Verifica si el grupo existiese
		if ! getent group "$group" >/dev/null 2>&1; then
			printf "\e[1;31mEl grupo '%s' no existe.\e[0m\n" "$group"
			echo
			echo "Pulse INTRO para continuar."
			read INTRO
			continue
		fi

		# Obtiene miembros del grupo (si los hay)
		members=$(getent group "$group" | cut -d: -f4)

		if [[ -n "$members" ]]; then
			printf "\e[1;33mAdvertencia: El grupo '%s' tiene los siguientes miembros:\e[0m\n%s\n\n" "$group" "$members"
		fi

		# Pide la confirmación
		printf "\e[1;33m¿Está seguro de eliminar el grupo '%s'? (y/n): \e[0m" "$group"
		read -n 1 ans
		echo

		if [[ "$ans" != "y" ]]; then
			printf "\e[1;31mEliminación cancelada.\e[0m\n"
			echo
			echo "Pulse INTRO para continuar."
			read INTRO
			continue
		fi

		# Elimina al grupo
		if sudo groupdel "$group"; then
			printf "\e[1;32mGrupo '%s' eliminado correctamente.\e[0m\n" "$group"
		else
			printf "\e[1;31mError al eliminar el grupo '%s'.\e[0m\n" "$group"
		fi

		echo
		echo "Pulse INTRO para continuar."
		read INTRO
		break
	done
}

# --- Menú de selección ---

while true; do

clear
printf "\e[1;36m--- Gestión de usuarios y grupos en entornos Linux ---\e[0m\n\n"
echo
echo "1) Crear un usuario."
echo "2) Eliminar un usuario."
echo "3) Comprobar si un usuario existe."
echo "4) Añadir a un usuario a un grupo."
echo "5) Eliminar a un usuario de un grupo"
echo "6) Crear un grupo"
echo "7) Eliminar un grupo"
echo "x) Salir."
echo
echo -n "Seleccione una opción del menú (1-7 o 'x'): "
read OP
case $OP in
	1) clear
		create_user
		;;
	2) clear
		delete_user
		;;
	3) clear
		user_exist
		;;
	4) clear
		add_user_group
		;;
	5) clear
		remove_user_group
		;;
	6) clear
		add_group
		;;
	7) clear
		remove_group
		;;
	x|X) clear
		echo "Saliendo..."
		exit 0
		;;
	*) clear
		printf "\e[1;31mOpción inválida.\e[0m\n"
		echo
		echo "Pulsa INTRO para continuar."
		read INTRO
		;;
esac
done
