#!/bin/bash

format_date() {
  date -u +"%Y-%m-%d %H:%M:%S"
}

log_line() {
  echo "$(format_date) pre-start --> $1"
}

# logfile cleanup in case of runaway logs
SIZE_LIMIT=$((100 * 1024 * 1024)) # 100 MB
MAIN_LOG_FILE_PATH="/var/log/unifi-talk/unifi-talk.log"
MAIN_LOG_FILE_SIZE=$(stat -c%s "$MAIN_LOG_FILE_PATH")

# check if logs exceed limit, truncate
if [[ -f "$MAIN_LOG_FILE_PATH" && $MAIN_LOG_FILE_SIZE -gt $SIZE_LIMIT ]]; then
  truncate -s 0 "$MAIN_LOG_FILE_PATH"
  log_line "truncated '$MAIN_LOG_FILE_PATH' (size: $((MAIN_LOG_FILE_SIZE / 1024 / 1024)) MB)"
fi

log_line "starting pre-start script"

USER="unifi-talk"
GROUP="unifi-talk"
FREESWITCH_USER="freeswitch"
FREESWITCH_GROUP="freeswitch"
DB_NAME="unifi-talk"
DB_USER="unifi-talk"
PKG="unifi-talk"
LOGROTATE="/etc/logrotate.d/$PKG"
mkdir -p "/usr/share/$PKG/app/runtime"
mkdir -p "/var/log/$PKG"
# Root-owned, no group write - see postinst's LOGDIR block for why a
# per-file exception (group-write plus a per-call chown/chmod fixup) was
# tried and reverted: it handed the account a durable root chown/chmod
# primitive on any name root vacates. This runs on every service start
# (ExecStartPre=+..., always as root regardless of the unit's own User=),
# so it has to carry the same fix or it silently re-asserts service-user
# ownership on every restart, undoing postinst's chown until this file
# agreed with it too - found live, exactly that way, testing the original
# version of this fix.
chown root:root "/var/log/$PKG"
chmod 755 "/var/log/$PKG"
# Self-heal for a console that ran the reverted, group-writable version of
# this fix: that version left the active log file itself group-owned and
# group-writable (root:unifi-talk 664), and nothing about reverting the
# directory above touches a file's own already-set mode.
#
# Link-refusing, not link-following - `[ -f ]` alone resolves through a
# symlink (stat(2)), which is not a defence, it is the bug: every console
# currently on base recursively chowns this directory to the account on
# every start (postinst and pre-start both, pre-fix), so the account has
# always been able to `rm` the real log and `ln -s /etc/shadow` in its
# place at any time before ever upgrading. Neither this file's nor
# postinst's new directory chown is recursive, so a plant made before the
# upgrade survives it untouched - and `[ -f ]` seeing that plant resolve to
# a real file, followed by a chown/chmod with no non-dereferencing form
# (GNU chown needs -h, but Linux chmod has none at all - no lchmod, no
# coreutils -h), is exactly the FW-11 primitive this whole fix exists to
# close, just reached through the *file's* history instead of the
# directory's. This is why the check below tests both -f and -L: -f alone
# cannot tell "root's real log" from "a symlink to one."
#
# Acts only when the entry is unambiguously a plain regular file - never a
# symlink, regardless of what it resolves to, and never any other non-
# regular type. Anything else is removed outright rather than touched, so
# the next thing to open this path (systemd's own append, on this same
# start) creates a fresh, safe, root-owned file in its place instead of
# writing through whatever was actually there. Safe to remove blind:
# directory write was already denied above, so nothing but this script can
# have changed what is at this path since.
if [ -f "$MAIN_LOG_FILE_PATH" ] && [ ! -L "$MAIN_LOG_FILE_PATH" ]; then
  chown root:root "$MAIN_LOG_FILE_PATH"
  chmod 644 "$MAIN_LOG_FILE_PATH"
elif [ -e "$MAIN_LOG_FILE_PATH" ] || [ -L "$MAIN_LOG_FILE_PATH" ]; then
  log_line "refusing to chown/chmod $MAIN_LOG_FILE_PATH: not a plain regular file (symlink or other non-regular entry) - removing it so the next open creates a safe one instead of writing through it"
  rm -f "$MAIN_LOG_FILE_PATH"
fi
chown -R "$USER:$GROUP" "/usr/share/$PKG/app/runtime" "/etc/freeswitch/" "/var/lib/freeswitch" "/usr/share/freeswitch"
usermod -a -G ${FREESWITCH_GROUP} $USER || true
usermod -a -G $GROUP ${FREESWITCH_USER} || true
chmod -R 770 "/usr/share/freeswitch/sounds"
chmod -R 770 "/var/lib/freeswitch"
chmod -R 770 "/var/log/freeswitch"
chmod -R 770 "/etc/freeswitch/"

log_line "cleaning up legacy service logs"
rm /var/log/unifi-talk-service.log
rm /var/log/unifi-base-service.log

while [ "$(systemctl is-active freeswitch)" = "activating" ]
do
  log_line "Waiting for Freeswitch to activate..."
  sleep 5
done

dependency=$(systemctl is-active freeswitch)
log_line "Freeswitch service status '${dependency}'"
if [ "${dependency}" != "active" ]; then
  log_line "Freeswitch status '${dependency}' is not 'active' -> exiting"
  exit 1
fi

log_line "creating db user"
psql -U postgres <<-EOSQL
  CREATE USER "${DB_USER}";
  CREATE DATABASE "${DB_NAME}";
EOSQL

# Datbase used to be owned by postgres, reassign databse owner if needed.
if [ "$( psql -U postgres -tAc "SELECT pg_catalog.pg_get_userbyid(d.datdba) FROM pg_catalog.pg_database d WHERE d.datname = '$DB_NAME'" )" = $DB_NAME ]
then
  log_line "Database is already owned by $DB_USER"
else
  psql -U postgres -c "ALTER DATABASE \"$DB_NAME\" OWNER TO \"$DB_USER\""
  psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE \"$DB_NAME\" to \"$DB_USER\""
  psql -U postgres -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO \"$DB_USER\"" $DB_NAME
  psql -U postgres -c "GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO \"$DB_USER\"" $DB_NAME
  for tbl in `psql -U postgres -qAt -c "select tablename from pg_tables where schemaname = 'public';" $DB_NAME` ; do  psql -U postgres -c "alter table \"$tbl\" owner to \"$DB_USER\"" $DB_NAME; done
  for tbl in `psql -U postgres -qAt -c "select sequence_name from information_schema.sequences where sequence_schema = 'public';" $DB_NAME` ; do  psql -U postgres -c "alter table \"$tbl\" owner to \"$DB_USER\"" $DB_NAME; done
  for tbl in `psql -U postgres -qAt -c "select table_name from information_schema.views where table_schema = 'public';" $DB_NAME` ; do  psql -U postgres -c "alter table \"$tbl\" owner to \"$DB_USER\"" $DB_NAME; done
fi

# UBC legacy db
UBC_DB_NAME="unifi-talk-base"
UBC_DB_USER="unifi-base"

# Legacy UBC database manipulations
# 1. rename db to "unifi-talk-base" so it's not lost on purge
# 2. rename table "device" to "device_discovery"
# 3. rename device_pkey index to device_discovery_pkey as device_pkey already exists
# 4. use pg_dump to copy the table over to unifi-talk database
# 5. set correct owner on the copied table

if [ "$( psql -U postgres -tAc "SELECT 1 FROM pg_catalog.pg_database WHERE datname='unifi-base'" )" = '1' ]
then
  log_line "renaming unifi-base db to $UBC_DB_NAME"
  psql -U postgres -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'unifi-base' AND pid <> pg_backend_pid()"
  psql -U postgres -c "ALTER DATABASE \"unifi-base\" RENAME TO \"$UBC_DB_NAME\""
  psql -U postgres -d $UBC_DB_NAME -c "ALTER TABLE IF EXISTS device RENAME TO device_discovery"
  psql -U postgres -d $UBC_DB_NAME -c "ALTER INDEX IF EXISTS device_pkey RENAME TO device_discovery_pkey"

  # only do this is device_discovery doesn't already exist in Talk DB
  if [ "$( psql -U postgres -d unifi-talk -tAc "select 1 from pg_tables where schemaname = 'public' and tablename = 'device_discovery'" )" = '1' ]
  then
    log_line "device_discovery table already exists in Talk DB, skipping import"
  else
    log_line "copying device_discovery table to unifi-talk DB"
    pg_dump -U postgres -t device_discovery $UBC_DB_NAME | psql -U postgres $DB_NAME
    psql -U postgres -d $DB_NAME -c "ALTER TABLE public.device_discovery OWNER TO \"$DB_USER\""
  fi

  # rename device_discovery in UBC DB to device_discovery_backup, this ensures even further that repeat startups of Talk won't break the process
  psql -U postgres -d $UBC_DB_NAME -c "ALTER TABLE IF EXISTS device_discovery RENAME TO device_discovery_backup"
else
  log_line "unifi-base db does not exist, proceeding"
fi

log_line "setting logrotate config"
# su root root: the log directory has no group write (see the chown above),
# so this account was never going to unlink or truncate anything here
# itself regardless of what user logrotate rotates as - back to root to
# match. Still always rewritten, not just on first install, so a future
# change to this stanza can't leave an upgrading console on a stale one -
# no assumption about install history, same reasoning as the chown above.
cat << EOF > ${LOGROTATE}
/var/log/unifi-talk/*.log {
         maxsize 10M
         rotate 5
         copytruncate
         compress
         notifempty
         missingok
         su root root
}
EOF

log_line "creating internal directories"
for dir in "$UFT_INTERNAL_DIR" "$UFT_INTERNAL_DIR/recordings" "$UFT_INTERNAL_DIR/sounds" "$UFT_INTERNAL_DIR/ivr" "$UFT_INTERNAL_DIR/call_center" "$UFT_INTERNAL_DIR/contacts" "$UFT_INTERNAL_DIR/voicemail" "$UFT_INTERNAL_DIR/voicemail/greetings" "$UFT_INTERNAL_DIR/custom_hold_music" "$UFT_INTERNAL_DIR/call_record_announcements" "$UFT_INTERNAL_DIR/config" "$UFT_INTERNAL_DIR/device_wallpapers" "$UFT_INTERNAL_DIR/device_wallpapers/landscape" "$UFT_INTERNAL_DIR/device_wallpapers/portrait" "$UFT_INTERNAL_DIR/ringtones/custom" "$UFT_INTERNAL_DIR/ringtones/standard"
do
    mkdir -p ${dir} || true
done

is_link() {
  [ -L "$1" ] && [ -e "$1" ] && return
  false
}

log_line "creating external directories"
if mountpoint -q /srv || is_link /srv; then
  for dir in "$UFT_EXTERNAL_DIR/recordings" "$UFT_EXTERNAL_DIR/contacts" "$UFT_EXTERNAL_DIR/voicemail" "$UFT_EXTERNAL_DIR/voicemail/greetings"
  do
      mkdir -p ${dir} || true
  done
  chown -R "$USER:${FREESWITCH_GROUP}" "$UFT_EXTERNAL_DIR"  || true
  chmod -R 770 "$UFT_EXTERNAL_DIR"  || true
fi

log_line "creating other directories"
for dir in "$UFT_EMMC_TMP_DIR"
do
    mkdir -p ${dir} || true
done

chown -R "$USER:${FREESWITCH_GROUP}" "$UFT_INTERNAL_DIR" "$UFT_EMMC_TMP_DIR"  || true
chmod -R 770 "$UFT_INTERNAL_DIR"  || true

ln -sf /usr/share/$PKG/app/node_modules/@babel/cli/bin/babel.js /usr/share/$PKG/app/node_modules/.bin/babel

log_line "pre-start script done"
