-
Bob Mottram authoredBob Mottram authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
freedombone-utils-webadmin 20.20 KiB
#!/bin/bash
# _____ _ _
# | __|___ ___ ___ _| |___ _____| |_ ___ ___ ___
# | __| _| -_| -_| . | . | | . | . | | -_|
# |__| |_| |___|___|___|___|_|_|_|___|___|_|_|___|
#
# Freedom in the Cloud
#
# Web based administration user interface
# typically abailanle on http://freedombone.local
#
# License
# =======
#
# Copyright © 2014-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/>.
function web_admin_avahi {
if [ -f /etc/avahi/services/webadmin.service ]; then
return
fi
{ echo '<?xml version="1.0" standalone="no"?><!--*-nxml-*-->';
echo '<!DOCTYPE service-group SYSTEM "avahi-service.dtd">';
echo '<service-group>';
echo ' <name replace-wildcards="yes">%h http</name>';
echo ' <service>';
echo ' <type>_http._tcp</type>';
echo ' <port>80</port>';
echo ' </service>';
echo ' <service>';
echo ' <type>_https._tcp</type>';
echo ' <port>443</port>';
echo ' </service>';
echo '</service-group>'; } > /etc/avahi/services/webadmin.service
systemctl restart avahi-daemon
}
function web_admin_create_users {
ADMIN_USER=$(get_completion_param "Admin user")
local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local
users_file="/var/www/${local_hostname}/htdocs/admin/users.html"
cp "/var/www/${local_hostname}/htdocs/admin/users_template.html" "$users_file"
sed -i '/users list/,/end of users/d' "$users_file"
sed -i '/<\/body>/d' "$users_file"
sed -i '/<\/html>/d' "$users_file"
echo " <div class=\"row\">" >> "$users_file"
echo " <div class=\"column\">" >> "$users_file"
rm "/var/www/${local_hostname}/htdocs/admin/userprofile_"*
for d in /home/*/ ; do
USERNAME=$(echo "$d" | awk -F '/' '{print $3}')
if [[ $(is_valid_user "$USERNAME") == "1" ]]; then
userfile="/var/www/${local_hostname}/htdocs/admin/userprofile_${USERNAME}.html"
useremail=${USERNAME}@${DEFAULT_DOMAIN_NAME}
GPG_ID=$(su -c "gpg --list-keys '$useremail'" - "$USERNAME" | sed -n '2p' | sed 's/^[ \t]*//')
if [ -f "/home/$USERNAME/.gnupg/gpg.conf" ]; then
if grep -q "default-key" "/home/$USERNAME/.gnupg/gpg.conf"; then
default_gpg_key=$(grep "default-key" "/home/$USERNAME/.gnupg/gpg.conf")
if [[ "$default_gpg_key" != *'#'* ]]; then
default_gpg_key=$(grep "default-key" "/home/$USERNAME/.gnupg/gpg.conf" | awk -F ' ' '{print $2}')
if [ ${#default_gpg_key} -gt 3 ]; then
GPG_ID=$(su -c "gpg --list-keys '$default_gpg_key'" - "$USERNAME" | sed -n '2p' | sed 's/^[ \t]*//')
fi
fi
fi
fi
pubkey_qrcode="/var/www/${local_hostname}/htdocs/admin/userprofile_${USERNAME}.png"
su -c "gpg --armor --export \"$GPG_ID\"" - "$USERNAME" | qrencode -t PNG -o "$pubkey_qrcode"
{ echo ' <div class="chip">';
echo " <a href=\"userprofile_${USERNAME}.html\">";
echo ' <img src="admin_users.png" alt="Person" width="96" height="96">';
echo " $USERNAME";
echo ' </a>';
echo ' </div>'; } >> "$users_file"
cp "/var/www/${local_hostname}/htdocs/admin/userprofile.html" "$userfile"
sed -i "s|USERNAME|${USERNAME}|g" "$userfile"
if [[ "$USERNAME" == "$ADMIN_USER" ]]; then
sed -i "s|USERTYPE|Admin|g" "$userfile"
sed -i '/remove user button/,/end of remove/d' "$userfile"
else
sed -i "s|USERTYPE|User|g" "$userfile"
fi
sed -i "s|USEREMAIL|${useremail}|g" "$userfile"
sed -i "s|USERGPG|${GPG_ID}|g" "$userfile"
chown www-data:www-data "$userfile"
chown www-data:www-data "$pubkey_qrcode"
fi
done
{ echo ' <div class="chip">';
echo " <a href=\"newuser.html\">";
echo ' <img src="admin_users.png" alt="Person" width="96" height="96">';
echo ' +';
echo ' </a>';
echo ' </div>';
echo ' </div>';
echo ' </div>';
echo ' </body>';
echo '</html>'; } >> "$users_file"
chown www-data:www-data "$users_file"
}
function web_admin_create_add_apps {
read_config_param DDNS_PROVIDER
local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local
apps_add_template_filename="/var/www/${local_hostname}/htdocs/admin/apps_add_template.html"
appslist_add_filename="/var/www/${local_hostname}/htdocs/admin/apps_add.html"
pending_installs="/var/www/${local_hostname}/htdocs/admin/pending_installs.txt"
icons_dir="/var/www/${local_hostname}/htdocs/admin/icons"
app_add_template_filename="/var/www/${local_hostname}/htdocs/admin/app_add_template.html"
FILES="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*"
if [ ! -d "$icons_dir" ]; then
mkdir -p "$icons_dir"
fi
if [ ! -f "$apps_add_template_filename" ]; then
return
fi
cp "$apps_add_template_filename" "$appslist_add_filename"
sed -i '/<\/body>/d' "$appslist_add_filename"
sed -i '/<\/html>/d' "$appslist_add_filename"
available_apps_ctr=0
app_index=0
for filename in $FILES
do
app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}')
app_index=0
app_is_installed=
# shellcheck disable=SC2068
for a in ${APPS_INSTALLED[@]}
do
installed_app_name=${APPS_INSTALLED_NAMES[$app_index]}
if [[ "$installed_app_name" == "$app_name" ]]; then
app_is_installed=1
break
fi
app_index=$((app_index+1))
done
# check if the app is pending installation
if [ -f "$pending_installs" ]; then
if grep -q "install_${app_name}" "$pending_installs"; then
app_is_installed=1
fi
fi
if [ ! $app_is_installed ]; then
app_filename="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}"
if [ -f "$app_filename" ]; then
# get the icon for the app
icon_filename="/usr/share/${PROJECT_NAME}/android-app/${app_name}.png"
if [ -f "$icon_filename" ]; then
cp "$icon_filename" "/var/www/${local_hostname}/htdocs/admin/icons/${app_name}.png"
else
icon_filename=
continue
fi
app_name_upper=$(echo "$app_name" | awk '{print toupper($0)}')
SHORT_DESCRIPTION=
DESCRIPTION=
if ! grep -q "${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename"; then
continue
fi
if grep -q "#${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename"; then
continue
fi
SHORT_DESCRIPTION="$(grep "${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename" | head -n 1 | sed 's|\$||g' | sed "s|'||g" | sed 's|\"||g' | awk -F '=' '{print $2}')"
if grep -q "${app_name_upper}_DESCRIPTION=" "$app_filename"; then
DESCRIPTION="$(grep "${app_name_upper}_DESCRIPTION=" "$app_filename" | head -n 1 | sed 's|\$||g' | sed "s|'||g" | sed 's|\"||g' | awk -F '=' '{print $2}')"
fi
if [ $available_apps_ctr -eq 0 ]; then
echo ' <div class="row">' >> "$appslist_add_filename"
fi
filename="/var/www/${local_hostname}/htdocs/admin/app_${app_name}.html"
if [ -f "$filename" ]; then
rm "$filename"
fi
filename="/var/www/${local_hostname}/htdocs/admin/app_add_${app_name}.html"
{ echo ' <div class="column">';
echo ' <div>';
echo " <a href=\"app_add_${app_name}.html\">";
echo " <img src=\"icons/${app_name}.png\" style=\"width:100%\">";
echo " <center>${app_name}</center>";
echo ' </a>';
echo ' </div>';
echo ' </div>'; } >> "$appslist_add_filename"
cp "$app_add_template_filename" "$filename"
# Replace app variables
sed -i "s|HOSTNAME|$(hostname)|g" "$filename"
sed -i "s|APPNAME|${app_name}|g" "$filename"
sed -i "s|APPDESCRIPTION|${DESCRIPTION}|g" "$filename"
# remove freedns if necessary
if [[ "$DDNS_PROVIDER" != *"freedns"* ]]; then
sed -i '/freedns_code/d' "$filename"
fi
available_apps_ctr=$((available_apps_ctr+1))
# four columns per row
if [ $available_apps_ctr -eq 4 ]; then
echo ' </div>' >> "$appslist_add_filename"
available_apps_ctr=0
fi
fi
fi
done
# Complete the rest of the four column row
# shellcheck disable=SC2034
for i in $(seq ${available_apps_ctr} 3)
do
{ echo ' <div class="column">';
echo ' <div>';
echo ' </div>';
echo ' </div>'; } >> "$appslist_add_filename"
done
echo ' </body>' >> "$appslist_add_filename"
echo '</html>' >> "$appslist_add_filename"
chown -R www-data:www-data "/var/www/${local_hostname}/htdocs/admin"
}
function web_admin_create_installed_apps {
local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local
appslist_template_filename="/var/www/${local_hostname}/htdocs/admin/apps_template.html"
app_template_filename="/var/www/${local_hostname}/htdocs/admin/app_template.html"
appslist_filename="/var/www/${local_hostname}/htdocs/admin/apps.html"
icons_dir="/var/www/${local_hostname}/htdocs/admin/icons"
pending_removes="/var/www/${local_hostname}/htdocs/admin/pending_removes.txt"
if [ ! -d "$icons_dir" ]; then
mkdir -p "$icons_dir"
fi
if [ ! -f "$appslist_template_filename" ]; then
return
fi
cp "$appslist_template_filename" "$appslist_filename"
sed -i '/<\/body>/d' "$appslist_filename"
sed -i '/<\/html>/d' "$appslist_filename"
installed_apps_ctr=0
app_index=0
# shellcheck disable=SC2068,SC2034
for a in ${APPS_INSTALLED[@]}
do
app_name=${APPS_INSTALLED_NAMES[$app_index]}
if [ "$app_name" ]; then
app_filename="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}"
if [ -f "$app_filename" ]; then
# check if the app is being removed
app_being_removed=
if [ -f "$pending_removes" ]; then
if grep -q "remove_${app_name}" "$pending_removes"; then
app_being_removed=1
fi
fi
if [ ! $app_being_removed ]; then
# get the icon for the app
icon_filename="/usr/share/${PROJECT_NAME}/android-app/${app_name}.png"
if [ -f "$icon_filename" ]; then
cp "$icon_filename" "/var/www/${local_hostname}/htdocs/admin/icons/${app_name}.png"
else
icon_filename=
fi
app_name_upper=$(echo "$app_name" | awk '{print toupper($0)}')
SHORT_DESCRIPTION=
DESCRIPTION=
if ! grep -q "${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename"; then
app_index=$((app_index+1))
continue
fi
if grep -q "#${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename"; then
app_index=$((app_index+1))
continue
fi
SHORT_DESCRIPTION="$(grep "${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename" | head -n 1 | sed 's|\$||g' | sed "s|'||g" | sed 's|\"||g' | awk -F '=' '{print $2}')"
if grep -q "${app_name_upper}_DESCRIPTION=" "$app_filename"; then
DESCRIPTION="$(grep "${app_name_upper}_DESCRIPTION=" "$app_filename" | head -n 1 | sed 's|\$||g' | sed "s|'||g" | sed 's|\"||g' | awk -F '=' '{print $2}')"
fi
read_config_param "${app_name_upper}_DOMAIN_NAME"
test_domain_name="${app_name_upper}_DOMAIN_NAME"
domain_name=${!test_domain_name}
if [ "$domain_name" ]; then
if [[ "$domain_name" != *'.onion' ]]; then
domain_name="https://${!test_domain_name}"
else
domain_name="http://${!test_domain_name}"
fi
fi
if [ $installed_apps_ctr -eq 0 ]; then
echo ' <div class="row">' >> "$appslist_filename"
fi
filename="/var/www/${local_hostname}/htdocs/admin/app_add_${app_name}.html"
if [ -f "$filename" ]; then
rm "$filename"
fi
filename="/var/www/${local_hostname}/htdocs/admin/app_${app_name}.html"
{ echo ' <div class="column">';
echo ' <div>';
echo " <a href=\"app_${app_name}.html\">";
echo " <img src=\"icons/${app_name}.png\" style=\"width:100%\">";
echo " <center>${app_name}</center>";
echo ' </a>';
echo ' </div>';
echo ' </div>'; } >> "$appslist_filename"
cp "$app_template_filename" "$filename"
# Replace app variables
sed -i "s|HOSTNAME|$(hostname)|g" "$filename"
sed -i "s|APPNAME|${app_name}|g" "$filename"
sed -i "s|APPURL|${domain_name}|g" "$filename"
sed -i "s|APPDESCRIPTION|${DESCRIPTION}|g" "$filename"
installed_apps_ctr=$((installed_apps_ctr+1))
# four columns per row
if [ $installed_apps_ctr -eq 4 ]; then
echo ' </div>' >> "$appslist_filename"
installed_apps_ctr=0
fi
fi
fi
fi
app_index=$((app_index+1))
done
# Complete the rest of the four column row
# shellcheck disable=SC2034
for i in $(seq ${installed_apps_ctr} 3)
do
{ echo ' <div class="column">';
echo ' <div>';
echo ' </div>';
echo ' </div>'; } >> "$appslist_filename"
done
echo ' </body>' >> "$appslist_filename"
echo '</html>' >> "$appslist_filename"
chown -R www-data:www-data "/var/www/${local_hostname}/htdocs/admin"
}
function install_web_admin {
# This is intended as an admin web user interface
# similar to Plinth or the yunohost
local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local
if [ ! -d "/var/www/${local_hostname}/htdocs/admin" ]; then
mkdir -p "/var/www/${local_hostname}/htdocs/admin"
fi
if [ -d "/usr/share/${PROJECT_NAME}/webadmin" ]; then
cp -r "/usr/share/${PROJECT_NAME}/webadmin"/* "/var/www/${local_hostname}/htdocs/admin"
else
echo "install_web_admin 5" > /tmp/debugweb
{ echo '<html>';
echo ' <body>';
echo " This is a placeholder for the web admin panel on ${local_hostname}";
echo ' </body>';
echo '</html>'; } > "/var/www/${local_hostname}/htdocs/admin/index.html"
fi
nginx_file=/etc/nginx/sites-available/$local_hostname
{ echo 'server {';
echo ' listen 80 default_server;';
echo ' #listen [::]:80;';
echo " server_name ${local_hostname};";
echo " root /var/www/${local_hostname}/htdocs;";
echo ' index index.html;';
echo '';
echo ' access_log /dev/null;';
echo ' error_log /dev/null;';
echo '';
echo ' location ^~ /admin {';
echo " root /var/www/${local_hostname}/htdocs;";
echo ' index index.html;';
echo " error_page 405 = \$uri;";
echo ' location ~ \.php {';
echo ' include snippets/fastcgi-php.conf;';
echo ' fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;';
echo ' fastcgi_read_timeout 30;';
echo ' }';
echo ' }';
echo '';
echo ' location /icons {';
echo ' autoindex on;';
echo ' break;';
echo ' }';
echo '';
echo ' rewrite ^/plinth/(.*)$ /api.json last;';
echo '';
echo ' location / {';
echo " root /var/www/${local_hostname}/htdocs/plinth;";
echo ' index api.json /api.json;';
echo " error_page 405 = \$uri;";
echo ' }';
echo '}';
echo '';
echo 'server {';
echo ' listen 443 default_server ssl;';
echo ' #listen [::]:443 ssl;';
echo " server_name ${local_hostname};";
echo " root /var/www/${local_hostname}/htdocs;";
echo ' index index.html;';
echo '';
echo ' access_log /dev/null;';
echo ' error_log /dev/null;';
echo ''; } > "$nginx_file"
nginx_ssl "${local_hostname}"
nginx_security_options "${local_hostname}"
{ echo ' add_header Strict-Transport-Security max-age=0;';
echo '';
echo ' location ^~ /admin {';
echo " root /var/www/${local_hostname}/htdocs;";
echo ' index index.html;';
echo " error_page 405 = \$uri;";
echo ' location ~ \.php {';
echo ' include snippets/fastcgi-php.conf;';
echo ' fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;';
echo ' fastcgi_read_timeout 30;';
echo ' }';
echo ' }';
echo '';
echo ' location /icons {';
echo ' autoindex on;';
echo ' break;';
echo ' }';
echo '';
echo ' rewrite ^/plinth/(.*)$ /api.json last;';
echo '';
echo ' location / {';
echo " root /var/www/${local_hostname}/htdocs/plinth;";
echo ' index api.json /api.json;';
echo " error_page 405 = \$uri;";
echo ' }';
echo '}'; } >> "$nginx_file"
if [ ! -f "/etc/ssl/certs/${local_hostname}.crt" ]; then
"${PROJECT_NAME}-addcert" -h "${local_hostname}" --dhkey "${DH_KEYLENGTH}"
fi
sed -i "s|ssl_certificate .*|ssl_certificate /etc/ssl/certs/${local_hostname}.crt;|g" "$nginx_file"
sed -i "s|ssl_certificate_key .*|ssl_certificate_key /etc/ssl/private/${local_hostname}.key;|g" "$nginx_file"
nginx_ensite "${local_hostname}"
# Compatibility with FreedomBox android app
# The installed apps get published to a json file called api.json
# in this directory
if [ ! -d "/var/www/${local_hostname}/htdocs/plinth" ]; then
mkdir -p "/var/www/${local_hostname}/htdocs/plinth"
fi
web_admin_create_users
# make list of apps which can be added
web_admin_create_add_apps
# make the list of apps
web_admin_create_installed_apps
chown -R www-data:www-data "/var/www/${local_hostname}/htdocs"
web_admin_avahi
}
# NOTE: deliberately no exit 0