mirror of
https://github.com/YunoHost-Apps/calibreweb_ynh.git
synced 2024-09-03 18:16:20 +02:00
commit
229980a3f9
18 changed files with 495 additions and 86 deletions
23
README.md
23
README.md
|
@ -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.*
|
||||
|
||||
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 :)
|
||||
|
||||
|
||||
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
|
||||
|
||||

|
||||
|
@ -31,10 +40,10 @@ yunohost app setting calibreweb backup_core_only -v 0
|
|||
By default, removing the app will **never** delete the library.
|
||||
|
||||
|
||||
## Limitations
|
||||
## Known Limitations
|
||||
|
||||
* No LDAP support
|
||||
* access to library to be done manually after install if Calibre library was already existing, for example :
|
||||
* 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
|
||||
* Authorization access to library to be done manually after install if Calibre library was already existing, for example :
|
||||
```
|
||||
chown -R calibreweb: path/to/library
|
||||
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
|
||||
* "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
|
||||
|
||||
|
@ -66,11 +76,12 @@ sudo yunohost app upgrade calibreweb -u https://github.com/Yunohost-Apps/calibre
|
|||
|
||||
## Todo
|
||||
- [X] Multiinstance
|
||||
- [ ] Better Multimedia integration : Integrate in Yunohost.multimedia
|
||||
- [ ] User and possibly LDAP integration
|
||||
- [X] Better Multimedia integration : Integrate in Yunohost.multimedia
|
||||
- [X] User and possibly LDAP integration, http auth
|
||||
- [X] Package_check integration
|
||||
- [X] On backup/remove/upgrade : check for database location to update settings
|
||||
- [ ] enable magic link
|
||||
- [ ] Add cronjob to reload database
|
||||
|
||||
|
||||
## LICENSE
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
Level 1=auto
|
||||
Level 2=auto
|
||||
Level 3=auto
|
||||
Level 4=na
|
||||
Level 4=1
|
||||
Level 5=auto
|
||||
Level 6=auto
|
||||
Level 7=auto
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#useless as long as V1.0 not issued
|
||||
SOURCE_URL=https://github.com/janeczku/calibre-web/archive/d0fd1a46014006138977398ee65f48c98df937e7.zip
|
||||
SOURCE_SUM=0d297719f32670840fb1fcee52d3e73fa6213127709809d9a232f862d037af03
|
||||
SOURCE_URL=https://github.com/janeczku/calibre-web/archive/9e5fa45df7cd840d8a26d25f953857a13d6bc5de.zip
|
||||
SOURCE_SUM=be288d5caa3ccdd612b66927b0849899107941f600a58dd2e0a3dc04feb594a2
|
||||
SOURCE_FORMAT=zip
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# Permet de générer le hash pour le password
|
||||
#Plus utilisé depuis la MAJ 0.92~ynh3 avec LDAP
|
||||
import sys
|
||||
path=sys.argv[2]
|
||||
sys.path.append(path)
|
||||
|
|
3
conf/init_calibre_db_ldap_settings
Normal file
3
conf/init_calibre_db_ldap_settings
Normal 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\'
|
|
@ -8,4 +8,4 @@ config_use_goodreads=0,
|
|||
config_logfile=\'\',
|
||||
config_converterpath=\'\',
|
||||
config_calibre=\'\',
|
||||
config_uploading=\'$upload\'
|
||||
config_uploading=\'$upload\',
|
||||
|
|
|
@ -10,6 +10,7 @@ location __PATH__ {
|
|||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Scheme $scheme;
|
||||
proxy_set_header X-Script-Name __PATH__;
|
||||
proxy_set_header X-Remote-User $remote_user;
|
||||
|
||||
# Include SSOWAT user panel.
|
||||
include conf.d/yunohost_panel.conf.inc;
|
||||
|
|
49
hooks/post_user_create
Normal file
49
hooks/post_user_create
Normal 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
38
hooks/post_user_delete
Normal 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
|
|
@ -6,7 +6,7 @@
|
|||
"en": "Calibre-web for Yunohost",
|
||||
"fr": "Calibre-web pour Yunohost"
|
||||
},
|
||||
"version": "0.91~ynh2",
|
||||
"version": "0.92~ynh3",
|
||||
"url": "https://github.com/janeczku/calibre-web",
|
||||
"license": "free",
|
||||
"maintainer": {
|
||||
|
@ -14,7 +14,7 @@
|
|||
"email": "misterl56@hotmail.com"
|
||||
},
|
||||
"requirements": {
|
||||
"yunohost": ">= 2.7.14"
|
||||
"yunohost": ">= 3.0.0"
|
||||
},
|
||||
"multi_instance": true,
|
||||
"services": [
|
||||
|
@ -40,18 +40,6 @@
|
|||
},
|
||||
"example": "/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",
|
||||
|
@ -69,13 +57,22 @@
|
|||
"en": "Is it a public application?",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"name": "language",
|
||||
"optional": true,
|
||||
"ask": {
|
||||
"en": "Select a default language (you may change it later in the app)",
|
||||
"fr": "Choisissez une langue par défaut (vous pourrez la changer ultérieurement dans l'application)"
|
||||
"en": "Select a default language",
|
||||
"fr": "Choisissez une langue par défaut"
|
||||
},
|
||||
"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"
|
||||
|
@ -83,20 +80,30 @@
|
|||
{
|
||||
"name": "upload",
|
||||
"type":"boolean",
|
||||
"optional": true,
|
||||
"ask": {
|
||||
"en": "Do you want to allow uploading of books (you may change it later in the app)?",
|
||||
"fr": "Voulez vous autoriser l'upload de livres (vous pourrez le changer ultérieurement dans l'application)?"
|
||||
"en": "Do you want to allow uploading of books?",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"name": "password",
|
||||
"type": "password",
|
||||
"name": "public_library",
|
||||
"type":"boolean",
|
||||
"optional": true,
|
||||
"ask": {
|
||||
"en": "Set the administrator password",
|
||||
"fr": "Définissez le mot de passe administrateur"
|
||||
"en": "Do you want to allow access to the library to all Yunohost users? ",
|
||||
"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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
#!/bin/bash
|
||||
|
||||
pkg_dependencies="sqlite3 python-pip imagemagick"
|
||||
PKG_DEPENDENCIES="sqlite3 python-pip imagemagick"
|
||||
DOSSIER_MEDIA=/home/yunohost.multimedia
|
||||
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
|
||||
|
@ -100,11 +111,11 @@ ynh_systemd_action() {
|
|||
#
|
||||
# usage: ynh_multimedia_build_main_dir
|
||||
ynh_multimedia_build_main_dir () {
|
||||
local ynh_media_release="v1.1"
|
||||
local checksum="9ec4321a92aa2c388af4ee0072735e3e"
|
||||
local ynh_media_release="v1.2"
|
||||
local checksum="806a827ba1902d6911095602a9221181"
|
||||
|
||||
# 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
|
||||
echo "${checksum} ${ynh_media_release}.tar.gz" | md5sum -c --status \
|
||||
|
|
|
@ -71,7 +71,7 @@ then
|
|||
path_url="$new_path"
|
||||
#Cannot use empty string for X-script-name, causes an issue in the python prg
|
||||
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
|
||||
# Create a dedicated nginx config
|
||||
ynh_add_nginx_config
|
||||
|
|
|
@ -25,13 +25,13 @@ path_url=$YNH_APP_ARG_PATH
|
|||
admin=$YNH_APP_ARG_ADMIN
|
||||
is_public=$YNH_APP_ARG_IS_PUBLIC
|
||||
language=$YNH_APP_ARG_LANGUAGE
|
||||
ynh_print_OFF
|
||||
pass=$YNH_APP_ARG_PASSWORD
|
||||
ynh_print_ON
|
||||
app=$YNH_APP_INSTANCE_NAME
|
||||
#removing / at the end for consistency
|
||||
calibre_dir=${3%/}
|
||||
upload=$7
|
||||
upload=$6
|
||||
public_library=$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
|
||||
|
@ -56,7 +56,7 @@ ynh_app_setting_set $app domain $domain
|
|||
ynh_app_setting_set $app path $path_url
|
||||
ynh_app_setting_set $app admin $admin
|
||||
ynh_app_setting_set $app is_public $is_public
|
||||
ynh_app_setting_set $app calibre_dir $calibre_dir
|
||||
|
||||
|
||||
#=================================================
|
||||
# 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
|
||||
ynh_setup_source "$final_path"
|
||||
|
||||
|
||||
#=================================================
|
||||
# INSTALL DEPENDENCIES
|
||||
#=================================================
|
||||
|
||||
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
|
||||
|
||||
#=================================================
|
||||
|
@ -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
|
||||
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
|
||||
|
||||
# Create a dedicated nginx config
|
||||
|
@ -120,25 +119,30 @@ ynh_add_systemd_config
|
|||
# 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
|
||||
if [ ! -e "$calibre_dir" ]; then
|
||||
ynh_print_info "Create calibre library folder $calibre_dir"
|
||||
mkdir -p $calibre_dir
|
||||
chown -R $app:$app $calibre_dir
|
||||
create_dir=1
|
||||
#build multimedia directory
|
||||
ynh_multimedia_build_main_dir
|
||||
ynh_multimedia_addaccess $app
|
||||
|
||||
if [ $is_public -eq 1 ]; then #app is public, library is public
|
||||
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
|
||||
|
||||
#Check if metadata.db file exists. If not create it (empty library)
|
||||
if [ ! -e "$calibre_dir"/metadata.db ]; then
|
||||
cp -a ../conf/metadata.db.empty $calibre_dir/metadata.db
|
||||
chown $app:$app $calibre_dir/*
|
||||
fi
|
||||
|
||||
|
||||
#ynh_multimedia_build_main_dir
|
||||
#ynh_multimedia_addfolder "eBook" "$calibre_dir"
|
||||
#ynh_multimedia_addaccess $app
|
||||
|
||||
ynh_app_setting_set $app calibre_dir $calibre_dir
|
||||
|
||||
#=================================================
|
||||
# SETUP LOGROTATE
|
||||
|
@ -158,25 +162,52 @@ chown -R $app:$app /var/log/$app
|
|||
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
|
||||
ynh_systemd_action -l "INFO in server: Starting Gevent server"
|
||||
#systemctl start $app
|
||||
|
||||
#sleep required on low spec like raspberryPi
|
||||
sleep 2s
|
||||
ynh_systemd_action -a stop
|
||||
|
||||
|
||||
#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"
|
||||
|
||||
conf="\"UPDATE user SET $(. <(echo -E echo $(<../conf/init_calibre_db_user))) WHERE ID=1\""
|
||||
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 ')
|
||||
ynh_print_OFF
|
||||
#ynh_print_OFF
|
||||
#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)
|
||||
sqlite3 $final_path/app.db "UPDATE user SET password='$pass' WHERE ID=1"
|
||||
ynh_print_ON
|
||||
#pass=$(python ../conf/generate_password_hash.py "$pass" $final_path/vendor)
|
||||
#sqlite3 $final_path/app.db "UPDATE user SET password='$pass' WHERE ID=1"
|
||||
#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
|
||||
|
@ -211,6 +242,11 @@ then
|
|||
# unprotected_uris allows SSO credentials to be passed anyway.
|
||||
ynh_app_setting_set $app unprotected_uris "/"
|
||||
fi
|
||||
if [ $public_library -eq 0 ]; then
|
||||
yunohost app addaccess $app -u $admin
|
||||
fi
|
||||
|
||||
|
||||
|
||||
#=================================================
|
||||
# RELOAD NGINX
|
||||
|
@ -218,11 +254,3 @@ fi
|
|||
ynh_print_info "Reload nginx and start $app"
|
||||
systemctl reload nginx
|
||||
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
|
|
@ -88,7 +88,7 @@ chown -R $app: $final_path
|
|||
|
||||
# Define and install dependencies
|
||||
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
|
||||
|
||||
#=================================================
|
||||
|
|
|
@ -44,6 +44,9 @@ ynh_clean_setup () {
|
|||
# Exit if an error occurs during the execution of the script
|
||||
ynh_abort_if_errors
|
||||
|
||||
#Stop the app in case database is updated
|
||||
ynh_systemd_action -a stop
|
||||
|
||||
#=================================================
|
||||
# CHECK THE PATH
|
||||
#=================================================
|
||||
|
@ -65,14 +68,18 @@ ynh_setup_source "$final_path"
|
|||
# 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
|
||||
ynh_add_nginx_config
|
||||
|
||||
#=================================================
|
||||
# UPGRADE DEPENDENCIES
|
||||
#=================================================
|
||||
|
||||
ynh_install_app_dependencies $pkg_dependencies
|
||||
ynh_print_info "Download and install dependencies"
|
||||
ynh_install_app_dependencies $PKG_DEPENDENCIES
|
||||
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)
|
||||
ynh_system_user_create $app
|
||||
|
||||
# Set permissions on app files (required to be able to update database)
|
||||
chown -R $app: $final_path
|
||||
|
||||
#=================================================
|
||||
# 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.
|
||||
### 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"
|
||||
|
||||
#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.
|
||||
ynh_store_file_checksum "$final_path/app.db"
|
||||
|
||||
|
|
24
sources/patches/app-config.patch
Normal file
24
sources/patches/app-config.patch
Normal 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>
|
103
sources/patches/app-ub.patch
Normal file
103
sources/patches/app-ub.patch
Normal 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 = {}
|
107
sources/patches/app-web.patch
Normal file
107
sources/patches/app-web.patch
Normal 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:
|
Loading…
Add table
Reference in a new issue