diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index bdb0cab..0000000 --- a/.gitattributes +++ /dev/null @@ -1,17 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.cs diff=csharp - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore deleted file mode 100644 index cd2946a..0000000 --- a/.gitignore +++ /dev/null @@ -1,47 +0,0 @@ -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# ========================= -# Operating System Files -# ========================= - -# OSX -# ========================= - -.DS_Store -.AppleDouble -.LSOverride - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk diff --git a/README.md b/README.md index 944caa3..839d52c 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,71 @@ -## HumHub +# HumHub for YunoHost -[![Integration level](https://dash.yunohost.org/integration/humhub.svg)](https://dash.yunohost.org/appci/app/humhub) ![](https://ci-apps.yunohost.org/ci/badges/humhub.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/humhub.maintain.svg) +[![Integration level](https://dash.yunohost.org/integration/humhub.svg)](https://dash.yunohost.org/appci/app/humhub) ![](https://ci-apps.yunohost.org/ci/badges/humhub.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/humhub.maintain.svg) +[![Install humhub with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=humhub) -HumHub is a feature rich and highly flexible OpenSource Social Network Kit written in PHP. +*[Lire ce readme en français.](./README_fr.md)* -![ScreenShot](https://www.humhub.org/img/features/app.png) +> *This package allows you to install HumHub quickly and simply on a YunoHost server. +If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.* -It's perfect for individual: -- Social Intranets -- Enterprise Social Networks -- Private Social Networks +## Overview +HumHub is an open source social network platform with a wide variety of use cases as social intranet, community or collaboration platform. HumHub consists of a core application, which can be extended through additional modules and adjusted to your needs by many configuration options. -## HumHub for YunoHost -This app installs HumHub on YunoHost: -- The installation is automated (the settings can be customized after installation) -- LDAP is automatically integrated: all YunoHost users are also HumHub users (this can be disabled in settings) -- The YunoHost user of your chosing becomes the HumHub default admin +**Shipped version:** 1.8.1 -**More information:** -- https://yunohost.org/ -- https://www.humhub.org/ +## Screenshots + +![](https://www.humhub.com/static/img/enterprise/app_small.png) + +## Demo + +* [Official demo](https://www.humhub.com/en) + +## Configuration + +How to configure this app: From an admin panel. + +## Documentation + + * Official documentation: https://docs.humhub.org + * YunoHost documentation: If specific documentation is needed, feel free to contribute. + +## YunoHost specific features + +#### Multi-user support + + * Are LDAP and HTTP auth supported? **Yes** + * Can the app be used by multiple users? **Yes** + +#### Supported architectures + +* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/humhub%20%28Apps%29.svg)](https://ci-apps.yunohost.org/ci/apps/humhub/) +* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/humhub%20%28Apps%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/humhub/) + +## Limitations + +* Any known limitations. + +## Additional information + +* Other info you would like to add about this app. + +## Links + + * Report a bug: https://github.com/YunoHost-Apps/humhub_ynh/issues + * App website: https://www.humhub.org/ + * Upstream app repository: https://github.com/humhub/humhub + * YunoHost website: https://yunohost.org/ + +--- + +## Developer info + +Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/humhub_ynh/tree/testing). + +To try the testing branch, please proceed like that. +``` +sudo yunohost app install https://github.com/YunoHost-Apps/humhub_ynh/tree/testing --debug +or +sudo yunohost app upgrade humhub -u https://github.com/YunoHost-Apps/humhub_ynh/tree/testing --debug +``` diff --git a/README_fr.md b/README_fr.md new file mode 100644 index 0000000..3f142ab --- /dev/null +++ b/README_fr.md @@ -0,0 +1,71 @@ +# HumHub pour YunoHost + +[![Niveau d'intégration](https://dash.yunohost.org/integration/humhub.svg)](https://dash.yunohost.org/appci/app/humhub) ![](https://ci-apps.yunohost.org/ci/badges/humhub.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/humhub.maintain.svg) +[![Installer Humhub avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=humhub) + +*[Read this readme in english.](./README.md)* + +> *Ce package vous permet d'installer HumHub rapidement et simplement sur un serveur YunoHost. +Si vous n'avez pas YunoHost, consultez [le guide](https://yunohost.org/#/install) pour apprendre comment l'installer.* + +## Vue d'ensemble +HumHub est une plate-forme de réseau social open source avec une grande variété de cas d'utilisation en tant qu'intranet social, plate-forme de communauté ou de collaboration. HumHub se compose d'une application principale, qui peut être étendue grâce à des modules supplémentaires et ajustée à vos besoins par de nombreuses options de configuration. + +**Version incluse :** 1.8.1 + +## Captures d'écran + +![](https://www.humhub.com/static/img/enterprise/app_small.png) + +## Démo + +* [Démo officielle](https://www.humhub.com/en) + +## Configuration + +Comment configurer cette application : via le panneau d'administration. + +## Documentation + + * Documentation officielle : https://docs.humhub.org + * Documentation YunoHost : Si une documentation spécifique est nécessaire, n'hésitez pas à contribuer. + +## Caractéristiques spécifiques YunoHost + +#### Support multi-utilisateur + +* L'authentification LDAP et HTTP est-elle prise en charge ? **Oui** +* L'application peut-elle être utilisée par plusieurs utilisateurs ? **Oui** + +#### Architectures supportées + +* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/humhub%20%28Apps%29.svg)](https://ci-apps.yunohost.org/ci/apps/humhub/) +* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/humhub%20%28Apps%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/humhub/) + +## Limitations + +* Limitations connues. + +## Informations additionnelles + +* Autres informations que vous souhaitez ajouter sur cette application. + +## Liens + + * Signaler un bug : https://github.com/YunoHost-Apps/humhub_ynh/issues + * Site de l'application : https://www.humhub.org/ + * Dépôt de l'application principale : https://github.com/humhub/humhub + * Site web YunoHost : https://yunohost.org/ + +--- + +## Informations pour les développeurs + +Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/humhub_ynh/tree/testing). + +Pour essayer la branche testing, procédez comme suit. +``` +sudo yunohost app install https://github.com/YunoHost-Apps/humhub_ynh/tree/testing --debug +ou +sudo yunohost app upgrade humhub -u https://github.com/YunoHost-Apps/humhub_ynh/tree/testing --debug +``` diff --git a/check_process b/check_process index cb6b37f..2bfd018 100644 --- a/check_process +++ b/check_process @@ -1,10 +1,9 @@ -;; Test HumHub - auto_remove=1 +;; Test complet ; Manifest - domain="domain.tld" (DOMAIN) - path="/humhub" (PATH) - admin="john" (USER) - is_public=0 (PUBLIC|public=0|private=1) + domain="domain.tld" (DOMAIN) + path="/path" (PATH) + admin="john" (USER) + is_public=1 (PUBLIC|public=1|private=0) ; Checks pkg_linter=1 setup_sub_dir=1 @@ -13,24 +12,17 @@ setup_private=1 setup_public=1 upgrade=1 + upgrade=0 from_commit=CommitHash backup_restore=1 multi_instance=1 - wrong_user=1 - wrong_path=1 - incorrect_path=1 - corrupt_source=0 - fail_download_source=0 port_already_use=0 - final_path_already_use=0 -;;; Levels - Level 1=auto - Level 2=auto - Level 3=auto - Level 4=na -# LDAP is integrated but no SSO yet - Level 5=auto - Level 6=auto - Level 7=auto - Level 8=0 - Level 9=0 - Level 10=0 + change_url=0 +;;; Options +Email= +Notification=none +;;; Upgrade options + ; commit=CommitHash + name=Name and date of the commit. + manifest_arg=domain=DOMAIN&path=PATH&admin=USER&language=fr&is_public=1&password=pass&port=666& + + diff --git a/conf/app.src b/conf/app.src new file mode 100644 index 0000000..3a57f14 --- /dev/null +++ b/conf/app.src @@ -0,0 +1,9 @@ +SOURCE_URL=https://www.humhub.com/download/package/humhub-1.8.1.tar.gz +SOURCE_SUM=2eca1561506bfa06f8e36358659a0ec0f72497547d949d2232a85dc788ad4758 +SOURCE_SUM_PRG=sha256sum +SOURCE_FORMAT=tar.gz +SOURCE_IN_SUBDIR=true +SOURCE_FILENAME=humhub-1.8.1.tar.gz +SOURCE_EXTRACT=true + + diff --git a/conf/common.php b/conf/common.php index 66d0b33..2068012 100644 --- a/conf/common.php +++ b/conf/common.php @@ -3,9 +3,9 @@ return [ 'components' => [ 'db' => [ - 'dsn' => 'mysql:host=localhost;dbname=DBNAME_TO_CHANGE', - 'username' => 'DBUSER_TO_CHANGE', - 'password' => 'DBPASS_TO_CHANGE', + 'dsn' => 'mysql:host=localhost;dbname=__DB_NAME__', + 'username' => '__DB_USER__', + 'password' => '__DB_PWD__', ], ] ]; diff --git a/conf/cron b/conf/cron new file mode 100644 index 0000000..a0bc207 --- /dev/null +++ b/conf/cron @@ -0,0 +1,2 @@ +* * * * * /usr/bin/php__PHPVERSION__ __FINALPATH__/protected/yii queue/run >/dev/null 2>&1 +* * * * * /usr/bin/php__PHPVERSION__ __FINALPATH__/protected/yii cron/run >/dev/null 2>&1 diff --git a/conf/ldap.sql b/conf/ldap.sql index 12429c2..53ff5e7 100644 --- a/conf/ldap.sql +++ b/conf/ldap.sql @@ -1,19 +1,28 @@ -REPLACE INTO setting (`name`, `value`, `module_id`) VALUES -('auth.ldap.enabled', '1', 'user'), -('auth.ldap.hostname', 'localhost', 'user'), -('auth.ldap.port', '389', 'user'), -('auth.ldap.encryption', '', 'user'), -('auth.ldap.username', '', 'user'), -('auth.ldap.password', '', 'user'), -('auth.ldap.baseDn', 'ou=users,dc=yunohost,dc=org', 'user'), -('auth.ldap.loginFilter', '(uid=%s)', 'user'), -('auth.ldap.userFilter', 'objectClass=mailAccount', 'user'), -('auth.ldap.emailAttribute', 'mail', 'user'), -('auth.ldap.usernameAttribute', 'uid', 'user'), -('auth.ldap.refreshUsers', '1', 'user'), +BEGIN; + +DELETE FROM setting WHERE +(`name` = 'auth.anonymousRegistration') OR +(`name` = 'auth.allowGuestAccess') OR +(`name` = 'auth.internalUsersCanInvite'); + +INSERT INTO setting (`name`, `value`, `module_id`) VALUES +('enabled', '1', 'ldap'), +('hostname', 'localhost', 'ldap'), +('port', '389', 'ldap'), +('encryption', '', 'ldap'), +('username', '', 'ldap'), +('password', '', 'ldap'), +('baseDn', 'ou=users,dc=yunohost,dc=org', 'ldap'), +('loginFilter', '(uid=%s)', 'ldap'), +('userFilter', 'objectClass=mailAccount', 'ldap'), +('emailAttribute', 'mail', 'ldap'), +('usernameAttribute', 'uid', 'ldap'), +('idAttribute', 'uid', 'ldap'), +('refreshUsers', '1', 'ldap'), ('auth.anonymousRegistration', '0', 'user'), ('auth.allowGuestAccess', '0', 'user'), ('auth.internalUsersCanInvite', '0', 'user'); -UPDATE `user` SET `auth_mode` = 'ldap' WHERE `user`.`username` = 'YNH_ADMIN_USER'; +UPDATE `user` SET `auth_mode` = 'ldap' WHERE `user`.`username` = '__ADMIN__'; +COMMIT; diff --git a/conf/nginx.conf b/conf/nginx.conf index 3652117..119f226 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,32 +1,38 @@ -location YNH_WWW_PATH/ { - alias YNH_WWW_ALIAS; +#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; +location __PATH__/ { + + # Path to source + alias __FINALPATH__/ ; + index index.php; + try_files $uri $uri/ index.php?$args; location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(/.*)$; - fastcgi_pass unix:/var/run/php5-fpm-YNH_WWW_APP.sock; + + set $fsn /index.php; + if (-f $document_root$fastcgi_script_name){ + set $fsn $fastcgi_script_name; + } + + fastcgi_pass unix:/var/run/php/php__PHPVERSION__-fpm-__NAME__.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param REMOTE_USER $remote_user; fastcgi_param PATH_INFO $fastcgi_path_info; - fastcgi_param SCRIPT_FILENAME $request_filename; + fastcgi_param SCRIPT_FILENAME $document_root$fsn; } - location ~ ^YNH_WWW_PATH/(?:ico|css|js|gif|jpe?g|png|ttf|woff)$ { - access_log off; - expires 30d; - add_header Pragma public; - add_header Cache-Control "public, mustrevalidate, proxy-revalidate"; - } + location ~ ^__PATH__/(assets|static|themes|uploads) { + access_log off; + expires 10d; + more_set_headers "Cache-Control: public, no-transform"; + } - location = YNH_WWW_PATH/protected { - deny all; - } - - location = YNH_WWW_PATH/uploads/file { - deny all; - } + location ~ ^__PATH__/(protected|framework|themes/\w+/views|\.|uploads/file) { + deny all; + } # Include SSOWAT user panel. include conf.d/yunohost_panel.conf.inc; diff --git a/conf/php-fpm.conf b/conf/php-fpm.conf index 927a3ff..120b431 100644 --- a/conf/php-fpm.conf +++ b/conf/php-fpm.conf @@ -1,10 +1,11 @@ ; Start a new pool named 'www'. -; the variable $pool can we used in any directive and will be replaced by the +; the variable $pool can be used in any directive and will be replaced by the ; pool name ('www' here) -[YNH_WWW_APP] +[__NAMETOCHANGE__] ; Per pool prefix ; It only applies on the following directives: +; - 'access.log' ; - 'slowlog' ; - 'listen' (unixsocket) ; - 'chroot' @@ -16,21 +17,43 @@ ; Default Value: none ;prefix = /path/to/pools/$pool +; Unix user/group of processes +; Note: The user is mandatory. If the group is not set, the default user's group +; will be used. +user = __USER__ +group = __USER__ + ; The address on which to accept FastCGI requests. ; Valid syntaxes are: -; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific address on +; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on ; a specific port; -; 'port' - to listen on a TCP socket to all addresses on a -; specific port; +; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on +; a specific port; +; 'port' - to listen on a TCP socket to all addresses +; (IPv6 and IPv4-mapped) on a specific port; ; '/path/to/unix/socket' - to listen on a unix socket. ; Note: This value is mandatory. -listen = /var/run/php5-fpm-YNH_WWW_APP.sock +listen = /var/run/php/php__PHPVERSION__-fpm-__NAMETOCHANGE__.sock -; Set listen(2) backlog. A value of '-1' means unlimited. -; Default Value: 128 (-1 on FreeBSD and OpenBSD) -;listen.backlog = -1 +; Set listen(2) backlog. +; Default Value: 511 (-1 on FreeBSD and OpenBSD) +;listen.backlog = 511 -; List of ipv4 addresses of FastCGI clients which are allowed to connect. +; Set permissions for unix socket, if one is used. In Linux, read/write +; permissions must be set in order to allow connections from a web server. Many +; BSD-derived systems allow connections regardless of permissions. +; Default Values: user and group are set as the running user +; mode is set to 0660 +listen.owner = www-data +listen.group = www-data +;listen.mode = 0660 +; When POSIX Access Control Lists are supported you can set them using +; these options, value is a comma separated list of user/group names. +; When set, listen.owner and listen.group are ignored +;listen.acl_users = +;listen.acl_groups = + +; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect. ; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original ; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address ; must be separated by a comma. If this value is left blank, connections will be @@ -38,26 +61,26 @@ listen = /var/run/php5-fpm-YNH_WWW_APP.sock ; Default Value: any ;listen.allowed_clients = 127.0.0.1 -; Set permissions for unix socket, if one is used. In Linux, read/write -; permissions must be set in order to allow connections from a web server. Many -; BSD-derived systems allow connections regardless of permissions. -; Default Values: user and group are set as the running user -; mode is set to 0666 -listen.owner = www-data -listen.group = www-data -listen.mode = 0600 +; Specify the nice(2) priority to apply to the pool processes (only if set) +; The value can vary from -19 (highest priority) to 20 (lower priority) +; Note: - It will only work if the FPM master process is launched as root +; - The pool processes will inherit the master process priority +; unless it specified otherwise +; Default Value: no set +; process.priority = -19 -; Unix user/group of processes -; Note: The user is mandatory. If the group is not set, the default user's group -; will be used. -user = www-data -group = www-data +; Set the process dumpable flag (PR_SET_DUMPABLE prctl) even if the process user +; or group is differrent than the master process user. It allows to create process +; core dump and ptrace the process for the pool user. +; Default Value: no +; process.dumpable = yes ; Choose how the process manager will control the number of child processes. ; Possible Values: ; static - a fixed number (pm.max_children) of child processes; ; dynamic - the number of child processes are set dynamically based on the -; following directives: +; following directives. With this process management, there will be +; always at least 1 children. ; pm.max_children - the maximum number of children that can ; be alive at the same time. ; pm.start_servers - the number of children created on startup. @@ -69,73 +92,150 @@ group = www-data ; state (waiting to process). If the number ; of 'idle' processes is greater than this ; number then some children will be killed. +; ondemand - no children are created at startup. Children will be forked when +; new requests will connect. The following parameter are used: +; pm.max_children - the maximum number of children that +; can be alive at the same time. +; pm.process_idle_timeout - The number of seconds after which +; an idle process will be killed. ; Note: This value is mandatory. pm = dynamic ; The number of child processes to be created when pm is set to 'static' and the -; maximum number of child processes to be created when pm is set to 'dynamic'. +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. ; This value sets the limit on the number of simultaneous requests that will be ; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. ; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP -; CGI. -; Note: Used when pm is set to either 'static' or 'dynamic' +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' ; Note: This value is mandatory. -pm.max_children = 6 +pm.max_children = 5 ; The number of child processes created on startup. ; Note: Used only when pm is set to 'dynamic' ; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 -pm.start_servers = 3 +pm.start_servers = 2 ; The desired minimum number of idle server processes. ; Note: Used only when pm is set to 'dynamic' ; Note: Mandatory when pm is set to 'dynamic' -pm.min_spare_servers = 3 +pm.min_spare_servers = 1 ; The desired maximum number of idle server processes. ; Note: Used only when pm is set to 'dynamic' ; Note: Mandatory when pm is set to 'dynamic' -pm.max_spare_servers = 5 +pm.max_spare_servers = 3 + +; The number of seconds after which an idle process will be killed. +; Note: Used only when pm is set to 'ondemand' +; Default Value: 10s +;pm.process_idle_timeout = 10s; ; The number of requests each child process should execute before respawning. ; This can be useful to work around memory leaks in 3rd party libraries. For ; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. ; Default Value: 0 -pm.max_requests = 500 +;pm.max_requests = 500 ; The URI to view the FPM status page. If this value is not set, no URI will be -; recognized as a status page. By default, the status page shows the following -; information: -; accepted conn - the number of request accepted by the pool; +; recognized as a status page. It shows the following informations: ; pool - the name of the pool; -; process manager - static or dynamic; +; process manager - static, dynamic or ondemand; +; start time - the date and time FPM has started; +; start since - number of seconds since FPM has started; +; accepted conn - the number of request accepted by the pool; +; listen queue - the number of request in the queue of pending +; connections (see backlog in listen(2)); +; max listen queue - the maximum number of requests in the queue +; of pending connections since FPM has started; +; listen queue len - the size of the socket queue of pending connections; ; idle processes - the number of idle processes; ; active processes - the number of active processes; -; total processes - the number of idle + active processes. +; total processes - the number of idle + active processes; +; max active processes - the maximum number of active processes since FPM +; has started; ; max children reached - number of times, the process limit has been reached, ; when pm tries to start more children (works only for -; pm 'dynamic') -; The values of 'idle processes', 'active processes' and 'total processes' are -; updated each second. The value of 'accepted conn' is updated in real time. +; pm 'dynamic' and 'ondemand'); +; Value are updated in real time. ; Example output: -; accepted conn: 12073 ; pool: www ; process manager: static -; idle processes: 35 -; active processes: 65 -; total processes: 100 -; max children reached: 1 +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 62636 +; accepted conn: 190460 +; listen queue: 0 +; max listen queue: 1 +; listen queue len: 42 +; idle processes: 4 +; active processes: 11 +; total processes: 15 +; max active processes: 12 +; max children reached: 0 +; ; By default the status page output is formatted as text/plain. Passing either -; 'html' or 'json' as a query string will return the corresponding output -; syntax. Example: +; 'html', 'xml' or 'json' in the query string will return the corresponding +; output syntax. Example: ; http://www.foo.bar/status ; http://www.foo.bar/status?json ; http://www.foo.bar/status?html +; http://www.foo.bar/status?xml +; +; By default the status page only outputs short status. Passing 'full' in the +; query string will also return status for each pool process. +; Example: +; http://www.foo.bar/status?full +; http://www.foo.bar/status?json&full +; http://www.foo.bar/status?html&full +; http://www.foo.bar/status?xml&full +; The Full status returns for each process: +; pid - the PID of the process; +; state - the state of the process (Idle, Running, ...); +; start time - the date and time the process has started; +; start since - the number of seconds since the process has started; +; requests - the number of requests the process has served; +; request duration - the duration in µs of the requests; +; request method - the request method (GET, POST, ...); +; request URI - the request URI with the query string; +; content length - the content length of the request (only with POST); +; user - the user (PHP_AUTH_USER) (or '-' if not set); +; script - the main script called (or '-' if not set); +; last request cpu - the %cpu the last request consumed +; it's always 0 if the process is not in Idle state +; because CPU calculation is done when the request +; processing has terminated; +; last request memory - the max amount of memory the last request consumed +; it's always 0 if the process is not in Idle state +; because memory calculation is done when the request +; processing has terminated; +; If the process is in Idle state, then informations are related to the +; last request the process has served. Otherwise informations are related to +; the current request being served. +; Example output: +; ************************ +; pid: 31330 +; state: Running +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 63087 +; requests: 12808 +; request duration: 1250261 +; request method: GET +; request URI: /test_mem.php?N=10000 +; content length: 0 +; user: - +; script: /home/fat/web/docs/php/test_mem.php +; last request cpu: 0.00 +; last request memory: 0 +; +; Note: There is a real-time FPM status monitoring sample web page available +; It's available in: /usr/share/php/7.0/fpm/status.html +; ; Note: The value must start with a leading slash (/). The value can be ; anything, but it may not be a good idea to use the .php extension or it ; may conflict with a real PHP file. ; Default Value: not set -pm.status_path = /fpm-status +;pm.status_path = /status ; The ping URI to call the monitoring page of FPM. If this value is not set, no ; URI will be recognized as a ping page. This could be used to test from outside @@ -147,39 +247,102 @@ pm.status_path = /fpm-status ; anything, but it may not be a good idea to use the .php extension or it ; may conflict with a real PHP file. ; Default Value: not set -ping.path = /ping +;ping.path = /ping ; This directive may be used to customize the response of a ping request. The ; response is formatted as text/plain with a 200 response code. ; Default Value: pong ;ping.response = pong -; The timeout for serving a single request after which the worker process will -; be killed. This option should be used when the 'max_execution_time' ini option -; does not stop script execution for some reason. A value of '0' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -request_terminate_timeout = 120s +; The access log file +; Default: not set +;access.log = log/$pool.access.log + +; The access log format. +; The following syntax is allowed +; %%: the '%' character +; %C: %CPU used by the request +; it can accept the following format: +; - %{user}C for user CPU only +; - %{system}C for system CPU only +; - %{total}C for user + system CPU (default) +; %d: time taken to serve the request +; it can accept the following format: +; - %{seconds}d (default) +; - %{miliseconds}d +; - %{mili}d +; - %{microseconds}d +; - %{micro}d +; %e: an environment variable (same as $_ENV or $_SERVER) +; it must be associated with embraces to specify the name of the env +; variable. Some exemples: +; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e +; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e +; %f: script filename +; %l: content-length of the request (for POST request only) +; %m: request method +; %M: peak of memory allocated by PHP +; it can accept the following format: +; - %{bytes}M (default) +; - %{kilobytes}M +; - %{kilo}M +; - %{megabytes}M +; - %{mega}M +; %n: pool name +; %o: output header +; it must be associated with embraces to specify the name of the header: +; - %{Content-Type}o +; - %{X-Powered-By}o +; - %{Transfert-Encoding}o +; - .... +; %p: PID of the child that serviced the request +; %P: PID of the parent of the child that serviced the request +; %q: the query string +; %Q: the '?' character if query string exists +; %r: the request URI (without the query string, see %q and %Q) +; %R: remote IP address +; %s: status (response code) +; %t: server time the request was received +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %T: time the log has been written (the request has finished) +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %u: remote user +; +; Default: "%R - %u %t \"%m %r\" %s" +;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" + +; The log file for slow requests +; Default Value: not set +; Note: slowlog is mandatory if request_slowlog_timeout is set +;slowlog = log/$pool.log.slow ; The timeout for serving a single request after which a PHP backtrace will be ; dumped to the 'slowlog' file. A value of '0s' means 'off'. ; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) ; Default Value: 0 -request_slowlog_timeout = 5s +;request_slowlog_timeout = 0 -; The log file for slow requests -; Default Value: not set -; Note: slowlog is mandatory if request_slowlog_timeout is set -slowlog = /var/log/nginx/YNH_WWW_APP.slow.log +; The timeout for serving a single request after which the worker process will +; be killed. This option should be used when the 'max_execution_time' ini option +; does not stop script execution for some reason. A value of '0' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +request_terminate_timeout = 1d ; Set open file descriptor rlimit. ; Default Value: system defined value -rlimit_files = 4096 +;rlimit_files = 1024 ; Set max core size rlimit. ; Possible Values: 'unlimited' or an integer greater or equal to 0 ; Default Value: system defined value -rlimit_core = 0 +;rlimit_core = 0 ; Chroot to this directory at the start. This value must be defined as an ; absolute path. When this value is not set, chroot is not used. @@ -195,14 +358,31 @@ rlimit_core = 0 ; Chdir to this directory at the start. ; Note: relative path can be used. ; Default Value: current directory or / when chroot -chdir = YNH_WWW_ALIAS +chdir = __FINALPATH__ ; Redirect worker stdout and stderr into main error log. If not set, stdout and ; stderr will be redirected to /dev/null according to FastCGI specs. ; Note: on highloaded environement, this can cause some delay in the page ; process time (several ms). ; Default Value: no -catch_workers_output = yes +;catch_workers_output = yes + +; Clear environment in FPM workers +; Prevents arbitrary environment variables from reaching FPM worker processes +; by clearing the environment in workers before env vars specified in this +; pool configuration are added. +; Setting to "no" will make all environment variables available to PHP code +; via getenv(), $_ENV and $_SERVER. +; Default Value: yes +;clear_env = no + +; Limits the extensions of the main script FPM will allow to parse. This can +; prevent configuration mistakes on the web server side. You should only limit +; FPM to .php extensions to prevent malicious users to use other extensions to +; execute php code. +; Note: set an empty value to allow all extensions. +; Default Value: .php +;security.limit_extensions = .php .php3 .php4 .php5 .php7 ; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from ; the current environment. @@ -238,14 +418,13 @@ catch_workers_output = yes ;php_admin_flag[log_errors] = on ;php_admin_value[memory_limit] = 32M -# Common values to change to increase file upload limit -php_value[upload_max_filesize] = 1G -php_value[post_max_size] = 1G -;php_value[mail.add_x_header] = Off - -# Other common parameters -;php_value[max_execution_time] = 600 -;php_value[max_input_time] = 300 -;php_value[memory_limit] = 256M -;php_value[short_open_tag] = On +; Common values to change to increase file upload limit +php_admin_value[upload_max_filesize] = 1G +php_admin_value[post_max_size] = 1G +; php_admin_flag[mail.add_x_header] = Off +; Other common parameters +; php_admin_value[max_execution_time] = 600 +; php_admin_value[max_input_time] = 300 +; php_admin_value[memory_limit] = 256M +; php_admin_flag[short_open_tag] = On diff --git a/manifest.json b/manifest.json index 4e8c9fc..5356077 100644 --- a/manifest.json +++ b/manifest.json @@ -7,18 +7,19 @@ "fr": "Réseau Social d'Entreprise." }, "url": "https://www.humhub.org", - "license": "free", + "license": "AGPL-3.0-only", "maintainer": { - "name": "Scith", - "url": "https://github.com/scith" + "name": "Nils Van Zuijlen", + "url": "https://github.com/nils-van-zuijlen" }, + "version": "1.8.1~ynh1", "requirements": { - "yunohost": ">= 2.4.0" + "yunohost": ">= 4.1.7" }, "multi_instance": true, "services": [ "nginx", - "php5-fpm", + "php7.3-fpm", "mysql" ], "arguments": { @@ -26,38 +27,22 @@ { "name": "domain", "type": "domain", - "ask": { - "en": "Choose a domain name for HumHub", - "fr": "Choisissez un nom de domaine pour HumHub" - }, "example": "example.com" }, { "name": "path", "type": "path", - "ask": { - "en": "Choose a path for HumHub", - "fr": "Choisissez un chemin pour HumHub" - }, "example": "/humhub", "default": "/humhub" }, { "name": "admin", "type": "user", - "ask": { - "en": "Choose an admin user", - "fr": "Choisissez l’administrateur" - }, "example": "johndoe" }, { "name": "is_public", "type": "boolean", - "ask": { - "en": "Is it a public site?", - "fr": "Est-ce un site public ?" - }, "default": false } ] diff --git a/scripts/_common.sh b/scripts/_common.sh new file mode 100644 index 0000000..7123bfb --- /dev/null +++ b/scripts/_common.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +#================================================= +# COMMON VARIABLES +#================================================= + +YNH_PHP_VERSION="7.3" + +extra_php_dependencies="php${YNH_PHP_VERSION}-imagick php${YNH_PHP_VERSION}-curl php${YNH_PHP_VERSION}-bz2 php${YNH_PHP_VERSION}-gd php${YNH_PHP_VERSION}-intl php${YNH_PHP_VERSION}-mysql php${YNH_PHP_VERSION}-zip php${YNH_PHP_VERSION}-apcu-bc php${YNH_PHP_VERSION}-apcu php${YNH_PHP_VERSION}-xml php${YNH_PHP_VERSION}-ldap" + +#================================================= +# PERSONAL HELPERS +#================================================= + +local_curl_csrf () { + # Define url of page to curl + local local_page=$(ynh_normalize_url_path $1) + local full_path=$path_url$local_page + + if [ "${path_url}" == "/" ]; then + full_path=$local_page + fi + + local full_page_url=https://localhost$full_path + + # Concatenate all other arguments with '&' to prepare POST data + local POST_data="" + local arg="" + for arg in "${@:2}" + do + POST_data="${POST_data}${arg}&" + done + if [ -n "$POST_data" ] + then + # Add --data arg and remove the last character, which is an unecessary '&' + POST_data="--data ${POST_data::-1}" + fi + + # Wait untils nginx has fully reloaded (avoid curl fail with http2) + sleep 2 + + local cookiefile=/tmp/ynh-$app-cookie.txt + touch $cookiefile + chown root $cookiefile + chmod 700 $cookiefile + + # Curl the URL for the CSRF token + local token_line=`curl --silent --show-error --insecure --location --header "Host: $domain" --resolve $domain:443:127.0.0.1 "$full_page_url" --cookie-jar $cookiefile --cookie $cookiefile | grep 'meta name="csrf-token"'` + + token_line=${token_line##*content=\"} + local csrf=${token_line%%\">*} + POST_data="${POST_data}&_csrf=${csrf}" + + curl --silent --show-error --insecure --location --header "Host: $domain" --resolve $domain:443:127.0.0.1 $POST_data "$full_page_url" --cookie-jar $cookiefile --cookie $cookiefile +} + +#Convert --data to --data-urlencode before ynh_local_curl +myynh_urlencode() { + local data + if [[ $# != 1 ]]; then + echo "Usage: $0 string-to-urlencode" + return 1 + fi + data="$(curl -s -o /dev/null -w %{url_effective} --get --data-urlencode "$1" "")" + if [[ $? != 3 ]]; then + echo "Unexpected error" 1>&2 + return 2 + fi + echo "${data##/?}" + return 0 +} + +#================================================= +# EXPERIMENTAL HELPERS +#================================================= + +#================================================= +# FUTURE OFFICIAL HELPERS +#================================================= diff --git a/scripts/_extrahelpers b/scripts/_extrahelpers deleted file mode 100644 index 07fa58f..0000000 --- a/scripts/_extrahelpers +++ /dev/null @@ -1,31 +0,0 @@ -# -# Extra helpers not implemeted yet in core -# - -# Curl abstraction to help with POST requests to local pages (such as installation forms) -# See https://github.com/YunoHost/yunohost/pull/288 -# $domain and $path_url should be defined externally (and correspond to the domain.tld and the /path (of the app?)) -# -# example: ynh_local_curl "/install.php?installButton" "foo=$var1" "bar=$var2" -# -# usage: ynh_local_curl "page_uri" "key1=value1" "key2=value2" ... -# | arg: page_uri - Path (relative to $path_url) of the page where POST data will be sent -# | arg: key1=value1 - (Optionnal) POST key and corresponding value -# | arg: key2=value2 - (Optionnal) Another POST key and corresponding value -# | arg: ... - (Optionnal) More POST keys and values -ynh_local_curl () { - # Define url of page to curl - full_page_url=https://localhost$path$1 - - # Concatenate all other arguments with '&' to prepare POST data - POST_data="" - for arg in "${@:2}" - do - POST_data="${POST_data}${arg}&" - done - # (Remove the last character, which is an unecessary '&') - POST_data=${POST_data::-1} - - # Curl the URL - curl -kL -H "Host: $domain" --resolve $domain:443:127.0.0.1 --data "$POST_data" "$full_page_url" 2>&1 -} diff --git a/scripts/backup b/scripts/backup index a3b93f1..d01a608 100644 --- a/scripts/backup +++ b/scripts/backup @@ -1,26 +1,78 @@ #!/bin/bash -# Exit on command errors and treat unset variables as an error -set -eu +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +# Keep this path for calling _common.sh inside the execution's context of backup and restore scripts +source ../settings/scripts/_common.sh +source /usr/share/yunohost/helpers + +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_clean_setup () { + ### Remove this function if there's nothing to clean before calling the remove script. + true +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_print_info --message="Loading installation settings..." app=$YNH_APP_INSTANCE_NAME -# Source YunoHost helpers - source /usr/share/yunohost/helpers +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +domain=$(ynh_app_setting_get --app=$app --key=domain) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) -# Backup sources & data - ynh_backup "/var/www/${app}" "sources" - ynh_backup "/etc/cron.d/${app}" "cron" +#================================================= +# DECLARE DATA AND CONF FILES TO BACKUP +#================================================= +ynh_print_info --message="Declaring files to be backed up..." -# MySQL - dbname=$app - dbuser=$app - dbpass=$(ynh_app_setting_get "$app" mysqlpwd) - mysqldump -u "$dbuser" -p"$dbpass" --no-create-db "$dbname" > ./dump.sql +#================================================= +# BACKUP THE APP MAIN DIR +#================================================= -# Copy NGINX configuration - domain=$(ynh_app_setting_get "$app" domain) - ynh_backup "/etc/nginx/conf.d/${domain}.d/${app}.conf" "nginx.conf" +ynh_backup --src_path="$final_path" -# Copy PHP-FPM configuration - ynh_backup "/etc/php5/fpm/pool.d/${app}.conf" "php-fpm.conf" +#================================================= +# BACKUP THE NGINX CONFIGURATION +#================================================= + +ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# BACKUP THE PHP-FPM CONFIGURATION +#================================================= + +ynh_backup --src_path="/etc/php/$phpversion/fpm/pool.d/$app.conf" + +#================================================= +# SPECIFIC BACKUP +#================================================= +# BACKUP VARIOUS FILES +#================================================= + +ynh_backup --src_path="/etc/cron.d/$app" + +#================================================= +# BACKUP THE MYSQL DATABASE +#================================================= +ynh_print_info --message="Backing up the MySQL database..." + +ynh_mysql_dump_db --database="$db_name" > db.sql + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info --message="Backup script completed for $app. (YunoHost will then actually copy those files to the archive)." diff --git a/scripts/install b/scripts/install index 8880bb2..a5a402b 100644 --- a/scripts/install +++ b/scripts/install @@ -1,135 +1,230 @@ #!/bin/bash -# Exit on command errors and treat unset variables as an error -set -eu +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_clean_setup () { + ### Remove this function if there's nothing to clean before calling the remove script. + true +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# RETRIEVE ARGUMENTS FROM THE MANIFEST +#================================================= + +domain=$YNH_APP_ARG_DOMAIN +path_url=$YNH_APP_ARG_PATH +admin=$YNH_APP_ARG_ADMIN +is_public=$YNH_APP_ARG_IS_PUBLIC app=$YNH_APP_INSTANCE_NAME -version=$(cat ../sources/version) -source='https://sourceforge.net/projects/humhub/files/' -# Retrieve arguments - domain=$YNH_APP_ARG_DOMAIN - path=$YNH_APP_ARG_PATH - admin=$YNH_APP_ARG_ADMIN - is_public=$YNH_APP_ARG_IS_PUBLIC +#================================================= +# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS +#================================================= +ynh_script_progression --message="Validating installation parameters..." --weight=1 -# Source YunoHost helpers - source /usr/share/yunohost/helpers - source ./_extrahelpers +final_path=/var/www/$app +test ! -e "$final_path" || ynh_die --message="This path already contains a folder" -# Correct path: puts a / at the start and nothing at the end - if [ "${path:0:1}" != "/" ]; then - path="/$path" - fi - if [ "${path:${#path}-1}" == "/" ] && [ ${#path} -gt 1 ]; then - path="${path:0:${#path}-1}" - fi +# Register (book) web path +ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url -# Check domain/path availability - sudo yunohost app checkurl "${domain}${path}" -a "$app" \ - || ynh_die "Path not available: ${domain}${path}" +#================================================= +# STORE SETTINGS FROM MANIFEST +#================================================= +ynh_script_progression --message="Storing installation settings..." --weight=1 -# Check admin user parameter - ynh_user_exists "$admin" \ - || ynh_die "The chosen admin user does not exist" - ynh_app_setting_set "$app" admin "$admin" +ynh_app_setting_set --app=$app --key=domain --value=$domain +ynh_app_setting_set --app=$app --key=path --value=$path_url +ynh_app_setting_set --app=$app --key=admin --value=$admin -# Copy source files - src_path=/var/www/$app - sudo mkdir -p $src_path - sudo wget -q "${source}humhub-${version}.zip/download" -O humhub-${version}.zip - sudo unzip -qq humhub-${version}.zip - sudo cp -a humhub-${version}/. $src_path +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# CREATE A MYSQL DATABASE +#================================================= +ynh_script_progression --message="Creating a MySQL database..." --weight=1 -# Hotfixes - # Fix LDAP email. See https://github.com/humhub/humhub/issues/1949 - sudo cp -a ../sources/fix/AuthClientHelpers.php $src_path/protected/humhub/modules/user/authclient/AuthClientHelpers.php - # Fix to allow passwordless LDAP login - sudo cp -a ../sources/fix/ZendLdapClient.php $src_path/protected/humhub/modules/user/authclient/ZendLdapClient.php - sudo sed -i "s@defined('YII_DEBUG') or define('YII_DEBUG', true);@//defined('YII_DEBUG') or define('YII_DEBUG', true);@g" $src_path/index.php - sudo sed -i "s@defined('YII_ENV') or define('YII_ENV', 'dev');@//defined('YII_ENV') or define('YII_ENV', 'dev');@g" $src_path/index.php +db_name=$(ynh_sanitize_dbid --db_name=$app) +db_user=$db_name +ynh_app_setting_set --app=$app --key=db_name --value=$db_name +ynh_mysql_setup_db --db_user=$db_user --db_name=$db_name -# MySQL - dbuser=$app - dbname=$app - dbpass=$(ynh_string_random 12) - ynh_app_setting_set "$app" mysqlpwd "$dbpass" - ynh_mysql_create_db "$dbname" "$dbuser" "$dbpass" - -# Conf - app_conf=../conf/common.php - sed -i "s@DBNAME_TO_CHANGE@$dbname@g" $app_conf - sed -i "s@DBUSER_TO_CHANGE@$dbuser@g" $app_conf - sed -i "s@DBPASS_TO_CHANGE@$dbpass@g" $app_conf - sudo cp $app_conf $src_path/protected/config/common.php +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= +ynh_script_progression --message="Setting up source files..." --weight=1 + +ynh_app_setting_set --app=$app --key=final_path --value=$final_path +# Download, check integrity, uncompress and patch the source from app.src +ynh_setup_source --dest_dir="$final_path" + +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Configuring NGINX web server..." --weight=4 + +# Create a dedicated NGINX config +ynh_add_nginx_config + +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Configuring system user..." --weight=2 + +# Create a system user +ynh_system_user_create --username=$app + +#================================================= +# PHP-FPM CONFIGURATION +#================================================= +ynh_script_progression --message="Configuring PHP-FPM..." --weight=1 + +# Create a dedicated PHP-FPM config +ynh_add_fpm_config --package="$extra_php_dependencies" +phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) + +#================================================= +# SPECIFIC SETUP +#================================================= +# SETUP SQL CREDENTIALS +#================================================= + +ynh_add_config --template="../conf/common.php" --destination="$final_path/protected/config/common.php" + +#================================================= +# DEACTIVATE DEBUG MODE +#================================================= + +ynh_replace_string --match_string="defined('YII_DEBUG') or define('YII_DEBUG', true);"\ + --replace_string="// defined('YII_DEBUG') or define('YII_DEBUG', true);"\ + --target_file="$final_path/index.php" +ynh_replace_string --match_string="defined('YII_ENV') or define('YII_ENV', 'dev');"\ + --replace_string="// defined('YII_ENV') or define('YII_ENV', 'dev');"\ + --target_file="$final_path/index.php" + +#================================================= +# SETUP APPLICATION WITH CURL +#================================================= + +# Set right permissions for curl install +chown -R $app: $final_path + +# Set the app as temporarily public for curl call +ynh_script_progression --message="Configuring SSOwat..." --weight=30 +# Making the app public for curl +ynh_permission_update --permission="main" --add="visitors" +# Reload SSOwat config +yunohost app ssowatconf + +# Reload NGINX +ynh_systemd_action --service_name=nginx --action=reload + +# Installation with curl +ynh_script_progression --message="Finalizing installation..." --weight=2 + +admin_temp_pass=$(ynh_string_random 6) +admin_email=$(yunohost user info "$admin" --output-as plain | ynh_get_plain_key mail) +admin_firstname=$(yunohost user info "$admin" --output-as plain | ynh_get_plain_key firstname) +admin_lastname=$(yunohost user info "$admin" --output-as plain | ynh_get_plain_key lastname) + +ynh_local_curl "/index.php?r=installer/index/go" + +local_curl_csrf "/index.php?r=installer/config/basic" \ + "ConfigBasicForm[name]=YunoHost" + +local_curl_csrf "/index.php?r=installer/config/use-case" \ + "UseCaseForm[useCase]=" \ + "UseCaseForm[useCase]=other" + +local_curl_csrf "/index.php?r=installer/config/admin" \ + `myynh_urlencode "User[username]=$admin"` \ + `myynh_urlencode "User[email]=$admin_email"` \ + `myynh_urlencode "Password[newPassword]=$admin_temp_pass"` \ + `myynh_urlencode "Password[newPasswordConfirm]=$admin_temp_pass"` \ + `myynh_urlencode "Profile[firstname]=${admin_firstname}"` \ + `myynh_urlencode "Profile[lastname]=${admin_lastname}"` \ + "save" + +local_curl_csrf "/index.php?r=installer/config/sample-data" \ + "SampleDataForm[sampleData]=0" + +# Populate the LDAP parameters +ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="../conf/ldap.sql" +mysql -u $db_user -p${db_pwd} $db_name < ../conf/ldap.sql + +# Remove the public access +ynh_permission_update --permission="main" --remove="visitors" + +#================================================= +# MODIFY A CONFIG FILE +#================================================= + +#================================================= +# STORE THE CONFIG FILE CHECKSUM +#================================================= + +### `ynh_store_file_checksum` is used to store the checksum of a file. +### That way, during the upgrade script, by using `ynh_backup_if_checksum_is_different`, +### you can make a backup of this file before modifying it again if the admin had modified it. + +# Calculate and store the config file checksum into the app settings +ynh_store_file_checksum --file="$final_path/protected/config/common.php" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# SECURE FILES AND DIRECTORIES +#================================================= # Set permissions to app files - sudo chown -R www-data: $src_path - -# Cron - echo "30 * * * * $src_path/protected/yii cron hourly >/dev/null 2>&1" > cron - echo "00 18 * * * $src_path/protected/yii cron daily >/dev/null 2>&1" > cron - sudo mv cron /etc/cron.d/${app} - sudo chown root /etc/cron.d/${app} +chown -R root: $final_path -# Modify Nginx configuration file and copy it to Nginx conf directory - nginx_conf=../conf/nginx.conf - sed -i "s@YNH_WWW_PATH@${path:-/}@g" $nginx_conf - sed -i "s@YNH_WWW_ALIAS@$src_path/@g" $nginx_conf - sed -i "s@YNH_WWW_APP@$app@g" $nginx_conf - sudo cp $nginx_conf /etc/nginx/conf.d/$domain.d/$app.conf +chown -R $app $final_path/assets +chown -R $app $final_path/protected/config +chown -R $app $final_path/protected/modules +chown -R $app $final_path/protected/runtime +chown -R $app $final_path/uploads/* -# PHP - sed -i "s@YNH_WWW_APP@$app@g" ../conf/php-fpm.conf - sed -i "s@YNH_WWW_ALIAS@$src_path/@g" ../conf/php-fpm.conf - finalphpconf=/etc/php5/fpm/pool.d/$app.conf - sudo cp ../conf/php-fpm.conf $finalphpconf - sudo chown root: $finalphpconf - sudo chmod 644 $finalphpconf +#================================================= +# SETUP CRON CONFIGURATION +#================================================= -# Reload services - sudo service php5-fpm reload - sudo service nginx reload +ynh_add_config --template="../conf/cron" --destination="/etc/cron.d/${app}" -# Install - # Disable SSO - ynh_app_setting_set "$app" unprotected_uris "/" - sudo yunohost app ssowatconf +#================================================= +# SETUP SSOWAT +#================================================= +ynh_script_progression --message="Configuring permissions..." --weight=35 - # Install with CURL - admin_temp_pass=$(ynh_string_random 6) - admin_email=$(sudo yunohost user info "$admin" --output-as plain | ynh_get_plain_key mail) - admin_firstname=$(sudo yunohost user info "$admin" --output-as plain | ynh_get_plain_key firstname) - admin_lastname=$(sudo yunohost user info "$admin" --output-as plain | ynh_get_plain_key lastname) +# Make app public if necessary +if [ $is_public -eq 1 ] +then + ynh_permission_update --permission="main" --add="visitors" +fi - ynh_local_curl "/index.php?r=installer/index/go" "go" +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=2 - ynh_local_curl "/index.php?r=installer/config/basic" \ - "ConfigBasicForm[name]=YunoHost" +ynh_systemd_action --service_name=nginx --action=reload - ynh_local_curl "/index.php?r=installer/config/use-case" \ - "UseCaseForm[useCase]=" \ - "UseCaseForm[useCase]=other" +#================================================= +# END OF SCRIPT +#================================================= - ynh_local_curl "/index.php?r=installer/config/admin" \ - "User[username]=$admin" \ - "User[email]=$admin_email" \ - "Password[newPassword]=$admin_temp_pass" \ - "Password[newPasswordConfirm]=$admin_temp_pass" \ - "Profile[firstname]=$admin_firstname" \ - "Profile[lastname]=$admin_lastname" \ - "save" - - ynh_local_curl "/index.php?r=installer/config/sample-data" \ - "SampleDataForm[sampleData]=0" - - # Populate the LDAP parameters - sed -i "s@YNH_ADMIN_USER@$admin@g" ../conf/ldap.sql - mysql -u ${dbuser} -p${dbpass} ${dbname} < ../conf/ldap.sql - - # Enable SSO if chosen by the user - if [ $is_public = 0 ]; - then - ynh_app_setting_delete $app unprotected_uris - sudo yunohost app ssowatconf - fi +ynh_script_progression --message="Installation of $app completed" --last diff --git a/scripts/remove b/scripts/remove index 3ca064d..124d7ca 100644 --- a/scripts/remove +++ b/scripts/remove @@ -1,30 +1,91 @@ #!/bin/bash -set -u + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=1 app=$YNH_APP_INSTANCE_NAME -# Source YunoHost helpers - source /usr/share/yunohost/helpers +domain=$(ynh_app_setting_get --app=$app --key=domain) +port=$(ynh_app_setting_get --app=$app --key=port) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name +final_path=$(ynh_app_setting_get --app=$app --key=final_path) -# Retrieve app settings - domain=$(ynh_app_setting_get "$app" domain) +#================================================= +# STANDARD REMOVE +#================================================= +# REMOVE THE MYSQL DATABASE +#================================================= +ynh_script_progression --message="Removing the MySQL database..." --weight=1 -# Remove sources - sudo rm -rf /var/www/$app - sudo rm -f /etc/cron.d/$app +# Remove a database if it exists, along with the associated user +ynh_mysql_remove_db --db_user=$db_user --db_name=$db_name -# Remove nginx configuration file - sudo rm -f /etc/nginx/conf.d/$domain.d/$app.conf +#================================================= +# REMOVE DEPENDENCIES +#================================================= +ynh_script_progression --message="Removing dependencies..." --weight=1 -# Remove PHP-FPM configuration file - sudo rm -f /etc/php5/fpm/pool.d/$app.conf +# Remove metapackage and its dependencies +ynh_remove_app_dependencies -# MySQL - dbname=$app - dbuser=$app - ynh_mysql_drop_db "$dbname" || true - ynh_mysql_drop_user "$dbuser" || true +#================================================= +# REMOVE APP MAIN DIR +#================================================= +ynh_script_progression --message="Removing app main directory..." --weight=1 -# Reload services - sudo service php5-fpm reload - sudo service nginx reload +# Remove the app directory securely +ynh_secure_remove --file="$final_path" + +#================================================= +# REMOVE NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Removing NGINX web server configuration..." --weight=2 + +# Remove the dedicated NGINX config +ynh_remove_nginx_config + +#================================================= +# REMOVE PHP-FPM CONFIGURATION +#================================================= +ynh_script_progression --message="Removing PHP-FPM configuration..." --weight=1 + +# Remove the dedicated PHP-FPM config +ynh_remove_fpm_config + +#================================================= +# SPECIFIC REMOVE +#================================================= +# REMOVE VARIOUS FILES +#================================================= +ynh_script_progression --message="Removing CRON configuration..." --weight=2 + +# Remove a cron file +ynh_secure_remove --file="/etc/cron.d/$app" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# REMOVE DEDICATED USER +#================================================= +ynh_script_progression --message="Removing the dedicated system user..." --weight=1 + +# Delete a system user +ynh_system_user_delete --username=$app + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Removal of $app completed" --last diff --git a/scripts/restore b/scripts/restore index 9cc7bc9..1e017c7 100644 --- a/scripts/restore +++ b/scripts/restore @@ -1,42 +1,122 @@ #!/bin/bash -# Exit on command errors and treat unset variables as an error -set -eu +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +# Keep this path for calling _common.sh inside the execution's context of backup and restore scripts +source ../settings/scripts/_common.sh +source /usr/share/yunohost/helpers + +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_clean_setup () { + #### Remove this function if there's nothing to clean before calling the remove script. + true +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=1 app=$YNH_APP_INSTANCE_NAME -# Source YunoHost helpers - source /usr/share/yunohost/helpers +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name +phpversion=$(ynh_app_setting_get --app=$app --key=phpversion) -# Retrieve old app settings - domain=$(ynh_app_setting_get "$app" domain) - path=$(ynh_app_setting_get "$app" path) +#================================================= +# CHECK IF THE APP CAN BE RESTORED +#================================================= +ynh_script_progression --message="Validating restoration parameters..." --weight=1 -# Check domain/path availability - sudo yunohost app checkurl "${domain}${path}" -a "$app" \ - || ynh_die "Path not available: ${domain}${path}" +ynh_webpath_available --domain=$domain --path_url=$path_url \ + || ynh_die --message="Path not available: ${domain}${path_url}" +test ! -d $final_path \ + || ynh_die --message="There is already a directory: $final_path " -# Restore sources & data - src_path="/var/www/${app}" - sudo cp -a ./sources "$src_path" - sudo cp -a ./cron "/etc/cron.d/${app}" +#================================================= +# STANDARD RESTORATION STEPS +#================================================= +# RESTORE THE NGINX CONFIGURATION +#================================================= -# Restore permissions to app files - sudo chown -R www-data: $src_path +ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" -# MySQL - dbname=$app - dbuser=$app - dbpass=$(ynh_app_setting_get "$app" mysqlpwd) - ynh_mysql_create_db "$dbname" "$dbuser" "$dbpass" - ynh_mysql_connect_as "$dbuser" "$dbpass" "$dbname" < ./dump.sql +#================================================= +# RESTORE THE APP MAIN DIR +#================================================= +ynh_script_progression --message="Restoring the app main directory..." --weight=1 -# Restore NGINX configuration - sudo cp -a ./nginx.conf "/etc/nginx/conf.d/${domain}.d/${app}.conf" +ynh_restore_file --origin_path="$final_path" -# Restore PHP-FPM configuration - sudo cp -a ./php-fpm.conf "/etc/php5/fpm/pool.d/${app}.conf" +#================================================= +# RECREATE THE DEDICATED USER +#================================================= +ynh_script_progression --message="Recreating the dedicated system user..." --weight=3 -# Restart services - sudo service php5-fpm reload - sudo service nginx reload +# Create the dedicated user (if not existing) +ynh_system_user_create --username=$app + +#================================================= +# RESTORE USER RIGHTS +#================================================= + +# Restore permissions on app files +chown -R root: $final_path + +chown -R $app $final_path/assets +chown -R $app $final_path/protected/config +chown -R $app $final_path/protected/modules +chown -R $app $final_path/protected/runtime +chown -R $app $final_path/uploads/* + +#================================================= +# RESTORE THE PHP-FPM CONFIGURATION +#================================================= +ynh_script_progression --message="Reconfiguring PHP-FPM..." --weight=5 + +ynh_restore_file --origin_path="/etc/php/$phpversion/fpm/pool.d/$app.conf" + +ynh_add_fpm_config --package="$extra_php_dependencies" + +#================================================= +# RESTORE THE MYSQL DATABASE +#================================================= +ynh_script_progression --message="Restoring the MySQL database..." --weight=2 + +db_pwd=$(ynh_app_setting_get --app=$app --key=mysqlpwd) +ynh_mysql_setup_db --db_user=$db_user --db_name=$db_name --db_pwd=$db_pwd +ynh_mysql_connect_as --user=$db_user --password=$db_pwd --database=$db_name < ./db.sql + +#================================================= +# RESTORE VARIOUS FILES +#================================================= + +ynh_restore_file --origin_path="/etc/cron.d/$app" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# RELOAD NGINX AND PHP-FPM +#================================================= +ynh_script_progression --message="Reloading NGINX web server and PHP-FPM..." --weight=1 + +ynh_systemd_action --service_name=php$phpversion-fpm --action=reload +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Restoration completed for $app" --last diff --git a/scripts/upgrade b/scripts/upgrade index cf226ee..085e671 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,83 +1,164 @@ #!/bin/bash -# Exit on command errors and treat unset variables as an error -set -eu +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=1 app=$YNH_APP_INSTANCE_NAME -version=$(cat ../sources/version) -source='https://sourceforge.net/projects/humhub/files/' -# Source YunoHost helpers - source /usr/share/yunohost/helpers +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +admin=$(ynh_app_setting_get --app=$app --key=admin) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +language=$(ynh_app_setting_get --app=$app --key=language) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_pwd=$(ynh_app_setting_get --app=$app --key=mysqlpwd) -# Retrieve app settings - domain=$(ynh_app_setting_get "$app" domain) - path=$(ynh_app_setting_get "$app" path) - dbuser=$app - dbname=$app - dbpass=$(ynh_app_setting_get "$app" mysqlpwd) - src_path=/var/www/$app +#================================================= +# CHECK VERSION +#================================================= -# Correct path: puts a / at the start and nothing at the end - if [ "${path:0:1}" != "/" ]; then - path="/$path" - fi - if [ "${path:${#path}-1}" == "/" ] && [ ${#path} -gt 1 ]; then - path="${path:0:${#path}-1}" - fi +upgrade_type=$(ynh_check_app_version_changed) -# Copy source files - sudo mv "$src_path" "$src_path.old" - sudo mkdir -p $src_path - sudo wget -q "${source}humhub-${version}.zip/download" -O humhub-${version}.zip - sudo unzip -qq humhub-${version}.zip - sudo cp -a humhub-$version/. $src_path +#================================================= +# ENSURE DOWNWARD COMPATIBILITY +#================================================= +ynh_script_progression --message="Ensuring downward compatibility..." --weight=1 -# Restore files - sudo cp -a "$src_path.old/uploads/." "$src_path/uploads/." - sudo cp -a "$src_path.old/protected/runtime" "$src_path/protected/runtime" - sudo cp -a "$src_path.old/protected/config/." "$src_path/protected/config/" - sudo cp -a "$src_path.old/protected/modules/." "$src_path/protected/modules/" - sudo cp -a "$src_path.old/themes/." "$src_path/themes/" +# Cleaning legacy permissions +if ynh_legacy_permissions_exists; then + ynh_legacy_permissions_delete_all -# Hotfixes - # Fix LDAP email. See https://github.com/humhub/humhub/issues/1949 - sudo cp -a ../sources/fix/AuthClientHelpers.php $src_path/protected/humhub/modules/user/authclient/AuthClientHelpers.php - # Fix to allow passwordless LDAP login - sudo cp -a ../sources/fix/ZendLdapClient.php $src_path/protected/humhub/modules/user/authclient/ZendLdapClient.php - sudo sed -i "s@defined('YII_DEBUG') or define('YII_DEBUG', true);@//defined('YII_DEBUG') or define('YII_DEBUG', true);@g" $src_path/index.php - sudo sed -i "s@defined('YII_ENV') or define('YII_ENV', 'dev');@//defined('YII_ENV') or define('YII_ENV', 'dev');@g" $src_path/index.php + ynh_app_setting_delete --app=$app --key=is_public +fi -# Set permissions to app files - sudo chown -R www-data: $src_path +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." --weight=1 -# Upgrade - sudo sudo -u www-data php $src_path/protected/yii migrate/up --includeModuleMigrations=1 --interactive=0 > /dev/null 2>&1 +# Backup the current version of the app +ynh_backup_before_upgrade +ynh_clean_setup () { + # Restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors -# Upgrade cron - echo "30 * * * * $src_path/protected/yii cron hourly >/dev/null 2>&1" > cron - echo "00 18 * * * $src_path/protected/yii cron daily >/dev/null 2>&1" > cron - sudo mv cron /etc/cron.d/${app} - sudo chown root /etc/cron.d/${app} +#================================================= +# STANDARD UPGRADE STEPS +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= -# Modify Nginx configuration file and copy it to Nginx conf directory - nginx_conf=../conf/nginx.conf - sed -i "s@YNH_WWW_PATH@${path:-/}@g" $nginx_conf - sed -i "s@YNH_WWW_ALIAS@$src_path/@g" $nginx_conf - sed -i "s@YNH_WWW_APP@$app@g" $nginx_conf - sudo cp $nginx_conf /etc/nginx/conf.d/$domain.d/$app.conf +# Deactivate cron jobs +ynh_secure_remove --file="/etc/cron.d/$app" -# PHP - sed -i "s@YNH_WWW_APP@$app@g" ../conf/php-fpm.conf - sed -i "s@YNH_WWW_ALIAS@$src_path/@g" ../conf/php-fpm.conf - finalphpconf=/etc/php5/fpm/pool.d/$app.conf - sudo cp ../conf/php-fpm.conf $finalphpconf - sudo chown root: $finalphpconf - sudo chmod 644 $finalphpconf +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Upgrading source files..." --weight=1 -# Reload nginx service - sudo service php5-fpm reload - sudo service nginx reload + # Backup user contents + mv "$final_path" "$final_path.old" -# Delete old source - sudo rm -rf "$src_path.old" + # Download, check integrity, uncompress and patch the source from app.src + ynh_setup_source --dest_dir="$final_path" + + # Restore user contents + cp -a "$final_path.old/uploads/." "$final_path/uploads/." + cp -a "$final_path.old/protected/runtime" "$final_path/protected/runtime" + cp -a "$final_path.old/protected/config/." "$final_path/protected/config/" + cp -a "$final_path.old/protected/modules/." "$final_path/protected/modules/" + cp -a "$final_path.old/themes/." "$final_path/themes/" + + # Delete old source + ynh_secure_remove --file="$final_path.old" +fi + +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Upgrading NGINX web server configuration..." --weight=1 + +# Create a dedicated NGINX config +ynh_add_nginx_config + +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Making sure dedicated system user exists..." --weight=1 + +# Create a dedicated user (if not existing) +ynh_system_user_create --username=$app + +#================================================= +# PHP-FPM CONFIGURATION +#================================================= +ynh_script_progression --message="Upgrading PHP-FPM configuration..." --weight=1 + +# Create a dedicated PHP-FPM config +ynh_add_fpm_config + +#================================================= +# SPECIFIC UPGRADE +#================================================= +# MIGRATE DATABASE +#================================================= +ynh_script_progression --message="Migrating database..." --weight=1 + +chown -R $app $final_path/ + +sudo -u $app /usr/bin/php$YNH_PHP_VERSION $final_path/protected/yii migrate/up --includeModuleMigrations=1 + +#================================================= +# UPDATE MODULES +#================================================= +ynh_script_progression --message="Updating modules..." --weight=1 + +sudo -u $app /usr/bin/php$YNH_PHP_VERSION $final_path/protected/yii module/update-all + +#================================================= +# REINSTALL CRONTAB +#================================================= +ynh_script_progression --message="Upgrading crontab..." --weight=1 + +ynh_add_config --template="../conf/cron" --destination="/etc/cron.d/${app}" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# SECURE FILES AND DIRECTORIES +#================================================= + +# Set permissions on app files +chown -R root: $final_path + +chown -R $app $final_path/assets +chown -R $app $final_path/protected/config +chown -R $app $final_path/protected/modules +chown -R $app $final_path/protected/runtime +chown -R $app $final_path/uploads/* + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=1 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Upgrade of $app completed" --last diff --git a/sources/fix/AuthClientHelpers.php b/sources/fix/AuthClientHelpers.php deleted file mode 100644 index 9e0766b..0000000 --- a/sources/fix/AuthClientHelpers.php +++ /dev/null @@ -1,261 +0,0 @@ -getUserAttributes(); - - if ($authClient instanceof interfaces\PrimaryClient) { - /** - * @var interfaces\PrimaryClient $authClient - */ - return User::findOne([ - $authClient->getUserTableIdAttribute() => $attributes['id'], - 'auth_mode' => $authClient->getId() - ]); - } - - $auth = Auth::find()->where(['source' => $authClient->getId(), 'source_id' => $attributes['id']])->one(); - if ($auth !== null) { - return $auth->user; - } - } - - /** - * Stores an authClient to an user record - * - * @param \yii\authclient\BaseClient $authClient - * @param User $user - */ - public static function storeAuthClientForUser(ClientInterface $authClient, User $user) - { - $attributes = $authClient->getUserAttributes(); - - if ($authClient instanceof interfaces\PrimaryClient) { - $user->auth_mode = $authClient->getId(); - $user->save(); - } else { - $auth = Auth::findOne(['source' => $authClient->getId(), 'source_id' => $attributes['id']]); - - /** - * Make sure authClient is not double assigned - */ - if ($auth !== null && $auth->user_id != $user->id) { - $auth->delete(); - $auth = null; - } - - - if ($auth === null) { - $auth = new \humhub\modules\user\models\Auth([ - 'user_id' => $user->id, - 'source' => (string) $authClient->getId(), - 'source_id' => (string) $attributes['id'], - ]); - - $auth->save(); - } - } - } - - /** - * Removes Authclient for a user - * - * @param \yii\authclient\BaseClient $authClient - * @param User $user - */ - public static function removeAuthClientForUser(ClientInterface $authClient, User $user) - { - Auth::deleteAll([ - 'user_id' => $user->id, - 'source' => (string) $authClient->getId() - ]); - } - - /** - * Updates (or creates) a user in HumHub using AuthClients Attributes - * This method will be called after login or by cron sync. - * - * @param \yii\authclient\BaseClient $authClient - * @param User $user - * @return boolean succeed - */ - public static function updateUser(ClientInterface $authClient, User $user = null) - { - if ($user === null) { - $user = self::getUserByAuthClient($authClient); - if ($user === null) { - return false; - } - } - - $authClient->trigger(BaseClient::EVENT_UPDATE_USER, new \yii\web\UserEvent(['identity' => $user])); - - if ($authClient instanceof interfaces\SyncAttributes) { - $attributes = $authClient->getUserAttributes(); - foreach ($authClient->getSyncAttributes() as $attributeName) { - if (isset($attributes[$attributeName])) { - if (in_array($attributeName, ['email', 'username'])) { - $user->setAttribute($attributeName, $attributes[$attributeName]); - } else { - $user->profile->setAttribute($attributeName, $attributes[$attributeName]); - } - } else { - if ($user->profile->hasAttribute($attributeName)) { - $user->profile->setAttribute($attributeName, ''); - } - } - } - - if (count($user->getDirtyAttributes()) !== 0 && !$user->save()) { - Yii::error('Could not update user attributes by AuthClient (UserId: ' . $user->id . ") - Error: " . print_r($user->getErrors(), 1)); - return false; - } - - if (count($user->profile->getDirtyAttributes()) !== 0 && !$user->profile->save()) { - Yii::error('Could not update user attributes by AuthClient (UserId: ' . $user->id . ") - Error: " . print_r($user->profile->getErrors(), 1)); - return false; - } - } - - return true; - } - - /** - * Automatically creates user by auth client attributes - * - * @param \yii\authclient\BaseClient $authClient - * @return boolean success status - */ - public static function createUser(ClientInterface $authClient) - { - $attributes = $authClient->getUserAttributes(); - - if (!isset($attributes['id'])) { - return false; - } - - // Hotfix for YunoHost. Select the first LDAP email address when there are several in the mail attribute. See https://github.com/humhub/humhub/issues/1949 - if (is_array($attributes['mail'])) { - $attributes['mail'] = $attributes['mail'][0]; - } - if (is_array($attributes['email'])) { - $attributes['email'] = $attributes['email'][0]; - } - - $registration = new \humhub\modules\user\models\forms\Registration(); - $registration->enablePasswordForm = false; - $registration->enableEmailField = true; - - if ($authClient instanceof interfaces\ApprovalBypass) { - $registration->enableUserApproval = false; - } - - unset($attributes['id']); - $registration->getUser()->setAttributes($attributes, false); - $registration->getProfile()->setAttributes($attributes, false); - $registration->getGroupUser()->setAttributes($attributes, false); - - if ($registration->validate() && $registration->register($authClient)) { - return $registration->getUser(); - } - - return null; - } - - /** - * Returns all users which are using an given authclient - * - * @param ClientInterface $authClient - * @return \yii\db\ActiveQuery - */ - public static function getUsersByAuthClient(ClientInterface $authClient) - { - $query = User::find(); - - if ($authClient instanceof interfaces\PrimaryClient) { - $query->where([ - 'auth_mode' => $authClient->getId() - ]); - } else { - $query->where(['user_auth.source' => $authClient->getId()]); - } - - return $query; - } - - /** - * Returns AuthClients used by given User - * - * @param User $user - * @return ClientInterface[] the users authclients - */ - public static function getAuthClientsByUser(User $user) - { - $authClients = []; - - foreach (Yii::$app->authClientCollection->getClients() as $client) { - /** - * @var $client ClientInterface - */ - // Add primary authClient - if ($user->auth_mode == $client->getId()) { - $authClients[] = $client; - } - - // Add additional authClient - foreach ($user->auths as $auth) { - if ($auth->source == $client->getId()) { - $authClients[] = $client; - } - } - } - - return $authClients; - } - - /** - * Returns a list of all synchornized user attributes - * - * @param User $user - * @return array attribute names - */ - public static function getSyncAttributesByUser(User $user) - { - $attributes = []; - foreach (self::getAuthClientsByUser($user) as $authClient) { - if ($authClient instanceof interfaces\SyncAttributes) { - $attributes = array_merge($attributes, $authClient->getSyncAttributes()); - } - } - return $attributes; - } - -} diff --git a/sources/fix/ZendLdapClient.php b/sources/fix/ZendLdapClient.php deleted file mode 100644 index 2e75f09..0000000 --- a/sources/fix/ZendLdapClient.php +++ /dev/null @@ -1,380 +0,0 @@ -idAttribute; - } - - /** - * @inheritdoc - */ - public function getUserTableIdAttribute() - { - return $this->userTableIdAttribute; - } - - /** - * @inheritdoc - */ - public function auth() - { - - $node = $this->getUserNode(); - if ($node !== null) { - $this->setUserAttributes($node->getAttributes()); - return true; - } - - return false; - } - - /** - * @inheritdoc - */ - protected function defaultNormalizeUserAttributeMap() - { - $map = []; - - // Username field - $usernameAttribute = Yii::$app->getModule('user')->settings->get('auth.ldap.usernameAttribute'); - if ($usernameAttribute == '') { - $usernameAttribute = 'sAMAccountName'; - } - $map['username'] = strtolower($usernameAttribute); - - // E-Mail field - $emailAttribute = Yii::$app->getModule('user')->settings->get('auth.ldap.emailAttribute'); - if ($emailAttribute == '') { - $emailAttribute = 'mail'; - } - $map['email'] = strtolower($emailAttribute); - - // Profile Field Mapping - foreach (ProfileField::find()->andWhere(['!=', 'ldap_attribute', ''])->all() as $profileField) { - $map[$profileField->internal_name] = strtolower($profileField->ldap_attribute); - } - - return $map; - } - - /** - * @inheritdoc - */ - protected function normalizeUserAttributes($attributes) - { - $normalized = []; - - // Fix LDAP Attributes - foreach ($attributes as $name => $value) { - if (is_array($value) && count($value) == 1 && $name != 'memberof') { - $normalized[$name] = $value[0]; - } else { - $normalized[$name] = $value; - } - } - - if (isset($normalized['objectguid'])) { - $normalized['objectguid'] = \humhub\libs\StringHelper::binaryToGuid($normalized['objectguid']); - } - - // Handle date fields (formats are specified in config) - foreach ($normalized as $name => $value) { - if (isset(Yii::$app->params['ldap']['dateFields'][$name]) && $value != '') { - $dateFormat = Yii::$app->params['ldap']['dateFields'][$name]; - $date = \DateTime::createFromFormat($dateFormat, $value); - - if ($date !== false) { - $normalized[$name] = $date->format('Y-m-d 00:00:00'); - } else { - $normalized[$name] = ""; - } - } - } - return parent::normalizeUserAttributes($normalized); - } - - /** - * @return array list of user attributes - */ - public function getUserAttributes() - { - $attributes = parent::getUserAttributes(); - - // Try to automatically set id and usertable id attribute by available attributes - if ($this->getIdAttribute() === null || $this->getUserTableIdAttribute() === null) { - if (isset($attributes['objectguid'])) { - $this->idAttribute = 'objectguid'; - $this->userTableIdAttribute = 'guid'; - } elseif (isset($attributes['mail'])) { - $this->idAttribute = 'mail'; - $this->userTableIdAttribute = 'email'; - } else { - throw new \yii\base\Exception("Could not automatically determine unique user id from ldap node!"); - } - } - - // Make sure id attributes sits on id attribute key - if (isset($attributes[$this->getIdAttribute()])) { - $attributes['id'] = $attributes[$this->getIdAttribute()]; - } - - // Map usertable id attribute against ldap id attribute - $attributes[$this->getUserTableIdAttribute()] = $attributes[$this->getIdAttribute()]; - - return $attributes; - } - - /** - * Returns Users LDAP Node - * - * @return Node the users ldap node - */ - protected function getUserNode() - { - $dn = $this->getUserDn(); - if ($dn !== '') { - return $this->getLdap()->getNode($dn); - } - - return null; - } - - /** - * Returns the users LDAP DN - * - * @return string the user dn if found - */ - protected function getUserDn() - { - $userName = $this->login->username; - - // Translate given e-mail to username - if (strpos($userName, '@') !== false) { - $user = User::findOne(['email' => $userName]); - if ($user !== null) { - $userName = $user->username; - } - } - - try { - $this->getLdap()->bind($userName, $this->login->password); - return $this->getLdap()->getCanonicalAccountName($userName, Ldap::ACCTNAME_FORM_DN); - } catch (LdapException $ex) { - // User not found in LDAP - } - return ''; - } - - /** - * Returns Zend LDAP - * - * @return \Zend\Ldap\Ldap - */ - public function getLdap() - { - if ($this->_ldap === null) { - $options = array( - 'host' => Yii::$app->getModule('user')->settings->get('auth.ldap.hostname'), - 'port' => Yii::$app->getModule('user')->settings->get('auth.ldap.port'), - //'username' => Yii::$app->getModule('user')->settings->get('auth.ldap.username'), - //'password' => Yii::$app->getModule('user')->settings->get('auth.ldap.password'), - 'username' => '', - 'password' => '', - 'useStartTls' => (Yii::$app->getModule('user')->settings->get('auth.ldap.encryption') == 'tls'), - 'useSsl' => (Yii::$app->getModule('user')->settings->get('auth.ldap.encryption') == 'ssl'), - 'bindRequiresDn' => true, - 'baseDn' => Yii::$app->getModule('user')->settings->get('auth.ldap.baseDn'), - 'accountFilterFormat' => Yii::$app->getModule('user')->settings->get('auth.ldap.loginFilter'), - ); - - $this->_ldap = new \Zend\Ldap\Ldap($options); - $this->_ldap->bind(); - } - - return $this->_ldap; - } - - /** - * Sets an Zend LDAP Instance - * - * @param \Zend\Ldap\Ldap $ldap - */ - public function setLdap(\Zend\Ldap\Ldap $ldap) - { - $this->_ldap = $ldap; - } - - /** - * @inheritdoc - */ - public function getSyncAttributes() - { - $attributes = ['username', 'email']; - - foreach (ProfileField::find()->andWhere(['!=', 'ldap_attribute', ''])->all() as $profileField) { - $attributes[] = $profileField->internal_name; - } - - return $attributes; - } - - /** - * Refresh ldap users - * - * New users (found in ldap) will be automatically created if all required fiélds are set. - * Profile fields which are bind to LDAP will automatically updated. - */ - public function syncUsers() - { - if (!Yii::$app->getModule('user')->settings->get('auth.ldap.enabled') || !Yii::$app->getModule('user')->settings->get('auth.ldap.refreshUsers')) { - return; - } - - $userFilter = Yii::$app->getModule('user')->settings->get('auth.ldap.userFilter'); - $baseDn = Yii::$app->getModule('user')->settings->get('auth.ldap.baseDn'); - try { - $ldap = $this->getLdap(); - - $userCollection = $ldap->search($userFilter, $baseDn, Ldap::SEARCH_SCOPE_SUB); - - $authClient = null; - $ids = []; - foreach ($userCollection as $attributes) { - $authClient = clone $this; - $authClient->init(); - $authClient->setUserAttributes($attributes); - $attributes = $authClient->getUserAttributes(); - - $user = AuthClientHelpers::getUserByAuthClient($authClient); - if ($user === null) { - if (!AuthClientHelpers::createUser($authClient)) { - Yii::warning('Could not automatically create LDAP user - check required attributes! (' . print_r($attributes, 1) . ')'); - } - } else { - AuthClientHelpers::updateUser($authClient, $user); - } - - $ids[] = $attributes['id']; - } - - /** - * Since userTableAttribute can be automatically set on user attributes - * try to take it from initialized authclient instance. - */ - $userTableIdAttribute = $this->getUserTableIdAttribute(); - if ($authClient !== null) { - $userTableIdAttribute = $authClient->getUserTableIdAttribute(); - } - - foreach (AuthClientHelpers::getUsersByAuthClient($this)->each() as $user) { - $foundInLdap = in_array($user->getAttribute($userTableIdAttribute), $ids); - // Enable disabled users that have been found in ldap - if ($foundInLdap && $user->status === User::STATUS_DISABLED) { - $user->status = User::STATUS_ENABLED; - $user->save(); - Yii::info('Enabled user' . $user->username . ' (' . $user->id . ') - found in LDAP!'); - // Disable users that were not found in ldap - } elseif (!$foundInLdap && $user->status !== User::STATUS_DISABLED) { - $user->status = User::STATUS_DISABLED; - $user->save(); - Yii::warning('Disabled user' . $user->username . ' (' . $user->id . ') - not found in LDAP!'); - } - } - } catch (\Zend\Ldap\Exception\LdapException $ex) { - Yii::error('Could not connect to LDAP instance: ' . $ex->getMessage()); - } catch (\Exception $ex) { - Yii::error('An error occurred while user sync: ' . $ex->getMessage()); - } - } - - /** - * Checks if LDAP is supported - */ - public static function isLdapAvailable() - { - if (!class_exists('Zend\Ldap\Ldap')) { - return false; - } - - if (!function_exists('ldap_bind')) { - return false; - } - - return true; - } - -} diff --git a/sources/patches/app-00-no-password-ldap.patch b/sources/patches/app-00-no-password-ldap.patch new file mode 100644 index 0000000..645e65f --- /dev/null +++ b/sources/patches/app-00-no-password-ldap.patch @@ -0,0 +1,13 @@ +diff --git a/protected/humhub/modules/ldap/models/LdapSettings.php b/protected/humhub/modules/ldap/models/LdapSettings.php +index e6402e8b3..3b653d590 100644 +--- a/protected/humhub/modules/ldap/models/LdapSettings.php ++++ b/protected/humhub/modules/ldap/models/LdapSettings.php +@@ -120,7 +120,7 @@ class LdapSettings extends Model + return [ + [['enabled', 'refreshUsers', 'usernameAttribute', 'emailAttribute', 'username', 'passwordField', 'hostname', 'port', 'idAttribute'], 'string', 'max' => 255], + [['baseDn', 'loginFilter', 'userFilter'], 'string'], +- [['usernameAttribute', 'username', 'passwordField', 'hostname', 'port', 'baseDn', 'loginFilter', 'userFilter', 'idAttribute'], 'required'], ++ [['usernameAttribute', 'hostname', 'port', 'baseDn', 'loginFilter', 'userFilter', 'idAttribute'], 'required'], + ['encryption', 'in', 'range' => ['', 'ssl', 'tls']], + ]; + } diff --git a/sources/version b/sources/version index 26aaba0..a8fdfda 100644 --- a/sources/version +++ b/sources/version @@ -1 +1 @@ -1.2.0 +1.8.1