mirror of
https://github.com/YunoHost-Apps/humhub_ynh.git
synced 2024-09-03 19:26:11 +02:00
Update 1.2.0.
Upgrade is broken though
This commit is contained in:
parent
c2049d74f7
commit
5fce14394e
7 changed files with 696 additions and 15 deletions
|
@ -9,6 +9,9 @@
|
||||||
LDAP settings:
|
LDAP settings:
|
||||||
* hostname : localhost
|
* hostname : localhost
|
||||||
* port : 389
|
* port : 389
|
||||||
|
* encryption : none
|
||||||
|
* username : put something random
|
||||||
|
* password : put something random
|
||||||
* baseDn : ou=users,dc=yunohost,dc=org
|
* baseDn : ou=users,dc=yunohost,dc=org
|
||||||
* loginFilter : (uid=%s)
|
* loginFilter : (uid=%s)
|
||||||
* userFilter : objectClass=mailAccount
|
* userFilter : objectClass=mailAccount
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
location YNH_WWW_PATH {
|
location YNH_WWW_PATH/ {
|
||||||
alias YNH_WWW_ALIAS ;
|
alias YNH_WWW_ALIAS;
|
||||||
index index.php;
|
index index.php;
|
||||||
try_files $uri $uri/ index.php?$args;
|
try_files $uri $uri/ index.php?$args;
|
||||||
|
|
||||||
|
@ -13,18 +13,18 @@ location YNH_WWW_PATH {
|
||||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ ^YNH_WWW_PATH(?:ico|css|js|gif|jpe?g|png|ttf|woff)$ {
|
location ~ ^YNH_WWW_PATH/(?:ico|css|js|gif|jpe?g|png|ttf|woff)$ {
|
||||||
access_log off;
|
access_log off;
|
||||||
expires 30d;
|
expires 30d;
|
||||||
add_header Pragma public;
|
add_header Pragma public;
|
||||||
add_header Cache-Control "public, mustrevalidate, proxy-revalidate";
|
add_header Cache-Control "public, mustrevalidate, proxy-revalidate";
|
||||||
}
|
}
|
||||||
|
|
||||||
location = YNH_WWW_PATHprotected {
|
location = YNH_WWW_PATH/protected {
|
||||||
deny all;
|
deny all;
|
||||||
}
|
}
|
||||||
|
|
||||||
location = YNH_WWW_PATHuploads/file {
|
location = YNH_WWW_PATH/uploads/file {
|
||||||
deny all;
|
deny all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
app=$YNH_APP_INSTANCE_NAME
|
app=$YNH_APP_INSTANCE_NAME
|
||||||
version='1.1.0'
|
version='1.2.0'
|
||||||
|
source='https://github.com/humhub/humhub'
|
||||||
|
|
||||||
# Retrieve arguments
|
# Retrieve arguments
|
||||||
domain=$YNH_APP_ARG_DOMAIN
|
domain=$YNH_APP_ARG_DOMAIN
|
||||||
|
@ -13,6 +14,14 @@ version='1.1.0'
|
||||||
# Source YunoHost helpers
|
# Source YunoHost helpers
|
||||||
source /usr/share/yunohost/helpers
|
source /usr/share/yunohost/helpers
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
# Check domain/path availability
|
# Check domain/path availability
|
||||||
sudo yunohost app checkurl "${domain}${path}" -a "$app" \
|
sudo yunohost app checkurl "${domain}${path}" -a "$app" \
|
||||||
|| ynh_die "Path not available: ${domain}${path}"
|
|| ynh_die "Path not available: ${domain}${path}"
|
||||||
|
@ -20,8 +29,14 @@ version='1.1.0'
|
||||||
# Copy source files
|
# Copy source files
|
||||||
src_path=/var/www/$app
|
src_path=/var/www/$app
|
||||||
sudo mkdir -p $src_path
|
sudo mkdir -p $src_path
|
||||||
sudo unzip -qq ../sources/humhub-$version.zip
|
sudo unzip -qq ../sources/humhub-${version}.zip
|
||||||
sudo cp -a humhub-$version/. $src_path
|
sudo cp -a humhub-${version}/. $src_path
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
# MySQL
|
# MySQL
|
||||||
dbuser=$app
|
dbuser=$app
|
||||||
|
@ -48,9 +63,10 @@ version='1.1.0'
|
||||||
|
|
||||||
# Modify Nginx configuration file and copy it to Nginx conf directory
|
# Modify Nginx configuration file and copy it to Nginx conf directory
|
||||||
nginx_conf=../conf/nginx.conf
|
nginx_conf=../conf/nginx.conf
|
||||||
sed -i "s@YNH_WWW_PATH@$path@g" $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_ALIAS@$src_path/@g" $nginx_conf
|
||||||
sudo cp $nginx_conf /etc/nginx/conf.d/$domain.d/$app.conf
|
sudo cp $nginx_conf /etc/nginx/conf.d/$domain.d/$app.conf
|
||||||
|
|
||||||
# Reload services
|
# Reload services
|
||||||
|
sudo service php5-fpm reload
|
||||||
sudo service nginx reload
|
sudo service nginx reload
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
app=$YNH_APP_INSTANCE_NAME
|
app=$YNH_APP_INSTANCE_NAME
|
||||||
version='1.1.0'
|
version='1.2.0'
|
||||||
|
|
||||||
# Source YunoHost helpers
|
# Source YunoHost helpers
|
||||||
source /usr/share/yunohost/helpers
|
source /usr/share/yunohost/helpers
|
||||||
|
@ -12,16 +12,36 @@ version='1.1.0'
|
||||||
# Retrieve app settings
|
# Retrieve app settings
|
||||||
domain=$(ynh_app_setting_get "$app" domain)
|
domain=$(ynh_app_setting_get "$app" domain)
|
||||||
path=$(ynh_app_setting_get "$app" path)
|
path=$(ynh_app_setting_get "$app" path)
|
||||||
|
dbuser=$app
|
||||||
|
dbname=$app
|
||||||
|
dbpass=$(ynh_app_setting_get "$app" mysqlpwd)
|
||||||
|
|
||||||
# Remove trailing "/" for next commands
|
# Correct path: puts a / at the start and nothing at the end
|
||||||
path=${path%/}
|
if [ "${path:0:1}" != "/" ]; then
|
||||||
|
path="/$path"
|
||||||
|
fi
|
||||||
|
if [ "${path:${#path}-1}" == "/" ] && [ ${#path} -gt 1 ]; then
|
||||||
|
path="${path:0:${#path}-1}"
|
||||||
|
fi
|
||||||
|
|
||||||
# Copy source files
|
# Copy source files
|
||||||
src_path=/var/www/$app
|
|
||||||
sudo mkdir -p $src_path
|
sudo mkdir -p $src_path
|
||||||
sudo unzip -qq ../sources/humhub-$version.zip
|
sudo unzip -qq ../sources/humhub-$version.zip
|
||||||
sudo cp -a humhub-$version/. $src_path
|
sudo cp -a humhub-$version/. $src_path
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
# Set permissions to app files
|
# Set permissions to app files
|
||||||
sudo chown -R www-data: $src_path
|
sudo chown -R www-data: $src_path
|
||||||
|
|
||||||
|
@ -33,9 +53,10 @@ version='1.1.0'
|
||||||
|
|
||||||
# Modify Nginx configuration file and copy it to Nginx conf directory
|
# Modify Nginx configuration file and copy it to Nginx conf directory
|
||||||
nginx_conf=../conf/nginx.conf
|
nginx_conf=../conf/nginx.conf
|
||||||
sed -i "s@YNH_WWW_PATH@$path@g" $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_ALIAS@$src_path/@g" $nginx_conf
|
||||||
sudo cp $nginx_conf /etc/nginx/conf.d/$domain.d/$app.conf
|
sudo cp $nginx_conf /etc/nginx/conf.d/$domain.d/$app.conf
|
||||||
|
|
||||||
# Reload nginx service
|
# Reload nginx service
|
||||||
|
sudo service php5-fpm reload
|
||||||
sudo service nginx reload
|
sudo service nginx reload
|
||||||
|
|
261
sources/fix/AuthClientHelpers.php
Normal file
261
sources/fix/AuthClientHelpers.php
Normal file
|
@ -0,0 +1,261 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://www.humhub.org/
|
||||||
|
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||||
|
* @license https://www.humhub.com/licences
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace humhub\modules\user\authclient;
|
||||||
|
|
||||||
|
use Yii;
|
||||||
|
use yii\authclient\ClientInterface;
|
||||||
|
use humhub\modules\user\models\Auth;
|
||||||
|
use humhub\modules\user\models\User;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AuthClientHelper provides helper functions fo auth clients
|
||||||
|
*
|
||||||
|
* @since 1.1
|
||||||
|
* @author luke
|
||||||
|
*/
|
||||||
|
class AuthClientHelpers
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the user object which is linked against given authClient
|
||||||
|
*
|
||||||
|
* @param ClientInterface $authClient the authClient
|
||||||
|
* @return User the user model or null if not found
|
||||||
|
*/
|
||||||
|
public static function getUserByAuthClient(ClientInterface $authClient)
|
||||||
|
{
|
||||||
|
$attributes = $authClient->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
380
sources/fix/ZendLdapClient.php
Normal file
380
sources/fix/ZendLdapClient.php
Normal file
|
@ -0,0 +1,380 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link http://www.yiiframework.com/
|
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||||
|
* @license http://www.yiiframework.com/license/
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace humhub\modules\user\authclient;
|
||||||
|
|
||||||
|
use Yii;
|
||||||
|
use Zend\Ldap\Ldap;
|
||||||
|
use Zend\Ldap\Node;
|
||||||
|
use Zend\Ldap\Exception\LdapException;
|
||||||
|
use humhub\modules\user\models\User;
|
||||||
|
use humhub\modules\user\models\ProfileField;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LDAP Authentication
|
||||||
|
*
|
||||||
|
* @todo create base ldap authentication, to bypass ApprovalByPass Interface
|
||||||
|
* @since 1.1
|
||||||
|
*/
|
||||||
|
class ZendLdapClient extends BaseFormAuth implements interfaces\AutoSyncUsers, interfaces\SyncAttributes, interfaces\ApprovalBypass, interfaces\PrimaryClient
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Zend\Ldap\Ldap
|
||||||
|
*/
|
||||||
|
private $_ldap = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID attribute to uniquely identify user
|
||||||
|
* If set to null, automatically a value email or objectguid will be used if available.
|
||||||
|
*
|
||||||
|
* @var string attribute name to identify node
|
||||||
|
*/
|
||||||
|
public $idAttribute = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string attribute name to user record
|
||||||
|
*/
|
||||||
|
public $userTableIdAttribute = 'guid';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public $byPassApproval = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return 'ldap';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
protected function defaultName()
|
||||||
|
{
|
||||||
|
return 'ldap';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
protected function defaultTitle()
|
||||||
|
{
|
||||||
|
return 'LDAP';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function getIdAttribute()
|
||||||
|
{
|
||||||
|
return $this->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
Loading…
Reference in a new issue