#! /bin/sh
# postinst script for gitlab
# copied from postinst script for hplip
# $Id: hplip.postinst,v 1.1 2005/10/15 21:39:04 hmh Exp $
#
# see: dh_installdeb(1)

set -e

# Setup variables
# Now using gitlab-common.defaults to override variables used only in
# maintainer scripts. Earlier versions used gitlab-debian.conf for this.
# Now gitlab-debian.conf will only have user/admin configurable variables
# and variables required by systemd services.
gitlab_common_defaults=/usr/lib/gitlab-common/gitlab-common.defaults
test -f ${gitlab_common_defaults} && . ${gitlab_common_defaults}

# Show debconf questions
. /usr/share/debconf/confmodule
. /usr/share/dbconfig-common/dpkg/postinst

# summary of how this script can be called:
#        * <postinst> `configure' <most-recently-configured-version>
#        * <old-postinst> `abort-upgrade' <new version>
#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
#          <new-version>
#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
#          <failed-install-package> <version> `removing'
#          <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
#
# quoting from the policy:
#     Any necessary prompting should almost always be confined to the
#     post-installation script, and should be protected with a conditional
#     so that unnecessary prompting doesn't happen if a package's
#     installation fails and the `postinst' is called with `abort-upgrade',
#     `abort-remove' or `abort-deconfigure'.

#######################################################################
# Read debian specific configuration
#######################################################################

# Always copy the example configuration file in case there are newer entries
# added by maintainer
cp ${gitlab_debian_conf_example} ${gitlab_debian_conf_private}
. ${gitlab_debian_conf_private}

# If /etc/gitlab/gitlab-debian.conf is already present, use it
test -f ${gitlab_debian_conf} && . ${gitlab_debian_conf}
export DB RAILS_ENV

# Read default values (we cannot do this before gitlab-debian.conf is exported
# as we want to override variables set by gitlab-debian.conf in earlier gitlab
# versions with gitlab-debian.defaults)
. ${gitlab_common_defaults}

# Read gitlab_user from gitlab-common.conf
test -f ${gitlab_common_conf} && . ${gitlab_common_conf}

# Required for embedded gems
export GEM_HOME=/var/lib/gitlab/.gem

#######################################################################
# update Gemfile.lock and yarn.lock, always
#######################################################################
runuser -u ${gitlab_user} -- sh -c "touch ${gitlab_data_dir}/Gemfile.lock && \
truncate -s 0 ${gitlab_data_dir}/Gemfile.lock"
# Don't modify yarn.lock until all dependencies are packaged
#runuser -u ${gitlab_user} -- sh -c "touch ${gitlab_data_dir}/yarn.lock && \
#truncate -s 0 ${gitlab_data_dir}/yarn.lock"
runuser -u ${gitlab_user} -- sh -c "touch ${gitlab_data_dir}/yarn-error.log"
cd ${gitlab_app_root}
if ! runuser -u ${gitlab_user} -- sh -c 'bundle --local --quiet'; then
  if [ "$1" = "triggered" ]; then
    # probably triggered in the middle of an system upgrade; ignore failure
    # but abort here
    echo "#########################################################################"
    echo "# Failed to detect gitlab dependencies; if you are in the middle of an #"
    echo "# upgrade, this is probably fine, there will be another attempt later.  #"
    echo "#                                                                       #"
    echo "# If you are NOT in the middle of an upgrade, there is probably a real  #"
    echo "# issue. Please report a bug.                                           #"
    echo "#########################################################################"
    exit 0
  else
    # something is really broken
    exit 1
  fi
fi
cd - >/dev/null

case "$1" in
  configure)
    gitlab_builds_log=${gitlab_log_dir}/builds
    gitlab_repo_path=${gitlab_data_dir}/repositories
    gitlab_uploads_path=${gitlab_data_dir}/public/uploads

    # Create directories and change ownership
    echo "Creating runtime directories for gitlab..."
    # Setup ssh key file
    runuser -u ${gitlab_user} -- sh -c "mkdir -p ${gitlab_data_dir}/.ssh"
    runuser -u ${gitlab_user} -- sh -c "touch ${gitlab_data_dir}/.ssh/authorized_keys"
    # Create .bundle for .bundle/config
    runuser -u ${gitlab_user} -- sh -c "mkdir -p ${gitlab_data_dir}/.bundle"
    # Create locale for app/assets/javascripts/locale
    runuser -u ${gitlab_user} -- sh -c "mkdir -p ${gitlab_data_dir}/locale"
    # Create backup directory for tmp/backups symbolic link
    runuser -u ${gitlab_user} -- sh -c "mkdir -p ${gitlab_data_dir}/backups"
    # Create more required directories
    mkdir -p ${gitlab_pid_path}
    chown ${gitlab_user}: ${gitlab_data_dir}/public ${gitlab_cache_path} \
    ${gitlab_log_dir} ${gitlab_shell_log} ${gitlab_pid_path} \
    ${gitlab_data_dir}/db ${gitlab_data_dir}/locale ${gitlab_data_dir}/shared \
    ${gitlab_data_dir}/shared/* ${gitlab_data_dir}/shared/artifacts/* \
    ${gitlab_data_dir}/shared/artifacts/tmp/*
    for i in ${gitlab_repo_path} ${gitlab_uploads_path}\
    ${gitlab_shell_log} ${gitlab_builds_log}; do
      runuser -u ${gitlab_user} -- sh -c "mkdir -p $i"
    done

    # nginx/httpd should be able to connect to gitlab-workhorse.socket and serve public
    chown ${gitlab_user}:${nginx_user} ${gitlab_uploads_path}/../* ${gitlab_pid_path}

    # Customize permissions
    echo "Updating file permissions..."
    chmod ug+rwX,o-rwx,u-s,g+s ${gitlab_repo_path}/
    for i in ${gitlab_data_dir} ${gitlab_shell_root}; do
      chown ${gitlab_user}: $i
    done

    # Make package.json writable for yarn 2
    chown ${gitlab_user}: /var/lib/gitlab/package.json

    runuser -u ${gitlab_user} -- sh -c "chmod 700 ${gitlab_uploads_path}"
    runuser -u ${gitlab_user} -- sh -c 'git config --global core.autocrlf "input"'

    # Commands below needs to be run from gitlab_app_root
    cd ${gitlab_app_root}

    # Obtain hostname from debconf db
    echo "Configuring hostname and email..."
    db_get gitlab/fqdn
    GITLAB_HOST=$RET
    GITLAB_EMAIL_FROM="no-reply@$GITLAB_HOST"
    GITLAB_EMAIL_DISPLAY_NAME="Gitlab"
    GITLAB_EMAIL_REPLY_TO="no-reply@$GITLAB_HOST"
    # Check if ssl option is selected
    db_get gitlab/ssl
    GITLAB_HTTPS=$RET
    gl_proto="http"
    db_get gitlab/letsencrypt
    gitlab_letsencrypt=$RET
    db_get gitlab/letsencrypt_email
    gitlab_letsencrypt_email=$RET

    cp -a -f ${gitlab_debian_conf_private} ${gitlab_debian_conf_private}.tmp

    # If the admin deleted or commented some variables but then set
    # them via debconf, (re-)add them to the conffile.
    test -z "$GITLAB_HOST" || grep -Eq '^ *GITLAB_HOST=' ${gitlab_debian_conf_private} || \
        echo "GITLAB_HOST=" >> ${gitlab_debian_conf_private}
    test -z "$GITLAB_EMAIL_FROM" || grep -Eq '^ *GITLAB_EMAIL_FROM=' ${gitlab_debian_conf_private} || \
        echo "GITLAB_EMAIL_FROM=" >> ${gitlab_debian_conf_private}
    test -z "$GITLAB_EMAIL_DISPLAY_NAME" || grep -Eq '^ *GITLAB_EMAIL_DISPLAY_NAME=' ${gitlab_debian_conf_private} || \
        echo "GITLAB_EMAIL_DISPLAY_NAME=" >> ${gitlab_debian_conf_private}
    test -z "$GITLAB_EMAIL_REPLY_TO" || grep -Eq '^ *GITLAB_EMAIL_REPLY_TO=' ${gitlab_debian_conf_private} || \
        echo "GITLAB_EMAIL_REPLY_TO=" >> ${gitlab_debian_conf_private}
    test -z "$GITLAB_HTTPS" || grep -Eq '^ *GITLAB_HTTPS=' ${gitlab_debian_conf_private} || \
        echo "GITLAB_HTTPS=" >> ${gitlab_debian_conf_private}
    test -z "$gitlab_letsencrypt" || grep -Eq '^ *gitlab_letsencrypt=' ${gitlab_debian_conf_private} || \
        echo "gitlab_letsencrypt=" >> ${gitlab_debian_conf_private}
    test -z "$gitlab_letsencrypt_email" || grep -Eq '^ *gitlab_letsencrypt_email=' ${gitlab_debian_conf_private} || \
        echo "gitlab_letsencrypt_email=" >> ${gitlab_debian_conf_private}
    sed -e "s/^ *GITLAB_HOST=.*/GITLAB_HOST=\"$GITLAB_HOST\"/" \
        -e "s/^ *GITLAB_EMAIL_FROM=.*/GITLAB_EMAIL_FROM=\"$GITLAB_EMAIL_FROM\"/" \
        -e "s/^ *GITLAB_EMAIL_DISPLAY_NAME=.*/GITLAB_EMAIL_DISPLAY_NAME=\"$GITLAB_EMAIL_DISPLAY_NAME\"/" \
        -e "s/^ *GITLAB_EMAIL_REPLY_TO=.*/GITLAB_EMAIL_REPLY_TO=\"$GITLAB_EMAIL_REPLY_TO\"/" \
        -e "s/^ *GITLAB_HTTPS=.*/GITLAB_HTTPS=\"$GITLAB_HTTPS\"/" \
        -e "s/^ *gitlab_letsencrypt=.*/gitlab_letsencrypt=\"$gitlab_letsencrypt\"/" \
        -e "s/^ *gitlab_letsencrypt_email=.*/gitlab_letsencrypt_email=\"$gitlab_letsencrypt_email\"/" \
            < ${gitlab_debian_conf_private} > ${gitlab_debian_conf_private}.tmp
    mv -f ${gitlab_debian_conf_private}.tmp ${gitlab_debian_conf_private}

    # Copy example configurations
    cp ${gitlab_yml_example} ${gitlab_yml_private}
    cp ${gitlab_shell_config_example} ${gitlab_shell_config_private}

    # Set gitlab user first time
    sed -i "s/GITLAB_USER/${gitlab_user}/" ${gitlab_yml_private}
    # Update gitlab user (its a hack, proper fix is to have gitlab accept GITLAB_USER variable)
    sed -i "s/^ *user:.* #gitlab_user/    user: $gitlab_user #gitlab_user/" ${gitlab_yml_private}

    if [ "$GITLAB_HTTPS" = "true" ]; then
      echo "Configuring nginx with HTTPS..."
      # Workaround for #813770
      gl_proto="https"
      echo "Configuring gitlab with HTTPS..."
      sed -i "s/#port: 80/port: 443/" ${gitlab_yml_private}
      sed -i "s/https: false/https: true/" ${gitlab_yml_private}
      echo "Updating gitlab_url in gitlab-shell configuration..."
      sed -i \
	  "s/gitlab_url: http*:\/\/.*/gitlab_url: ${gl_proto}:\/\/${GITLAB_HOST}/"\
	  ${gitlab_shell_config_private}
      
      mkdir -p /etc/gitlab/ssl
      nginx_conf_example=${nginx_ssl_conf_example}

      # Check if letsencrypt option is selected
      if [ "$gitlab_letsencrypt" = "true" ]; then
	  echo "Configuring letsencrypt..."
        ln -sf /etc/letsencrypt/live/${GITLAB_HOST}/fullchain.pem \
        /etc/gitlab/ssl/gitlab.crt
        ln -sf /etc/letsencrypt/live/${GITLAB_HOST}/privkey.pem \
        /etc/gitlab/ssl/gitlab.key
	    
        # Check if certificate is already present
        if [ -e /etc/letsencrypt/live/${GITLAB_HOST}/fullchain.pem ]; then
          echo "Let's encrypt certificate already present."
        else
          # Port 80 and 443 should be available for letsencrypt
          if command -v nginx > /dev/null; then
	    echo "Stopping nginx for letsencrypt..."
	    invoke-rc.d nginx stop
	  fi
          db_get gitlab/letsencrypt_email
          gitlab_letsencrypt_email=$RET
          LETSENCRYPT_CMD="letsencrypt --standalone --agree-tos -m $gitlab_letsencrypt_email -d ${GITLAB_HOST} certonly"
          $LETSENCRYPT_CMD || {
	    echo "letsencrypt auto configuration failed..."
	    echo "Stop your webserver and try running letsencrypt manually..."
	    echo "$LETSENCRYPT_CMD"
	  }
          if command -v nginx > /dev/null; then
		  echo "Starting nginx (letsencrypt configuration completed) ..."
	    invoke-rc.d nginx start
	  fi
        fi 
      fi
    else
      # Revert https setting
      sed -i "s/port: 443/#port: 80/" ${gitlab_yml_private}
      sed -i "s/https: true/https: false/" ${gitlab_yml_private}
    fi

    # Cleanup in case letsencrypt were disabled later
    if [ "$gitlab_letsencrypt" = "false" ]; then
        if [ -L /etc/gitlab/ssl/gitlab.crt ]; then
          if [ "$(file /etc/gitlab/ssl/gitlab.crt|awk '{ print $NF }')" = "/etc/letsencrypt/live/${GITLAB_HOST}/fullchain.pem" ]; then
            echo "Removing symbolic links to letsencrypt certificate..."
            rm -f /etc/gitlab/ssl/gitlab.crt
          fi
        fi
        if [ -L /etc/gitlab/ssl/gitlab.key ]; then
          if [ "$(file /etc/gitlab/ssl/gitlab.key|awk '{ print $NF }')" = "/etc/letsencrypt/live/${GITLAB_HOST}/privkey.pem" ]; then
            echo "Removing symbolic links to letsencrypt certificate private key..."
            rm -f /etc/gitlab/ssl/gitlab.key
          fi
        fi
    fi

      # Override User for systemd services
      for service in mailroom puma sidekiq workhorse; do
        path=/etc/systemd/system/gitlab-${service}.service.d
        mkdir -p $path
        if [ -e $path/override.conf ]; then
          echo "$path/override.conf already exist"
          # Make sure only gitlab user is updated
          sed -i "s/^ *User=.*/User=$gitlab_user/" $path/override.conf
        else
          printf "[Service]\nUser=${gitlab_user}\n" > $path/override.conf
        fi
      done

      # Manage gitlab-shell's config.yml via ucf
      mkdir -p /etc/gitlab-shell
      echo "Registering ${gitlab_shell_config} via ucf"
      ucf --debconf-ok --three-way ${gitlab_shell_config_private} ${gitlab_shell_config}
      ucfr gitlab ${gitlab_shell_config}

      # Manage gitlab.yml via ucf
      echo "Registering ${gitlab_yml} via ucf"
      ucf --debconf-ok --three-way ${gitlab_yml_private} ${gitlab_yml}
      ucfr gitlab ${gitlab_yml}

      # Manage gitlab-debian.conf via ucf
      echo "Registering ${gitlab_debian_conf} via ucf"
      ucf --debconf-ok --three-way ${gitlab_debian_conf_private} ${gitlab_debian_conf}
      ucfr gitlab ${gitlab_debian_conf}

      # configure nginx site
      if test -d /etc/nginx/sites-available/; then
        if test -f ${nginx_conf_example}; then
          nginx_site="/etc/nginx/sites-available/${GITLAB_HOST}"
          sed -e "s/YOUR_SERVER_FQDN/${GITLAB_HOST}/"\
          ${nginx_conf_example} >${nginx_site_private}
          ucf --debconf-ok --three-way ${nginx_site_private} ${nginx_site}
          ucfr gitlab ${nginx_site}
          ln -fs ${nginx_site} /etc/nginx/sites-enabled/
        else
          echo "nginx example configuration file not found"
          exit 1
        fi
      fi
      # Reload nginx
      if command -v nginx > /dev/null; then
        echo "Reloading nginx configuration..."
        invoke-rc.d nginx reload
      fi
    
    dbc_go gitlab "$@"
    db_stop

    # enable the pg_trgm extension
    runuser -u postgres -- sh -c "psql -d gitlab_production -c \"CREATE EXTENSION IF NOT EXISTS pg_trgm;\""

    # enable the btree_gist extension
    runuser -u postgres -- sh -c "psql -d gitlab_production -c \"CREATE EXTENSION IF NOT EXISTS btree_gist;\""
    # Allow gitlab user to create schema
    runuser -u postgres -- sh -c "psql -c \"GRANT CREATE ON database gitlab_production TO ${gitlab_user};\""

    # Remove Gemfile.lock if present
    rm -f ${gitlab_data_dir}/Gemfile.lock

    # Create Gemfile.lock and .secret in /var/lib/gitlab
    runuser -u ${gitlab_user} -- sh -c "touch ${gitlab_data_dir}/Gemfile.lock"

    echo "Verifying we have all required libraries..."
    runuser -u ${gitlab_user} -- sh -c 'bundle install --without development test --local'
        
    echo "Running final rake tasks and tweaks..."
    . /usr/lib/gitlab/scripts/rake-tasks.sh
    ;;

  triggered)
    # Already handled
    ;;

  abort-upgrade|abort-remove|abort-deconfigure)
    ;;

  *)
    echo "postinst called with unknown argument \`$1'" >&2
    exit 1
    ;;
esac

#DEBHELPER#

case "$1" in
  configure)
    if command -v gitaly > /dev/null; then
      echo "Restarting gitaly..."
      invoke-rc.d gitaly restart
    fi
    echo "Restarting gitlab-sidekiq..."
    systemctl restart gitlab-sidekiq
    echo "Restarting gitlab..."
    invoke-rc.d gitlab restart
    echo "Running rake checks..."
    gitlab-rake gitlab:check
  ;;
esac