#!/bin/bash

_server_domain="share.os.mos.ru"
_shared_folder="/run/media/glusterfs"

# Вывод сообщения в журнал systemd
# $1 - сообщение
# $2 - приоритет
log()
{
    printf "%b" "$1" | systemd-cat -t mos-auth-folders -p "$2"
}

# Проверка ip-адреса, чтобы первый октет был равен 10, а последний 20.
_check_ip()
{
    [[ "$(host -t a $_server_domain | tail -n1 | awk '{print $NF}' | awk -F"." '{print $1"."$4}' )" == "10.20" ]]
}

# Проверяем наличие у пользователя $1 необходимой группы.
check_user_group()
{
    id -nGz "$1" | grep -qzxF -e "mos-teacher" -e "mos-admin" -e "mos-student"
}

# Создать ссылки на сетевые папки для пользователя $1.
create_folder_links()
{
    # Если отсутствует личная папка у пользователя.
    if { ! test -d "$_shared_folder/$1" ; }
    then
        mkdir -p "$_shared_folder/$1"

        # NOTE: Рекурсивно меняем права на содержимое личной папки.
        # Иногда может возникнуть ошибка, в случае битых файлов на сервере (например: `stale file handle`).
        # Поэтому игнорируем те файлы, на которых не удалось сменить права (через cmd || true).
        chown "$1":"$1" "$_shared_folder/$1" -R || true
        chmod 750 "$_shared_folder/$1" -R || true
    fi

    local desktop_path
    desktop_path=$(sudo -u "$1" xdg-user-dir DESKTOP)

    local home_path
    home_path=$(sudo -u "$1" xdg-user-dir HOME)

    local link_pers_home="$home_path/Персональная"
    local link_pers_desktop="$desktop_path/Персональная"

    test -L "$link_pers_home" || ln -s "$_shared_folder/$1" "$link_pers_home"
    test -L "$link_pers_desktop" || ln -s "$_shared_folder/$1" "$link_pers_desktop"

    # Если в группе teacher, то создаем ссылки и на общую папку.
    if { id -nGz "$1" | grep -qzxF "mos-teacher" ; }
    then
        local link_public_home="$home_path/Общая"
        local link_public_desktop="$desktop_path/Общая"

        test -L "$link_public_home" || ln -s $_shared_folder/public "$link_public_home"
        test -L "$link_public_desktop" || ln -s $_shared_folder/public "$link_public_desktop"
    fi
}

# Удалить ссылки на сетевые папки для пользователя $1.
delete_folder_links()
{
    local desktop_path
    desktop_path=$(sudo -u "$1" xdg-user-dir DESKTOP)

    local home_path
    home_path=$(sudo -u "$1" xdg-user-dir HOME)

    local link_pers_home="$home_path/Персональная"
    local link_pers_desktop="$desktop_path/Персональная"
    local link_public_home="$home_path/Общая"
    local link_public_desktop="$desktop_path/Общая"

    test -L "$link_pers_home" && unlink "$link_pers_home"
    test -L "$link_pers_desktop" && unlink "$link_pers_desktop"
    test -L "$link_public_home" && unlink "$link_public_home"
    test -L "$link_public_desktop" && unlink "$link_public_desktop"

    return 0
}

# Удалить ссылки на сетевые папки для всех пользователей в `/home`.
delete_folder_links_for_all()
{
    log "Удаление ссылок на сетевые папки для всех пользователей в '/home'..." "debug"
    for uname in /home/*
    do
        if { ! check_user_group "${uname##*/}" ; }
        then
            continue
        fi

        delete_folder_links "${uname##*/}"
    done

    log "Ссылки на сетевые папки для всех пользователей в '/home' были удалены." "debug"
}

# Функция для получения ip сервера сетевых папок.
# Заодно проверяем корректность адреса. Если не тот, что нужен - очищаем кэш DNS.
# Если и после этого не тот - удаляем ссылки на папки и завершаем работу.
get_shared_ip()
{
    if { _check_ip || (systemd-resolve --flush-caches && _check_ip) }
    then
        host -t a $_server_domain | tail -n1 | awk '{print $NF}'
        return 0
    else
        log "Некорректный IP-адрес сервера сетевых папок ($_server_domain).\nПроверьте настройки DNS и доступность сервера по адресу '$_server_domain'." "err"
        delete_folder_links_for_all
        return 1
    fi
}

get_shared_folder()
{
    echo $_shared_folder
}

get_server_domain()
{
    echo $_server_domain
}

# Примонтировать сетевые папки от сервера по адресу $1.
mount_shared_folder()
{
    mkdir -p $_shared_folder

    log "Монтируем сетевую папку ($_server_domain)..." "debug"

    if { /usr/sbin/mount.glusterfs "$1":/share "$_shared_folder" ; }
    then
        chown root:root "$_shared_folder"
        chmod 755 "$_shared_folder"
        return 0
    else
        log "Не удалось примонтировать сетевую папку ($_server_domain).\nВероятно, сервер ($_server_domain) в данный момент не доступен." "err"
        delete_folder_links_for_all
        return 1
    fi
}

# Создать общую папку (на тот случай, если её нет).
create_public_folder()
{
    # Создаем общую папку, если её нет.
    mkdir -p $_shared_folder/public

    # Создадим группу 'mos-teacher', если её нет.
    getent group 311 > /dev/null || /usr/sbin/groupadd -g 311 mos-teacher

    # NOTE: Нерекурсивно меняем права на общую папку.
    # Если в общей папке находится большое количество тяжелых файлов,
    # рекурсивный обход может приводить к большим задержкам (несколько минут ожидания).
    # Также есть вероятность, что весь этот процесс может сильно нагружать сервер с сетевой ФС,
    # поэтому меняем права только на саму папку, но не содержимое.
    # Иногда может возникнуть ошибка, в случае битых файлов на сервере (например: `stale file handle`).
    # Поэтому игнорируем, если не удалось сменить права (через cmd || true).
    chown root:mos-teacher $_shared_folder/public || true
    chmod 770 $_shared_folder/public || true
}

# Если не примонтировано, удаляем все симлинки.
delete_folder_links_if_unmounted()
{
    if { ! timeout -s SIGKILL --preserve-status 3 mountpoint $_shared_folder -q ; }
    then
        delete_folder_links_for_all
    fi
}

# Монтируем, если не смонтировано, по адресу $1. И создаем общую папку.
prepare_shared_folders()
{
    # Проверяем, примонтирована ли папка.
    if { ! timeout -s SIGKILL --preserve-status 3 mountpoint $_shared_folder -q ; }
    then
        mount_shared_folder "$1"
    fi

    create_public_folder
}
