diff --git a/README.md b/README.md index c348900..01e6ffe 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,15 @@ The idea of [æneria](https://aeneria.com) is to display energy consumption and * Analyse energy consumption throw weather data -**Shipped version:** 1.1.6~ynh5 +**Shipped version:** 2.1.0~ynh1 + +**Demo:** https://demo.aeneria.com ## Screenshots -![Screenshot of æneria](./doc/screenshots/screenshot1.png) +![Screenshot of æneria](./doc/screenshots/preview-2.png) +![Screenshot of æneria](./doc/screenshots/preview-3.png) +![Screenshot of æneria](./doc/screenshots/preview-1.png) ## Documentation and resources diff --git a/README_fr.md b/README_fr.md index 4277f4f..d35f89e 100644 --- a/README_fr.md +++ b/README_fr.md @@ -21,11 +21,15 @@ L'idée de [æneria](https://aeneria.com) est d'afficher la consommation d'éner * Mieux comprendre sa propre consommation d'énergie * Analyser la consommation d'énergie et les données météorologiques -**Version incluse :** 1.1.6~ynh5 +**Version incluse :** 2.1.0~ynh1 + +**Démo :** https://demo.aeneria.com ## Captures d’écran -![Capture d’écran de æneria](./doc/screenshots/screenshot1.png) +![Capture d’écran de æneria](./doc/screenshots/preview-2.png) +![Capture d’écran de æneria](./doc/screenshots/preview-3.png) +![Capture d’écran de æneria](./doc/screenshots/preview-1.png) ## Documentations et ressources diff --git a/conf/.env b/conf/.env index 2ecf0d2..85584b3 100644 --- a/conf/.env +++ b/conf/.env @@ -32,10 +32,23 @@ AENERIA_DEMO_MODE=0 # Welcome message AENERIA_WELCOME_MESSAGE='

Bienvenue sur æneria

' -### Enedis Data Hub ### +# æneria proxy URL (no trailing slash !) +AENERIA_PROXY_URL=https://proxy.aeneria.com +# should the app use æneria proxy (1 for yes, 0 for no) +AENERIA_PROXY_FOR_ENEDIS=1 +AENERIA_PROXY_FOR_GRDF=1 + +# Enedis Data Hub ENEDIS_CLIENT_ID=noneed ENEDIS_CLIENT_SECRET=noneed ENEDIS_REDIRECT_URI=noneed -ENEDIS_ENDPOINT_AUTH=https://proxy.aeneria.com/enedis-data-connect -ENEDIS_ENDPOINT_TOKEN=https://proxy.aeneria.com/enedis-data-connect -ENEDIS_ENDPOINT_DATA=https://gw.prd.api.enedis.fr +ENEDIS_ENDPOINT_AUTH=noneed +ENEDIS_ENDPOINT_TOKEN=noneed +ENEDIS_ENDPOINT_DATA=noneed + +# Grdf adict +GRDF_CLIENT_ID=noneed +GRDF_CLIENT_SECRET=noneed +GRDF_REDIRECT_URI=noneed +GRDF_ENDPOINT_AUTH=noneed +GRDF_ENDPOINT_DATA=noneed diff --git a/conf/nginx.conf b/conf/nginx.conf index ddda443..ca4834f 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -7,19 +7,17 @@ location __PATH__/ { client_body_timeout 60m; proxy_read_timeout 60m; fastcgi_read_timeout 60m; - - # Common parameter to increase upload size limit in conjunction with dedicated php-fpm file - #client_max_body_size 50M; + client_max_body_size 50M; try_files $uri @__NAME__; - location ~ ^__PATH__/index\.php(/|$) { - fastcgi_split_path_info ^(.+\.php)(/.*)$; - fastcgi_pass unix:/var/run/php/php__PHPVERSION__-fpm-__NAME__.sock; + location ~ ^__PATH__/index\.php(/|$) { include fastcgi_params; - fastcgi_param REMOTE_USER $remote_user; - fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_split_path_info ^(.+\.php)(/.*)$; fastcgi_param SCRIPT_FILENAME $request_filename; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param REMOTE_USER $remote_user; + fastcgi_pass unix:/var/run/php/php__PHPVERSION__-fpm-__NAME__.sock; fastcgi_intercept_errors on; } @@ -36,8 +34,3 @@ location __PATH__/ { location @__NAME__ { rewrite ^ __PATH__/index.php/$is_args$args; } - -#for-subdir location __PATH__ { -#for-subdir return 301 __PATH__/; -#for-subdir } - diff --git a/doc/PRE_UPGRADE.d/2.0.0~ynh1.md b/doc/PRE_UPGRADE.d/2.0.0~ynh1.md new file mode 100644 index 0000000..8296f65 --- /dev/null +++ b/doc/PRE_UPGRADE.d/2.0.0~ynh1.md @@ -0,0 +1,6 @@ +Since version 2, æneria must be installed under its own domain. + +If æneria is currently installed under a path, before upgrading, change æneria URL: + +* delete the path +* switch to a new dedicated domain (if needed) diff --git a/doc/screenshots/preview-1.png b/doc/screenshots/preview-1.png new file mode 100644 index 0000000..c813783 Binary files /dev/null and b/doc/screenshots/preview-1.png differ diff --git a/doc/screenshots/preview-2.png b/doc/screenshots/preview-2.png new file mode 100644 index 0000000..fc1bb90 Binary files /dev/null and b/doc/screenshots/preview-2.png differ diff --git a/doc/screenshots/preview-3.png b/doc/screenshots/preview-3.png new file mode 100644 index 0000000..0df0919 Binary files /dev/null and b/doc/screenshots/preview-3.png differ diff --git a/doc/screenshots/screenshot1.png b/doc/screenshots/screenshot1.png deleted file mode 100644 index 3e5d59b..0000000 Binary files a/doc/screenshots/screenshot1.png and /dev/null differ diff --git a/hooks/post_app_addaccess b/hooks/post_app_addaccess deleted file mode 100644 index cc14389..0000000 --- a/hooks/post_app_addaccess +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -app=$1 - -# Run only if we are altering aeneria's permissions -[[ "$app" != "__APP__" ]] && exit 0 - -# Source YunoHost helpers -source /usr/share/yunohost/helpers -source /etc/yunohost/apps/$app/scripts/_common.sh - -# Retrieve arguments -usernames=$2 -permission=$3 -groups=$4 -install_dir=$(ynh_app_setting_get "$app" install_dir) -phpversion=$(ynh_app_setting_get "$app" phpversion) - -IFS=',' read -r -a user_list <<< "$usernames" -IFS=',' read -r -a group_list <<< "$groups" - -for group in "${group_list[@]}" -do - group_array=$(yunohost user group list --output-as json --quiet | jq -r --arg group "$group" ".groups.$group.members | @csv" | tr -d \") - IFS=',' read -r -a group_array <<< "$group_array" - user_list+=("${group_array[@]}") -done - -pushd $install_dir - for user in "${user_list[@]}" - do - mail=$(ynh_user_get_info --username="$user" --key=mail) - user_exists=$(ynh_exec_as $app php$phpversion bin/console aeneria:user:exist "$mail") - if [ $user_exists -eq 0 ] - then - user_pass=$(ynh_string_random) - ynh_exec_as $app php$phpversion bin/console aeneria:user:add "$mail" "$user_pass" -n - else - ynh_exec_as $app php$phpversion bin/console aeneria:user:activate "$mail" - fi - done -popd diff --git a/hooks/post_app_removeaccess b/hooks/post_app_removeaccess deleted file mode 100644 index af784b5..0000000 --- a/hooks/post_app_removeaccess +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -app=$1 - -# Run only if we are altering aeneria's permissions -[[ "$app" != "__APP__" ]] && exit 0 - -# Source YunoHost helpers -source /usr/share/yunohost/helpers -source /etc/yunohost/apps/$app/scripts/_common.sh - -# Retrieve arguments -usernames=$2 -permission=$3 -groups=$4 -install_dir=$(ynh_app_setting_get "$app" install_dir) -phpversion=$(ynh_app_setting_get "$app" phpversion) - -IFS=',' read -r -a user_list <<< "$usernames" -IFS=',' read -r -a group_list <<< "$groups" - -for group in "${group_list[@]}" -do - group_array=$(yunohost user group list --output-as json --quiet | jq -r --arg group "$group" ".groups.$group.members | @csv" | tr -d \") - IFS=',' read -r -a group_array <<< "$group_array" - user_list+=("${group_array[@]}") -done - -for user in "${user_list[@]}" -do - mail=$(ynh_user_get_info --username="$user" --key=mail) - cd "$install_dir" && ynh_exec_as $app php$phpversion bin/console aeneria:user:deactivate "$mail" -n -done diff --git a/manifest.toml b/manifest.toml index d69b9d7..319ab00 100644 --- a/manifest.toml +++ b/manifest.toml @@ -2,10 +2,10 @@ packaging_format = 2 id = "aeneria" name = "æneria" -description.en = "Dashboard to analyse your energy consumption data from Linky & weather" -description.fr = "Tableau de bord pour analyser votre consomation d'énergie à partir des données d'un Linky et de la météo" +description.en = "Analyse your energy consumption (from Linky & Gazpar) & weather data" +description.fr = "Analyser sa consommation d'énergie (via Linky & Gazpar) avec des données météo" -version = "1.1.6~ynh5" +version = "2.1.0~ynh1" maintainers = ["Simon Mellerin"] @@ -14,15 +14,16 @@ license = "AGPL-3.0-or-later" website = "https://aeneria.com" admindoc = "https://docs.aeneria.com" code = "https://gitlab.com/aeneria/aeneria-app" +demo = "https://demo.aeneria.com" [integration] yunohost = ">= 11.2" architectures = "all" multi_instance = true -ldap = false +ldap = true -sso = false +sso = true disk = "50M" ram.build = "50M" @@ -32,24 +33,19 @@ ram.runtime = "50M" [install.domain] type = "domain" - [install.path] - type = "path" - default = "/aeneria" - [install.admin] type = "user" [install.init_main_permission] - help.en = "Choose whether the app should be accessible only for your yunohost users or for everyone." - help.fr = "Choisissez si l'application doit être accessible uniquement pour vos utilisateurs yunohost ou pour tout le monde." + help.en = "Choose whether the app should be accessible only for your YunoHost users or for everyone." + help.fr = "Choisissez si l'application doit être accessible uniquement pour vos utilisateurs YunoHost ou pour tout le monde." type = "group" - default = false + default = "all_users" [resources] - [resources.sources.main] - url = "https://statics.aeneria.com/aeneria-app-1.1.6.tar.gz" - sha256 = "2923c3aee79a02154c2168537a18250abe6a3a84fd7b4a5f0309bd7ad604a98b" - + [resources.sources.main] + url = "https://statics.aeneria.com/aeneria-app-2.1.0.tar.gz" + sha256 = "c2f4dc9825fd769a6dff2cdacfa64ddbf9b54de1bc2660a4a515fee5444d1e5a" [resources.system_user] @@ -59,7 +55,7 @@ ram.runtime = "50M" main.url = "/" [resources.apt] - packages = "postgresql, apt-transport-https, postgresql-contrib, php7.4-zip, php7.4-pgsql, php7.4-xml, php7.4-intl, php7.4-mbstring, php7.4-gd, php7.4-curl, php7.4-bcmath, php7.4-opcache" + packages = "postgresql, apt-transport-https, postgresql-contrib, php8.2-zip, php8.2-pgsql, php8.2-xml, php8.2-intl, php8.2-gd, php8.2-curl, php8.2-bcmath, php8.2-opcache, php8.2-ldap" [resources.database] type = "postgresql" diff --git a/scripts/_common.sh b/scripts/_common.sh index b867d23..2ad9093 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -17,10 +17,10 @@ # hour: random value between 0 and 2 # These two variables are used in conf/aeneria.cron so that it runs every 3 hours starting at 00:MM, 01:MM, or 02:MM. generate_random_minutes_hour () { - minutes="$(ynh_string_random --length=1 --filter=0-5)$(ynh_string_random --length=1 --filter=0-9)" - hour="$(ynh_string_random --length=1 --filter=0-2)" - ynh_app_setting_set --app=$app --key=minutes --value=$minutes - ynh_app_setting_set --app=$app --key=hour --value=$hour + minutes="$(ynh_string_random --length=1 --filter=0-5)$(ynh_string_random --length=1 --filter=0-9)" + hour="$(ynh_string_random --length=1 --filter=0-2)" + ynh_app_setting_set --app=$app --key=minutes --value=$minutes + ynh_app_setting_set --app=$app --key=hour --value=$hour } #================================================= diff --git a/scripts/change_url b/scripts/change_url index d50c1a8..b377908 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -9,6 +9,20 @@ source _common.sh source /usr/share/yunohost/helpers +#================================================= +# ENSURE DOWNWARD COMPATIBILITY +#================================================= + +# Before version 2.x æneria could be installed under a path, +# this functionnality has been deprecated since version 2.0.0 and æneria +# now need to be installed under its own domain. +# If the app is currently installed under a path, we warn the admin +# that he should move the app under its own domain +if [ "$path" != "/" ]; then + ynh_die --message="Since version 2.0.0, $app need to be installed under its own domain. \ + Before upgrading, change $app URL: delete the path and switch to a new domain if needed." +fi + #================================================= # STANDARD MODIFICATIONS #================================================= @@ -22,4 +36,4 @@ ynh_change_url_nginx_config # END OF SCRIPT #================================================= -ynh_script_progression --message="Change of URL completed for $app" --last +ynh_script_progression --message="Change of URL completed for $app" --last \ No newline at end of file diff --git a/scripts/install b/scripts/install index 1fa354e..53fd869 100644 --- a/scripts/install +++ b/scripts/install @@ -24,8 +24,8 @@ ynh_script_progression --message="Setting up source files..." --weight=1 # Download, check integrity, uncompress and patch the source from app.src ynh_setup_source --dest_dir="$install_dir" -chmod -R o-rwx "$install_dir" chown -R $app:www-data "$install_dir" +chmod -R 750 "$install_dir" #================================================= # SYSTEM CONFIGURATION @@ -57,11 +57,11 @@ ynh_script_progression --message="Installing aeneria..." --weight=1 # Install aeneria pushd $install_dir - ynh_exec_as $app php$phpversion bin/console aeneria:install "$app" -n - # Create admin user - mail=$(ynh_user_get_info --username="$admin" --key='mail') - ynh_exec_as $app php$phpversion bin/console aeneria:user:add "$mail" "$(ynh_string_random)" -n - ynh_exec_as $app php$phpversion bin/console aeneria:user:grant "$mail" + ynh_exec_as $app php$phpversion bin/console aeneria:install "$app" -n + # Create admin user + mail=$(ynh_user_get_info --username="$admin" --key='mail') + ynh_exec_as $app php$phpversion bin/console aeneria:user:add "$mail" "$(ynh_string_random)" -n + ynh_exec_as $app php$phpversion bin/console aeneria:user:grant "$mail" popd #================================================= @@ -76,14 +76,6 @@ ynh_add_config --template="aeneria.cron" --destination="/etc/cron.d/$app" chown root: "/etc/cron.d/$app" chmod 644 "/etc/cron.d/$app" -#================================================= -# ADAPT HOOK FOR AENERIA INSTANCE -#================================================= -ynh_script_progression --message="Adapting hooks..." --weight=1 - -ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="../hooks/post_app_addaccess" -ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="../hooks/post_app_removeaccess" - #================================================= # END OF SCRIPT #================================================= diff --git a/scripts/upgrade b/scripts/upgrade index bea1232..0676498 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -24,8 +24,18 @@ ynh_script_progression --message="Ensuring downward compatibility..." # If minutes or hour do not exist, create them if [ -z "${minutes:-}" ] || [ -z "${hour:-}" ]; then - # Generate random running schedule, and save $hour and $minutes as app parameters - generate_random_minutes_hour + # Generate random running schedule, and save $hour and $minutes as app parameters + generate_random_minutes_hour +fi + +# Before version 2.x æneria could be installed under a path, +# this functionnality has been deprecated since version 2.0.0 and æneria +# now need to be installed under its own domain. +# If the app is currently installed under a path, we warn the admin +# that he should move the app under its own domain +if [ "$path" != "/" ]; then + ynh_die --message="Since version 2.0.0, $app need to be installed under its own domain. \ + Before upgrading, change $app URL: delete the path and switch to a new domain if needed." fi #================================================= @@ -34,28 +44,31 @@ fi if [ "$upgrade_type" == "UPGRADE_APP" ] then - ynh_script_progression --message="Upgrading source files..." + ynh_script_progression --message="Upgrading source files..." - # For aeneria source update, we use a temporary directory because - # without it, patches can't be apply correctly: - # In 'app-00-ldap-auth.patch' we create a new file, if we try - # to apply the patch a second time while the file already exists, it - # throws a warning leading to an upgrade fail. + # For aeneria source update, we use a temporary directory because + # without it, patches can't be apply correctly: + # In 'app-00-ldap-auth.patch' we create a new file, if we try + # to apply the patch a second time while the file already exists, it + # throws a warning leading to an upgrade fail. - # Create tmpdir for new sources - tmpdir="$(ynh_smart_mktemp min_size=300)" + # Create tmpdir for new sources + tmpdir="$(ynh_smart_mktemp min_size=300)" - # Download, check integrity, uncompress and patch the source from app.src - ynh_setup_source --dest_dir="$tmpdir" + # Download, check integrity, uncompress and patch the source from app.src + ynh_setup_source --dest_dir="$tmpdir" - # Replace the old aeneria by the new one - ynh_secure_remove --file="$install_dir" - mv "$tmpdir" "$install_dir" - ynh_secure_remove --file="$tmpdir" + # Keep private dir + mv "$install_dir/private" "$tmpdir" + + # Replace the old aeneria by the new one + ynh_secure_remove --file="$install_dir" + mv "$tmpdir" "$install_dir" + ynh_secure_remove --file="$tmpdir" fi -chmod -R o-rwx "$install_dir" chown -R $app:www-data "$install_dir" +chmod -R 750 "$install_dir" #================================================= # REAPPLY SYSTEM CONFIGURATIONS @@ -91,30 +104,22 @@ ynh_script_progression --message="Upgrading $app..." --weight=1 # Install dependencies and aeneria pushd $install_dir - ynh_exec_as $app php$phpversion bin/console cache:clear -n - ynh_exec_as $app php$phpversion bin/console doctrine:migrations:migrate -n + ynh_exec_as $app php$phpversion bin/console cache:clear -n + ynh_exec_as $app php$phpversion bin/console doctrine:migrations:migrate -n - # Set admin user - mail=$(ynh_user_get_info --username="$admin" --key='mail') - user_exists=$(ynh_exec_as $app php$phpversion bin/console aeneria:user:exist "$mail") - if [ $user_exists -eq 0 ] - then - user_pass=$(ynh_string_random) - ynh_exec_as $app php$phpversion bin/console aeneria:user:add "$mail" "$user_pass" -n - fi + # Set admin user + mail=$(ynh_user_get_info --username="$admin" --key='mail') + user_exists=$(ynh_exec_as $app php$phpversion bin/console aeneria:user:exist "$mail") + if [ $user_exists -eq 0 ] + then + user_pass=$(ynh_string_random) + ynh_exec_as $app php$phpversion bin/console aeneria:user:add "$mail" "$user_pass" -n + fi - # Regenerate RSA keys - ynh_exec_as $app php$phpversion bin/console aeneria:generate-key --force -n + # Regenerate RSA keys + ynh_exec_as $app php$phpversion bin/console aeneria:generate-key -n popd -#================================================= -# ADAPT HOOK FOR AENERIA INSTANCE -#================================================= -ynh_script_progression --message="Adapting hooks..." --weight=1 - -ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="../hooks/post_app_addaccess" -ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="../hooks/post_app_removeaccess" - #================================================= # END OF SCRIPT #================================================= diff --git a/sources/patches/app-00-ldap-auth.patch b/sources/patches/app-00-ldap-auth.patch deleted file mode 100644 index 09ec5aa..0000000 --- a/sources/patches/app-00-ldap-auth.patch +++ /dev/null @@ -1,179 +0,0 @@ -commit c7a763a0fae7e1933f280b29bd2a1911b01f7170 -Author: Simon Mellerin -Date: Fri Nov 27 12:19:02 2020 +0100 - -diff --git a/config/packages/security.yaml b/config/packages/security.yaml -index 15ef608..8516775 100644 ---- a/config/packages/security.yaml -+++ b/config/packages/security.yaml -@@ -10,6 +10,8 @@ security: - entity: - class: App\Entity\User - property: username -+ user_provider_yunohost: -+ id: yunohost.provider.ldap - firewalls: - dev: - pattern: ^/(_(profiler|wdt)|css|images|js)/ -@@ -20,6 +22,10 @@ security: - provider: app_user_provider - authenticators: - - App\Security\LoginFormAuthenticator -+ http_basic_ldap: -+ provider: user_provider_yunohost -+ service: yunohost.ldap -+ dn_string: "uid={username},ou=users,dc=yunohost,dc=org" - logout: - path: security.logout - target: security.login -diff --git a/config/services.yaml b/config/services.yaml -index 533c244..9362ef5 100644 ---- a/config/services.yaml -+++ b/config/services.yaml -@@ -70,3 +70,16 @@ services: - - Aeneria\EnedisDataConnectApi\Service\DataConnectServiceInterface: - alias: Aeneria\EnedisDataConnectApi\Service\DataConnectService -+ -+ yunohost.provider.ldap: -+ class: App\Security\YunohostLdapUserProvider -+ arguments: ["@yunohost.ldap", "ou=users,dc=yunohost,dc=org"] -+ -+ yunohost.ldap: -+ class: Symfony\Component\Ldap\Ldap -+ arguments: ['@yunohost.ldap.adapter'] -+ -+ yunohost.ldap.adapter: -+ class: Symfony\Component\Ldap\Adapter\ExtLdap\Adapter -+ arguments: -+ - host: "localhost" -diff --git a/src/Security/YunohostLdapUserProvider.php b/src/Security/YunohostLdapUserProvider.php -new file mode 100644 -index 0000000..39ba1e8 ---- /dev/null -+++ b/src/Security/YunohostLdapUserProvider.php -@@ -0,0 +1,123 @@ -+ -+ * @author Charles Sarrazin -+ * @author Robin Chalas -+ */ -+class YunohostLdapUserProvider implements UserProviderInterface -+{ -+ /** @var LdapInterface */ -+ private $ldap; -+ /** @var string */ -+ private $baseDn; -+ /** @var string */ -+ private $searchDn; -+ /** @var string */ -+ private $searchPassword; -+ /** @var string[] */ -+ private $defaultRoles; -+ /** @var string */ -+ private $uidKey; -+ /** @var string */ -+ private $defaultSearch; -+ /** @var UserRepository */ -+ private $userRepository; -+ -+ public function __construct( -+ LdapInterface $ldap, -+ string $baseDn, -+ string $searchDn = null, -+ string $searchPassword = null, -+ array $defaultRoles = [], -+ UserRepository $userRepository -+ ) { -+ $this->ldap = $ldap; -+ $this->baseDn = $baseDn; -+ $this->searchDn = $searchDn; -+ $this->searchPassword = $searchPassword; -+ $this->defaultRoles = $defaultRoles; -+ $this->defaultSearch = '(uid={username})'; -+ -+ $this->userRepository = $userRepository; -+ } -+ -+ /** -+ * {@inheritdoc} -+ */ -+ public function loadUserByUsername(string $username) -+ { -+ try { -+ $this->ldap->bind($this->searchDn, $this->searchPassword); -+ $username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_FILTER); -+ $query = str_replace('{username}', $username, $this->defaultSearch); -+ $search = $this->ldap->query($this->baseDn, $query); -+ } catch (ConnectionException $e) { -+ throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username), 0, $e); -+ } -+ -+ $entries = $search->execute(); -+ $count = \count($entries); -+ -+ if (!$count) { -+ die($username . 'ldap pas trouvé'); -+ throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username)); -+ } -+ -+ if ($count > 1) { -+ throw new UsernameNotFoundException('More than one user found.'); -+ } -+ -+ $entry = $entries[0]; -+ -+ $username = $this->getAttributeValue($entry, 'mail'); -+ -+ return $this->userRepository->findOneBy(['username' => $username]); -+ } -+ -+ /** -+ * {@inheritdoc} -+ */ -+ public function refreshUser(UserInterface $user) -+ { -+ if (!$user instanceof User) { -+ throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', \get_class($user))); -+ } -+ -+ return $this->userRepository->findOneBy(['username' => $user->getUsername()]); -+ } -+ -+ /** -+ * {@inheritdoc} -+ */ -+ public function supportsClass(string $class) -+ { -+ return User::class === $class; -+ } -+ -+ private function getAttributeValue(Entry $entry, string $attribute) -+ { -+ if (!$entry->hasAttribute($attribute)) { -+ throw new InvalidArgumentException(sprintf('Missing attribute "%s" for user "%s".', $attribute, $entry->getDn())); -+ } -+ -+ $values = $entry->getAttribute($attribute); -+ -+ return $values[0]; -+ } -+} --- diff --git a/sources/patches/main-00-ldap-auth.patch b/sources/patches/main-00-ldap-auth.patch new file mode 100644 index 0000000..8bedb2c --- /dev/null +++ b/sources/patches/main-00-ldap-auth.patch @@ -0,0 +1,157 @@ +commit 7a3e622666fa16ab124158cffec73d9a3e6748bf +Author: Simon Mellerin +Date: Sun Jan 7 16:25:06 2024 +0100 + + YNH LDAP + +diff --git a/config/packages/security.yaml b/config/packages/security.yaml +index 6c4457f1..e716ba39 100644 +--- a/config/packages/security.yaml ++++ b/config/packages/security.yaml +@@ -11,6 +11,11 @@ security: + entity: + class: App\Entity\User + property: username ++ ldap_user_provider: ++ id: ynh.ldap.user.provider ++ all_users: ++ chain: ++ providers: ['ldap_user_provider', 'app_user_provider'] + firewalls: + dev: + pattern: ^/(_(profiler|wdt)|css|images|js)/ +@@ -22,7 +27,12 @@ security: + form_login: + login_path: security.login + check_path: security.login ++ provider: app_user_provider + enable_csrf: true ++ http_basic_ldap: ++ provider: ldap_user_provider ++ service: ynh.ldap ++ dn_string: 'uid={username},ou=users,dc=yunohost,dc=org' + logout: + path: security.logout + target: security.login +diff --git a/config/services.yaml b/config/services.yaml +index 3e770913..83fbec0d 100644 +--- a/config/services.yaml ++++ b/config/services.yaml +@@ -104,3 +104,21 @@ services: + + Aeneria\GrdfAdictApi\Client\GrdfAdictClientInterface: + alias: Aeneria\GrdfAdictApi\Client\GrdfAdictClient ++ ++ ynh.ldap.user.provider: ++ class: App\Security\YnhLdapUserProvider ++ arguments: ++ $ldap: '@ynh.ldap' ++ $baseDn: "dc=yunohost,dc=org" ++ # $searchDn: 'uid={username},ou=users,dc=yunohost,dc=org' ++ $uidKey: "uid" ++ ++ ynh.ldap: ++ class: Symfony\Component\Ldap\Ldap ++ arguments: ['@ynh.ldap.adapter'] ++ tags: ['ldap'] ++ ++ ynh.ldap.adapter: ++ class: Symfony\Component\Ldap\Adapter\ExtLdap\Adapter ++ arguments: ++ - host: "localhost" +diff --git a/src/Security/YnhLdapUserProvider.php b/src/Security/YnhLdapUserProvider.php +new file mode 100755 +index 00000000..eb8b1149 +--- /dev/null ++++ b/src/Security/YnhLdapUserProvider.php +@@ -0,0 +1,89 @@ ++getAttribute('mail'); ++ ++ // Dans le cadre de la connexion LDAP Yunohost, ++ // on cherche l'utilisateur par son mail. ++ // ++ $user = $this->userRepository->findOneBy(['username' => $email]); ++ ++ // Si l'utilisateur n'existe pas encore, on le crée. ++ if (!$user) { ++ $user = (new User()) ++ ->setUsername(\reset($email)) ++ ->setPassword(\bin2hex(\random_bytes(32))) ++ ->setActive(true) ++ ->setUpdatedAt(new \DateTimeImmutable()) ++ ; ++ ++ $this->entityManager->persist($user); ++ $this->entityManager->flush(); ++ } ++ ++ return $user ++ ->setUsername(\reset($email)) ++ ->setUserIdentifier($identifier) ++ ; ++ } ++} ++ \ No newline at end of file diff --git a/tests.toml b/tests.toml index eb73b8d..7bd1328 100644 --- a/tests.toml +++ b/tests.toml @@ -1,3 +1,5 @@ test_format = 1.0 -[default] \ No newline at end of file +[default] + # aeneria needs its own dedicated domain + exclude = ["install.subdir"]