#!/bin/sh
#
# TazU - SliTaz Users account utility
#
# This tool is used to mange SliTaz users accounts on bugs.slitaz.org
# and scn.slitaz.org. It can also be used to admin TinyCM users DB.
#
# Copyright 2017 (C) SliTaz GNU/Linux - BSD License
# Author: Christophe Lincoln <pankso@slitaz.org>
#
. /lib/libtaz.sh
check_root
user="$1"

people="/var/lib/slitaz/people"
authfile="/var/lib/slitaz/auth/people"
admin="/var/lib/slitaz/auth/admin"

# Sanity check
for file in ${authfile} ${admin}; do
	if ! [ -f "$file" ]; then
		echo check $file
		install -d -m 0700 -o www -g www $(dirname $file)
		touch ${file} && chown www.www ${file} && chmod 0600 ${file}
	fi
done

#
# Functions
#

usage() {
	cat << EOT

$(boldify "Usage:") $(basename $0) [user|command] [--option]

Commands:
  stats      SliTaz users DB stats
  list       List all users accounts
  last       List last active users
  check      Check for corrupted accounts

Options:
  --admin    Make user admin
  --edit     Edit user account.conf
  --search   Search for users using patterns
  --passwd   Prompt to change a user password
  --del      Delete a user account (or all corrupted) 
  
Examples:
  tazu username --admin
  tazu "user name" --search

EOT
}

no_account() {
	echo "No user account for: $user"
}

md5crypt() {
	echo -n "$1" | md5sum | awk '{print $1}'
}

# Delete a user (we may have corrupted accounts: check twice)
# Usage: deluser "username"
deluser() {
	if [ -d "${people}/${1}" ] || grep -q "^$1:" ${authfile}; then
		if [ -d "${people}/${1}" ]; then
			echo -n "Deleting account: $(colorize 34 "$1")"
			rm -rf "${people}/${1}" && status
		fi
		if grep -q "^$user:" ${authfile}; then
			echo -n "Removing '$1' from authfile..."
			sed -i "/^${1}:/"d ${authfile} && status
		fi
	else
		no_account
	fi
}

#
# Commands
#

case "$1" in
	"") usage ;;
	
	stats)
		newline
		boldify "SliTaz users stats"
		separator
		cat << EOT
People DB       : $people
Authfile path   : $authfile
Admin users     : $admin
User accounts   : $(ls $people | wc -l)
Authfile users  : $(cat $authfile | wc -l)
Admin users     : $(cat $admin | wc -l)
EOT
		separator && newline ;;
	
	last)
		[ ! "$count" ] && count=15
		newline
		boldify "Last active users"
		separator
		find ${people} -name "last" | xargs ls -1t | head -n ${count} | while read last;
		do
			dir="$(dirname $last)"
			echo -n "$(basename $dir)"
			indent 26 "$(cat $last)"
		done 
		separator && newline ;;
	
	list)
		# List all users
		newline
		boldify "SliTaz users list"
		separator
		for user in $(ls $people)
		do
			if ! [ -f "$people/$user/account.conf" ]; then
				echo -n "$(colorize 31 "$user")"
				indent 20 "CORRUPTED" && continue
			fi
			echo -n "$(colorize 34 "$user")"
			indent 20 "${NAME}"
		done 
		separator
		echo "$(boldify "Users:") $(ls $people | wc -l)"
		echo -n "$(boldify "Admin users:") "
		for u in $(cat $admin); do
			echo -n "$u "
		done && newline 
		separator && newline ;;
	
	check)
		# Check accounts and auth file
		tmp=/tmp/tazu_corrupted
		newline
		boldify "SliTaz accounts integrity"
		separator
		echo "$(colorize 33 "Checking users: account.conf")"
		for user in $(ls $people)
		do
			if ! [ -f "$people/$user/account.conf" ]; then
				echo -n "$(colorize 31 "$user")"
				indent 26 "Missing account.conf"
			else # Check empty VALUES
				. "$people/$user/account.conf"
				if [ -z "$NAME" ]; then
					echo -n "$(colorize 31 "$user")"
					indent 26 "Missing NAME"
				fi
				if [ -z "$MAIL" ]; then
					echo -n $(colorize 31 "$user")
					indent 26 "Missing MAIL"
				fi
				# Invalid mail
				if ! echo "$MAIL" | grep -q "@"; then
					echo -n $(colorize 31 "$user")
					indent 26 "Invalid MAIL: $MAIL"
					echo "$user" >> ${tmp}
				fi
				# account.conf but not in authfile ?
				if ! grep -q "^${user}:" ${authfile}; then
					echo -n $(colorize 31 "$user")
					indent 26 "Missing in authfile"
					echo "$user" >> ${tmp}
				fi
				unset NAME MAIL
			fi
		done
		# Check authfile
		echo "$(colorize 33 "Checking users in authfile...")"
		IFS=":"
		cat ${authfile} | while read user passwd;
		do
			if ! [ -d "$people/$user" ]; then
				echo -n $(colorize 31 "$user")
				indent 26 "Missing in DB"
				echo "$user" >> ${tmp}
			fi
		done
		unset IFS
		separator
		# Handle --del option
		if [ "$del" ] && [ -f "$tmp" ]; then
			boldify "Deleting accounts..."
			cat $tmp | uniq | while read u;
			do
				deluser "$u"
			done && separator
		else
			echo "To remove a single corrupted account you can use: tazu 'user' --del"
		fi
		newline && rm -f ${tmp} ;;

	*)
		# Handle general: --options
		case " $@ " in
			*\ --admin\ *)
				# Admin user
				if fgrep -q ${user} ${admin}; then
					echo -n "User is already admin: " && colorize 34 "$user" 
				else
					echo -n "Adding $user to admin users..."
					echo "$user" >> ${admin} && status
				fi ;;
			
			*\ --edit\ *)
				# Edit a user account
				if [ -f "${people}/${user}/account.conf" ]; then 
					nano ${people}/${user}/account.conf
				else
					no_account
				fi ;;
			
			*\ --search\ *)
				# Search for a user
				newline
				echo -n "Searching for: "; colorize 34 "$1"
				separator
				IFS=":"
				grep -i "$1" ${people}/*/account.conf | while read path patterm;
				do
					. ${path}
					if ! echo "$found" | grep -w -q "$USER"; then
						found="$found $USER"
						echo "$(colorize 34 $USER) $(indent 20 $NAME) $(indent 46 $MAIL)"
					fi
				done
				unset IFS && separator && newline ;;
			
			*\ --passwd\ *)
				user="$1"
				if [ -d "${people}/${user}" ]; then
					echo -n "New password for $1: "; read pass
					if [ "$pass" ]; then
						echo -n "Changing password..."
						sed -i "/^${user}:/"d ${authfile}
						echo "$user:$(md5crypt $pass)" >> ${authfile} && status
					fi
				else
					no_account
				fi ;;
			
			*\ --del\ *)
				deluser "$user" ;;
			
			*)
				# Show user info
				if [ -d "${people}/${user}" ]; then
					newline
					if fgrep -w -q "$user" ${admin}; then
						echo "$(colorize 35 "Admin user:") $(colorize 34 "$user")"
					else
						echo "$(boldify "User:") $(colorize 34 "$user")"
					fi
					separator
					cat $people/$user/account.conf | grep "="
					separator
					
					newline
				else
					no_account
				fi ;;
		esac ;;
esac

exit 0
