From e03d056d8af00b120679d2473f0c63a3dfce9193 Mon Sep 17 00:00:00 2001
From: Bob Mottram <bob@freedombone.net>
Date: Mon, 21 May 2018 13:45:54 +0100
Subject: [PATCH] Beginning of hackmd

---
 src/freedombone-app-hackmd | 484 +++++++++++++++++++++++++++++++++++++
 1 file changed, 484 insertions(+)
 create mode 100755 src/freedombone-app-hackmd

diff --git a/src/freedombone-app-hackmd b/src/freedombone-app-hackmd
new file mode 100755
index 000000000..c2a50e913
--- /dev/null
+++ b/src/freedombone-app-hackmd
@@ -0,0 +1,484 @@
+#!/bin/bash
+#
+#  _____               _           _
+# |   __|___ ___ ___ _| |___ _____| |_ ___ ___ ___
+# |   __|  _| -_| -_| . | . |     | . | . |   | -_|
+# |__|  |_| |___|___|___|___|_|_|_|___|___|_|_|___|
+#
+#                              Freedom in the Cloud
+#
+# License
+# =======
+#
+# Copyright (C) 2018 Bob Mottram <bob@freedombone.net>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+VARIANTS='full full-vim'
+
+IN_DEFAULT_INSTALL=0
+SHOW_ON_ABOUT=1
+
+HACKMD_DOMAIN_NAME=
+HACKMD_CODE=
+HACKMD_ONION_PORT=9052
+HACKMD_REPO="https://github.com/hackmdio/hackmd"
+HACKMD_COMMIT='c71361467d6eee6519b050fb5c40fc32520a19a8'
+HACKMD_PORT_INTERNAL=TODO
+
+hackmd_variables=(ONION_ONLY
+                  HACKMD_DOMAIN_NAME
+                  HACKMD_CODE
+                  DDNS_PROVIDER
+                  MY_USERNAME)
+
+function logging_on_hackmd {
+    echo -n ''
+}
+
+function logging_off_hackmd {
+    echo -n ''
+}
+
+function remove_user_hackmd {
+    remove_username="$1"
+
+    "${PROJECT_NAME}-pass" -u "$remove_username" --rmapp hackmd
+}
+
+function add_user_hackmd {
+    new_username="$1"
+    new_user_password="$2"
+
+    "${PROJECT_NAME}-pass" -u "$new_username" -a hackmd -p "$new_user_password"
+    echo '0'
+}
+
+function install_interactive_hackmd {
+    if [ ! "$ONION_ONLY" ]; then
+        ONION_ONLY='no'
+    fi
+
+    if [[ "$ONION_ONLY" != "no" ]]; then
+        HACKMD_DOMAIN_NAME='hackmd.local'
+        write_config_param "HACKMD_DOMAIN_NAME" "$HACKMD_DOMAIN_NAME"
+    else
+        interactive_site_details "hackmd" "HACKMD_DOMAIN_NAME" "HACKMD_CODE"
+    fi
+    APP_INSTALLED=1
+}
+
+function change_password_hackmd {
+    curr_username="$1"
+    new_user_password="$2"
+
+    read_config_param 'HACKMD_DOMAIN_NAME'
+
+    "${PROJECT_NAME}-pass" -u "$curr_username" -a hackmd -p "$new_user_password"
+}
+
+function hackmd_create_database {
+    if [ -f $IMAGE_PASSWORD_FILE ]; then
+        HACKMD_ADMIN_PASSWORD="$(printf "%d" "$(cat "")")"
+    else
+        if [ ! $HACKMD_ADMIN_PASSWORD ]; then
+            HACKMD_ADMIN_PASSWORD="$(create_password ${MINIMUM_PASSWORD_LENGTH})"
+        fi
+    fi
+    if [ ! $HACKMD_ADMIN_PASSWORD ]; then
+        return
+    fi
+
+    create_database hackmd "$HACKMD_ADMIN_PASSWORD" $MY_USERNAME
+}
+
+function reconfigure_hackmd {
+    # This is used if you need to switch identity. Dump old keys and generate new ones
+    echo -n ''
+}
+
+function configure_interactive_hackmd {
+    W=(1 $"Option 1"
+       2 $"Option 2")
+
+    while true
+    do
+        # shellcheck disable=SC2068
+        selection=$(dialog --backtitle $"Freedombone Administrator Control Panel" --title $"hackmd" --menu $"Choose an operation, or ESC for main menu:" 14 70 3 "${W[@]}" 3>&2 2>&1 1>&3)
+
+        if [ ! "$selection" ]; then
+            break
+        fi
+        case $selection in
+            1) # call some function for option 1
+            ;;
+            2) # call some function for option 2
+            ;;
+        esac
+    done
+}
+
+function upgrade_hackmd {
+    CURR_HACKMD_COMMIT=$(get_completion_param "hackmd commit")
+    if [[ "$CURR_HACKMD_COMMIT" == "$HACKMD_COMMIT" ]]; then
+        return
+    fi
+
+    if grep -q "hackmd domain" "$COMPLETION_FILE"; then
+        HACKMD_DOMAIN_NAME=$(get_completion_param "hackmd domain")
+    fi
+
+    # update to the next commit
+    set_repo_commit "/etc/hackmd" "hackmd commit" "$HACKMD_COMMIT" "$HACKMD_REPO"
+    chown -R hackmd:hackmd "/etc/hackmd"
+    systemctl restart hackmd
+}
+
+function backup_local_hackmd {
+    HACKMD_DOMAIN_NAME='hackmd'
+    if grep -q "hackmd domain" "$COMPLETION_FILE"; then
+        HACKMD_DOMAIN_NAME=$(get_completion_param "hackmd domain")
+    fi
+
+    source_directory=/etc/hackmd
+
+    suspend_site "${HACKMD_DOMAIN_NAME}"
+
+    systemctl stop hackmd
+
+    dest_directory=hackmd
+    backup_directory_to_usb "$source_directory" $dest_directory
+
+    backup_database_to_usb hackmd
+
+    restart_site
+    systemctl start hackmd
+}
+
+function restore_local_hackmd {
+    if ! grep -q "hackmd domain" "$COMPLETION_FILE"; then
+        return
+    fi
+    HACKMD_DOMAIN_NAME=$(get_completion_param "hackmd domain")
+    if [ ! "$HACKMD_DOMAIN_NAME" ]; then
+        return
+    fi
+    suspend_site "${HACKMD_DOMAIN_NAME}"
+    systemctl stop hackmd
+
+    temp_restore_dir=/root/temphackmd
+    hackmd_dir=/etc/hackmd
+
+    hackmd_create_database
+
+    restore_database hackmd
+    if [ -d $temp_restore_dir ]; then
+        rm -rf $temp_restore_dir
+    fi
+
+    restore_directory_from_usb $temp_restore_dir hackmd
+    if [ -d $temp_restore_dir ]; then
+        if [ -d "$temp_restore_dir$hackmd_dir" ]; then
+            cp -rp "$temp_restore_dir$hackmd_dir"/* "$hackmd_dir"/
+        else
+            if [ ! -d "$hackmd_dir" ]; then
+                mkdir "$hackmd_dir"
+            fi
+            cp -rp "$temp_restore_dir"/* "$hackmd_dir"/
+        fi
+        chown -R hackmd:hackmd "$hackmd_dir"
+        rm -rf $temp_restore_dir
+    fi
+    systemctl start hackmd
+
+    restart_site
+}
+
+function backup_remote_hackmd {
+    HACKMD_DOMAIN_NAME='hackmd'
+    if grep -q "hackmd domain" "$COMPLETION_FILE"; then
+        HACKMD_DOMAIN_NAME=$(get_completion_param "hackmd domain")
+    fi
+
+    source_directory=/etc/hackmd
+
+    suspend_site "${HACKMD_DOMAIN_NAME}"
+    systemctl stop hackmd
+
+    dest_directory=hackmd
+    backup_directory_to_friend "$source_directory" $dest_directory
+    backup_database_to_friend hackmd
+
+
+    systemctl start hackmd
+
+    restart_site
+}
+
+function restore_remote_hackmd {
+    if ! grep -q "hackmd domain" "$COMPLETION_FILE"; then
+        return
+    fi
+    HACKMD_DOMAIN_NAME=$(get_completion_param "hackmd domain")
+    if [ ! "$HACKMD_DOMAIN_NAME" ]; then
+        return
+    fi
+    suspend_site "${HACKMD_DOMAIN_NAME}"
+    systemctl stop hackmd
+
+    temp_restore_dir=/root/temphackmd
+    hackmd_dir=/etc/hackmd
+
+    hackmd_create_database
+
+    restore_database_from_friend hackmd
+    if [ -d "$temp_restore_dir" ]; then
+        rm -rf $temp_restore_dir
+    fi
+
+    restore_directory_from_friend $temp_restore_dir hackmd
+    if [ -d $temp_restore_dir ]; then
+        if [ -d "$temp_restore_dir$hackmd_dir" ]; then
+            cp -rp "$temp_restore_dir$hackmd_dir"/* "$hackmd_dir"/
+        else
+            if [ ! -d "$hackmd_dir" ]; then
+                mkdir "$hackmd_dir"
+            fi
+            cp -rp $temp_restore_dir/* "$hackmd_dir"/
+        fi
+        chown -R hackmd:hackmd "$hackmd_dir"
+        rm -rf $temp_restore_dir
+    fi
+    systemctl start hackmd
+
+    restart_site
+}
+
+function remove_hackmd {
+    nginx_dissite "$HACKMD_DOMAIN_NAME"
+    remove_certs "$HACKMD_DOMAIN_NAME"
+
+    if [ -f /etc/systemd/system/hackmd.service ]; then
+        systemctl stop hackmd
+        systemctl disable hackmd
+        rm /etc/systemd/system/hackmd.service
+    fi
+    userdel -r hackmd
+    remove_nodejs hackmd
+
+
+    if [ -d "/var/www/$HACKMD_DOMAIN_NAME" ]; then
+        rm -rf "/var/www/$HACKMD_DOMAIN_NAME"
+    fi
+    if [ -f "/etc/nginx/sites-available/$HACKMD_DOMAIN_NAME" ]; then
+        rm "/etc/nginx/sites-available/$HACKMD_DOMAIN_NAME"
+    fi
+    drop_database hackmd
+    remove_onion_service hackmd "${HACKMD_ONION_PORT}"
+    if grep -q "hackmd" /etc/crontab; then
+        sed -i "/hackmd/d" /etc/crontab
+    fi
+    remove_app hackmd
+    remove_completion_param install_hackmd
+    sed -i '/hackmd/d' "$COMPLETION_FILE"
+
+    remove_ddns_domain "$HACKMD_DOMAIN_NAME"
+}
+
+function hackmd_create_config {
+    { echo '{';
+      echo '    "production": {';
+      echo '        "domain": "localhost",';
+      echo '        "hsts": {';
+      echo '            "enable": true,';
+      echo '            "maxAgeSeconds": "31536000",';
+      echo '            "includeSubdomains": true,';
+      echo '            "preload": true';
+      echo '        },';
+      echo '        "csp": {';
+      echo '            "enable": true,';
+      echo '            "directives": {';
+      echo '            },';
+      echo '            "upgradeInsecureRequests": "auto",';
+      echo '            "addDefaults": true,';
+      echo '            "addDisqus": true,';
+      echo '            "addGoogleAnalytics": true';
+      echo '        },';
+      echo '        "db": {';
+      echo "            \"username\": \"root\",";
+      echo "            \"password\": \"$MARIADB_PASSWORD\",";
+      echo '            "database": "hackmd",';
+      echo '            "host": "localhost",';
+      echo '            "port": "5432",';
+      echo '            "dialect": "mysql"';
+      echo '        },';
+      echo '        "github": {';
+      echo '            "clientID": "change this",';
+      echo '            "clientSecret": "change this"';
+      echo '        },';
+      echo '        "gitlab": {';
+      echo '            "baseURL": "change this",';
+      echo '            "clientID": "change this",';
+      echo '            "clientSecret": "change this",';
+      echo '            "scope": "use read_user scope for auth user only or remove this property if you need gitlab snippet import/export support (will result to be default scope api)"';
+      echo '        }';
+      echo '    }';
+      echo '}'; } > config.json
+}
+
+function install_hackmd {
+    install_mariadb
+
+    get_mariadb_password
+
+    install_nodejs hackmd
+    if [ ! "$HACKMD_DOMAIN_NAME" ]; then
+        echo $'No domain name was given'
+        exit 3568356
+    fi
+
+    if [ -d "/var/www/$HACKMD_DOMAIN_NAME/htdocs" ]; then
+        rm -rf "/var/www/$HACKMD_DOMAIN_NAME/htdocs"
+    fi
+    if [ -d /repos/hackmd ]; then
+        mkdir "/var/www/$HACKMD_DOMAIN_NAME/htdocs"
+        cp -r -p /repos/hackmd/. "/etc/hackmd"
+        cd "/etc/hackmd" || exit 36487365
+        git pull
+    else
+        git_clone "$HACKMD_REPO" "/etc/hackmd"
+    fi
+
+    if [ ! -d "/etc/hackmd" ]; then
+        echo $'Unable to clone hackmd repo'
+        exit 87525
+    fi
+
+    cd "/etc/hackmd" || exit 3463754637
+    git checkout "$HACKMD_COMMIT" -b "$HACKMD_COMMIT"
+    set_completion_param "hackmd commit" "$HACKMD_COMMIT"
+
+    if [ ! -f bin/setup ]; then
+        echo $'No setup file found'
+        exit 36587356
+    fi
+    chmod +x bin/setup
+    ./bin/setup
+    hackmd_create_config
+    npm run build
+
+    chmod g+w "/var/www/$HACKMD_DOMAIN_NAME/htdocs"
+    chown -R www-data:www-data "/var/www/$HACKMD_DOMAIN_NAME/htdocs"
+
+    hackmd_create_database
+
+    add_ddns_domain "$HACKMD_DOMAIN_NAME"
+
+    HACKMD_ONION_HOSTNAME=$(add_onion_service hackmd 80 "${HACKMD_ONION_PORT}")
+
+    hackmd_nginx_site=/etc/nginx/sites-available/$HACKMD_DOMAIN_NAME
+    if [[ "$ONION_ONLY" == "no" ]]; then
+        nginx_http_redirect "$HACKMD_DOMAIN_NAME" "index index.html"
+        { echo 'server {';
+          echo '  listen 443 ssl;';
+          echo '  #listen [::]:443 ssl;';
+          echo "  server_name $HACKMD_DOMAIN_NAME;";
+          echo ''; } >> "$hackmd_nginx_site"
+        nginx_compress "$HACKMD_DOMAIN_NAME"
+        echo '' >> "$hackmd_nginx_site"
+        echo '  # Security' >> "$hackmd_nginx_site"
+        nginx_ssl "$HACKMD_DOMAIN_NAME"
+
+        nginx_security_options "$HACKMD_DOMAIN_NAME"
+
+        { echo '  add_header Strict-Transport-Security max-age=15768000;';
+          echo '';
+          echo '    access_log /dev/null;';
+          echo '    error_log /dev/null;';
+          echo '';
+          echo "    root /var/www/$HACKMD_DOMAIN_NAME/htdocs;";
+          echo '';
+          echo '  index index.html;';
+          echo '  # Location';
+          echo '  location / {'; } >> "$hackmd_nginx_site"
+        nginx_limits "$HACKMD_DOMAIN_NAME" '15m'
+        { echo "    proxy_pass http://localhost:$HACKMD_PORT_INTERNAL;";
+          echo '  }';
+          echo '}'; } >> "$hackmd_nginx_site"
+    else
+        echo -n '' > "$hackmd_nginx_site"
+    fi
+    { echo 'server {';
+      echo "    listen 127.0.0.1:$HACKMD_ONION_PORT default_server;";
+      echo "    server_name $HACKMD_ONION_HOSTNAME;";
+      echo ''; } >> "$hackmd_nginx_site"
+    nginx_compress "$HACKMD_DOMAIN_NAME"
+    echo '' >> "$hackmd_nginx_site"
+    nginx_security_options "$HACKMD_DOMAIN_NAME"
+    { echo '';
+      echo '    access_log /dev/null;';
+      echo '    error_log /dev/null;';
+      echo '';
+      echo "    root /var/www/$HACKMD_DOMAIN_NAME/htdocs;";
+      echo '';
+      echo '  index index.html;';
+      echo '  # Location';
+      echo '  location / {'; } >> "$hackmd_nginx_site"
+    nginx_limits "$HACKMD_DOMAIN_NAME" '15m'
+    { echo "    proxy_pass http://localhost:$HACKMD_PORT_INTERNAL;";
+      echo '  }';
+      echo '}'; } >> "$hackmd_nginx_site"
+
+    adduser --system --home="/etc/hackmd" --group hackmd
+
+
+
+    { echo '[Unit]';
+      echo 'Description=hackmd';
+      echo 'After=syslog.target';
+      echo 'After=network.target';
+      echo "Documentation=$HACKMD_REPO";
+      echo '';
+      echo '[Service]';
+      echo 'Type=simple';
+      echo 'User=hackmd';
+      echo 'Group=hackmd';
+      echo 'WorkingDirectory=/etc/hackmd';
+      echo 'ExecStart=/usr/local/bin/npm start';
+      echo 'ExecStop=/usr/local/bin/npm stop';
+      echo 'Environment=USER=hackmd';
+      echo 'Restart=always';
+      echo 'StandardError=syslog';
+      echo '';
+      echo '[Install]';
+      echo 'WantedBy=multi-user.target'; } >> "/etc/systemd/system/hackmd.service"
+    systemctl enable hackmd
+    chown -R hackmd:hackmd "/etc/hackmd"
+    systemctl start hackmd
+
+    create_site_certificate "$HACKMD_DOMAIN_NAME" 'yes'
+
+    nginx_ensite "$HACKMD_DOMAIN_NAME"
+
+    systemctl restart mariadb
+
+    systemctl restart nginx
+
+    "${PROJECT_NAME}-pass" -u "$MY_USERNAME" -a hackmd -p "$HACKMD_ADMIN_PASSWORD"
+    set_completion_param "hackmd domain" "$HACKMD_DOMAIN_NAME"
+
+    APP_INSTALLED=1
+}
+
+# NOTE: deliberately there is no "exit 0"
-- 
GitLab