1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/calibreweb_ynh.git synced 2024-09-03 18:16:20 +02:00

Merge pull request #16 from YunoHost-Apps/Testing

Testing
This commit is contained in:
Krakinou 2019-01-30 23:55:16 +01:00 committed by GitHub
commit 229980a3f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 495 additions and 86 deletions

View file

@ -13,10 +13,19 @@ Calibre-Web is a web app providing a clean interface for browsing, reading and d
*This software is a fork of [library](https://github.com/mutschler/calibreserver) and licensed under the GPL v3 License.* *This software is a fork of [library](https://github.com/mutschler/calibreserver) and licensed under the GPL v3 License.*
Alternatively, you may use [COPS](https://github.com/YunoHost-Apps/cops_ynh) which also allows access to you Calibre Library, but in read-only mode. Alternatively, you may use [COPS](https://github.com/YunoHost-Apps/cops_ynh) which also allows access to your Calibre Library, but in read-only mode.
**Shipped version:** To be 1.0, let's say 0.9 :) **Shipped version:** To be 1.0, let's say 0.9 :)
Library will be placed in `/home/yunohost.multimedia/share/eBook` folder except if both :
- calibreweb is set as a private application
- calibreweb library is set as a public library
In this case the library will be set in `/home/yunohost.multimedia/[admin]/eBook` folder. Library folder can always be changed manually in the application settings by the administrator.
This app support http authentification.
## Screenshots ## Screenshots
![screenshot](https://raw.githubusercontent.com/janeczku/docker-calibre-web/master/screenshot.png) ![screenshot](https://raw.githubusercontent.com/janeczku/docker-calibre-web/master/screenshot.png)
@ -31,10 +40,10 @@ yunohost app setting calibreweb backup_core_only -v 0
By default, removing the app will **never** delete the library. By default, removing the app will **never** delete the library.
## Limitations ## Known Limitations
* No LDAP support * Partial LDAP support : user existing both in Yunohost and calibreweb can use their Yunohost password to log in, but user existing previously to the application installation will not be duplicated in the database automatically
* access to library to be done manually after install if Calibre library was already existing, for example : * Authorization access to library to be done manually after install if Calibre library was already existing, for example :
``` ```
chown -R calibreweb: path/to/library chown -R calibreweb: path/to/library
or or
@ -42,6 +51,7 @@ chmod o+rw path/to/library
``` ```
* Do not use a Nextcloud folder. It's all right if the folder is an external storage in Nextcloud but not if it's an internal one : Changing the data in the library will cause trouble with the sync * Do not use a Nextcloud folder. It's all right if the folder is an external storage in Nextcloud but not if it's an internal one : Changing the data in the library will cause trouble with the sync
* "Magic link feature is not yet available * "Magic link feature is not yet available
* Change to library made outside calibreweb are not automatically updated in calibreweb. It is required to disconnect and reconnect to see the changes
## Links ## Links
@ -66,11 +76,12 @@ sudo yunohost app upgrade calibreweb -u https://github.com/Yunohost-Apps/calibre
## Todo ## Todo
- [X] Multiinstance - [X] Multiinstance
- [ ] Better Multimedia integration : Integrate in Yunohost.multimedia - [X] Better Multimedia integration : Integrate in Yunohost.multimedia
- [ ] User and possibly LDAP integration - [X] User and possibly LDAP integration, http auth
- [X] Package_check integration - [X] Package_check integration
- [X] On backup/remove/upgrade : check for database location to update settings - [X] On backup/remove/upgrade : check for database location to update settings
- [ ] enable magic link - [ ] enable magic link
- [ ] Add cronjob to reload database
## LICENSE ## LICENSE

View file

@ -43,7 +43,7 @@
Level 1=auto Level 1=auto
Level 2=auto Level 2=auto
Level 3=auto Level 3=auto
Level 4=na Level 4=1
Level 5=auto Level 5=auto
Level 6=auto Level 6=auto
Level 7=auto Level 7=auto

View file

@ -1,4 +1,3 @@
#useless as long as V1.0 not issued SOURCE_URL=https://github.com/janeczku/calibre-web/archive/9e5fa45df7cd840d8a26d25f953857a13d6bc5de.zip
SOURCE_URL=https://github.com/janeczku/calibre-web/archive/d0fd1a46014006138977398ee65f48c98df937e7.zip SOURCE_SUM=be288d5caa3ccdd612b66927b0849899107941f600a58dd2e0a3dc04feb594a2
SOURCE_SUM=0d297719f32670840fb1fcee52d3e73fa6213127709809d9a232f862d037af03
SOURCE_FORMAT=zip SOURCE_FORMAT=zip

View file

@ -1,6 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Permet de générer le hash pour le password # Permet de générer le hash pour le password
#Plus utilisé depuis la MAJ 0.92~ynh3 avec LDAP
import sys import sys
path=sys.argv[2] path=sys.argv[2]
sys.path.append(path) sys.path.append(path)

View file

@ -0,0 +1,3 @@
config_use_ldap=1,
config_ldap_provider_url=\'localhost:389\',
config_ldap_dn=\'uid=%s,ou=users,dc=yunohost,dc=org\'

View file

@ -8,4 +8,4 @@ config_use_goodreads=0,
config_logfile=\'\', config_logfile=\'\',
config_converterpath=\'\', config_converterpath=\'\',
config_calibre=\'\', config_calibre=\'\',
config_uploading=\'$upload\' config_uploading=\'$upload\',

View file

@ -4,12 +4,13 @@ location __PATH__ {
if ($scheme = http) { if ($scheme = http) {
rewrite ^ https://$server_name$request_uri? permanent; rewrite ^ https://$server_name$request_uri? permanent;
} }
proxy_pass http://localhost:__PORT__; proxy_pass http://localhost:__PORT__;
proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme; proxy_set_header X-Scheme $scheme;
proxy_set_header X-Script-Name __PATH__; proxy_set_header X-Script-Name __PATH__;
proxy_set_header X-Remote-User $remote_user;
# Include SSOWAT user panel. # Include SSOWAT user panel.
include conf.d/yunohost_panel.conf.inc; include conf.d/yunohost_panel.conf.inc;

49
hooks/post_user_create Normal file
View file

@ -0,0 +1,49 @@
#!/bin/bash
# Source YunoHost helpers
source /usr/share/yunohost/helpers
#pour récupérer l'app_id, on prend le nom du fichier puis on retire les 3 premiers caratères
app=`basename "$0"`
app=${app:3}
source /etc/yunohost/apps/$app/scripts/_common.sh
username=$1
mail=$2
pass_clear=$3
final_path=$(ynh_app_setting_get $app final_path)
public_library=$(ynh_app_setting_get "$app" public_library)
#User are duplicated in the database only if library is public
if [ public_library -eq 1 ]; then
######################################
#1 get admin user and id from database
######################################
#we take the admin user as we're sure there is at least this one
admin=$(ynh_app_setting_get $app admin)
admin_id=$(sqlite3 $final_path/app.db "SELECT id FROM user WHERE nickname='$admin'")
######################################
#get user table structure
######################################
table_schema=$(get_db "user")
######################################
#Build new entry for user
######################################
insert_user=$table_schema
insert_user="${insert_user/id/null}" #so that a new entry is created
insert_user="${insert_user/nickname/\'$username\'}"
insert_user="${insert_user/role/0}" #standard role
pass_hash=$(python /etc/yunohost/apps/$app/conf/generate_password_hash.py "$pass_clear" $final_path/vendor)
insert_user="${insert_user/password/\'$pass_hash\'}" #we get the same pass even if it's not thanks to LDAP, ones never knows...
insert_user="${insert_user/email/\'$mail\'}"
#######################################
# Insert New entry in database
#######################################
sqlite3 $final_path/app.db "INSERT INTO user ($table_schema) SELECT $insert_user FROM user WHERE ID = $admin_id;"
fi

38
hooks/post_user_delete Normal file
View file

@ -0,0 +1,38 @@
#!/bin/bash
# Source YunoHost helpers
source /usr/share/yunohost/helpers
#pour récupérer l'app_id, on prend le nom du fichier puis on retire les 3 premiers caratères
app=`basename "$0"`
app=${app:3}
source /etc/yunohost/apps/$app/scripts/_common.sh
username=$1
final_path=$(ynh_app_setting_get $app final_path)
del_tables_user="book_read_link remote_auth_token downloads shelf bookmark"
del_tables_shelf="book_shelf_link"
del_id() {
#$1=table
#$2=id_type
#$3=id
sqlite3 $final_path/app.db "DELETE FROM $1 WHERE $2='$3'"
}
user_id=$(sqlite3 $final_path/app.db "SELECT id from user WHERE nickname='$username'")
shelf_id=$(sqlite3 $final_path/app.db "SELECT id from shelf WHERE user_id='$user_id'")
#Delete all entry with dependencies for user
#pas de check sur l'existence de l'utilisateur car fonctionne sans
for i in $del_tables_shelf
do
del_id "$i" "shelf" $shelf_id
done
for i in $del_tables_user
do
del_id "$i" "user_id" $user_id
done
#delete user
del_id "user" "id" $user_id

View file

@ -6,7 +6,7 @@
"en": "Calibre-web for Yunohost", "en": "Calibre-web for Yunohost",
"fr": "Calibre-web pour Yunohost" "fr": "Calibre-web pour Yunohost"
}, },
"version": "0.91~ynh2", "version": "0.92~ynh3",
"url": "https://github.com/janeczku/calibre-web", "url": "https://github.com/janeczku/calibre-web",
"license": "free", "license": "free",
"maintainer": { "maintainer": {
@ -14,7 +14,7 @@
"email": "misterl56@hotmail.com" "email": "misterl56@hotmail.com"
}, },
"requirements": { "requirements": {
"yunohost": ">= 2.7.14" "yunohost": ">= 3.0.0"
}, },
"multi_instance": true, "multi_instance": true,
"services": [ "services": [
@ -40,18 +40,6 @@
}, },
"example": "/calibre", "example": "/calibre",
"default": "/calibre" "default": "/calibre"
},
{
"name": "calibre_path",
"ask": {
"en": "Select the folder containing the Calibre library",
"fr": "Choisissez le répertoire contenant la bibliothèque Calibre"
},
"help": {
"en": "This folder should have read write access. It will be created if it does not exist.",
"fr": "Le répertoire doit être accessible en lecture écriture, il sera créé s'il n'existe pas."
},
"default": "/home/yunohost.app/calibreweb"
}, },
{ {
"name": "admin", "name": "admin",
@ -69,34 +57,53 @@
"en": "Is it a public application?", "en": "Is it a public application?",
"fr": "Est-ce une application publique ?" "fr": "Est-ce une application publique ?"
}, },
"help":{
"en":"No will set the library in /home/yunohost.multimedia/admin/eBook, except if you set the library as public",
"fr":"Non parametrera la bibliothèque pour /home/yunohost.multimedia/admin/eBook sauf si la bibliothèque est également publique"
},
"default": false "default": false
}, },
{ {
"name": "language", "name": "language",
"optional": true,
"ask": { "ask": {
"en": "Select a default language (you may change it later in the app)", "en": "Select a default language",
"fr": "Choisissez une langue par défaut (vous pourrez la changer ultérieurement dans l'application)" "fr": "Choisissez une langue par défaut"
}, },
"choices": [ "fr", "en", "es", "de"], "help":{
"en":"You may change it later in the app",
"fr":"Vous pourrez la changer ultérieurement dans l'application"
},
"choices": [ "fr", "en", "es", "de"],
"default": "fr" "default": "fr"
}, },
{ {
"name": "upload", "name": "upload",
"type":"boolean", "type":"boolean",
"optional": true,
"ask": { "ask": {
"en": "Do you want to allow uploading of books (you may change it later in the app)?", "en": "Do you want to allow uploading of books?",
"fr": "Voulez vous autoriser l'upload de livres (vous pourrez le changer ultérieurement dans l'application)?" "fr": "Voulez vous autoriser l'upload de livres?"
},
"help":{
"en":"You may change it later in the app",
"fr":"Vous pourrez le changer ultérieurement dans l'application"
}, },
"default": false "default": false
}, },
{ {
"name": "password", "name": "public_library",
"type": "password", "type":"boolean",
"optional": true,
"ask": { "ask": {
"en": "Set the administrator password", "en": "Do you want to allow access to the library to all Yunohost users? ",
"fr": "Définissez le mot de passe administrateur" "fr": "Voulez vous autoriser l'accès à la bibliothèque à tous les utilisateurs Yunohost?"
}, },
"example": "Averystrongpassword" "help":{
"en":"Yes will set the library in /home/yunohost.multimedia/share/eBook",
"fr":"Oui parametrera la bibliothèque pour /home/yunohost.multimedia/share/eBook"
},
"default": true
} }
] ]
} }

View file

@ -1,8 +1,19 @@
#!/bin/bash #!/bin/bash
pkg_dependencies="sqlite3 python-pip imagemagick" PKG_DEPENDENCIES="sqlite3 python-pip imagemagick"
DOSSIER_MEDIA=/home/yunohost.multimedia
create_dir=0 create_dir=0
get_db() {
# $1 = nom de la table
# cette ligne de malade :
# 1/ Recupere le schém de la table user
# 2/ En extrait les noms de champs (en prenant le premier mot après la tabulation)
# 3/ en supprime les clé UNIQUE, PRIMARY et CHECK dont on ne veut pas
# 4/ remplace la liste avec retour à la ligne par une liste séparé par des virgules
# 5/ Enlève la dernière virgule
sqlite3 $final_path/app.db ".schema $1" | awk '/\t/ {print $1}' | grep -v -e "UNIQUE" -e "PRIMARY" -e "CHECK" -e "FOREIGN" | awk '{printf "%s, ", $0}' | head -c -2
}
#================================================= #=================================================
# EXPERIMENTAL HELPERS # EXPERIMENTAL HELPERS
@ -100,11 +111,11 @@ ynh_systemd_action() {
# #
# usage: ynh_multimedia_build_main_dir # usage: ynh_multimedia_build_main_dir
ynh_multimedia_build_main_dir () { ynh_multimedia_build_main_dir () {
local ynh_media_release="v1.1" local ynh_media_release="v1.2"
local checksum="9ec4321a92aa2c388af4ee0072735e3e" local checksum="806a827ba1902d6911095602a9221181"
# Download yunohost.multimedia scripts # Download yunohost.multimedia scripts
wget -nv https://github.com/YunoHost-Apps/yunohost.multimedia/archive/${ynh_media_release}.tar.gz wget -nv https://github.com/Yunohost-Apps/yunohost.multimedia/archive/${ynh_media_release}.tar.gz
# Check the control sum # Check the control sum
echo "${checksum} ${ynh_media_release}.tar.gz" | md5sum -c --status \ echo "${checksum} ${ynh_media_release}.tar.gz" | md5sum -c --status \

View file

@ -71,7 +71,7 @@ then
path_url="$new_path" path_url="$new_path"
#Cannot use empty string for X-script-name, causes an issue in the python prg #Cannot use empty string for X-script-name, causes an issue in the python prg
if [ $path_url = "/" ] ; then if [ $path_url = "/" ] ; then
ynh_replace_string "X-Script-Name __PATH__;" "X-Script-Name /$app;" ../conf/nginx.conf ynh_replace_string " proxy_set_header X-Script-Name" "# proxy_set_header X-Script-Name" ../conf/nginx.conf
fi fi
# Create a dedicated nginx config # Create a dedicated nginx config
ynh_add_nginx_config ynh_add_nginx_config

View file

@ -25,13 +25,13 @@ path_url=$YNH_APP_ARG_PATH
admin=$YNH_APP_ARG_ADMIN admin=$YNH_APP_ARG_ADMIN
is_public=$YNH_APP_ARG_IS_PUBLIC is_public=$YNH_APP_ARG_IS_PUBLIC
language=$YNH_APP_ARG_LANGUAGE language=$YNH_APP_ARG_LANGUAGE
ynh_print_OFF
pass=$YNH_APP_ARG_PASSWORD
ynh_print_ON
app=$YNH_APP_INSTANCE_NAME app=$YNH_APP_INSTANCE_NAME
#removing / at the end for consistency upload=$6
calibre_dir=${3%/} public_library=$7
upload=$7 #if app is public, we assume library is public
if [ $is_public -eq 1 ]; then
public_library=1
fi
#================================================= #=================================================
# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS # CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS
@ -56,7 +56,7 @@ ynh_app_setting_set $app domain $domain
ynh_app_setting_set $app path $path_url ynh_app_setting_set $app path $path_url
ynh_app_setting_set $app admin $admin ynh_app_setting_set $app admin $admin
ynh_app_setting_set $app is_public $is_public ynh_app_setting_set $app is_public $is_public
ynh_app_setting_set $app calibre_dir $calibre_dir
#================================================= #=================================================
# STANDARD MODIFICATIONS # STANDARD MODIFICATIONS
@ -80,13 +80,12 @@ ynh_print_info "Downloading sources to $final_path"
# Download, check integrity, uncompress and patch the source from app.src # Download, check integrity, uncompress and patch the source from app.src
ynh_setup_source "$final_path" ynh_setup_source "$final_path"
#================================================= #=================================================
# INSTALL DEPENDENCIES # INSTALL DEPENDENCIES
#================================================= #=================================================
ynh_print_info "Installing dependencies and pip packages" ynh_print_info "Installing dependencies and pip packages"
ynh_install_app_dependencies $pkg_dependencies ynh_install_app_dependencies $PKG_DEPENDENCIES
pip install --target $final_path/vendor -r $final_path/requirements.txt pip install --target $final_path/vendor -r $final_path/requirements.txt
#================================================= #=================================================
@ -94,7 +93,7 @@ pip install --target $final_path/vendor -r $final_path/requirements.txt
#================================================= #=================================================
#Cannot use empty string for X-script-name, causes an issue in the python prg #Cannot use empty string for X-script-name, causes an issue in the python prg
if [ $path_url = "/" ] ; then if [ $path_url = "/" ] ; then
ynh_replace_string "X-Script-Name __PATH__;" "X-Script-Name /$app;" ../conf/nginx.conf ynh_replace_string " proxy_set_header X-Script-Name" "# proxy_set_header X-Script-Name" ../conf/nginx.conf
fi fi
# Create a dedicated nginx config # Create a dedicated nginx config
@ -120,25 +119,30 @@ ynh_add_systemd_config
# CREATE FILES AND DIRECTORIES # CREATE FILES AND DIRECTORIES
#================================================= #=================================================
#Logic is as follow : if app is set to be publicly accessible, we will assume that the library should be set in "Share" multimedia directory
# If app is set to be private but access is requested for all user, we will assume the same
# If app is set to be private but access is limited to the admin user, we will set it inside his own multimedia directory.
# Access to the app is managed in the SSOwat part of the script.
#Check if library folder exists. If not create it #build multimedia directory
if [ ! -e "$calibre_dir" ]; then ynh_multimedia_build_main_dir
ynh_print_info "Create calibre library folder $calibre_dir" ynh_multimedia_addaccess $app
mkdir -p $calibre_dir
chown -R $app:$app $calibre_dir if [ $is_public -eq 1 ]; then #app is public, library is public
create_dir=1 calibre_dir=$DOSSIER_MEDIA/share/eBook
elif [ $is_public -eq 0 ] && [ $public_library -eq 1 ]; then #app is private, library is public
calibre_dir=$DOSSIER_MEDIA/share/eBook
else #app is private, library is private
calibre_dir=$DOSSIER_MEDIA/$admin/eBook
fi fi
#Check if metadata.db file exists. If not create it (empty library) #Check if metadata.db file exists. If not create it (empty library)
if [ ! -e "$calibre_dir"/metadata.db ]; then if [ ! -e "$calibre_dir"/metadata.db ]; then
cp -a ../conf/metadata.db.empty $calibre_dir/metadata.db cp -a ../conf/metadata.db.empty $calibre_dir/metadata.db
chown $app:$app $calibre_dir/* chown $app:$app $calibre_dir/*
fi fi
ynh_app_setting_set $app calibre_dir $calibre_dir
#ynh_multimedia_build_main_dir
#ynh_multimedia_addfolder "eBook" "$calibre_dir"
#ynh_multimedia_addaccess $app
#================================================= #=================================================
# SETUP LOGROTATE # SETUP LOGROTATE
@ -158,25 +162,52 @@ chown -R $app:$app /var/log/$app
ynh_print_info "Setting up database and settings" ynh_print_info "Setting up database and settings"
#we need to start and stop the service so that initial app.db file is created and that we can set default data #we need to start and stop the service so that initial app.db file is created and that we can set default data
ynh_systemd_action -l "INFO in server: Starting Gevent server" ynh_systemd_action -l "INFO in server: Starting Gevent server"
#systemctl start $app
#sleep required on low spec like raspberryPi #sleep required on low spec like raspberryPi
sleep 2s sleep 2s
ynh_systemd_action -a stop ynh_systemd_action -a stop
#set database settings as per conf file #set database settings as per conf file
conf="\"UPDATE settings SET $(. <(echo -E echo $(<../conf/init_calibre_db_settings))) WHERE ID=1\"" conf="\"UPDATE settings SET $(. <(echo -E echo $(<../conf/init_calibre_db_settings))) $(. <(echo -E echo $(<../conf/init_calibre_db_ldap_settings))) WHERE ID=1\""
eval sqlite3 $final_path/app.db "$conf" eval sqlite3 $final_path/app.db "$conf"
conf="\"UPDATE user SET $(. <(echo -E echo $(<../conf/init_calibre_db_user))) WHERE ID=1\"" conf="\"UPDATE user SET $(. <(echo -E echo $(<../conf/init_calibre_db_user))) WHERE ID=1\""
eval sqlite3 $final_path/app.db "$conf" eval sqlite3 $final_path/app.db "$conf"
#mise à jour du mot de passe (je ne sais pas pourquoi, je n'arrive pas à l'intégrer dans le fichier de conf, pb de " et ') #mise à jour du mot de passe (je ne sais pas pourquoi, je n'arrive pas à l'intégrer dans le fichier de conf, pb de " et ')
ynh_print_OFF #ynh_print_OFF
#had to set it on two lines or package_linter cries like a baby... #had to set it on two lines or package_linter cries like a baby...
pass=$(python ../conf/generate_password_hash.py "$pass" $final_path/vendor) #pass=$(python ../conf/generate_password_hash.py "$pass" $final_path/vendor)
sqlite3 $final_path/app.db "UPDATE user SET password='$pass' WHERE ID=1" #sqlite3 $final_path/app.db "UPDATE user SET password='$pass' WHERE ID=1"
ynh_print_ON #ynh_print_ON
#Creation des autres utilisateurs
if [ $public_library -eq 1 ]; then
table_schema=$(get_db "user")
for i in $(ynh_user_list); do
if [ $i = $admin ]; then continue; fi
mail=$(ynh_user_get_info $i 'mail')
######################################
#Build new entry for user
######################################
insert_user=$table_schema
insert_user="${insert_user/id/null}" #so that a new entry is created
insert_user="${insert_user/nickname/\'$i\'}"
insert_user="${insert_user/role/0}" #standard role
# pass_hash=$(python /etc/yunohost/apps/$app/conf/generate_password_hash.py "$pass_clear" $final_path/vendor)
# insert_user="${insert_user/password/\'$pass_hash\'}" #we get the same pass even if it's not thanks to LDAP, ones never knows...
insert_user="${insert_user/email/\'$mail\'}"
#######################################
# Insert New entry in database
#######################################
sqlite3 $final_path/app.db "INSERT INTO user ($table_schema) SELECT $insert_user FROM user WHERE ID = 1;"
done
fi
#================================================= #=================================================
# SECURE FILES AND DIRECTORIES # SECURE FILES AND DIRECTORIES
@ -211,6 +242,11 @@ then
# unprotected_uris allows SSO credentials to be passed anyway. # unprotected_uris allows SSO credentials to be passed anyway.
ynh_app_setting_set $app unprotected_uris "/" ynh_app_setting_set $app unprotected_uris "/"
fi fi
if [ $public_library -eq 0 ]; then
yunohost app addaccess $app -u $admin
fi
#================================================= #=================================================
# RELOAD NGINX # RELOAD NGINX
@ -218,11 +254,3 @@ fi
ynh_print_info "Reload nginx and start $app" ynh_print_info "Reload nginx and start $app"
systemctl reload nginx systemctl reload nginx
ynh_systemd_action -l "INFO in server: Starting Gevent server" ynh_systemd_action -l "INFO in server: Starting Gevent server"
#=================================================
# WARNING FOR READ ACCESS
#=================================================
if [[ $create_dir = 0 ]] ; then
ynh_print_warn "Please, give required access to $app user to the $calibre_dir folder."
fi

View file

@ -88,7 +88,7 @@ chown -R $app: $final_path
# Define and install dependencies # Define and install dependencies
ynh_print_info "Installing dependencies and pip packages" ynh_print_info "Installing dependencies and pip packages"
ynh_install_app_dependencies $pkg_dependencies ynh_install_app_dependencies $PKG_DEPENDENCIES
pip install --target $final_path/vendor -r $final_path/requirements.txt pip install --target $final_path/vendor -r $final_path/requirements.txt
#================================================= #=================================================

View file

@ -44,6 +44,9 @@ ynh_clean_setup () {
# Exit if an error occurs during the execution of the script # Exit if an error occurs during the execution of the script
ynh_abort_if_errors ynh_abort_if_errors
#Stop the app in case database is updated
ynh_systemd_action -a stop
#================================================= #=================================================
# CHECK THE PATH # CHECK THE PATH
#================================================= #=================================================
@ -65,14 +68,18 @@ ynh_setup_source "$final_path"
# NGINX CONFIGURATION # NGINX CONFIGURATION
#================================================= #=================================================
if [ $path_url = "/" ] ; then
ynh_replace_string " proxy_set_header X-Script-Name" "# proxy_set_header X-Script-Name" ../conf/nginx.conf
fi
# Create a dedicated nginx config # Create a dedicated nginx config
ynh_add_nginx_config ynh_add_nginx_config
#================================================= #=================================================
# UPGRADE DEPENDENCIES # UPGRADE DEPENDENCIES
#================================================= #=================================================
ynh_print_info "Download and install dependencies"
ynh_install_app_dependencies $pkg_dependencies ynh_install_app_dependencies $PKG_DEPENDENCIES
pip install --target $final_path/vendor -r $final_path/requirements.txt pip install --target $final_path/vendor -r $final_path/requirements.txt
#================================================= #=================================================
@ -82,16 +89,36 @@ pip install --target $final_path/vendor -r $final_path/requirements.txt
# Create a dedicated user (if not existing) # Create a dedicated user (if not existing)
ynh_system_user_create $app ynh_system_user_create $app
# Set permissions on app files (required to be able to update database)
chown -R $app: $final_path
#================================================= #=================================================
# SPECIFIC UPGRADE # SPECIFIC UPGRADE
#================================================= #=================================================
# ... #build multimedia directory
#=================================================
#Create multimedia directory but we do not change the calibre_dir : It's the user to make this choice.
ynh_multimedia_build_main_dir
ynh_multimedia_addaccess $app
#=================================================
#Update database structure
#================================================= #=================================================
### Verify the checksum of a file, stored by `ynh_store_file_checksum` in the install script. ### Verify the checksum of a file, stored by `ynh_store_file_checksum` in the install script.
### And create a backup of this file if the checksum is different. So the file will be backed up if the admin had modified it. ### And create a backup of this file if the checksum is different. So the file will be backed up if the admin had modified it.
ynh_backup_if_checksum_is_different "$final_path/app.db" ynh_backup_if_checksum_is_different "$final_path/app.db"
#set database settings as per conf file : restart server so that app.db is regenerated, then add new ldap settings
ynh_systemd_action -l "INFO in server: Starting Gevent server"
#sleep required on low spec like raspberryPi
sleep 2s
ynh_systemd_action -a stop
conf="\"UPDATE settings SET $(. <(echo -E echo $(<../conf/init_calibre_db_ldap_settings))) WHERE ID=1\""
eval sqlite3 $final_path/app.db "$conf"
# Recalculate and store the checksum of the file for the next upgrade. # Recalculate and store the checksum of the file for the next upgrade.
ynh_store_file_checksum "$final_path/app.db" ynh_store_file_checksum "$final_path/app.db"

View file

@ -0,0 +1,24 @@
--- a/cps/templates/config_edit.html 2019-01-12 09:01:08.000000000 +0100
+++ b/cps/templates/config_edit.html 2019-01-13 11:21:11.000000000 +0100
@@ -162,6 +162,21 @@
</div>
</div>
{% endif %}
+ <div class="form-group">
+ <input type="checkbox" id="config_use_ldap" name="config_use_ldap" data-control="ldap-settings" {% if content.config_use_ldap %}checked{% endif %}>
+ <label for="config_use_ldap">{{_('Use')}} LDAP Authentication</label>
+ </div>
+ <div data-related="ldap-settings">
+ <div class="form-group">
+ <label for="config_ldap_provider_url">{{_('LDAP Provider URL')}}</label>
+ <input type="text" class="form-control" id="config_ldap_provider_url" name="config_ldap_provider_url" value="{% if content.config_use_ldap != None %}{{ content.config_ldap_provider_url }}{% endif %}" autocomplete="off">
+ </div>
+ <div class="form-group">
+ <label for="config_ldap_dn">{{_('LDAP Distinguished Name (DN)')}}</label>
+ <input type="text" class="form-control" id="config_ldap_dn" name="config_ldap_dn" value="{% if content.config_use_ldap != None %}{{ content.config_ldap_dn }}{% endif %}" autocomplete="off">
+ </div>
+ </div>
+ </div>
</div>
</div>
</div>

View file

@ -0,0 +1,103 @@
--- a/cps/ub.py 2019-01-16 17:50:51.000000000 +0100
+++ b/cps/ub.py 2019-01-30 22:23:29.709075421 +0100
@@ -148,6 +148,16 @@
def __repr__(self):
return '<User %r>' % self.nickname
+#Yunohost Integration - 1
+ #Login via LDAP method
+ @staticmethod
+ def try_login(username, password):
+ conn = get_ldap_connection()
+ conn.simple_bind_s(
+ config.config_ldap_dn.replace("%s", username),
+ password
+ )
+#END Yunohost Integration - 1
# Baseclass for Users in Calibre-Web, settings which are depending on certain users are stored here. It is derived from
# User Base (all access methods are declared there)
@@ -268,8 +278,8 @@
domain = Column(String)
def __repr__(self):
- return u"<Registration('{0}')>".format(self.domain)
-
+ return u"<Registration('{0}')>".format(self.domain)
+
# Baseclass for representing settings in app.db with email server settings and Calibre database settings
# (application settings)
@@ -306,6 +316,11 @@
config_use_goodreads = Column(Boolean)
config_goodreads_api_key = Column(String)
config_goodreads_api_secret = Column(String)
+#Yunohost Integration - 2
+ config_use_ldap = Column(Boolean)
+ config_ldap_provider_url = Column(String)
+ config_ldap_dn = Column(String)
+#END Yunohost Integration - 2
config_mature_content_tags = Column(String)
config_logfile = Column(String)
config_ebookconverter = Column(Integer, default=0)
@@ -379,6 +394,11 @@
self.config_use_goodreads = data.config_use_goodreads
self.config_goodreads_api_key = data.config_goodreads_api_key
self.config_goodreads_api_secret = data.config_goodreads_api_secret
+#Yunohost Integration - 3
+ self.config_use_ldap = data.config_use_ldap
+ self.config_ldap_provider_url = data.config_ldap_provider_url
+ self.config_ldap_dn = data.config_ldap_dn
+#END Yunohost Integration - 3
if data.config_mature_content_tags:
self.config_mature_content_tags = data.config_mature_content_tags
else:
@@ -555,7 +575,7 @@
conn.execute("ALTER TABLE Settings ADD column `config_use_google_drive` INTEGER DEFAULT 0")
conn.execute("ALTER TABLE Settings ADD column `config_google_drive_folder` String DEFAULT ''")
conn.execute("ALTER TABLE Settings ADD column `config_google_drive_watch_changes_response` String DEFAULT ''")
- session.commit()
+ session.commit()
try:
session.query(exists().where(Settings.config_columns_to_ignore)).scalar()
except exc.OperationalError:
@@ -624,6 +644,16 @@
conn.execute("ALTER TABLE Settings ADD column `config_goodreads_api_key` String DEFAULT ''")
conn.execute("ALTER TABLE Settings ADD column `config_goodreads_api_secret` String DEFAULT ''")
try:
+#Yunohost Integration - 4
+ session.query(exists().where(Settings.config_use_ldap)).scalar()
+ except exc.OperationalError:
+ conn = engine.connect()
+ conn.execute("ALTER TABLE Settings ADD column `config_use_ldap` INTEGER DEFAULT 0")
+ conn.execute("ALTER TABLE Settings ADD column `config_ldap_provider_url` String DEFAULT ''")
+ conn.execute("ALTER TABLE Settings ADD column `config_ldap_dn` String DEFAULT ''")
+ session.commit()
+ try:
+#END Yunohost Integration - 4
session.query(exists().where(Settings.config_mature_content_tags)).scalar()
except exc.OperationalError:
conn = engine.connect()
@@ -668,7 +698,6 @@
conn.execute("ALTER TABLE Settings ADD column `config_theme` INTEGER DEFAULT 0")
session.commit()
-
# Remove login capability of user Guest
conn = engine.connect()
conn.execute("UPDATE user SET password='' where nickname = 'Guest' and password !=''")
@@ -778,6 +807,14 @@
migrate_Database()
clean_database()
+#Yunohost Integration - 5
+#get LDAP connection
+def get_ldap_connection():
+ import ldap
+ conn = ldap.initialize('ldap://{}'.format(config.config_ldap_provider_url))
+ return conn
+#END Yunohost Integration - 5
+
# Generate global Settings Object accessible from every file
config = Config()
searched_ids = {}

View file

@ -0,0 +1,107 @@
--- a/cps/web.py 2019-01-16 17:50:51.000000000 +0100
+++ b/cps/web.py 2019-01-19 10:55:51.728967203 +0100
@@ -58,6 +58,11 @@
import server
from reverseproxy import ReverseProxied
+#Yunohost LDAP integration - 1
+vlogout = 0
+#END Yunohost LDAP integration -1
+
+
try:
from googleapiclient.errors import HttpError
except ImportError:
@@ -1072,7 +1077,7 @@
json_dumps = json.dumps([dict(name=r.name.replace('|',',')) for r in entries])
return json_dumps
-
+
@app.route("/get_tags_json", methods=['GET', 'POST'])
@login_required_if_no_ano
def get_tags_json():
@@ -1192,8 +1197,8 @@
r = requests.get(repository_url + '/git/commits/' + commit['object']['sha'])
r.raise_for_status()
update_data = r.json()
- except requests.exceptions.HTTPError as e:
- status['error'] = _(u'HTTP Error') + ' ' + str(e)
+ except requests.exceptions.HTTPError as ex:
+ status['error'] = _(u'HTTP Error') + ' ' + str(ex)
except requests.exceptions.ConnectionError:
status['error'] = _(u'Connection error')
except requests.exceptions.Timeout:
@@ -2360,10 +2365,36 @@
return redirect(url_for('basic_configuration'))
if current_user is not None and current_user.is_authenticated:
return redirect(url_for('index'))
+#Yunohost integration - 2
+ auth_user = request.headers.get('X-Remote-User')
+ global vlogout
+ if auth_user and config.config_use_ldap and not vlogout:
+ vlogout = 0
+ user = ub.session.query(ub.User).filter(func.lower(ub.User.nickname) == auth_user.strip().lower()).first()
+ login_user(user, remember=True)
+ flash(_(u"you are now logged in as: '%(nickname)s'", nickname=user.nickname), category="success")
+ return redirect(url_for("index"))
+#END Yunohost integration - 2
if request.method == "POST":
form = request.form.to_dict()
user = ub.session.query(ub.User).filter(func.lower(ub.User.nickname) == form['username'].strip().lower()).first()
- if user and check_password_hash(user.password, form['password']) and user.nickname is not "Guest":
+#Yunohost integration - 3
+# if user and check_password_hash(user.password, form['password']) and user.nickname is not "Guest":
+#END Yunohost integration - 3
+#Yunohost Integration - 4
+ if config.config_use_ldap and user:
+ import ldap
+ try:
+ ub.User.try_login(form['username'], form['password'])
+ login_user(user, remember=True)
+ flash(_(u"you are now logged in as: '%(nickname)s'", nickname=user.nickname), category="success")
+ return redirect_back(url_for("index"))
+ except ldap.INVALID_CREDENTIALS:
+ ipAdress = request.headers.get('X-Forwarded-For', request.remote_addr)
+ app.logger.info('LDAP Login failed for user "' + form['username'] + '" IP-adress: ' + ipAdress)
+ flash(_(u"Wrong Username or Password"), category="error")
+ elif user and check_password_hash(user.password, form['password']) and user.nickname is not "Guest":
+#End Yunohost Integration - 4
login_user(user, remember=True)
flash(_(u"you are now logged in as: '%(nickname)s'", nickname=user.nickname), category="success")
return redirect_back(url_for("index"))
@@ -2384,6 +2415,10 @@
@login_required
def logout():
if current_user is not None and current_user.is_authenticated:
+#Yunohost Integration - 5
+ global vlogout
+ vlogout = 1
+#End Yunohost integration - 5
logout_user()
return redirect(url_for('login'))
@@ -3088,6 +3123,23 @@
if "config_ebookconverter" in to_save:
content.config_ebookconverter = int(to_save["config_ebookconverter"])
+#Yunohost Integration - 6
+ #LDAP configuration,
+ if "config_use_ldap" in to_save and to_save["config_use_ldap"] == "on":
+ if not "config_ldap_provider_url" in to_save or not "config_ldap_dn" in to_save:
+ ub.session.commit()
+ flash(_(u'Please enter a LDAP provider and a DN'), category="error")
+ return render_title_template("config_edit.html", content=config, origin=origin,
+ gdrive=gdriveutils.gdrive_support, gdriveError=gdriveError,
+ goodreads=goodreads_support, title=_(u"Basic Configuration"),
+ page="config")
+ else:
+ content.config_use_ldap = 1
+ content.config_ldap_provider_url = to_save["config_ldap_provider_url"]
+ content.config_ldap_dn = to_save["config_ldap_dn"]
+ db_change = True
+#END Yunohost integration - 6
+
# Remote login configuration
content.config_remote_login = ("config_remote_login" in to_save and to_save["config_remote_login"] == "on")
if not content.config_remote_login: