#!/bin/bash -x
#
# Federated Convert Domain
#
# Converts Federated Core services
# From: customer.federatedcomputer.cloud
# To: domain.com
#
# Assumes all services are currently running

. /federated/lib/functions.sh
. /etc/federated

check_gluerecords() {
  echo -ne "\n* Checking glue records for $DOMAIN_NEW.."
  local DOMAIN_PARENT=$(echo $DOMAIN_NEW |cut -d. -f2-)
  local NS_PARENT=""
  while true; do
    NS_PARENT="$(dig @8.8.8.8 +short NS "$DOMAIN_PARENT." | head -n 1)"
    [ -n "$NS_PARENT" ] && break
    if ! echo $DOMAIN_PARENT |grep -q '\.'; then
      failcheck "Could not determine parent NS for $DOMAIN_NEW"
    fi
    # When handling a subdomain, the parent NS may not be at the next
    # level -- imagine
    # DOMAIN_NEW=fed.a.b.c.d.com
    # d.com has:
    # c NS whatever
    # c.d.com has
    # b A something
    # a.b A something
    # fed.a.b NS something
    DOMAIN_PARENT="$(echo $DOMAIN_PARENT |cut -d. -f2-)"
  done

  if dig +noall +authority +additional +norecurse @"$NS_PARENT" NS "$DOMAIN_NEW". | grep NS | grep -iE '\.dns\.fedcom\.net\.'; then
    echo "Not needed (using dns.fedcom.net)"
    return
  fi

  CHECK_NS1=`dig +noall +authority +additional +norecurse @"$NS_PARENT" NS "$DOMAIN_NEW". | grep NS | grep -i ns1.$DOMAIN_NEW`
  [ $? -ne 0 ] && failcheck "Couldn't find glue / authoritative NS record ns1.$DOMAIN_NEW"

  CHECK_NS2=`dig +noall +authority +additional +norecurse @"$NS_PARENT" NS "$DOMAIN_NEW". | grep NS | grep -i ns2.$DOMAIN_NEW`
  [ $? -ne 0 ] && failcheck "Couldn't find glue / authoritative NS record ns2.$DOMAIN_NEW"

  CHECK_A1=`dig +noall +authority +additional +norecurse @"$NS_PARENT" NS "$DOMAIN_NEW". | grep A | grep -i ns1.$DOMAIN_NEW | grep $EXTERNALIP`
  [ $? -ne 0 ] && failcheck "Couldn't find glue / authoritative A record ns1.$DOMAIN_NEW to $EXTERNALIP"

  CHECK_A2=`dig +noall +authority +additional +norecurse @"$NS_PARENT" NS "$DOMAIN_NEW". | grep A | grep -i ns2.$DOMAIN_NEW | grep $EXTERNALIP`
  [ $? -ne 0 ] && failcheck "Couldn't find glue / authoritative A record ns2.$DOMAIN_NEW to $EXTERNALIP"

  echo -ne "done."
}
do_serviceprep_dns() {
  # Create DNS records for newdomain
  docker exec pdns pdnsutil create-zone $DOMAIN_NEW
  docker exec pdns pdnsutil set-kind $DOMAIN_NEW primary
  docker exec pdns pdnsutil set-meta $DOMAIN_NEW SOA-EDIT-API DEFAULT

  for i in ns1 powerdns traefik mail www computer panel nextcloud collabora jitsi matrix element listmonk vaultwarden vpn wireguard baserow gitea blog documentation podcasts castopod caddy wordpress bookstack freescout msp espocrm dashboard plane calcom; do
    docker exec pdns pdnsutil add-record $DOMAIN_NEW $i A 86400 $EXTERNALIP
  done
  FEDCOMDNS_IP=$(host -t a dns.fedcom.net |cut -d' ' -f4)
  docker exec pdns pdnsutil add-record $DOMAIN_NEW ns2 A 86400 $FEDCOMDNS_IP

  docker exec pdns pdnsutil add-record $DOMAIN_NEW @ NS ns1.$DOMAIN_NEW
  docker exec pdns pdnsutil add-record $DOMAIN_NEW @ NS ns2.$DOMAIN_NEW
  docker exec pdns pdnsutil add-record $DOMAIN_NEW @ MX 86400 "10 mail.$DOMAIN_NEW"
  docker exec pdns pdnsutil add-record $DOMAIN_NEW @ TXT 86400 "\"v=spf1 mx a:$DOMAIN_NEW ~all\""
  docker exec pdns pdnsutil add-record $DOMAIN_NEW \* CNAME 86400 www.$DOMAIN_NEW
  docker exec pdns pdnsutil add-record $DOMAIN_NEW @ A 86400 $EXTERNALIP
  docker exec pdns pdnsutil activate-tsig-key $DOMAIN_NEW fedcomdns primary
}
do_serviceprep_ldap() {
  docker exec ldap bash -c "slapcat > /root/convertdomain.ldif"

  # Remove first lines of ldap config, replace dc= with new domain, replace domain name
  sed -n '/^dn: ou=people,dc=federatedcomputer,dc=cloud$/,$p' /federated/apps/ldap/data/root/convertdomain.ldif > /federated/apps/ldap/data/root/convertdomain1.ldif
  sed -i "s#dc=federatedcomputer,dc=cloud#$DOMAIN_NEW_LDAP_dc#g" /federated/apps/ldap/data/root/convertdomain1.ldif
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/ldap/data/root/convertdomain1.ldif
}
convert_generic() {
  #### Conversions that must be done for almost everything
  # FIXME check if Jitsi really needs upper-case DC. If we can use lower case dc like everywhere else,
  # we can avoid generating DOMAIN_NEW_LDAP_DC
  # dc=federatedcomputer,dc=cloud is hardcoded for some stuff in initial
  # core creation even if the original domain isn't under federatedcomputer.cloud,
  # so let's migrate from that unconditionally
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g;s#$DOMAIN_LDAP_dc#$DOMAIN_NEW_LDAP_dc#g;s#$DOMAIN_LDAP_DC#$DOMAIN_NEW_LDAP_DC#g;s#dc=federatedcomputer,dc=cloud#$DOMAIN_NEW_LDAP_dc#g" /federated/apps/$1/docker-compose.yml
  [ -e /federated/apps/$1/.env ] && sed -i "s#$DOMAIN#$DOMAIN_NEW#g;s#$DOMAIN_LDAP_dc#$DOMAIN_NEW_LDAP_dc#g;s#$DOMAIN_LDAP_DC#$DOMAIN_NEW_LDAP_DC#g;s#dc=federatedcomputer,dc=cloud#$DOMAIN_NEW_LDAP_dc#g" /federated/apps/$1/.env
}
convert_calcom() {
  echo -ne "\n* Converting calcom..."
  convert_generic calcom
  /federated/bin/sync-calcomusers
  start_service_convert "calcom" "nc -z 192.168.0.48 3000 &>/dev/null"
  echo done
}
convert_plane() {
  echo -ne "\n* Converting plane..."
  convert_generic plane
  docker exec postgresql psql -U plane -c "UPDATE instances SET domain='$DOMAIN_NEW' WHERE domain='$DOMAIN'"
  docker exec postgresql psql -U plane -c "UPDATE users SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN'"
  docker exec postgresql psql -U plane -c "UPDATE profiles SET company_name='$DOMAIN_NEW' WHERE company_name='$DOMAIN'"
  start_service_convert "plane" "nc -z 192.168.0.50 3000 &>/dev/null"
  echo done
}
convert_pdnsmysql() {
  #### Convert PowerDNS pdnsmysql
  echo -ne "\n* Converting pdnsmysql.."

  convert_generic pdnsmysql

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/pdnsmysql/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "pdnsmysql" "nc -z ${SERVICE_IP} 3306 &> /dev/null"

  echo -ne "done."
}
convert_pdns() {
  #### Convert PowerDNS pdns
  echo -ne "\n* Converting pdns.."

  convert_generic pdns

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/pdns/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "pdns" "nc -z ${SERVICE_IP} 8081 &> /dev/null"

  echo -ne "done."
}
convert_pdnsadmin() {
  #### Convert PowerDNS pdnsadmin
  echo -ne "\n* Converting pdnsadmin.."

  convert_generic pdnsadmin

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/pdnsadmin/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "pdnsadmin" "nc -z ${SERVICE_IP} 9494 &> /dev/null"

  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD pdns -e \"UPDATE user SET username=REPLACE(username, '@$DOMAIN', '@$DOMAIN_NEW') WHERE username LIKE '%@$DOMAIN';\""
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD pdns -e \"UPDATE user SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN';\""

  echo -ne "done."
}
convert_traefik() {
  #### Convert Traefik
  echo -ne "\n* Converting traefik. "
  if ! $DNS_DONE; then
    echo -n "Waiting 60s first for dns.."
    sleep 60
  fi

  convert_generic traefik
  rm -rf /federated/apps/traefik/data/letsencrypt/acme.json

  # Start Traefik
  docker compose -f /federated/apps/traefik/docker-compose.yml -p traefik up -d &> /dev/null

  # Keep trying to see that certificates are generated
  RETRY="20"
  while [ $RETRY -gt 0 ]; do
    traefik-certs-dumper file --version v2 --source /federated/apps/traefik/data/letsencrypt/acme.json --dest /federated/certs &> /dev/null

    # Check if certs are generated
    ls /federated/certs/private/$DOMAIN_NEW.key /federated/certs/certs/$DOMAIN_NEW.crt &> /dev/null
    if [ $? -eq 0 ]; then
      break
    else
      if [ "$RETRY" == 1 ]; then
        docker compose -f /federated/apps/traefik/docker-compose.yml -p traefik down &> /dev/null
        failcheck "There was a problem starting service /federated/apps/traefik\nCheck the output of 'docker logs traefik'"
      fi
      ((RETRY--))
      sleep 9
    fi
  done

  echo -ne "done."
}
convert_postgresql() {
  #### Convert Postgresql
  echo -ne "\n* Converting postgresql.."

  convert_generic postgresql
  cp /federated/certs/certs/$DOMAIN_NEW.crt /federated/apps/postgresql/data/var/lib/postgresql/server.crt
  cp /federated/certs/private/$DOMAIN_NEW.key /federated/apps/postgresql/data/var/lib/postgresql/server.key
  chown 999 /federated/apps/postgresql/data/var/lib/postgresql/server.crt /federated/apps/postgresql/data/var/lib/postgresql/server.key
  chmod 600 /federated/apps/postgresql/data/var/lib/postgresql/server.crt /federated/apps/postgresql/data/var/lib/postgresql/server.key

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/postgresql/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "postgresql" "nc -z ${SERVICE_IP} 5432 &> /dev/null"

  echo -ne "done."
}
convert_ldap() {
  #### Convert LDAP
  echo -ne "\n* Converting ldap.."
 
  # Remove LDAP files so we can start clean
  rm -rf /federated/apps/ldap/data/var/lib/ldap/*
  rm -rf /federated/apps/ldap/data/etc/ldap/slapd.d/*
  rm -rf /federated/apps/ldap/data/root/.ldaprc
  rm -rf /federated/apps/ldap/data/certs/dhparam.pem

  convert_generic ldap
  sed -i "s#LDAP_DOMAIN=.*#LDAP_DOMAIN=$DOMAIN_NEW#g" /federated/apps/ldap/.env
  sed -i "s#LDAP_ORGANISATION=.*#LDAP_ORGANISATION=$ORG_NEW#g" /federated/apps/ldap/.env
  cp /federated/certs/certs/$DOMAIN_NEW.crt /federated/certs/private/$DOMAIN_NEW.key /federated/apps/ldap/data/certs/

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/ldap/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "ldap" "nc -z $SERVICE_IP 636 &> /dev/null"

  # DEBUG output of the ldif
  echo "/root/convertdomain1.ldif before import"
  echo "---------------------------------------"
  cat /federated/apps/ldap/data/root/convertdomain1.ldif

  # This imports the modified LDAP configuration above
  docker exec ldap bash -c "slapadd -v -l /root/convertdomain1.ldif"
  [ $? -ne 0 ] && failcheck "Couldn't slapadd convertdomain1.ldif inside ldap container"

  echo -ne "done."
}
convert_mail() {
  #### Convert Mail
  echo -ne "\n* Converting mail.."

  convert_generic mail
  cp /federated/certs/certs/$DOMAIN_NEW.crt /federated/certs/private/$DOMAIN_NEW.key /federated/apps/mail/data/root/certs/
  
  # Grab the container IP from docker-compose 
  SERVICE_IP=`grep ipv4_address /federated/apps/mail/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "mail" "nc -z $SERVICE_IP 25 &> /dev/null"

  # Generate the DKIM DNS key for new domain
  docker exec mail setup config dkim keysize 2048 domain $DOMAIN_NEW &> /dev/null
  [ $? -ne 0 ] && fail "Couldn't generate DKIM record"

  # Insert the DKIM DNS TXT entry into /federated/apps/pdns container
  DKIM_RECORD_STRIP=`cat /federated/apps/mail/data/tmp/docker-mailserver/opendkim/keys/$DOMAIN_NEW/mail.txt | sed 's/.*(//'`
  DKIM_RECORD=`echo $DKIM_RECORD_STRIP | sed 's/).*//'`
  docker exec pdns pdnsutil add-record $DOMAIN_NEW mail._domainkey TXT 86400 "$DKIM_RECORD" &> /dev/null
  [ $? -ne 0 ] && fail "Couldn't insert DKIM record into /federated/apps/pdns container"

  # Insert the DMARC DNS TXT entry into /federated/apps/pdns container
  docker exec pdns pdnsutil add-record $DOMAIN_NEW _dmarc TXT 86400 "\"v=DMARC1; p=quarantine; rua=mailto:admin@$DOMAIN_NEW; ruf=mailto:admin@$DOMAIN_NEW; sp=none; ri=86400\"" &> /dev/null
  [ $? -ne 0 ] && fail "Couldn't insert DMARC record into /federated/apps/pdns container"

  # Stop and Start mail to reload DKIM
  /federated/bin/stop mail &> /dev/null
  /federated/bin/start mail &> /dev/null

  echo -ne "done."
}
convert_collabora() {
  #### Convert Collabora
  echo -ne "\n* Converting collabora.."

  convert_generic collabora
  cp /federated/certs/certs/$DOMAIN_NEW.crt /federated/certs/private/$DOMAIN_NEW.key /federated/apps/collabora/data/root/certs/
  chown 104 /federated/apps/collabora/data/root/certs/*

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/collabora/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "collabora" "nc -z $SERVICE_IP 9980 &> /dev/null"

  echo -ne "done."
}
convert_nextcloud() {
  #### Convert Nextcloud
  echo -ne "\n* Converting nextcloud.."

  convert_generic nextcloud
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/nextcloud/data/var/www/html/config/config.php
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_accounts SET data=REPLACE(data, '$DOMAIN', '$DOMAIN_NEW') WHERE data LIKE '%$DOMAIN%'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_accounts_data SET value=REPLACE(value, '$DOMAIN', '$DOMAIN_NEW') WHERE value LIKE '%$DOMAIN%'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_appconfig SET configvalue=REPLACE(configvalue, '$DOMAIN', '$DOMAIN_NEW') WHERE configvalue LIKE '%$DOMAIN%'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_appconfig SET configvalue=REPLACE(configvalue, '$DOMAIN_LDAP_dc', '$DOMAIN_NEW_LDAP_dc') WHERE configvalue LIKE '%$DOMAIN%'"
  # (for initial hardcoded federatedcomputer,cloud in temp domains)
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_appconfig SET configvalue=REPLACE(configvalue, 'dc=federatedcomputer,dc=cloud', '$DOMAIN_NEW_LDAP_dc') WHERE configvalue LIKE '%dc=federatedcomputer,dc=cloud'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_mail_accounts SET inbound_host=REPLACE(inbound_host, '$DOMAIN', '$DOMAIN_NEW') WHERE inbound_host LIKE '%$DOMAIN'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_preferences SET configvalue=REPLACE(configvalue, '$DOMAIN', '$DOMAIN_NEW') WHERE configvalue LIKE '%$DOMAIN'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_richdocuments_wopi SET server_host=REPLACE(server_host, '$DOMAIN', '$DOMAIN_NEW') WHERE server_host LIKE '%$DOMAIN%'"
  # Authelia integration...
  # FIXME should we just wipe oc_user_oidc_sessions, given they will probably be invalid
  # with reconfigured authelia anyway?
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_user_oidc_providers SET discovery_endpoint=REPLACE(discovery_endpoint, '$DOMAIN', '$DOMAIN_NEW') WHERE discovery_endpoint LIKE '%$DOMAIN%'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_user_oidc_providers SET end_session_endpoint=REPLACE(end_session_endpoint, '$DOMAIN', '$DOMAIN_NEW') WHERE end_session_endpoint LIKE '%$DOMAIN%'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_user_oidc_sessions SET iss=REPLACE(iss, '$DOMAIN', '$DOMAIN_NEW') WHERE iss LIKE '%$DOMAIN%'"
  # DAV links...
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_calendars SET uri=REPLACE(uri, '/$DOMAIN/', '/$DOMAIN_NEW/') WHERE uri LIKE '%/$DOMAIN/%'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_calendars SET displayname=REPLACE(displayname, '/$DOMAIN/', '/$DOMAIN_NEW/') WHERE displayname LIKE '%/$DOMAIN/%'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_calendarsubscriptions SET uri=REPLACE(uri, '$DOMAIN', '$DOMAIN_NEW') WHERE uri LIKE '%$DOMAIN%'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_calendarsubscriptions SET displayname=REPLACE(displayname, '/$DOMAIN/', '/$DOMAIN_NEW/') WHERE displayname LIKE '%/$DOMAIN/%'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_calendarsubscriptions SET source=REPLACE(source, '/$DOMAIN/', '/$DOMAIN_NEW/') WHERE source LIKE '%/$DOMAIN/%'"
  # Email addresses (for authentication and otherwise)...
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_authtoken SET login_name=REPLACE(login_name, '@$DOMAIN', '@$DOMAIN_NEW') WHERE login_name LIKE '%@$DOMAIN'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_calendar_invitations SET attendee=REPLACE(attendee, '@$DOMAIN', '@$DOMAIN_NEW') WHERE attendee LIKE '%@$DOMAIN'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_calendar_invitations SET organizer=REPLACE(organizer, '@$DOMAIN', '@$DOMAIN_NEW') WHERE attendee LIKE '%@$DOMAIN'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_cards_properties SET value=REPLACE(value, '@$DOMAIN', '@$DOMAIN_NEW') WHERE value LIKE '%@$DOMAIN'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_mail_accounts SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_mail_accounts SET inbound_user=REPLACE(inbound_user, '@$DOMAIN', '@$DOMAIN_NEW') WHERE inbound_user LIKE '%@$DOMAIN'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_mail_coll_addresses SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_mail_recipients SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_mail_trusted_senders SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_recent_contact SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN'"
  # May contain links to dashboard.$DOMAIN etc.
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_bookmarks SET url=REPLACE(url, '$DOMAIN', '$DOMAIN_NEW') WHERE url LIKE '%$DOMAIN%'"
  # This can contain Jitsi links
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_calendar_appt_configs SET location=REPLACE(location, '$DOMAIN', '$DOMAIN_NEW') WHERE location LIKE '%$DOMAIN%'"
  docker exec postgresql psql -U nextcloud -c "UPDATE oc_calendarobjects_props SET value=REPLACE(value, '$DOMAIN', '$DOMAIN_NEW') WHERE value LIKE '%$DOMAIN%'"

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/nextcloud/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "nextcloud" "nc -z $SERVICE_IP 80 &> /dev/null"

  echo -ne "done."
}
convert_matrix() {
  #### Convert Matrix
  echo -ne "\n* Converting matrix.."

  # Delete matrix database so we can start from scratch
  MATRIX_SECRET=$(create_password);
  COTURN_MATRIX_SECRET=$(create_password);
  docker exec postgresql psql -U postgres -c "drop database matrix" &> /dev/null
  docker exec postgresql psql -U postgres -c "drop user matrix" &> /dev/null
  docker exec postgresql psql -U postgres -c "CREATE USER matrix WITH PASSWORD '$MATRIX_SECRET'"
  docker exec postgresql psql -U postgres -c "CREATE DATABASE matrix"
  docker exec postgresql psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE matrix TO matrix"

  convert_generic matrix

  rm -rf /federated/apps/matrix/data
  mkdir -p /federated/apps/matrix/data/matrix
  cp /federated/certs/certs/$DOMAIN_NEW.crt /federated/certs/private/$DOMAIN_NEW.key /federated/apps/matrix/data/matrix/
  chmod 644 /federated/apps/matrix/data/matrix/$DOMAIN_NEW.crt /federated/apps/matrix/data/matrix/$DOMAIN_NEW.key
  chown -R 991:991 /federated/apps/matrix/data/matrix

  # Generate the matrix homeserver.yaml file
  docker run --rm -v "/federated/apps/matrix/data/matrix:/data" -e SYNAPSE_SERVER_NAME=matrix.$DOMAIN_NEW -e SYNAPSE_REPORT_STATS=yes matrixdotorg/synapse:latest generate &> /dev/null
  [ $? -ne 0 ] && fail "Couldn't run docker matrixdotorg/synapse:latest generate"

  # Take out default Sqlite database config
  sed -i 's!database: /data/homeserver.db!!g' /federated/apps/matrix/data/matrix/homeserver.yaml
  sed -i 's!database:!!g' /federated/apps/matrix/data/matrix/homeserver.yaml
  sed -i 's!name: sqlite3!!g' /federated/apps/matrix/data/matrix/homeserver.yaml
  sed -i 's!args:!!g' /federated/apps/matrix/data/matrix/homeserver.yaml

  # Insert our Postgres and LDAP config
cat >> /federated/apps/matrix/data/matrix/homeserver.yaml <<EOF

web_client_location: https://element.$DOMAIN/
public_baseurl: https://matrix.$DOMAIN_NEW/
serve_server_wellknown: true
turn_uris: [ "turn:turn.$DOMAIN_NEW?transport=udp", "turn:turn.$DOMAIN_NEW?transport=tcp" ]
turn_shared_secret: "$COTURN_MATRIX_SECRET"
turn_user_lifetime: 86400000
database:
    name: psycopg2
    args:
        user: matrix
        password: $MATRIX_SECRET
        host: postgresql.$DOMAIN_NEW
        database: matrix
        cp_min: 5
        cp_max: 10
email:
  smtp_host: "mail.$DOMAIN_NEW"
  smtp_port: 587
  smtp_user: "$SMTPUSER"
  smtp_pass: "$ADMINPASS"
  force_tls: true
  #  require_transport_security: true
  enable_tls: true
  notif_from: "Your Friendly %(app)s homeserver <matrix@matrix.$DOMAIN_NEW>"
  app_name: $ORG_NEW Matrix Server

modules:
  - module: "ldap_auth_provider.LdapAuthProviderModule"
    config:
      enabled: true
      uri: "ldaps://ldap.$DOMAIN_NEW:636"
      start_tls: true
      base: "$DOMAIN_NEW_LDAP_dc"
      attributes:
        mail: "mail"
        uid: "uid"
        name: "givenName"
      bind_dn: cn=admin,$DOMAIN_NEW_LDAP_dc
      bind_password: $LDAP_SECRET
      tls_options:
        validate: true
        local_certificate_file: /data/$DOMAIN_NEW.crt
        local_private_key_file: /data/$DOMAIN_NEW.key
EOF

  chown -R 991:991 /federated/apps/matrix/data/matrix

#  sed -i "s#server_name: \"matrix.$DOMAIN\"#server_name: \"matrix.$DOMAIN_NEW\"#g" /federated/apps/matrix/data/matrix/homeserver.yaml
#  sed -i "s#smtp_host: \"mail.$DOMAIN\"#smtp_host: \"mail.$DOMAIN_NEW\"#g" /federated/apps/matrix/data/matrix/homeserver.yaml
#  sed -i "s#notif_from:.*#notif_from: \"Your Friendly %(app)s homeserver <matrix@matrix.$DOMAIN_NEW>\"#g" /federated/apps/matrix/data/matrix/homeserver.yaml
#  sed -i "s#app_name:.*#app_name: $ORG_NEW Matrix Server#g" /federated/apps/matrix/data/matrix/homeserver.yaml
#  sed -i "s#postgresql.$DOMAIN#postgresql.$DOMAIN_NEW#g" /federated/apps/matrix/data/matrix/homeserver.yaml
#  sed -i "s#ldap.$DOMAIN#ldap.$DOMAIN_NEW#g" /federated/apps/matrix/data/matrix/homeserver.yaml
#  sed -i "s#$DOMAIN.crt#$DOMAIN_NEW.crt#g" /federated/apps/matrix/data/matrix/homeserver.yaml
#  sed -i "s#$DOMAIN.key#$DOMAIN_NEW.key#g" /federated/apps/matrix/data/matrix/homeserver.yaml


  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/matrix/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "matrix" "nc -z $SERVICE_IP 8008 &> /dev/null"

  chown -R 991:991 /federated/apps/matrix/data/matrix

  # Set admin user as admin in Matrix
  docker exec postgresql psql -U matrix -c "update users set admin='1' where name='\"@admin:matrix.$DOMAIN_NEW\"'" &> /dev/null

  # Configure SSO to Authelia
  MATRIX_CLIENT_SECRET=$(cat /federated/apps/matrix/.matrix.client.secret)

cat >> /federated/apps/matrix/data/matrix/homeserver.yaml <<EOF
oidc_providers:
  - idp_id: authelia
    idp_name: "Authelia"
    idp_icon: "mxc://authelia.com/cKlrTPsGvlpKxAYeHWJsdVHI"
    discover: true
    issuer: "https://authelia.$DOMAIN_NEW"
    client_id: "matrix"
    client_secret: "$MATRIX_CLIENT_SECRET"
    scopes: ["openid", "profile", "email"]
    allow_existing_users: true
    user_mapping_provider:
      config:
        subject_claim: "sub"
        localpart_template: "{{ user.name }}"
        display_name_template: "{{ user.name }}"
        email_template: "{{ user.email }}"
EOF

  # Restart Matrix for changes to take the above configuration
  run_command "/federated/bin/stop matrix"
  run_command "/federated/bin/start matrix"

  echo -ne "done."
}
convert_element() {
  #### Convert Element
  echo -ne "\n* Converting element.."

  convert_generic element
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/element/data/element/element-config.json

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/element/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "element" "nc -z $SERVICE_IP 80 &> /dev/null"

  echo -ne "done."
}
convert_listmonk() {
  #### Convert Listmonk
  echo -ne "\n* Converting listmonk.."

  convert_generic listmonk
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/listmonk/data/listmonk/config.toml

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/listmonk/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "listmonk" "nc -z $SERVICE_IP 9000 &> /dev/null"

  # Change app.root_url and other settings to our domain
  docker exec postgresql psql -U listmonk -c "update settings set value='\"http://listmonk.$DOMAIN_NEW\"' where key='app.root_url'" &> /dev/null
  docker exec postgresql psql -U listmonk -c "update settings set value='\"listmonk <listmonk@listmonk.$DOMAIN_NEW>\"' where key='app.from_email'" &> /dev/null
  docker exec postgresql psql -U listmonk -c "update settings set value='[{\"host\": \"mail.$DOMAIN_NEW\", \"port\": 587, \"enabled\": true, \"password\": \"$ADMINPASS\", \"tls_type\": \"STARTTLS\", \"username\": \"$SMTPUSER\", \"max_conns\": 10, \"idle_timeout\": \"15s\", \"wait_timeout\": \"5s\", \"auth_protocol\": \"login\", \"email_headers\": [], \"hello_hostname\": \"\", \"max_msg_retries\": 2, \"tls_skip_verify\": false}, {\"host\": \"smtp.gmail.com\", \"port\": 465, \"enabled\": false, \"password\": \"password\", \"tls_type\": \"TLS\", \"username\": \"username@gmail.com\", \"max_conns\": 10, \"idle_timeout\": \"15s\", \"wait_timeout\": \"5s\", \"auth_protocol\": \"login\", \"email_headers\": [], \"hello_hostname\": \"\", \"max_msg_retries\": 2, \"tls_skip_verify\": false}]' where key='smtp';" &> /dev/null

  echo -ne "done."
}
convert_vaultwarden() {
  #### Convert Vaultwarden
  echo -ne "\n* Converting vaultwarden.."

  convert_generic vaultwarden

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/vaultwarden/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "vaultwarden" "nc -z $SERVICE_IP 80 &> /dev/null"

  echo -ne "done."
}
convert_panel() {
  #### Convert Panel
  echo -ne "\n* Converting panel.."

  convert_generic panel
  sed -i "s#SITE_NAME=.*#SITE_NAME=$ORG_NEW Panel#g" /federated/apps/panel/.env

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/panel/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "panel" "nc -z $SERVICE_IP 80 &> /dev/null"

  echo -ne "done."
}
convert_wireguard() {
  #### Convert Wireguard
  echo -ne "\n* Converting wireguard.."

  convert_generic wireguard
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/wireguard/data/config/.donoteditthisfile
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/wireguard/data/config/peer1/peer1.conf
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/wireguard/data/config/coredns/Corefile

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/wireguard/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "wireguard" "nc -uvz $SERVICE_IP 51820 &> /dev/null"

  echo -ne "done."
}
convert_jitsi() {
  #### Convert Jitsi
  echo -ne "\n* Converting jitsi.."

  convert_generic jitsi

  start_service_convert "jitsi" "nc -z 192.168.0.25 443 &> /dev/null"

  echo -ne "done."
}
convert_baserow() {
  #### Convert Baserow
  echo -ne "\n* Converting baserow.."

  convert_generic baserow
  docker exec postgresql bash -c "psql -U baserow -c \"UPDATE auth_user SET username=REPLACE(username, '@$DOMAIN','@$DOMAIN_NEW') WHERE username LIKE '%@$DOMAIN'\"" &> /dev/null
  [ $? -ne 0 ] && fail "Couldn't update auth_user table (username) in baserow"

  docker exec postgresql bash -c "psql -U baserow -c \"UPDATE auth_user SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN'\"" &> /dev/null
  [ $? -ne 0 ] && fail "Couldn't update auth_user table (email) in baserow"

  start_service_convert "baserow" "docker exec baserow curl http://localhost:8000 &> /dev/null"

  echo -ne "done."
}
convert_gitea() {
  #### Convert Gitea
  echo -ne "\n* Converting gitea.."

  convert_generic gitea
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/gitea/data/data/gitea/conf/app.ini

  # Replace users in Gitea postgres database with new domain name
  LOWER_DOMAIN_NEW="$(echo $DOMAIN_NEW |tr 'A-Z' 'a-z')"
  docker exec postgresql bash -c "psql -U gitea -c \"UPDATE email_address SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN'\""
  docker exec postgresql bash -c "psql -U gitea -c \"UPDATE email_address SET lower_email=REPLACE(lower_email, '@$DOMAIN', '@$LOWER_DOMAIN_NEW') WHERE lower_email LIKE '%@$DOMAIN'\""

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/gitea/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "gitea" "nc -z $SERVICE_IP 3000 &> /dev/null"

  # Delete the current admin and create the admin user with new domain name
  # FIXME we used to do
  #docker exec --user 1000 gitea bash -c "gitea admin user delete --id 1"
  #docker exec --user 1000 gitea gitea admin user create --admin --username gitea --password $ADMINPASS --email admin@$DOMAIN_NEW
  # here, but that doesn't seem necessary given we fixed the users above?

  # Configure SSO to Authelia
  GITEA_CLIENT_SECRET=$(cat /federated/apps/gitea/.gitea.client.secret)
  GITEA_AUTH_ID=$(docker exec --user 1000 gitea gitea admin auth list | tail -1 | awk '{ print $1 }')
  docker exec --user 1000 gitea gitea admin auth delete --id ${GITEA_AUTH_ID}
  docker exec --user 1000 gitea gitea admin auth add-oauth --name "Authelia" --provider "openidConnect" --key "gitea" --secret "$GITEA_CLIENT_SECRET" --auto-discover-url "https://authelia.$DOMAIN_NEW/.well-known/openid-configuration" --skip-local-2fa "true" --scopes "openid email profile" --group-claim-name "groups" --admin-group "admin" --restricted-group "guest"

  echo -ne "done."
}
convert_caddy() {
  #### Convert Caddy
  echo -ne "\n* Converting caddy.."

  convert_generic caddy
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/caddy/data/etc/caddy/Caddyfile

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/caddy/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "caddy" "nc -z $SERVICE_IP 80 &> /dev/null"

  echo -ne "done."
}
convert_castopod() {
  #### Convert Castopod
  echo -ne "\n* Converting castopod.."

  convert_generic castopod

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/castopod/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "castopod" "nc -z $SERVICE_IP 8000 &> /dev/null"

  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD castopod -e \"UPDATE cp_auth_identities SET secret=REPLACE(secret, '@$DOMAIN', '@$DOMAIN_NEW) WHERE secret LIKE '%@$DOMAIN';\""
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD castopod -e \"UPDATE cp_users SET username=REPLACE(username, '@$DOMAIN', '@$DOMAIN_NEW') WHERE username LIKE '%@$DOMAIN';\""

  echo -ne "done."
}
convert_autodiscover() {
  #### Convert Autodiscover
  echo -ne "\n* Converting autodiscover.."

  convert_generic autodiscover
  sed -i "s#COMPANY_NAME=.*#COMPANY_NAME=$ORG_NEW#g" /federated/apps/autodiscover/.env

  # Add DNS records for auto discovery
  docker exec pdns pdnsutil add-record $DOMAIN_NEW autoconfig A 86400 $EXTERNALIP
  [ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
  docker exec pdns pdnsutil add-record $DOMAIN_NEW autodiscover A 86400 $EXTERNALIP
  [ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
  docker exec pdns pdnsutil add-record $DOMAIN_NEW @ TXT 86400 "\"mailconf=https://autoconfig.$DOMAIN_NEW/mail/config-v1.1.xml\""
  [ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
  docker exec pdns pdnsutil add-record $DOMAIN_NEW _imaps._tcp SRV 86400 "0 0 993 mail.$DOMAIN_NEW"
  [ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
  docker exec pdns pdnsutil add-record $DOMAIN_NEW _pop3s._tcp SRV 86400 "0 0 995 mail.$DOMAIN_NEW"
  [ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
  docker exec pdns pdnsutil add-record $DOMAIN_NEW _imaps._tcp SRV 86400 "0 0 993 mail.$DOMAIN_NEW"
  [ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
  docker exec pdns pdnsutil add-record $DOMAIN_NEW _submission._tcp SRV 86400 "0 0 587 $DOMAIN_NEW"
  [ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
  docker exec pdns pdnsutil add-record $DOMAIN_NEW _autodiscover._tcp SRV 86400 "0 0 443 autodiscover.$DOMAIN_NEW"
  [ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"
  docker exec pdns pdnsutil add-record $DOMAIN_NEW _ldap._tcp SRV 86400 "0 0 636 ldap.$DOMAIN_NEW"
  [ $? -ne 0 ] && fail "Couldn't add dns record for auto discovery"

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/autodiscover/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "autodiscover" "nc -z $SERVICE_IP 8000 &> /dev/null"

  echo -ne "done."
}
convert_wordpress() {
  #### Convert Wordpress
  echo -ne "\n* Converting wordpress.."

  convert_generic wordpress
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/wordpress/data/bitnami/wordpress/wp-config.php
  sed -i "s#WORDPRESS_BLOG_NAME=.*#WORDPRESS_BLOG_NAME=$ORG_NEW#g" /federated/apps/wordpress/.env

  # This covers option_name='home', 'siteurl' and 'admin_email' (and potentially more)
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD wordpress -e \"UPDATE wp_options SET option_value=REPLACE(option_value, '$DOMAIN', '$DOMAIN_NEW') WHERE option_value LIKE '%$DOMAIN%';\""
  # Users
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD wordpress -e \"UPDATE wp_users SET user_login=REPLACE(user_login, '@$DOMAIN', '@$DOMAIN_NEW') WHERE user_login LIKE '%@$DOMAIN';\""
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD wordpress -e \"UPDATE wp_users SET user_email=REPLACE(user_email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE user_email LIKE '%@$DOMAIN';\""
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD wordpress -e \"UPDATE wp_usermeta SET meta_value=REPLACE(meta_value, '@$DOMAIN', '@$DOMAIN_NEW') WHERE meta_value LIKE '%@$DOMAIN';\""
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD wordpress -e \"UPDATE wp_users SET display_name=REPLACE(display_name, '@$DOMAIN', '@$DOMAIN_NEW') WHERE display_name LIKE '%@$DOMAIN';\""
  # Fix references in posts
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD wordpress -e \"UPDATE wp_posts SET post_content=REPLACE(post_content, '$DOMAIN', '$DOMAIN_NEW') WHERE post_content LIKE '%$DOMAIN%';\""

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/wordpress/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "wordpress" "nc -z $SERVICE_IP 8080 &> /dev/null"

  echo -ne "done."
}
convert_coturn() {
  #### Convert Coturn
  echo -ne "\n* Converting coturn.."

  convert_generic coturn
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/coturn/data/etc/turnserver.conf
  sed -i "s#static-auth-secret=.*#static-auth-secret=$COTURN_MATRIX_SECRET#g" /federated/apps/coturn/data/etc/turnserver.conf

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/coturn/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "coturn" "nc -z $SERVICE_IP 3478 &> /dev/null"

  echo -ne "done."
}
convert_bookstack() {
  #### Convert Bookstack
  echo -ne "\n* Converting bookstack.."

  convert_generic bookstack
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/bookstack/data/config/www/.env

  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD bookstack -e \"UPDATE users SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN';\""

  # Setup external_auth_id for each user in bookstack users table
  BOOKSTACK_SECRET=$(cat /federated/apps/bookstack/.env | grep "DB_PASS" | awk -F= '{ print $2 }')
#  for i in $(docker exec pdnsmysql mysql -ubookstack -p${BOOKSTACK_SECRET} bookstack -sN -e "select email from users;"); do
#    docker exec pdnsmysql mysql -ubookstack -p${BOOKSTACK_SECRET} bookstack -e "update users set external_auth_id = '$i' where email = '$i'";
#  done

  LOWER_DOMAIN="$(echo $DOMAIN |tr 'A-Z' 'a-z')"
  LOWER_DOMAIN_NEW="$(echo $DOMAIN_NEW |tr 'A-Z' 'a-z')"
  docker exec pdnsmysql mysql -ubookstack -p${BOOKSTACK_SECRET} bookstack -sN -e "UPDATE users SET email=REPLACE(email, '@$LOWER_DOMAIN', '@$LOWER_DOMAIN_NEW') WHERE email LIKE '%@$LOWER_DOMAIN';";
  docker exec pdnsmysql mysql -ubookstack -p${BOOKSTACK_SECRET} bookstack -sN -e "UPDATE users SET external_auth_id=REPLACE(external_auth_id, '@$LOWER_DOMAIN', '@$LOWER_DOMAIN_NEW') WHERE external_auth_id LIKE '%@$LOWER_DOMAIN';";

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/bookstack/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "bookstack" "nc -z $SERVICE_IP 80 &> /dev/null"

  echo -ne "done."
}
convert_freescout() {
  #### Convert Freescout
  echo -ne "\n* Converting freescout.."

  convert_generic freescout

  docker exec postgresql bash -c "psql -U freescout -c \"UPDATE users SET email=REPLACE(email, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email LIKE '%@$DOMAIN'\""

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/freescout/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "freescout" "nc -z $SERVICE_IP 80 &> /dev/null"

  echo -ne "done."
}
convert_msp() {
  #### Convert MSP
  echo -ne "\n* Converting msp.."

  convert_generic msp

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/msp/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "msp" "nc -z $SERVICE_IP 3000 &> /dev/null"

  echo -ne "done."
}
convert_espocrm() {
  #### Convert EspoCRM
  echo -ne "\n* Converting espocrm.."

  # Grab the SSO client secret for config below before removing espocrm
  ESPOCRM_CLIENT_SECRET=$(cat /federated/apps/espocrm/.env | grep ESPOCRM_CONFIG_OIDC_CLIENT_SECRET | awk -F= '{ print $2 }')
  ESPOCRM_IMAGE_VERSION=$(cat /federated/apps/espocrm/.env | grep IMAGE_VERSION | awk -F\" '{ print $2 }')

  convert_generic espocrm
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g;s#$DOMAIN_LDAP_dc#$DOMAIN_NEW_LDAP_dc#g;s#$DOMAIN_LDAP_DC#$DOMAIN_NEW_LDAP_DC#g;s#dc=federatedcomputer,dc=cloud#$DOMAIN_NEW_LDAP_dc#g" /federated/apps/espocrm/data/var/www/html/data/config.php /federated/apps/espocrm/data/var/www/html/data/config-internal.php

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/espocrm/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "espocrm" "nc -z $SERVICE_IP 80 &> /dev/null"

  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD espocrm -e \"UPDATE user SET user_name=REPLACE(user_name, '@$DOMAIN', '@$DOMAIN_NEW') WHERE user_name LIKE '%@$DOMAIN';\""
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD espocrm -e \"UPDATE email_account SET email_address=REPLACE(email_address, '@$DOMAIN', '@$DOMAIN_NEW') WHERE email_address LIKE '%@$DOMAIN';\""
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD espocrm -e \"UPDATE email_account SET username=REPLACE(username, '@$DOMAIN', '@$DOMAIN_NEW') WHERE username LIKE '%@$DOMAIN';\""
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD espocrm -e \"UPDATE email_account SET smtp_username=REPLACE(smtp_username, '@$DOMAIN', '@$DOMAIN_NEW') WHERE smtp_username LIKE '%@$DOMAIN';\""
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD espocrm -e \"UPDATE email_address SET name=REPLACE(name, '@$DOMAIN', '@$DOMAIN_NEW') WHERE name LIKE '%@$DOMAIN';\""
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD espocrm -e \"UPDATE email_address SET lower=REPLACE(lower, '@$DOMAIN', '@$DOMAIN_NEW') WHERE lower LIKE '%@$DOMAIN';\""
  # FIXME did we catch every possible place for email addresses above?

  run_command "/federated/bin/stop espocrm"
  run_command "/federated/bin/start espocrm"

  echo -ne "done."
}
convert_dashboard() {
  #### Convert Dashboard
  echo -ne "\n* Converting dashboard.."

  convert_generic dashboard

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/dashboard/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "dashboard" "nc -z $SERVICE_IP 8080 &> /dev/null"

  echo -ne "done."
}
convert_roundcube() {
  #### Convert Roundcube
  echo -ne "\n* Converting roundcube.."

  convert_generic roundcube
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/roundcube/data/var/www/html/config/config.inc.php

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/roundcube/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "roundcube" "nc -z $SERVICE_IP 80 &> /dev/null"

  echo -ne "done."
}
convert_authelia() {
  #### Convert Authelia
  echo -ne "\n* Converting authelia.."

  convert_generic authelia
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/authelia/data/config/configuration.yml
  sed -i "s#$DOMAIN#$DOMAIN_NEW#g" /federated/apps/authelia/data/config/idproviders.yml

  # Configure SSO to Authelia
  # Delete the entries in the pdns settings table
  [[ -d "/federated/apps/pdnsmysql/data/var/lib/mysql/pdnsadmin" ]] && POWERDNS_DB="pdnsadmin" || POWERDNS_DB="pdns"
  POWERDNS_CLIENT_SECRET=$(docker exec pdnsmysql mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e "select value from setting where name='oidc_oauth_secret';" |tail -n1)
  docker exec pdnsmysql mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e "delete from setting where name like '%oidc_oauth%';"

  # Insert PowerDNS configuration because we need an initial
  # config for Authelia to run
  PDNS_MYSQL_COMMAND1="insert into setting (name, value) values (\"oidc_oauth_enabled\", \"True\");insert into setting (name, value) values (\"oidc_oauth_key\", \"powerdns\");"
  PDNS_MYSQL_COMMAND2="insert into setting (name, value) values (\"oidc_oauth_scope\", \"openid profile groups email\");insert into setting (name, value) values (\"oidc_oauth_api_url\", \"https://authelia.$DOMAIN_NEW/api/oidc/userinfo\");"
  PDNS_MYSQL_COMMAND3="insert into setting (name, value) values (\"oidc_oauth_auto_configure\", \"True\");insert into setting (name, value) values (\"oidc_oauth_metadata_url\", \"https://authelia.$DOMAIN_NEW/.well-known/openid-configuration\");"
  PDNS_MYSQL_COMMAND4="insert into setting (name, value) values (\"oidc_oauth_token_url\", \"\");insert into setting (name, value) values (\"oidc_oauth_authorize_url\", \"\");"
  PDNS_MYSQL_COMMAND5="insert into setting (name, value) values (\"oidc_oauth_logout_url\", \"https://authelia.$DOMAIN_NEW/logout\");insert into setting (name, value) values (\"oidc_oauth_username\", \"preferred_username\");"
  PDNS_MYSQL_COMMAND6="insert into setting (name, value) values (\"oidc_oauth_email\", \"email\");insert into setting (name, value) values (\"oidc_oauth_firstname\", \"preferred_username\");"
  PDNS_MYSQL_COMMAND7="insert into setting (name, value) values (\"oidc_oauth_last_name\", \"name\");insert into setting (name, value) values (\"oidc_oauth_account_name_property\", \"preferred_username\");"
  PDNS_MYSQL_COMMAND8="insert into setting (name, value) values (\"oidc_oauth_account_description_property\", \"name\");insert into setting (name, value) values (\"oidc_oauth_secret\", \"$POWERDNS_CLIENT_SECRET\");"
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND;'"
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND1;'"
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND2;'"
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND3;'"
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND4;'"
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND5;'"
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND6;'"
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND7;'"
  docker exec pdnsmysql bash -c "mysql -uroot -p$MYSQL_ROOTPASSWORD $POWERDNS_DB -e '$PDNS_MYSQL_COMMAND8;'"

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/authelia/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  start_service_convert "authelia" "nc -z $SERVICE_IP 9091 &> /dev/null"

  echo -ne "done."
}
convert_jitsiopenid() {
  #### Convert JitsiOpenID
  echo -ne "\n* Converting jitsiopenid.."

  convert_generic jitsiopenid

  # Grab the container IP from docker-compose
  SERVICE_IP=`grep ipv4_address /federated/apps/jitsiopenid/docker-compose.yml | awk '{ print $2 }'`

  # Start service with command to make sure it's up before proceeding
  run_command "/federated/bin/start jitsiopenid"

  echo -ne "done."
}

usage() {
  echo "$0: <domain.com> <organization name>"
  exit 2
}

DNS_DONE=false
if [ "$1" = "-d" -o "$1" = "--dns-done" ]; then
	DNS_DONE=true
	shift
fi

[ $# != 2 ] && usage
DOMAIN_NEW=$1
ORG_NEW=$2

# Check if DNS works
EXTERNALIP=`dig @resolver4.opendns.com myip.opendns.com +short 2> /dev/null`
[ $? -ne 0 ] && failcheck "Couldn't run dig, dns is not working"

# Setup DOMAIN variables for domain or subdomain
if ! echo $DOMAIN_NEW |grep -q '\.'; then
  failcheck "$DOMAIN_NEW is not a valid domain.com or sub.domain.com"
fi
DOMAIN_NEW_LDAP_dc="dc=${DOMAIN_NEW//./,dc=}"
DOMAIN_NEW_LDAP_DC="DC=${DOMAIN_NEW//./,DC=}"
DOMAIN_LDAP_dc="dc=${DOMAIN//./,dc=}"
DOMAIN_LDAP_DC="DC=${DOMAIN//./,DC=}"

ADMINPASS=`cat /federated/bin/.adminpass | head -1`
LDAP_SECRET=`cat /federated/apps/ldap/.ldap.secret`

MYSQL_ROOTPASSWORD=`cat /federated/apps/pdnsmysql/.env | grep MYSQL_ROOT_PASSWORD | awk -F= '{ print $2 }'`

# Set SMTP user based on if fcore exists
[[ $(docker exec ldap slapcat | grep fcore) ]] && SMTPUSER="fcore" || SMTPUSER="admin"

echo -ne "\n\nConverting Federated Core $DOMAIN to $DOMAIN_NEW.\n\n"

# Key initial steps
if ! $DNS_DONE; then
	check_gluerecords
#get_installedapps
	do_serviceprep_dns
fi
do_serviceprep_ldap

# Stop all services
/federated/bin/stop all &> /dev/null

# Convert each services in SERVICES list
for i in "${SERVICES[@]}"; do
  if [ -d "/federated/apps/$i" ]; then
    convert_$i
  fi
done
