#!/bin/sh
# qunattended-ctl: narrow root wrapper backing q4os-updater's single
# "Fully unattended updates" master toggle (Control Center / um_config.exu)
# and its "Add all repositories to Allowed-origins" sub-option. Deliberately
# takes only a fixed set of actions - no arbitrary apt.conf.d key/value
# pairs like the generic aptwriteconfig.sh accepts - so the sudoers
# NOPASSWD grant this needs (see ../sudoers.d/q4os-updater-common) can be
# scoped to exactly these fixed invocations, the same narrow-grant
# precedent as qflatpak/qapt-get/qdpkg.
#
# usage: qunattended-ctl enable|disable|test|refresh-origins|origins-all|origins-curated

PERIODIC_CFGFILE="/etc/apt/apt.conf.d/20auto-upgrades"
DPKGOPT_CFGFILE="/etc/apt/apt.conf.d/53unattended-upgrades-q4os-dpkgopts"
ORIGINS_CFGFILE="/etc/apt/apt.conf.d/54unattended-upgrades-q4os-dynamic-origins"
TIMER_UNIT="q4os-updatemgr-flatpak-unattended.timer"
APTWRITECONFIG="/usr/share/apps/q4os_system/bin/aptwriteconfig.sh"

if [ "$( id -u )" != "0" ] ; then
  #refresh-origins is the automatic apt Post-Invoke-Success hook, not a
  #user-invoked action, and a hook that returns non-zero aborts the whole
  #apt run with "E: Problem executing scripts APT::Update::Post-Invoke-
  #Success" (forum #6289). Without root it has nothing it could do anyway -
  #the file it writes lives in /etc - so it no-ops quietly instead of
  #breaking "apt update"/Discover for the user. Every other action stays
  #a hard error, as those are always invoked deliberately via sudo.
  if [ "$1" = "refresh-origins" ] ; then
    exit 0
  fi
  echo "only root can run this script, exiting .."
  exit 10
fi

#unconditional generation - actually (re)writes $ORIGINS_CFGFILE from
#whatever's currently configured. Only ever called by origins-all
#(explicit user request) and refresh-origins's own guarded wrapper below
#(automatic apt hook, keeps an already-active "all repos" scope current) -
#never called directly for a system currently in "curated" scope, so it
#never spontaneously re-widens the scope on its own
write_origins_file()
{
  TMPFILE="${ORIGINS_CFGFILE}.tmp"
  {
    echo "// Written by qunattended-ctl (q4os-updater's \"Full unattended-"
    echo "// upgrades\" toggle, \"Add all repositories to Allowed-origins\""
    echo "// sub-option). Regenerated on every apt list refresh so a"
    echo "// repository added after this feature was first enabled still"
    echo "// gets unattended-upgrades coverage, matching what the"
    echo "// interactive updater already does for any configured repo."
    echo "Unattended-Upgrade::Origins-Pattern {"
    apt-get indextargets 2> /dev/null | awk -F': ' '/^Origin:/{print $2}' | grep -v '"' | sort -u | while read -r origin ; do
      [ -n "$origin" ] && echo "   \"o=$origin\";"
    done
    echo "};"
  } > "$TMPFILE"
  mv -f "$TMPFILE" "$ORIGINS_CFGFILE"
}

#invoked unconditionally from the static apt Post-Invoke-Success hook, on
#every apt list refresh - a no-op unless BOTH the master toggle is
#actually on AND "all repos" scope is the currently active choice
#($ORIGINS_CFGFILE already existing IS that choice - see origins-curated
#below, which removes it precisely so this stays a no-op afterward)
do_refresh_origins()
{
  if ! grep -q '^APT::Periodic::Unattended-Upgrade "1"' "$PERIODIC_CFGFILE" 2> /dev/null ; then
    exit 0
  fi
  if [ ! -f "$ORIGINS_CFGFILE" ] ; then
    exit 0
  fi
  write_origins_file
  exit "$?"
}

case "$1" in
  test)
    # side-effect-free; used only as a probe by q4os-updatemgr-backend's
    # check-unattended action to test whether "sudo -n qunattended-ctl
    # test" works passwordlessly on this system - exactly the role
    # "qflatpak --version" plays for check-flatpak
    exit 0
    ;;

  refresh-origins)
    do_refresh_origins
    ;;

  origins-all)
    # explicit user request ("Add all repositories to Allowed-origins"
    # checked): force-(re)write the dynamic origins file right now,
    # regardless of whether it already existed
    write_origins_file
    exit "$?"
    ;;

  origins-curated)
    # explicit user request (unchecked): remove the dynamic origins file -
    # unattended-upgrades falls back to whatever Origins-Pattern is
    # already configured by the static 51/52-series files (its own
    # "allowed origins"), and refresh-origins's own guard above keeps it
    # that way on every future automatic apt list refresh
    rm -f "$ORIGINS_CFGFILE"
    exit "$?"
    ;;

  enable)
    dash "$APTWRITECONFIG" "$PERIODIC_CFGFILE" "APT::Periodic::Update-Package-Lists" "1"
    dash "$APTWRITECONFIG" "$PERIODIC_CFGFILE" "APT::Periodic::Unattended-Upgrade" "1"
    cat > "$DPKGOPT_CFGFILE" << 'EOF'
// Written by qunattended-ctl (q4os-updater's "Full unattended-upgrades"
// toggle). Answers dpkg conffile prompts the same way the interactive
// updater's own dist-upgrade already does (--force-confdef/--force-confold),
// so unattended-upgrades' own independent apt-get/dpkg run doesn't silently
// hold back any package that would otherwise need a conffile decision.
//
// NOTE: Dpkg::Options is a *global* apt.conf.d setting - while this file is
// present, it also governs manual/interactive apt-get and dpkg invocations
// run directly by a human on this system, not just unattended-upgrades' own
// background runs.
Dpkg::Options {
   "--force-confdef";
   "--force-confold";
};
EOF
    #fresh enable always (re)starts in "all repos" scope, matching the
    #existing tested default; origins-curated can narrow it afterward
    "$0" origins-all
    systemctl enable --now "$TIMER_UNIT"
    exit "$?"
    ;;

  disable)
    dash "$APTWRITECONFIG" "$PERIODIC_CFGFILE" "APT::Periodic::Unattended-Upgrade" "0"
    rm -f "$DPKGOPT_CFGFILE" "$ORIGINS_CFGFILE"
    systemctl disable --now "$TIMER_UNIT"
    exit "$?"
    ;;

  *)
    echo "usage: $0 enable|disable|test|refresh-origins|origins-all|origins-curated"
    exit 2
    ;;
esac
