#!/bin/bash
set -e
set -u
set -f

TMPDIR="$(mktemp -d)"
export TMPDIR
trap 'rm -fr "$TMPDIR"' EXIT

if [ "$UID" -ne 0 ] && command -v sudo >/dev/null 2>&1
    then SUDO="sudo "
    else SUDO=""
fi

_help(){
    cat << EOF
Команда mos-auth-config включает и отключает вход в систему через учетную запись на mos.ru.
Требуется ее запуск от root.

Для включения входа через mos.ru выполните:
  ${SUDO}mos-auth-config enable
Для отключения входа через mos.ru выполните:
  ${SUDO}mos-auth-config disable
После чего перезагрузите компьютер (или перезапустите DM).

При включении (enable) выполняются следующие действия:
* устанавливается тема mos-auth в SDDM,
* изменяется диапазон UID пользователей, отображаемых на экране входа,
* устанавливается PAM-механизм автоочистки профиля гостя,
* включается поддержка сетевых папок (если установлен пакет 'mos-auth-folders').

При выключении (disable) выполняются следующие действия:
* возвращается тема SDDM, которая была настроена до включения,
* возвращается диапазон UID пользователей, который был до включения,
* выключается PAM-механизм автоочистки профиля гостя,
* выключается поддержка сетевых папок.

Вы можете настраивать поведение авторизации через mos.ru путем изменения конфигурационного файла.
Для редактирования файла с конфигурацией (настройками) выполните:
  ${SUDO}mos-auth-config edit

Список команд:
  enable		Включение авторизации через mos.ru
  disable		Выключение авторизации через mos.ru
  status		Вывод текущего статуса авторизации через mos.ru в системе
  edit			Редактирование конфигурационного файла
  help			Вызов текущей справки
EOF
}

_check_root(){
    if [ "$UID" -ne 0 ]; then
        echo "Ошибка: необходимы root-права!"
        echo ""
        _help
        return 1
    fi
}

# $1: путь к конфигу SDDM для редактирования
# $2: путь к drop-in директории конфигурации SDDM
_sddm_config(){
    local fsddm
    local fsddm_dropin
    local tmp

    fsddm="$1"
    fsddm_dropin="$2"
    tmp="$(mktemp)"

    cat "$fsddm" > "$tmp"

    echo "[SDDM] Новое значение для [Theme] Current (тема SDDM): mos-auth"
    py-ini-config set "$tmp" Theme Current mos-auth
    echo "[SDDM] Новое значение для [Users] MaximumUid (верхний порог диапазона UID): 2 000 000 000"
    py-ini-config set "$tmp" Users MaximumUid 2000000000
    if py-ini-config is_set Users MinimumUid -a "$fsddm_dropin" -a "$fsddm" -i
    then
        m=$(expr "$(py-ini-config get Users MinimumUid -a "$fsddm_dropin" -a "$fsddm" -i)" + 0)
        if [[ ${m} -gt 10000000 ]]
        then
            echo "[SDDM] Текущее значение [Users] MinimumUid: ${m} превышает допустимый нижний порог диапазона UID."
            echo "[SDDM] Новое значение для [Users] MinimumUid (нижний порог диапазона UID): 10 000 000"
            py-ini-config set "$tmp" Users MinimumUid 10000000
            grep -q 'MinimumUid=10000000' "$tmp"
        fi
    fi
    grep -q 'Current=mos-auth' "$tmp"
    grep -q 'MaximumUid=2000000000' "$tmp"

    cat "$tmp" > "$fsddm"
    rm -f "$tmp"
}

# $1: skip_sddm_config - необходимо ли пропускать изменения SDDM конфигурации
_backup_and_configure_sddm(){
    local skip_sddm_config
    local fsddm
    local fsddm_dropin
    local fold

    skip_sddm_config=$1
    fsddm="/etc/sddm.conf"
    fsddm_dropin="/usr/lib/sddm/sddm.conf"
    fold="/var/lib/mos-auth/mos-auth-old-settings"

    if test -f "$fsddm" && ! $skip_sddm_config
    then
        echo "[SDDM] Настраиваем конфигурацию для SDDM..."
        echo "[SDDM] Перед какими-либо изменениями, текущие значения сохранятся в $fold"
        cp -f "$fsddm" /var/lib/mos-auth/sddm.conf.mos-auth-bak
        touch "$fold"
        if py-ini-config is_set Theme Current -a $fsddm_dropin -a $fsddm -i
        then
            val=$(py-ini-config get Theme Current -a $fsddm_dropin -a $fsddm -i)
            echo "[SDDM] В текущей конфигурации SDDM обнаружено значение для [Theme] Current: $val"
            py-ini-config set "$fold" Theme Current "$val"
        fi
        if py-ini-config is_set Users MinimumUid -a $fsddm_dropin -a $fsddm -i
        then
            val=$(py-ini-config get Users MinimumUid -a $fsddm_dropin -a $fsddm -i)
            echo "[SDDM] В текущей конфигурации SDDM обнаружено значение для [Users] MinimumUid: $val"
            py-ini-config set "$fold" Users MinimumUid "$val"
        fi
        if py-ini-config is_set Users MaximumUid -a $fsddm_dropin -a $fsddm -i
        then
            val=$(py-ini-config get Users MaximumUid -a $fsddm_dropin -a $fsddm -i)
            echo "[SDDM] В текущей конфигурации SDDM обнаружено значение для [Users] MaximumUid: $val"
            py-ini-config set "$fold" Users MaximumUid "$val"
        fi
        if ! _sddm_config "$fsddm" "$fsddm_dropin"; then
            echo "[SDDM] Ошибка правки конфига SDDM"
            return 1
        fi
    else
        echo "[SDDM] Пропускаем настройку SDDM, так как задан параметр '--skip-sddm-config' или нет файла /etc/sddm.conf"
    fi
}

# $1: skip_sddm_config - необходимо ли пропускать изменения SDDM конфигурации
_enable(){
    if test -f /var/lib/mos-auth/enabled
    then
        echo "Уже настроено. Выполните disable и снова enable"
        return 1
    fi
    mkdir -p /var/lib/mos-auth

    _backup_and_configure_sddm "$1"

    # Проверим, корректная ли конфигурация authselect.
    if ! authselect check &> /dev/null;
    then
        # Если мигрируем с профиля sssd, который не прошел проверку
        # (то есть был отредактирован вручную не через authselect)
        if authselect current --raw | grep -q 'sssd'
        then
            # Устанавливаем "sssd" профиль заново через скрипт-хелпер
            # (который сам включит необходимые модули).
            /usr/libexec/realmd-rosa-setup sssd
        else
            # Иначе установим "local" профиль, если PAM настроен сейчас не через `authselect`.
            authselect select local --force
        fi
    fi

    local authselect_preserved_options="/var/lib/authselect/preserved-options"
    local authselect_preserved_options_nodomain="/var/lib/authselect/preserved-options-nodomain"

    # Активируем опцию для профиля гостя.
    local with_mos_auth_guest="with-mos-auth-guest"

    if authselect current --raw | grep -q "$with_mos_auth_guest"
    then
        echo "Опция для гостя в PAM-конфигурации уже активирована."
    else
        echo "Активируем опцию для гостя в PAM-конфигурации..."
        authselect enable-feature "$with_mos_auth_guest"
        if ! grep -q "$with_mos_auth_guest" "$authselect_preserved_options"
        then
            echo "$with_mos_auth_guest" >> "$authselect_preserved_options"
        fi
    fi

    # Активируем 'faillock' для профиля 'local'.
    local with_faillock="with-faillock"

    if authselect current --raw | grep -q 'local'
    then
        if authselect current --raw | grep -q "$with_faillock"
        then
            echo "Опция 'faillock' в PAM-конфигурации уже активирована."
        else
            echo "Активируем опцию 'faillock' в PAM-конфигурации..."
            authselect enable-feature "$with_faillock"
            if ! grep -q "$with_faillock" "$authselect_preserved_options_nodomain"
            then
                echo "$with_faillock" >> "$authselect_preserved_options_nodomain"
            fi
        fi
    else
        echo "Текущий профиль не является 'local'. Пропускаем настройку faillock."
    fi

    # Активируем опцию для сетевых папок.
    local with_mos_auth_folders="with-mos-auth-folders"
    local folders_binary="/usr/bin/mos-auth-folders-functions"

    if authselect current --raw | grep -q "$with_mos_auth_folders"
    then
        echo "Опция для сетевых папок в PAM-конфигурации уже активирована."
    else
        if test -f "$folders_binary"
        then
            echo "Активируем опцию для сетевых папок в PAM-конфигурации..."
            authselect enable-feature "$with_mos_auth_folders"
            if ! grep -q "$with_mos_auth_folders" "$authselect_preserved_options"
            then
                echo "$with_mos_auth_folders" >> "$authselect_preserved_options"
            fi
        fi
    fi

    # Если отсутствуют проводные подключения, удаляем специальный файл NetworkManager,
    # который отключает автоматическое создание стандартного подключения.
    if ! nmcli connection show | grep -iq ethernet
    then
        rm -f /var/lib/NetworkManager/no-auto-default.state
    fi

    touch /var/lib/mos-auth/enabled
}

_restore_sddm(){
    local fold
    local fsddm
    fold="/var/lib/mos-auth/mos-auth-old-settings"
    echo "[SDDM] Восстанавливаем конфигурацию SDDM до состояния до активации mos-auth..."
    for fsddm in "/etc/sddm.conf" "/etc/sddm.conf.d/kde_settings.conf"
    do
        if test -f "$fsddm"
        then
            echo "[SDDM] Проверяем конфигурационный файл: $fsddm"
            if test -f "$fold" && py-ini-config is_set $fold Theme Current
            then
                val=$(py-ini-config get $fold Theme Current)
                echo "[SDDM] Восстанавливаем в файл сохраненное значение [Theme] Current: $val"
                py-ini-config set "$fsddm" Theme Current "$val"
            else
                if py-ini-config is_set "$fsddm" Theme Current
                then
                    echo "[SDDM] Удаляем из файла значение [Theme] Current, поскольку оно отсутствовало до активации"
                    py-ini-config del "$fsddm" Theme Current --flush
                fi
            fi
            if test -f "$fold" && py-ini-config is_set $fold Users MinimumUid
            then
                val=$(py-ini-config get $fold Users MinimumUid)
                echo "[SDDM] Записываем в файл сохраненное значение [Users] MinimumUid: $val"
                py-ini-config set "$fsddm" Users MinimumUid "$val"
            else
                if py-ini-config is_set "$fsddm" Users MinimumUid
                then
                    echo "[SDDM] Удаляем из файла значение [Users] MinimumUid, поскольку оно отсутствовало до активации"
                    py-ini-config del "$fsddm" Users MinimumUid --flush
                fi
            fi
            if test -f "$fold" && py-ini-config is_set $fold Users MaximumUid
            then
                val=$(py-ini-config get $fold Users MaximumUid)
                echo "[SDDM] Записываем в файл сохраненное значение [Users] MaximumUid: $val"
                py-ini-config set "$fsddm" Users MaximumUid "$val"
            else
                if py-ini-config is_set "$fsddm" Users MaximumUid
                then
                    echo "[SDDM] Удаляем из файла значение [Users] MaximumUid, поскольку оно отсутствовало до активации"
                    py-ini-config del "$fsddm" Users MaximumUid --flush
                fi
            fi
        fi
    done
    rm -f "$fold"
}

# $1: skip_sddm_config - необходимо ли пропускать изменения SDDM конфигурации
_disable(){
    local skip_sddm_config
    skip_sddm_config=$1

    if ! $skip_sddm_config; then
        _restore_sddm
    fi

    local authselect_preserved_options="/var/lib/authselect/preserved-options"
    local authselect_preserved_options_nodomain="/var/lib/authselect/preserved-options-nodomain"

    # Деактивируем опцию для профиля гостя.
    local with_mos_auth_guest="with-mos-auth-guest"
    if authselect current --raw | grep -q "$with_mos_auth_guest"
    then
        echo "Деактивируем опцию для гостя в PAM-конфигурации..."
        authselect disable-feature "$with_mos_auth_guest"
        if test -f "$authselect_preserved_options"
        then
            sed -i "/$with_mos_auth_guest/d" "$authselect_preserved_options"
        fi
    fi

    # Деактивируем 'faillock' для профиля 'local'.
    local with_faillock="with-faillock"
    if authselect current --raw | grep -q 'local'
    then
        if authselect current --raw | grep -q "$with_faillock"
        then
            echo "Деактивируем опцию 'faillock' в PAM-конфигурации..."
            authselect disable-feature "$with_faillock"
            if test -f "$authselect_preserved_options_nodomain"
            then
                sed -i "/$with_faillock/d" "$authselect_preserved_options_nodomain"
            fi
        fi
    fi

    # Деактивируем опцию для сетевых папок.
    local with_mos_auth_folders="with-mos-auth-folders"
    local folders_binary="/usr/bin/mos-auth-folders-functions"
    if authselect current --raw | grep -q "$with_mos_auth_folders"
    then
        echo "Деактивируем опцию для сетевых папок в PAM-конфигурации..."
        authselect disable-feature "$with_mos_auth_folders"
        if test -f "$authselect_preserved_options"
        then
            sed -i "/$with_mos_auth_folders/d" "$authselect_preserved_options"
        fi
    fi

    rm -f /var/lib/mos-auth/enabled

    echo "Конфигурация mos-auth успешно отключена."
}

_status(){
    if test -f /var/lib/mos-auth/enabled
    then
        echo "В данный момент авторизация через mos.ru включена."
    else
        echo "В данный момент авторизация через mos.ru выключена."
    fi
}

_edit(){
    command ${VISUAL:-${EDITOR:-$(command -v nano)}} /etc/mos-auth/mos-auth.conf
}

_main(){
    case "${1:-X}" in
        enable )
            _check_root

            local skip_sddm_config
            skip_sddm_config=false

            case "${2:-X}" in
                "--skip-sddm-config" )
                    skip_sddm_config=true
                ;;
            esac

            _enable $skip_sddm_config
        ;;
        disable )
            _check_root

            local skip_sddm_config
            skip_sddm_config=false

            case "${2:-X}" in
                "--skip-sddm-config" )
                    skip_sddm_config=true
                ;;
            esac

            _disable $skip_sddm_config
        ;;
        help )
            _help
        ;;
        status )
            _status
        ;;
        edit )
            _check_root
            _edit
        ;;
        * )
            _help
            exit 1
        ;;
    esac
}

if [ "${SOURCING:-0}" -ne 1 ]; then
    _main "$@"
fi
