#!/bin/sh

## Required
domain=""
dbpasswd=""

soft="curl dig mariadb wget bash"
domains="teamdo.ru hub.teamdo.ru"
hub="https://hub.teamdo.ru/v2/ https://app.teamdo.ru/go/docker-registry/auth/"
user="teamdo"
userid="1000"

## Optional
wssport="10003"
appdir="/teamdo"
dbhost="127.0.0.1"
dbuser="teamdo"
dbname="teamdo"
ip="no"

help() {
    echo "Использование $(basename $0) -Ключ значение ..."
    echo "ключ  по умолчанию  описание"
    echo "  -a  /teamdo       Директория приложения"
    echo "  -d  -             Адрес сайта (example.ru)"
    echo "  -w  10003         Порт websocket"
    echo "  -h  127.0.0.1     Адрес хоста сервера БД"
    echo "  -u  teamdo        Имя пользователя БД"
    echo "  -n  teamdo        Имя БД"
    echo "  -p  -             Пароль пользователя БД"
    echo "  -i  no            Разрешение имени домена во внешней адрес сервера (yes)"
    exit 128
}

[ -z "$1" ] || [ "$1" = --help ] || [ "$1" = help ] && help

while getopts ":w:d:a:h:u:n:p:i:" opt; do
  case "$opt" in
    w)
        wssport="$OPTARG"; ;;
    d)
    domain="$OPTARG"
    domains="$domain $domains"; ;;
    a)
    appdir="$OPTARG"; ;;
    h)
    dbhostr="$OPTARG"; ;;
    u)
    dbuser="$OPTARG"; ;;
    n)
    dbname="$OPTARG"; ;;
    p)
    dbpasswd="$OPTARG"; ;;
    i)
    ip="$OPTARG"; ;;
    \?)
      echo "Неизвестная опция: -$OPTARG" >&2
      exit 1; ;;
    :)
      echo "Опция -$OPTARG требует значения" >&2
      exit 1; ;;
  esac
done

[ -z "$domain" ] || [ -z "$dbpasswd" ] && help

DEF='\033[0;0m'
BLACK='\033[1;30m'      # чёрный цвет знаков
RED='\033[1;31m'        # красный цвет знаков
GREEN='\033[1;32m'      # зелёный цвет знаков
YELLOW='\033[1;33m'     # желтый цвет знаков
BLUE='\033[1;34m'       # синий цвет знаков
MAGENTA='\033[1;35m'    # фиолетовый цвет знаков
CYAN='\033[1;36m'       # морская волна цвет знаков
GRAY='\033[1;37m'       # серый цвет знаков
BOLD='\033[1m'          # жирный шрифт (интенсивный цвет)
DBOLD='\033[2m'         # полу яркий цвет (тёмно-серый, независимо от цвета)
NBOLD='\033[22m'        # установить нормальную интенсивность
BLINK='\033[5m'         # мигающий

sep() {
    printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' -
}

msg() {
    [ -z "$1" ] && m="выполнено" || m="$1"
    ${ech} "${DBOLD}${GRAY}$m${DEF}"
}

err() {
    ec=$?
    [ $ec = 0 ] && return
    [ -z "$1" ] && m="ошибка" || m="$1"
    ${ech} "${YELLOW}$m${DEF}, код выхода $ec"
    exit $ec
}

msg_st() {
    ec=$?
    if [ $ec = 0 ]; then
    ${ech} "${BLUE}$1${DEF} ... ${DBOLD}${GREEN}ok${DEF}"
    else
    ${ech} "${BLUE}$1${DEF} ... ${RED}failed${DEF}"
    fi
    return $ec
}

check_timedate() {
    msg "Проверка синхронизации времени"
    t=$(timedatectl | grep "synchronized:" | cut -d':' -f2 | tr -d [:space:])
    [ "$t" = "yes" ]
    msg_st "Синхронизация NTP"
    msg
    sep
}

check_soft() {
    er=0
    msg "Проверка необходимого софта"
    ## Проверка docker
    if which docker > /dev/null 2>&1; then
    docker -v > /dev/null 2>&1
    msg_st "docker" || (( er++ ))
    else
    msg_st "docker" || (( er++ ))
    fi
    ## Docker Compose
    if docker compose version > /dev/null 2>&1; then
    msg_st "docker compose"
    elif docker-compose version > /dev/null 2>&1; then
    msg_st "docker-compose"
    else
    msg_st "docker compose" || (( er++ ))
    fi
    ## Утилиты из $soft
    for p in $@; do
    which ${p} > /dev/null 2>&1
    msg_st "$p" || (( er++ ))
    done
    [ $er = 0 ] && msg || err "Установите отсутствующий софт"
    sep
}

check_dns() {
    msg "Проверка ДНС"
    for d in $@; do
    a="$(dig +noall +answer A $d)"
    [ -n "$a" ]
    msg_st "$d"
    done
    msg
    sep
}

check_hub() {
    er=0
    msg "Проверка доступности hub.teamdo.ru"
    for u in $hub; do
    d=$(echo ${u#*//}} | cut -d'/' -f1)
    a=$(curl --max-time 3 -w "\n%{http_code}" $u 2>/dev/null)
    code=$(echo $a | grep -oE "[0-9]{3}$") \
    && auth=$(echo $a | grep -oi "UNAUTHORIZED")
    [ "$code" = 401 ] && [ -n "$auth" ]
    msg_st "$d"
    done
    msg
    sep
}

check_site() {
    if [ $ip = "yes" ]; then
    ipaddr="$(hostname -I | cut -d' ' -f1)"
    add_opts="--connect-to ::$ipaddr"
    else
    add_opts=""
    fi
    er=0
    msg "Проверка доступности $domain"
    a=$(curl $add_opts --max-time 3 http://$domain/ping/ 2>/dev/null)
    [ "$a" = pong ]
    msg_st "$domain port 80"
    a=$(curl $add_opts -k --max-time 3 https://$domain/ping/ 2>/dev/null)
    [ "$a" = pong ]
    msg_st "$domain port 443"
    a=$(curl $add_opts -k --max-time 3 https://$domain:$wssport/ping/ 2>/dev/null)
    [ "$a" = pong ]
    msg_st "$domain port $wssport"
    msg
    sep
}

chek_user() {
    msg "Проверка пользователя"
    cat /etc/passwd | grep -q "^$1" \
    && uid=$(id -u $1) \
    && [ $uid = $2 ]
    msg_st "пользователь $1 id:$2"
    cat /etc/group | grep -q "^docker.*${1}"
    msg_st "пользователь $1 в группе docker"
    msg
    sep
}

check_dir() {
    msg "Проверка директории приложения"
    if [ ! -d "$appdir" ]; then
    false
    msg_st "директория $1"
    else
    owner="$(stat --printf=%U:%G $1)"
    [ "$owner" = "teamdo:teamdo" ]
    msg_st "владелец директории $1 teamdo:teamdo"
    perms="$(stat --printf=%a $1)"
    [ $perms = 2771 ]
    msg_st "права для директории $1 2771"
    fi
    msg
    sep
}

check_db() {
    msg "Проверка базы данных"
    export MYSQL_PWD="$3"
    mariadb -h$1 -u$2 -e "USE $4;"
    msg_st "бд: $4, пользователь: $2"
    msg
    sep
}

## Проверка времени
os=$(cat /etc/os-release | grep PRETTY_NAME | grep -oE "ALT|Debian|Astra|RED") || err "не удалось определить ОС"

case $os in
    ALT)
    ech="echo -e"; ;;
    Astra)
    ech="echo -e"; ;;
    Debian)
    ech="echo"; ;;
    RED)
    ech="echo -e"; ;;
    *)
    err "не удалось определить ОС"; ;;
esac

msg "OS: $os"
sep

check_soft $soft

check_timedate

check_dns $domains

check_site $domain

check_hub $hub

chek_user $user $userid

check_dir $appdir

check_db "$dbhost" "$dbuser" "$dbpasswd" "$dbname"
