#!/bin/sh
# skylac-users — gestion des comptes membres de la webradio skylac.
# Fichier de comptes : /usr/local/etc/skylac/users (lignes "login:bcrypthash").
# À installer sur donald (ex. /usr/local/bin/skylac-users) et lancer en root.
#
#   skylac-users list
#   skylac-users add    <login> [motdepasse]
#   skylac-users passwd <login> [motdepasse]
#   skylac-users del    <login>
#
# Si le mot de passe est omis, il est demandé sans écho (saisie masquée).

USERS_FILE="/usr/local/etc/skylac/users"
WWW_USER="www"
WWW_GROUP="www"
PHP="/usr/local/bin/php"

die() { echo "Erreur : $*" >&2; exit 1; }

usage() {
    cat >&2 <<EOF
Usage :
  $0 list
  $0 add    <login> [motdepasse]
  $0 passwd <login> [motdepasse]
  $0 del    <login>
EOF
    exit 1
}

# Vérifie qu'un login est syntaxiquement valide (pas de ':' ni d'espace, non vide).
valid_login() {
    case "$1" in
        ''|*:*|*' '*|*"	"*) return 1 ;;
        *) return 0 ;;
    esac
}

# Renvoie 0 si le login existe déjà dans le fichier.
login_exists() {
    [ -f "$USERS_FILE" ] || return 1
    cut -d: -f1 "$USERS_FILE" | grep -qxF "$1"
}

# Lit un mot de passe sans écho (deux fois, vérifie qu'ils correspondent).
read_password() {
    stty -echo 2>/dev/null
    printf "Mot de passe pour '%s' : " "$1" >&2; read p1; echo >&2
    printf "Confirmer            : " >&2;       read p2; echo >&2
    stty echo 2>/dev/null
    [ -n "$p1" ] || die "mot de passe vide"
    [ "$p1" = "$p2" ] || die "les mots de passe ne correspondent pas"
    PASSWORD="$p1"
}

# Calcule le hash bcrypt d'un mot de passe (passé via l'environnement, jamais en argv).
hash_password() {
    SKYLAC_PW="$1" "$PHP" -r 'echo password_hash(getenv("SKYLAC_PW"), PASSWORD_BCRYPT);' \
        || die "échec du hachage (php absent ?)"
}

# Réapplique propriétaire + permissions sur le fichier.
fix_perms() {
    chown "${WWW_USER}:${WWW_GROUP}" "$USERS_FILE" 2>/dev/null
    chmod 640 "$USERS_FILE"
}

ensure_file() {
    if [ ! -f "$USERS_FILE" ]; then
        mkdir -p "$(dirname "$USERS_FILE")"
        : > "$USERS_FILE"
        fix_perms
    fi
}

cmd="$1"; [ -n "$cmd" ] || usage
shift 2>/dev/null

case "$cmd" in
    list)
        [ -f "$USERS_FILE" ] || { echo "(aucun compte)"; exit 0; }
        echo "Comptes skylac :"
        cut -d: -f1 "$USERS_FILE" | sed 's/^/  - /'
        ;;

    add)
        login="$1"; [ -n "$login" ] || usage
        valid_login "$login" || die "login invalide (pas de ':' ni d'espace)"
        ensure_file
        login_exists "$login" && die "le login '$login' existe déjà (utilise 'passwd')"
        if [ -n "$2" ]; then PASSWORD="$2"; else read_password "$login"; fi
        hash=$(hash_password "$PASSWORD")
        printf '%s:%s\n' "$login" "$hash" >> "$USERS_FILE"
        fix_perms
        echo "Compte '$login' ajouté."
        ;;

    passwd)
        login="$1"; [ -n "$login" ] || usage
        ensure_file
        login_exists "$login" || die "le login '$login' n'existe pas"
        if [ -n "$2" ]; then PASSWORD="$2"; else read_password "$login"; fi
        hash=$(hash_password "$PASSWORD")
        # Réécrit le fichier en remplaçant la ligne du login (tmp + mv atomique).
        tmp=$(mktemp) || die "mktemp"
        while IFS= read -r line; do
            u=${line%%:*}
            if [ "$u" = "$login" ]; then
                printf '%s:%s\n' "$login" "$hash" >> "$tmp"
            else
                printf '%s\n' "$line" >> "$tmp"
            fi
        done < "$USERS_FILE"
        mv "$tmp" "$USERS_FILE"
        fix_perms
        echo "Mot de passe de '$login' changé."
        ;;

    del)
        login="$1"; [ -n "$login" ] || usage
        ensure_file
        login_exists "$login" || die "le login '$login' n'existe pas"
        tmp=$(mktemp) || die "mktemp"
        # Recopie toutes les lignes sauf celle du login (comparaison sur le 1er champ).
        while IFS= read -r line; do
            u=${line%%:*}
            [ "$u" = "$login" ] || printf '%s\n' "$line" >> "$tmp"
        done < "$USERS_FILE"
        mv "$tmp" "$USERS_FILE"
        fix_perms
        echo "Compte '$login' supprimé."
        ;;

    *)
        usage
        ;;
esac
