mirror of
https://github.com/humhub/humhub.git
synced 2025-01-17 14:18:27 +01:00
Enh #117: Refactored authentication (pluggable yii2-authclient support)
This commit is contained in:
parent
de93b1b625
commit
8191d4ef86
@ -18,6 +18,7 @@
|
||||
"yiisoft/yii2": ">=2.0.4",
|
||||
"yiisoft/yii2-bootstrap": "*",
|
||||
"yiisoft/yii2-swiftmailer": "*",
|
||||
"yiisoft/yii2-authclient": "*",
|
||||
"raoul2000/yii2-jcrop-widget": "*",
|
||||
"cebe/markdown": "1.0.2",
|
||||
"yiisoft/yii2-jui": "^2.0",
|
||||
|
@ -24,10 +24,17 @@ class HForm extends \yii\base\Component
|
||||
public $models = array();
|
||||
public $definition = array();
|
||||
|
||||
public function __construct($definition, $primaryModel = null)
|
||||
/**
|
||||
* @var boolean manually mark form as submitted
|
||||
*/
|
||||
public $markedAsSubmitted = false;
|
||||
|
||||
public function __construct($definition = [], $primaryModel = null)
|
||||
{
|
||||
$this->definition = $definition;
|
||||
$this->primaryModel = $primaryModel;
|
||||
|
||||
$this->init();
|
||||
}
|
||||
|
||||
public function submitted($buttonName = "")
|
||||
@ -43,6 +50,8 @@ class HForm extends \yii\base\Component
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} elseif ($this->markedAsSubmitted) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -66,6 +75,17 @@ class HForm extends \yii\base\Component
|
||||
return !$hasErrors;
|
||||
}
|
||||
|
||||
public function clearErrors()
|
||||
{
|
||||
if ($this->primaryModel !== null) {
|
||||
$this->primaryModel->clearErrors();
|
||||
}
|
||||
|
||||
foreach ($this->models as $model) {
|
||||
$model->clearErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$hasErrors = false;
|
||||
|
@ -85,6 +85,10 @@ $config = [
|
||||
'charset' => 'utf8',
|
||||
'enableSchemaCache' => true,
|
||||
],
|
||||
'authClientCollection' => [
|
||||
'class' => 'humhub\modules\user\authclient\Collection',
|
||||
'clients' => [],
|
||||
],
|
||||
],
|
||||
'params' => [
|
||||
'installed' => false,
|
||||
|
72
protected/humhub/docs/guide/admin-adv-auth.md
Normal file
72
protected/humhub/docs/guide/admin-adv-auth.md
Normal file
@ -0,0 +1,72 @@
|
||||
Authentication
|
||||
==============
|
||||
|
||||
## Example: GitHub Authentication
|
||||
|
||||
- Obtain Application ID and Secret from GitHub
|
||||
- Add following block to protected/config/common.php
|
||||
|
||||
```
|
||||
// ...
|
||||
'components' => [
|
||||
// ...
|
||||
'authClientCollection' => [
|
||||
'class' => 'yii\authclient\Collection',
|
||||
'clients' => [
|
||||
'github' => [
|
||||
'class' => 'yii\authclient\clients\GitHub',
|
||||
'clientId' => '--->your-client-id<---',
|
||||
'clientSecret' => '--->your-client-secret<---',
|
||||
'normalizeUserAttributeMap' => [
|
||||
'username' => 'login',
|
||||
'firstname' => function ($attributes) {
|
||||
list($f, $l) = mb_split(' ', $attributes['name'], 2);
|
||||
return $f;
|
||||
},
|
||||
'lastname' => function ($attributes) {
|
||||
list($f, $l) = mb_split(' ', $attributes['name'], 2);
|
||||
return $l;
|
||||
},
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
// ..
|
||||
],
|
||||
// ...
|
||||
```
|
||||
|
||||
## Example: Facebook
|
||||
|
||||
- Obtain Application ID and Secret from Facebook
|
||||
- Add following block to protected/config/common.php
|
||||
|
||||
```
|
||||
// ...
|
||||
'components' => [
|
||||
// ...
|
||||
'authClientCollection' => [
|
||||
'class' => 'yii\authclient\Collection',
|
||||
'clients' => [
|
||||
'facebook' => [
|
||||
'class' => 'yii\authclient\clients\Facebook',
|
||||
'clientId' => '1662633133992750',
|
||||
'clientSecret' => '3c786f625a26f7f3649bd5cc8d8c6a61',
|
||||
'normalizeUserAttributeMap' => [
|
||||
'username' => 'name',
|
||||
'firstname' => function ($attributes) {
|
||||
list($f, $l) = mb_split(' ', $attributes['name'], 2);
|
||||
return $f;
|
||||
},
|
||||
'lastname' => function ($attributes) {
|
||||
list($f, $l) = mb_split(' ', $attributes['name'], 2);
|
||||
return $l;
|
||||
},
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
// ..
|
||||
],
|
||||
// ...
|
||||
```
|
@ -171,7 +171,7 @@ class SelfTest
|
||||
|
||||
// Checks LDAP Extension
|
||||
$title = 'LDAP Support';
|
||||
if (\humhub\modules\user\libs\Ldap::isAvailable()) {
|
||||
if (\humhub\modules\user\authclient\ZendLdapClient::isLdapAvailable()) {
|
||||
$checks[] = array(
|
||||
'title' => Yii::t('base', $title),
|
||||
'state' => 'OK'
|
||||
|
51
protected/humhub/libs/StringHelper.php
Normal file
51
protected/humhub/libs/StringHelper.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\libs;
|
||||
|
||||
/**
|
||||
* StringHelper
|
||||
*
|
||||
* @since 1.1
|
||||
* @author luke
|
||||
*/
|
||||
class StringHelper extends \yii\helpers\StringHelper
|
||||
{
|
||||
|
||||
/**
|
||||
* Converts (LDAP) Binary to Ascii GUID
|
||||
*
|
||||
* @param string $object_guid a binary string containing data.
|
||||
* @return string the guid
|
||||
*/
|
||||
public static function binaryToGuid($object_guid)
|
||||
{
|
||||
$hex_guid = bin2hex($object_guid);
|
||||
|
||||
if ($hex_guid == "")
|
||||
return "";
|
||||
|
||||
$hex_guid_to_guid_str = '';
|
||||
for ($k = 1; $k <= 4; ++$k) {
|
||||
$hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2);
|
||||
}
|
||||
$hex_guid_to_guid_str .= '-';
|
||||
for ($k = 1; $k <= 2; ++$k) {
|
||||
$hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2);
|
||||
}
|
||||
$hex_guid_to_guid_str .= '-';
|
||||
for ($k = 1; $k <= 2; ++$k) {
|
||||
$hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2);
|
||||
}
|
||||
$hex_guid_to_guid_str .= '-' . substr($hex_guid, 16, 4);
|
||||
$hex_guid_to_guid_str .= '-' . substr($hex_guid, 20);
|
||||
|
||||
return strtolower($hex_guid_to_guid_str);
|
||||
}
|
||||
|
||||
}
|
@ -187,6 +187,7 @@ class SettingController extends Controller
|
||||
Yii::$app->response->redirect(Url::toRoute('/admin/setting/authentication-ldap'));
|
||||
}
|
||||
|
||||
|
||||
$enabled = false;
|
||||
$userCount = 0;
|
||||
$errorMessage = "";
|
||||
@ -194,11 +195,9 @@ class SettingController extends Controller
|
||||
if (Setting::Get('enabled', 'authentication_ldap')) {
|
||||
$enabled = true;
|
||||
try {
|
||||
if (Ldap::getInstance()->ldap !== null) {
|
||||
$userCount = Ldap::getInstance()->ldap->count(Setting::Get('userFilter', 'authentication_ldap'), Setting::Get('baseDn', 'authentication_ldap'), \Zend\Ldap\Ldap::SEARCH_SCOPE_SUB);
|
||||
} else {
|
||||
$errorMessage = Yii::t('AdminModule.controllers_SettingController', 'Could not load LDAP! - Check PHP Extension');
|
||||
}
|
||||
$ldapAuthClient = new \humhub\modules\user\authclient\ZendLdapClient();
|
||||
$ldap = $ldapAuthClient->getLdap();
|
||||
$userCount = $ldap->count(Setting::Get('userFilter', 'authentication_ldap'), Setting::Get('baseDn', 'authentication_ldap'), \Zend\Ldap\Ldap::SEARCH_SCOPE_SUB);
|
||||
} catch (\Zend\Ldap\Exception\LdapException $ex) {
|
||||
$errorMessage = $ex->getMessage();
|
||||
} catch (Exception $ex) {
|
||||
|
@ -11,9 +11,9 @@ namespace humhub\modules\admin\controllers;
|
||||
use Yii;
|
||||
use yii\helpers\Url;
|
||||
use humhub\compat\HForm;
|
||||
use humhub\modules\user\models\forms\Registration;
|
||||
use humhub\modules\admin\components\Controller;
|
||||
use humhub\modules\user\models\User;
|
||||
use humhub\modules\user\models\Password;
|
||||
use humhub\modules\user\models\Group;
|
||||
|
||||
/**
|
||||
@ -80,15 +80,6 @@ class UserController extends Controller
|
||||
'super_admin' => array(
|
||||
'type' => 'checkbox',
|
||||
),
|
||||
'auth_mode' => array(
|
||||
'type' => 'dropdownlist',
|
||||
'disabled' => 'disabled',
|
||||
'class' => 'form-control',
|
||||
'items' => array(
|
||||
User::AUTH_MODE_LOCAL => Yii::t('AdminModule.controllers_UserController', 'Local'),
|
||||
User::AUTH_MODE_LDAP => Yii::t('AdminModule.controllers_UserController', 'LDAP'),
|
||||
),
|
||||
),
|
||||
'status' => array(
|
||||
'type' => 'dropdownlist',
|
||||
'class' => 'form-control',
|
||||
@ -149,110 +140,13 @@ class UserController extends Controller
|
||||
|
||||
public function actionAdd()
|
||||
{
|
||||
$userModel = new User();
|
||||
$userModel->scenario = 'registration';
|
||||
|
||||
$userPasswordModel = new Password();
|
||||
$userPasswordModel->scenario = 'registration';
|
||||
|
||||
$profileModel = $userModel->profile;
|
||||
$profileModel->scenario = 'registration';
|
||||
|
||||
// Build Form Definition
|
||||
$definition = array();
|
||||
$definition['elements'] = array();
|
||||
|
||||
$groupModels = \humhub\modules\user\models\Group::find()->orderBy('name ASC')->all();
|
||||
$defaultUserGroup = \humhub\models\Setting::Get('defaultUserGroup', 'authentication_internal');
|
||||
$groupFieldType = "dropdownlist";
|
||||
if ($defaultUserGroup != "") {
|
||||
$groupFieldType = "hidden";
|
||||
} else if (count($groupModels) == 1) {
|
||||
$groupFieldType = "hidden";
|
||||
$defaultUserGroup = $groupModels[0]->id;
|
||||
$registration = new Registration();
|
||||
$registration->enableEmailField = true;
|
||||
$registration->enableUserApproval = false;
|
||||
if ($registration->submitted('save') && $registration->validate() && $registration->register()) {
|
||||
return $this->redirect(Url::to(['edit', 'id' => $registration->getUser()->id]));
|
||||
}
|
||||
if ($groupFieldType == 'hidden') {
|
||||
$userModel->group_id = $defaultUserGroup;
|
||||
}
|
||||
// Add User Form
|
||||
$definition['elements']['User'] = array(
|
||||
'type' => 'form',
|
||||
'title' => Yii::t('UserModule.controllers_AuthController', 'Account'),
|
||||
'elements' => array(
|
||||
'username' => array(
|
||||
'type' => 'text',
|
||||
'class' => 'form-control',
|
||||
'maxlength' => 25,
|
||||
),
|
||||
'email' => array(
|
||||
'type' => 'text',
|
||||
'class' => 'form-control',
|
||||
'maxlength' => 100,
|
||||
),
|
||||
'group_id' => array(
|
||||
'type' => $groupFieldType,
|
||||
'class' => 'form-control',
|
||||
'items' => \yii\helpers\ArrayHelper::map($groupModels, 'id', 'name'),
|
||||
'value' => $defaultUserGroup,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Add User Password Form
|
||||
$definition['elements']['UserPassword'] = array(
|
||||
'type' => 'form',
|
||||
#'title' => 'Password',
|
||||
'elements' => array(
|
||||
'newPassword' => array(
|
||||
'type' => 'password',
|
||||
'class' => 'form-control',
|
||||
'maxlength' => 255,
|
||||
),
|
||||
'newPasswordConfirm' => array(
|
||||
'type' => 'password',
|
||||
'class' => 'form-control',
|
||||
'maxlength' => 255,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Add Profile Form
|
||||
$definition['elements']['Profile'] = array_merge(array('type' => 'form'), $profileModel->getFormDefinition());
|
||||
|
||||
// Get Form Definition
|
||||
$definition['buttons'] = array(
|
||||
'save' => array(
|
||||
'type' => 'submit',
|
||||
'class' => 'btn btn-primary',
|
||||
'label' => Yii::t('UserModule.controllers_AuthController', 'Create account'),
|
||||
),
|
||||
);
|
||||
|
||||
$form = new HForm($definition);
|
||||
$form->models['User'] = $userModel;
|
||||
$form->models['UserPassword'] = $userPasswordModel;
|
||||
$form->models['Profile'] = $profileModel;
|
||||
|
||||
if ($form->submitted('save') && $form->validate()) {
|
||||
|
||||
$this->forcePostRequest();
|
||||
|
||||
$form->models['User']->status = User::STATUS_ENABLED;
|
||||
if ($form->models['User']->save()) {
|
||||
// Save User Profile
|
||||
$form->models['Profile']->user_id = $form->models['User']->id;
|
||||
$form->models['Profile']->save();
|
||||
|
||||
// Save User Password
|
||||
$form->models['UserPassword']->user_id = $form->models['User']->id;
|
||||
$form->models['UserPassword']->setPassword($form->models['UserPassword']->newPassword);
|
||||
$form->models['UserPassword']->save();
|
||||
|
||||
return $this->redirect(Url::to(['index']));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('add', array('hForm' => $form));
|
||||
return $this->render('add', array('hForm' => $registration));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4,7 +4,6 @@ use yii\widgets\ActiveForm;
|
||||
use humhub\compat\CHtml;
|
||||
use humhub\models\Setting;
|
||||
use yii\helpers\Url;
|
||||
|
||||
?>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><?php echo Yii::t('AdminModule.views_setting_authentication', '<strong>Authentication</strong> - Basic'); ?></div>
|
||||
@ -14,11 +13,9 @@ use yii\helpers\Url;
|
||||
<li class="active"><a
|
||||
href="<?php echo Url::toRoute('authentication'); ?>"><?php echo Yii::t('AdminModule.views_setting_authentication', 'Basic'); ?></a>
|
||||
</li>
|
||||
<?php if (humhub\modules\user\libs\Ldap::isAvailable()): ?>
|
||||
<li>
|
||||
<a href="<?php echo Url::toRoute('authentication-ldap'); ?>"><?php echo Yii::t('AdminModule.views_setting_authentication', 'LDAP'); ?></a>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
|
||||
|
||||
|
@ -38,7 +38,6 @@ class InstallController extends Controller
|
||||
$user = new User();
|
||||
$user->group_id = 1;
|
||||
$user->username = "Admin";
|
||||
$user->auth_mode = 'local';
|
||||
$user->email = 'humhub@example.com';
|
||||
$user->status = User::STATUS_ENABLED;
|
||||
$user->language = '';
|
||||
|
@ -243,7 +243,6 @@ class ConfigController extends Controller
|
||||
$profileModel->scenario = 'registration';
|
||||
|
||||
$userModel->status = User::STATUS_ENABLED;
|
||||
$userModel->auth_mode = "local";
|
||||
$userModel->username = "david1986";
|
||||
$userModel->email = "david.roberts@humhub.com";
|
||||
$userModel->super_admin = 0;
|
||||
@ -273,7 +272,6 @@ class ConfigController extends Controller
|
||||
$profileModel2->scenario = 'registration';
|
||||
|
||||
$userModel2->status = User::STATUS_ENABLED;
|
||||
$userModel2->auth_mode = "local";
|
||||
$userModel2->username = "sara1989";
|
||||
$userModel2->email = "sara.schuster@humhub.com";
|
||||
$userModel2->super_admin = 0;
|
||||
@ -361,7 +359,7 @@ class ConfigController extends Controller
|
||||
|
||||
|
||||
$userModel = new User();
|
||||
$userModel->scenario = 'registration';
|
||||
$userModel->scenario = 'registration_email';
|
||||
$userPasswordModel = new Password();
|
||||
$userPasswordModel->scenario = 'registration';
|
||||
$profileModel = $userModel->profile;
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace humhub\modules\user;
|
||||
|
||||
use Yii;
|
||||
use humhub\modules\user\models\User;
|
||||
use humhub\modules\user\models\GroupAdmin;
|
||||
use humhub\modules\user\models\Password;
|
||||
@ -22,7 +23,7 @@ class Events extends \yii\base\Object
|
||||
/**
|
||||
* On rebuild of the search index, rebuild all user records
|
||||
*
|
||||
* @param type $event
|
||||
* @param \yii\base\Event $event
|
||||
*/
|
||||
public static function onSearchRebuild($event)
|
||||
{
|
||||
@ -34,7 +35,7 @@ class Events extends \yii\base\Object
|
||||
/**
|
||||
* On delete of a Content or ContentAddon
|
||||
*
|
||||
* @param type $event
|
||||
* @param \yii\base\Event $event
|
||||
*/
|
||||
public static function onContentDelete($event)
|
||||
{
|
||||
@ -45,7 +46,7 @@ class Events extends \yii\base\Object
|
||||
/**
|
||||
* Callback to validate module database records.
|
||||
*
|
||||
* @param Event $event
|
||||
* @param \yii\base\Event $event
|
||||
*/
|
||||
public static function onIntegrityCheck($event)
|
||||
{
|
||||
@ -126,14 +127,22 @@ class Events extends \yii\base\Object
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tasks on hourly cron job
|
||||
*
|
||||
* @param \yii\base\Event $event
|
||||
*/
|
||||
public static function onHourlyCron($event)
|
||||
{
|
||||
$controller = $event->sender;
|
||||
|
||||
if (Setting::Get('enabled', 'authentication_ldap') && Setting::Get('refreshUsers', 'authentication_ldap') && Ldap::isAvailable()) {
|
||||
$controller->stdout("Refresh ldap users... ");
|
||||
Ldap::getInstance()->refreshUsers();
|
||||
$controller->stdout('done.' . PHP_EOL, \yii\helpers\Console::FG_GREEN);
|
||||
foreach (Yii::$app->authClientCollection->getClients() as $authClient) {
|
||||
if ($authClient instanceof authclient\interfaces\AutoSyncUsers) {
|
||||
/**
|
||||
* @var authclient\interfaces\AutoSyncUsers $authClient
|
||||
*/
|
||||
$authClient->syncUsers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\modules\user;
|
||||
|
||||
/**
|
||||
* User Module
|
||||
*/
|
||||
class Module extends \humhub\components\Module
|
||||
{
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $controllerNamespace = 'humhub\modules\user\controllers';
|
||||
|
||||
/**
|
||||
* @var boolean default state of remember me checkbox on login page
|
||||
*/
|
||||
public $loginRememberMeDefault = true;
|
||||
|
||||
/**
|
||||
* @var int number of seconds that the user can remain in logged-in status if remember me is clicked on login
|
||||
*/
|
||||
public $loginRememberMeDuration = 3600 * 24 * 30;
|
||||
|
||||
}
|
||||
|
238
protected/humhub/modules/user/authclient/AuthClientHelpers.php
Normal file
238
protected/humhub/modules/user/authclient/AuthClientHelpers.php
Normal file
@ -0,0 +1,238 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 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(['user_id' => $user->id, 'source' => $authClient->getId(), 'source_id' => $attributes['id']]);
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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->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;
|
||||
}
|
||||
|
||||
$registration = new \humhub\modules\user\models\forms\Registration();
|
||||
$registration->enablePasswordForm = false;
|
||||
|
||||
if ($authClient instanceof interfaces\ApprovalBypass) {
|
||||
$registration->enableUserApproval = false;
|
||||
}
|
||||
|
||||
unset($attributes['id']);
|
||||
$registration->getUser()->setAttributes($attributes, false);
|
||||
$registration->getProfile()->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;
|
||||
}
|
||||
|
||||
}
|
32
protected/humhub/modules/user/authclient/BaseClient.php
Normal file
32
protected/humhub/modules/user/authclient/BaseClient.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\modules\user\authclient;
|
||||
|
||||
/**
|
||||
* Extended BaseClient with additional events
|
||||
*
|
||||
* @since 1.1
|
||||
* @author luke
|
||||
*/
|
||||
class BaseClient extends \yii\authclient\BaseClient
|
||||
{
|
||||
|
||||
/**
|
||||
* @event Event an event raised on update user data.
|
||||
* @see AuthClientHelpers::updateUser()
|
||||
*/
|
||||
const EVENT_UPDATE_USER = 'update';
|
||||
|
||||
/**
|
||||
* @event Event an event raised on create user.
|
||||
* @see AuthClientHelpers::createUser()
|
||||
*/
|
||||
const EVENT_CREATE_USER = 'create';
|
||||
|
||||
}
|
37
protected/humhub/modules/user/authclient/BaseFormAuth.php
Normal file
37
protected/humhub/modules/user/authclient/BaseFormAuth.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?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\base\NotSupportedException;
|
||||
use humhub\modules\user\models\forms\Login;
|
||||
|
||||
/**
|
||||
* BaseFormAuth is a base class for AuthClients using the Login Form
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
class BaseFormAuth extends BaseClient
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Login the login form model
|
||||
*/
|
||||
public $login = null;
|
||||
|
||||
/**
|
||||
* Authenticate the user using the login form.
|
||||
*
|
||||
* @throws NotSupportedException
|
||||
*/
|
||||
public function auth()
|
||||
{
|
||||
throw new NotSupportedException('Method "' . get_class($this) . '::' . __FUNCTION__ . '" not implemented.');
|
||||
}
|
||||
|
||||
}
|
140
protected/humhub/modules/user/authclient/Collection.php
Normal file
140
protected/humhub/modules/user/authclient/Collection.php
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\modules\user\authclient;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Component;
|
||||
use yii\base\InvalidParamException;
|
||||
use humhub\models\Setting;
|
||||
|
||||
/**
|
||||
* Extended AuthClient collection with event support
|
||||
*
|
||||
* @author luke
|
||||
* @since 1.1
|
||||
*/
|
||||
class Collection extends Component
|
||||
{
|
||||
|
||||
/**
|
||||
* @event Event an event raised after the clients are set.
|
||||
*/
|
||||
const EVENT_AFTER_CLIENTS_SET = 'client_set';
|
||||
|
||||
/**
|
||||
* @var array list of Auth clients with their configuration in format: 'clientId' => [...]
|
||||
*/
|
||||
private $_clients = [];
|
||||
|
||||
/**
|
||||
* @param array $clients list of auth clients
|
||||
*/
|
||||
public function setClients(array $clients)
|
||||
{
|
||||
$this->_clients = array_merge($this->getDefaultClients(), $clients);
|
||||
$this->trigger(self::EVENT_AFTER_CLIENTS_SET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClientInterface[] list of auth clients.
|
||||
*/
|
||||
public function getClients($load = true)
|
||||
{
|
||||
$clients = [];
|
||||
foreach ($this->_clients as $id => $client) {
|
||||
$clients[$id] = $this->getClient($id, $load);
|
||||
}
|
||||
|
||||
return $clients;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id service id.
|
||||
* @return ClientInterface auth client instance.
|
||||
* @throws InvalidParamException on non existing client request.
|
||||
*/
|
||||
public function getClient($id, $load = true)
|
||||
{
|
||||
if (!array_key_exists($id, $this->_clients)) {
|
||||
throw new InvalidParamException("Unknown auth client '{$id}'.");
|
||||
}
|
||||
if (!is_object($this->_clients[$id]) && $load) {
|
||||
$this->_clients[$id] = $this->createClient($id, $this->_clients[$id]);
|
||||
}
|
||||
|
||||
return $this->_clients[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if client exists in the hub.
|
||||
* @param string $id client id.
|
||||
* @return boolean whether client exist.
|
||||
*/
|
||||
public function hasClient($id)
|
||||
{
|
||||
return array_key_exists($id, $this->_clients);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a client by id and config
|
||||
*
|
||||
* @param string $id auth client id.
|
||||
* @param array $config auth client instance configuration.
|
||||
*/
|
||||
public function setClient($id, $config)
|
||||
{
|
||||
$this->_clients[$id] = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes client by id
|
||||
*
|
||||
* @param string $id client id.
|
||||
*/
|
||||
public function removeClient($id)
|
||||
{
|
||||
unset($this->_clients[$id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates auth client instance from its array configuration.
|
||||
* @param string $id auth client id.
|
||||
* @param array $config auth client instance configuration.
|
||||
* @return ClientInterface auth client instance.
|
||||
*/
|
||||
protected function createClient($id, $config)
|
||||
{
|
||||
$config['id'] = $id;
|
||||
|
||||
return Yii::createObject($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configuration of default auth clients
|
||||
*
|
||||
* @return array the default auth clients
|
||||
*/
|
||||
protected function getDefaultClients()
|
||||
{
|
||||
$clients = [];
|
||||
|
||||
$clients['password'] = [
|
||||
'class' => 'humhub\modules\user\authclient\Password'
|
||||
];
|
||||
|
||||
if (Setting::Get('enabled', 'authentication_ldap')) {
|
||||
$clients['ldap'] = [
|
||||
'class' => 'humhub\modules\user\authclient\ZendLdapClient'
|
||||
];
|
||||
}
|
||||
|
||||
return $clients;
|
||||
}
|
||||
|
||||
}
|
68
protected/humhub/modules/user/authclient/Password.php
Normal file
68
protected/humhub/modules/user/authclient/Password.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?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 humhub\modules\user\models\User;
|
||||
|
||||
/**
|
||||
* Standard password authentication client
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
class Password extends BaseFormAuth implements interfaces\PrimaryClient
|
||||
{
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return 'local';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function defaultName()
|
||||
{
|
||||
return 'password';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function defaultTitle()
|
||||
{
|
||||
return 'Password';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getUserTableIdAttribute()
|
||||
{
|
||||
return 'id';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function auth()
|
||||
{
|
||||
$user = User::find()->where(['username' => $this->login->username])->orWhere(['email' => $this->login->password])->one();
|
||||
|
||||
if ($user !== null && $user->currentPassword !== null && $user->currentPassword->validatePassword($this->login->password)) {
|
||||
$this->setUserAttributes(['id' => $user->id]);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
342
protected/humhub/modules/user/authclient/ZendLdapClient.php
Normal file
342
protected/humhub/modules/user/authclient/ZendLdapClient.php
Normal file
@ -0,0 +1,342 @@
|
||||
<?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\models\Setting;
|
||||
use humhub\modules\user\models\User;
|
||||
use humhub\modules\user\models\ProfileField;
|
||||
use humhub\modules\user\authclient\AuthClientHelpers;
|
||||
|
||||
/**
|
||||
* 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 = Setting::Get('usernameAttribute', 'authentication_ldap');
|
||||
if ($usernameAttribute == '') {
|
||||
$usernameAttribute = 'sAMAccountName';
|
||||
}
|
||||
$map['username'] = strtolower($usernameAttribute);
|
||||
|
||||
// E-Mail field
|
||||
$emailAttribute = Setting::Get('emailAttribute', 'authentication_ldap');
|
||||
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) {
|
||||
$normalized[$name] = $value[0];
|
||||
} else {
|
||||
$normalized[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($normalized['objectguid'])) {
|
||||
$normalized['objectguid'] = \humhub\libs\StringHelper::binaryToGuid($normalized['objectguid']);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
// ToDo: Search user even by e-mail address
|
||||
try {
|
||||
$this->getLdap()->bind($this->login->username, $this->login->password);
|
||||
return $this->getLdap()->getCanonicalAccountName($this->login->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' => Setting::Get('hostname', 'authentication_ldap'),
|
||||
'port' => Setting::Get('port', 'authentication_ldap'),
|
||||
'username' => Setting::Get('username', 'authentication_ldap'),
|
||||
'password' => Setting::Get('password', 'authentication_ldap'),
|
||||
'useStartTls' => (Setting::Get('encryption', 'authentication_ldap') == 'tls'),
|
||||
'useSsl' => (Setting::Get('encryption', 'authentication_ldap') == 'ssl'),
|
||||
'bindRequiresDn' => true,
|
||||
'baseDn' => Setting::Get('baseDn', 'authentication_ldap'),
|
||||
'accountFilterFormat' => Setting::Get('loginFilter', 'authentication_ldap'),
|
||||
);
|
||||
|
||||
$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 (!Setting::Get('enabled', 'authentication_ldap') || !Setting::Get('refreshUsers', 'authentication_ldap')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$userFilter = Setting::Get('userFilter', 'authentication_ldap');
|
||||
$baseDn = Setting::Get('baseDn', 'authentication_ldap');
|
||||
$userCollection = $this->getLdap()->search($userFilter, $baseDn, Ldap::SEARCH_SCOPE_SUB);
|
||||
|
||||
$ids = [];
|
||||
foreach ($userCollection as $attributes) {
|
||||
$authClient = new static;
|
||||
$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 ' . $attributes['email'] . ' - check required attributes!');
|
||||
}
|
||||
} 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();
|
||||
}
|
||||
|
||||
// Disable not longer existing users
|
||||
foreach (AuthClientHelpers::getUsersByAuthClient($this)->each() as $user) {
|
||||
if ($user->status !== User::STATUS_DISABLED && !in_array($user->getAttribute($userTableIdAttribute), $ids)) {
|
||||
$user->status = User::STATUS_DISABLED;
|
||||
$user->save();
|
||||
Yii::warning('Disabled user ' . $user->username . ' (' . $user->id . ') - Not found in LDAP!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\modules\user\authclient\interfaces;
|
||||
|
||||
/**
|
||||
* ApprovalBypass interface allow user approvals of an authclient
|
||||
*
|
||||
* @since 1.1
|
||||
* @author luke
|
||||
*/
|
||||
interface ApprovalBypass
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\modules\user\authclient\interfaces;
|
||||
|
||||
/**
|
||||
* AutoSyncUsers interface adds the possiblity to automatically update/create users via AuthClient.
|
||||
* If this interface is implemented the cron will hourly execute the authclient's
|
||||
* syncronization method.
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
interface AutoSyncUsers
|
||||
{
|
||||
|
||||
public function syncUsers();
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\modules\user\authclient\interfaces;
|
||||
|
||||
/**
|
||||
* PrimaryClient authclient interface
|
||||
*
|
||||
* It's not possible to have to primary auth clients at the same time.
|
||||
* E.g. LDAP and Password
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
interface PrimaryClient
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the user model attribute name which should be mapped against
|
||||
* the id attribute in the authClient user attributes.
|
||||
*
|
||||
* @return string the user model id attribute e.g. id, guid or email
|
||||
*/
|
||||
public function getUserTableIdAttribute();
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\modules\user\authclient\interfaces;
|
||||
|
||||
/**
|
||||
* SyncAttributes interface allows the possiblitz to specify user attributes which will be automatically
|
||||
* updated on login or by daily cronjob if AutoSyncUsers is enabled.
|
||||
*
|
||||
* These attributes are also not writable by user.
|
||||
*
|
||||
* @since 1.1
|
||||
* @author luke
|
||||
*/
|
||||
interface SyncAttributes
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns attribute names which should be synced on login
|
||||
*
|
||||
* @return array attribute names to be synced
|
||||
*/
|
||||
public function getSyncAttributes();
|
||||
}
|
@ -8,6 +8,10 @@
|
||||
|
||||
namespace humhub\modules\user\components;
|
||||
|
||||
use Yii;
|
||||
use yii\authclient\ClientInterface;
|
||||
use humhub\modules\user\authclient\AuthClientHelpers;
|
||||
|
||||
/**
|
||||
* Description of User
|
||||
*
|
||||
@ -16,6 +20,11 @@ namespace humhub\modules\user\components;
|
||||
class User extends \yii\web\User
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ClientInterface[] the users authclients
|
||||
*/
|
||||
private $_authClients = null;
|
||||
|
||||
/**
|
||||
* @var PermissionManager
|
||||
*/
|
||||
@ -63,4 +72,58 @@ class User extends \yii\web\User
|
||||
return $this->permissionManager;
|
||||
}
|
||||
|
||||
public function canChangePassword()
|
||||
{
|
||||
foreach ($this->getAuthClients() as $authClient) {
|
||||
if ($authClient->className() == \humhub\modules\user\authclient\Password::className()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function canChangeEmail()
|
||||
{
|
||||
if (in_array('email', AuthClientHelpers::getSyncAttributesByUser($this->getIdentity()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function canDeleteAccount()
|
||||
{
|
||||
foreach ($this->getAuthClients() as $authClient) {
|
||||
if ($authClient instanceof \humhub\modules\user\authclient\interfaces\AutoSyncUsers) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getAuthClients()
|
||||
{
|
||||
if ($this->_authClients === null) {
|
||||
$this->_authClients = AuthClientHelpers::getAuthClientsByUser($this->getIdentity());
|
||||
}
|
||||
|
||||
return $this->_authClients;
|
||||
}
|
||||
|
||||
public function setCurrentAuthClient(ClientInterface $authClient)
|
||||
{
|
||||
Yii::$app->session->set('currentAuthClientId', $authClient->getId());
|
||||
}
|
||||
|
||||
public function getCurrentAuthClient()
|
||||
{
|
||||
foreach ($this->getAuthClients() as $authClient) {
|
||||
if ($authClient->getId() == Yii::$app->session->get('currentAuthClientId')) {
|
||||
return $authClient;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -109,6 +109,40 @@ class AccountController extends Controller
|
||||
return $this->render('editSettings', array('model' => $model, 'languages' => Yii::$app->params['availableLanguages']));
|
||||
}
|
||||
|
||||
public function actionConnectedAccounts()
|
||||
{
|
||||
if (Yii::$app->request->isPost && Yii::$app->request->get('disconnect')) {
|
||||
foreach (Yii::$app->user->getAuthClients() as $authClient) {
|
||||
if ($authClient->getId() == Yii::$app->request->get('disconnect')) {
|
||||
\humhub\modules\user\authclient\AuthClientHelpers::removeAuthClientForUser($authClient, Yii::$app->user->getIdentity());
|
||||
}
|
||||
}
|
||||
return $this->redirect(['connected-accounts']);
|
||||
}
|
||||
$clients = [];
|
||||
foreach (Yii::$app->get('authClientCollection')->getClients() as $client) {
|
||||
if (!$client instanceof humhub\modules\user\authclient\BaseFormAuth && !$client instanceof \humhub\modules\user\authclient\interfaces\PrimaryClient) {
|
||||
$clients[] = $client;
|
||||
}
|
||||
}
|
||||
|
||||
$currentAuthProviderId = "";
|
||||
if (Yii::$app->user->getCurrentAuthClient() !== null) {
|
||||
$currentAuthProviderId = Yii::$app->user->getCurrentAuthClient()->getId();
|
||||
}
|
||||
|
||||
$activeAuthClientIds = [];
|
||||
foreach (Yii::$app->user->getAuthClients() as $authClient) {
|
||||
$activeAuthClientIds[] = $authClient->getId();
|
||||
}
|
||||
|
||||
return $this->render('connected-accounts', [
|
||||
'authClients' => $clients,
|
||||
'currentAuthProviderId' => $currentAuthProviderId,
|
||||
'activeAuthClientIds' => $activeAuthClientIds
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the user to enable user specifc modules
|
||||
*/
|
||||
@ -159,8 +193,8 @@ class AccountController extends Controller
|
||||
$isSpaceOwner = false;
|
||||
$user = Yii::$app->user->getIdentity();
|
||||
|
||||
if ($user->auth_mode != User::AUTH_MODE_LOCAL) {
|
||||
throw new HttpException(500, 'This is not a local account! You cannot delete it. (e.g. LDAP)!');
|
||||
if (!Yii::$app->user->canDeleteAccount()) {
|
||||
throw new HttpException(500, 'Account deletion not allowed');
|
||||
}
|
||||
|
||||
foreach (\humhub\modules\space\models\Membership::GetUserSpaces() as $space) {
|
||||
@ -213,9 +247,8 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function actionChangeEmail()
|
||||
{
|
||||
$user = Yii::$app->user->getIdentity();
|
||||
if ($user->auth_mode != User::AUTH_MODE_LOCAL) {
|
||||
throw new HttpException(500, Yii::t('UserModule.controllers_AccountController', 'You cannot change your e-mail address here.'));
|
||||
if (!Yii::$app->user->canChangeEmail()) {
|
||||
throw new HttpException(500, 'Change E-Mail is not allowed');
|
||||
}
|
||||
|
||||
$model = new \humhub\modules\user\models\forms\AccountChangeEmail;
|
||||
@ -233,15 +266,15 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function actionChangeEmailValidate()
|
||||
{
|
||||
$user = Yii::$app->user->getIdentity();
|
||||
|
||||
if ($user->auth_mode != User::AUTH_MODE_LOCAL) {
|
||||
throw new CHttpException(500, Yii::t('UserModule.controllers_AccountController', 'You cannot change your e-mail address here.'));
|
||||
if (!Yii::$app->user->canChangeEmail()) {
|
||||
throw new HttpException(500, 'Change E-Mail is not allowed');
|
||||
}
|
||||
|
||||
$token = Yii::$app->request->get('token');
|
||||
$email = Yii::$app->request->get('email');
|
||||
|
||||
$user = Yii::$app->user->getIdentity();
|
||||
|
||||
// Check if Token is valid
|
||||
if (md5(\humhub\models\Setting::Get('secret') . $user->guid . $email) != $token) {
|
||||
throw new HttpException(404, Yii::t('UserModule.controllers_AccountController', 'Invalid link! Please make sure that you entered the entire url.'));
|
||||
@ -264,10 +297,8 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function actionChangePassword()
|
||||
{
|
||||
$user = Yii::$app->user->getIdentity();
|
||||
|
||||
if ($user->auth_mode != User::AUTH_MODE_LOCAL) {
|
||||
throw new CHttpException(500, Yii::t('UserModule.controllers_AccountController', 'You cannot change your e-mail address here.'));
|
||||
if (!Yii::$app->user->canChangePassword()) {
|
||||
throw new HttpException(500, 'Password change is not allowed');
|
||||
}
|
||||
|
||||
$userPassword = new \humhub\modules\user\models\Password();
|
||||
|
@ -10,6 +10,11 @@ namespace humhub\modules\user\controllers;
|
||||
|
||||
use Yii;
|
||||
use humhub\components\Controller;
|
||||
use humhub\modules\user\models\User;
|
||||
use humhub\modules\user\models\Auth;
|
||||
use humhub\modules\user\models\Invite;
|
||||
use humhub\modules\user\models\forms\Login;
|
||||
use humhub\modules\user\authclient\AuthClientHelpers;
|
||||
|
||||
/**
|
||||
* AuthController handles login and logout
|
||||
@ -38,60 +43,148 @@ class AuthController extends Controller
|
||||
'captcha' => [
|
||||
'class' => 'yii\captcha\CaptchaAction',
|
||||
],
|
||||
'external-auth' => [
|
||||
'class' => 'yii\authclient\AuthAction',
|
||||
'successCallback' => [$this, 'onAuthSuccess'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function beforeAction($action)
|
||||
{
|
||||
// Remove authClient from session - if already exists
|
||||
Yii::$app->session->remove('authClient');
|
||||
|
||||
return parent::beforeAction($action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the login page
|
||||
*/
|
||||
public function actionLogin()
|
||||
{
|
||||
|
||||
// If user is already logged in, redirect him to the dashboard
|
||||
if (!Yii::$app->user->isGuest) {
|
||||
$this->redirect(Yii::$app->user->returnUrl);
|
||||
}
|
||||
|
||||
// Show/Allow Anonymous Registration
|
||||
$loginModel = new \humhub\modules\user\models\forms\AccountLogin;
|
||||
if ($loginModel->load(Yii::$app->request->post()) && $loginModel->login()) {
|
||||
// Login Form Handling
|
||||
$login = new Login;
|
||||
if ($login->load(Yii::$app->request->post()) && $login->validate()) {
|
||||
return $this->onAuthSuccess($login->authClient);
|
||||
}
|
||||
|
||||
// Self Invite
|
||||
$invite = new Invite();
|
||||
$invite->scenario = 'invite';
|
||||
if ($invite->load(Yii::$app->request->post()) && $invite->selfInvite()) {
|
||||
if (Yii::$app->request->getIsAjax()) {
|
||||
return $this->htmlRedirect(Yii::$app->user->returnUrl);
|
||||
return $this->render('register_success_modal', ['model' => $invite]);
|
||||
} else {
|
||||
return $this->redirect(Yii::$app->user->returnUrl);
|
||||
}
|
||||
}
|
||||
$loginModel->password = "";
|
||||
|
||||
$canRegister = \humhub\models\Setting::Get('anonymousRegistration', 'authentication_internal');
|
||||
$registerModel = new \humhub\modules\user\models\forms\AccountRegister;
|
||||
|
||||
if ($canRegister) {
|
||||
if ($registerModel->load(Yii::$app->request->post()) && $registerModel->validate()) {
|
||||
|
||||
$invite = \humhub\modules\user\models\Invite::findOne(['email' => $registerModel->email]);
|
||||
if ($invite === null) {
|
||||
$invite = new \humhub\modules\user\models\Invite();
|
||||
}
|
||||
$invite->email = $registerModel->email;
|
||||
$invite->source = \humhub\modules\user\models\Invite::SOURCE_SELF;
|
||||
$invite->language = Yii::$app->language;
|
||||
$invite->save();
|
||||
$invite->sendInviteMail();
|
||||
|
||||
if (Yii::$app->request->getIsAjax()) {
|
||||
return $this->render('register_success_modal', ['model' => $registerModel]);
|
||||
} else {
|
||||
return $this->render('register_success', ['model' => $registerModel]);
|
||||
}
|
||||
return $this->render('register_success', ['model' => $invite]);
|
||||
}
|
||||
}
|
||||
|
||||
if (Yii::$app->request->getIsAjax()) {
|
||||
return $this->renderAjax('login_modal', array('model' => $loginModel, 'registerModel' => $registerModel, 'canRegister' => $canRegister));
|
||||
} else {
|
||||
return $this->render('login', array('model' => $loginModel, 'registerModel' => $registerModel, 'canRegister' => $canRegister));
|
||||
return $this->renderAjax('login_modal', array('model' => $login, 'invite' => $invite, 'canRegister' => $invite->allowSelfInvite()));
|
||||
}
|
||||
return $this->render('login', array('model' => $login, 'invite' => $invite, 'canRegister' => $invite->allowSelfInvite()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle successful authentication
|
||||
*
|
||||
* @param \yii\authclient\BaseClient $authClient
|
||||
* @return Response
|
||||
*/
|
||||
public function onAuthSuccess(\yii\authclient\BaseClient $authClient)
|
||||
{
|
||||
$attributes = $authClient->getUserAttributes();
|
||||
|
||||
// User already logged in - Add new authclient to existing user
|
||||
if (!Yii::$app->user->isGuest) {
|
||||
AuthClientHelpers::storeAuthClientForUser($authClient, Yii::$app->user->getIdentity());
|
||||
return $this->redirect(['/user/account/connected-accounts']);
|
||||
}
|
||||
|
||||
// Login existing user
|
||||
$user = AuthClientHelpers::getUserByAuthClient($authClient);
|
||||
if ($user !== null) {
|
||||
return $this->login($user, $authClient);
|
||||
}
|
||||
|
||||
// Check if E-Mail is given
|
||||
if (!isset($attributes['email'])) {
|
||||
Yii::$app->session->setFlash('error', "Missing E-Mail Attribute from AuthClient.");
|
||||
return $this->redirect(['/user/auth/login']);
|
||||
}
|
||||
|
||||
if (!isset($attributes['id'])) {
|
||||
Yii::$app->session->setFlash('error', "Missing ID AuthClient Attribute from AuthClient.");
|
||||
return $this->redirect(['/user/auth/login']);
|
||||
}
|
||||
|
||||
// Check if e-mail is already taken
|
||||
if (User::findOne(['email' => $attributes['email']]) !== null) {
|
||||
Yii::$app->session->setFlash('error', Yii::t('UserModule.base', 'User with the same email already exists but isn\'t linked to you. Login using your email first to link it.'));
|
||||
return $this->redirect(['/user/auth/login']);
|
||||
}
|
||||
|
||||
// Try automatically create user & login user
|
||||
$user = AuthClientHelpers::createUser($authClient);
|
||||
if ($user !== null) {
|
||||
return $this->login($user, $authClient);
|
||||
}
|
||||
|
||||
// Make sure we normalized user attributes before put it in session (anonymous functions)
|
||||
$authClient->setNormalizeUserAttributeMap([]);
|
||||
|
||||
// Store authclient in session - for registration controller
|
||||
Yii::$app->session->set('authClient', $authClient);
|
||||
|
||||
// Start registration process
|
||||
return $this->redirect(['/user/registration']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Login user
|
||||
*
|
||||
* @param User $user
|
||||
* @param \yii\authclient\BaseClient $authClient
|
||||
* @return Response the current response object
|
||||
*/
|
||||
protected function login($user, $authClient)
|
||||
{
|
||||
$redirectUrl = ['/user/auth/login'];
|
||||
if ($user->status == User::STATUS_ENABLED) {
|
||||
$duration = 0;
|
||||
if ($authClient instanceof \humhub\modules\user\authclient\BaseFormAuth) {
|
||||
if ($authClient->login->rememberMe) {
|
||||
$duration = Yii::$app->getModule('user')->loginRememberMeDuration;
|
||||
}
|
||||
}
|
||||
AuthClientHelpers::updateUser($authClient, $user);
|
||||
|
||||
if (Yii::$app->user->login($user, $duration)) {
|
||||
Yii::$app->user->setCurrentAuthClient($authClient);
|
||||
$url = Yii::$app->user->returnUrl;
|
||||
}
|
||||
} elseif ($user->status == User::STATUS_DISABLED) {
|
||||
Yii::$app->session->setFlash('error', 'Your account is disabled!');
|
||||
} elseif ($user->status == User::STATUS_NEED_APPROVAL) {
|
||||
Yii::$app->session->setFlash('error', 'Your account is not approved yet!');
|
||||
} else {
|
||||
Yii::$app->session->setFlash('error', 'Unknown user status!');
|
||||
}
|
||||
|
||||
if (Yii::$app->request->getIsAjax()) {
|
||||
return $this->htmlRedirect($redirectUrl);
|
||||
}
|
||||
|
||||
return $this->redirect($redirectUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,13 +9,15 @@
|
||||
namespace humhub\modules\user\controllers;
|
||||
|
||||
use Yii;
|
||||
use yii\web\HttpException;
|
||||
use yii\helpers\Url;
|
||||
use yii\web\HttpException;
|
||||
use yii\authclient\ClientInterface;
|
||||
use humhub\components\Controller;
|
||||
use humhub\modules\user\models\Invite;
|
||||
use humhub\compat\HForm;
|
||||
use humhub\modules\user\models\User;
|
||||
use humhub\modules\user\models\Password;
|
||||
use humhub\modules\user\models\Invite;
|
||||
use humhub\modules\user\models\forms\Registration;
|
||||
use humhub\modules\user\authclient\AuthClientHelpers;
|
||||
use humhub\modules\user\authclient\interfaces\ApprovalBypass;
|
||||
|
||||
/**
|
||||
* RegistrationController handles new user registration
|
||||
@ -35,6 +37,18 @@ class RegistrationController extends Controller
|
||||
*/
|
||||
public $subLayout = "_layout";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function beforeAction($action)
|
||||
{
|
||||
if (!Yii::$app->user->isGuest) {
|
||||
throw new HttpException(401, 'Your are already logged in! - Logout first!');
|
||||
}
|
||||
|
||||
return parent::beforeAction($action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registration Form
|
||||
*
|
||||
@ -43,136 +57,78 @@ class RegistrationController extends Controller
|
||||
*/
|
||||
public function actionIndex()
|
||||
{
|
||||
$needApproval = \humhub\models\Setting::Get('needApproval', 'authentication_internal');
|
||||
$registration = new Registration();
|
||||
|
||||
if (!Yii::$app->user->isGuest)
|
||||
throw new HttpException(401, 'Your are already logged in! - Logout first!');
|
||||
/**
|
||||
* @var \yii\authclient\BaseClient
|
||||
*/
|
||||
$authClient = null;
|
||||
$inviteToken = Yii::$app->request->get('token', '');
|
||||
|
||||
|
||||
$userInvite = Invite::findOne(['token' => Yii::$app->request->get('token')]);
|
||||
if (!$userInvite)
|
||||
throw new HttpException(404, 'Token not found!');
|
||||
|
||||
if ($userInvite->language)
|
||||
Yii::$app->language = $userInvite->language;
|
||||
|
||||
$userModel = new User();
|
||||
$userModel->scenario = 'registration';
|
||||
$userModel->email = $userInvite->email;
|
||||
|
||||
$userPasswordModel = new Password();
|
||||
$userPasswordModel->scenario = 'registration';
|
||||
|
||||
$profileModel = $userModel->profile;
|
||||
$profileModel->scenario = 'registration';
|
||||
|
||||
// Build Form Definition
|
||||
$definition = array();
|
||||
$definition['elements'] = array();
|
||||
|
||||
|
||||
$groupModels = \humhub\modules\user\models\Group::find()->orderBy('name ASC')->all();
|
||||
$defaultUserGroup = \humhub\models\Setting::Get('defaultUserGroup', 'authentication_internal');
|
||||
$groupFieldType = "dropdownlist";
|
||||
if ($defaultUserGroup != "") {
|
||||
$groupFieldType = "hidden";
|
||||
} else if (count($groupModels) == 1) {
|
||||
$groupFieldType = "hidden";
|
||||
$defaultUserGroup = $groupModels[0]->id;
|
||||
}
|
||||
if ($groupFieldType == 'hidden') {
|
||||
$userModel->group_id = $defaultUserGroup;
|
||||
if ($inviteToken != '') {
|
||||
$this->handleInviteRegistration($inviteToken, $registration);
|
||||
} elseif (Yii::$app->session->has('authClient')) {
|
||||
$authClient = Yii::$app->session->get('authClient');
|
||||
$this->handleAuthClientRegistration($authClient, $registration);
|
||||
} else {
|
||||
Yii::$app->session->setFlash('error', 'Registration failed.');
|
||||
return $this->redirect(['/user/auth/login']);
|
||||
}
|
||||
|
||||
// Add User Form
|
||||
$definition['elements']['User'] = array(
|
||||
'type' => 'form',
|
||||
'title' => Yii::t('UserModule.controllers_AuthController', 'Account'),
|
||||
'elements' => array(
|
||||
'username' => array(
|
||||
'type' => 'text',
|
||||
'class' => 'form-control',
|
||||
'maxlength' => 25,
|
||||
),
|
||||
'group_id' => array(
|
||||
'type' => $groupFieldType,
|
||||
'class' => 'form-control',
|
||||
'items' => \yii\helpers\ArrayHelper::map($groupModels, 'id', 'name'),
|
||||
'value' => $defaultUserGroup,
|
||||
),
|
||||
),
|
||||
);
|
||||
if ($registration->submitted('save') && $registration->validate() && $registration->register($authClient)) {
|
||||
Yii::$app->session->remove('authClient');
|
||||
|
||||
// Add User Password Form
|
||||
$definition['elements']['UserPassword'] = array(
|
||||
'type' => 'form',
|
||||
#'title' => 'Password',
|
||||
'elements' => array(
|
||||
'newPassword' => array(
|
||||
'type' => 'password',
|
||||
'class' => 'form-control',
|
||||
'maxlength' => 255,
|
||||
),
|
||||
'newPasswordConfirm' => array(
|
||||
'type' => 'password',
|
||||
'class' => 'form-control',
|
||||
'maxlength' => 255,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Add Profile Form
|
||||
$definition['elements']['Profile'] = array_merge(array('type' => 'form'), $profileModel->getFormDefinition());
|
||||
|
||||
// Get Form Definition
|
||||
$definition['buttons'] = array(
|
||||
'save' => array(
|
||||
'type' => 'submit',
|
||||
'class' => 'btn btn-primary',
|
||||
'label' => Yii::t('UserModule.controllers_AuthController', 'Create account'),
|
||||
),
|
||||
);
|
||||
|
||||
$form = new HForm($definition);
|
||||
$form->models['User'] = $userModel;
|
||||
$form->models['UserPassword'] = $userPasswordModel;
|
||||
$form->models['Profile'] = $profileModel;
|
||||
|
||||
if ($form->submitted('save') && $form->validate()) {
|
||||
|
||||
$this->forcePostRequest();
|
||||
|
||||
// Registe User
|
||||
$form->models['User']->email = $userInvite->email;
|
||||
$form->models['User']->language = Yii::$app->language;
|
||||
if ($form->models['User']->save()) {
|
||||
|
||||
// Save User Profile
|
||||
$form->models['Profile']->user_id = $form->models['User']->id;
|
||||
$form->models['Profile']->save();
|
||||
|
||||
// Save User Password
|
||||
$form->models['UserPassword']->user_id = $form->models['User']->id;
|
||||
$form->models['UserPassword']->setPassword($form->models['UserPassword']->newPassword);
|
||||
$form->models['UserPassword']->save();
|
||||
|
||||
// Autologin user
|
||||
if (!$needApproval) {
|
||||
Yii::$app->user->switchIdentity($form->models['User']);
|
||||
// Autologin when user is enabled (no approval required)
|
||||
if ($registration->getUser()->status === User::STATUS_ENABLED) {
|
||||
Yii::$app->user->switchIdentity($registration->models['User']);
|
||||
return $this->redirect(Url::to(['/dashboard/dashboard']));
|
||||
}
|
||||
|
||||
return $this->render('success', array(
|
||||
'form' => $form,
|
||||
'needApproval' => $needApproval,
|
||||
));
|
||||
}
|
||||
return $this->render('success', [
|
||||
'form' => $registration,
|
||||
'needApproval' => ($registration->getUser()->status === User::STATUS_NEED_APPROVAL)
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->render('index', array(
|
||||
'hForm' => $form,
|
||||
'needAproval' => $needApproval)
|
||||
);
|
||||
return $this->render('index', ['hForm' => $registration]);
|
||||
}
|
||||
|
||||
protected function handleInviteRegistration($inviteToken, Registration $form)
|
||||
{
|
||||
$userInvite = Invite::findOne(['token' => $inviteToken]);
|
||||
if (!$userInvite) {
|
||||
throw new HttpException(404, 'Invalid registration token!');
|
||||
}
|
||||
if ($userInvite->language) {
|
||||
Yii::$app->language = $userInvite->language;
|
||||
}
|
||||
$form->getUser()->email = $userInvite->email;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \yii\authclient\BaseClient $authClient
|
||||
* @param Registration $registration
|
||||
* @return boolean already all registration data gathered
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function handleAuthClientRegistration(ClientInterface $authClient, Registration $registration)
|
||||
{
|
||||
$attributes = $authClient->getUserAttributes();
|
||||
|
||||
if (!isset($attributes['id'])) {
|
||||
throw new Exception("No user id given by authclient!");
|
||||
}
|
||||
|
||||
$registration->enablePasswordForm = false;
|
||||
if ($authClient instanceof ApprovalBypass) {
|
||||
$registration->enableUserApproval = false;
|
||||
}
|
||||
|
||||
// do not store id attribute
|
||||
unset($attributes['id']);
|
||||
|
||||
$registration->getUser()->setAttributes($attributes, false);
|
||||
$registration->getProfile()->setAttributes($attributes, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,281 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\modules\user\libs;
|
||||
|
||||
use Exception;
|
||||
use Yii;
|
||||
use yii\base\Object;
|
||||
use humhub\models\Setting;
|
||||
use humhub\libs\ParameterEvent;
|
||||
use humhub\modules\user\models\User;
|
||||
use humhub\modules\user\models\Group;
|
||||
use humhub\modules\user\models\ProfileField;
|
||||
use humhub\modules\space\models\Space;
|
||||
|
||||
/**
|
||||
* LDAP Connector
|
||||
*
|
||||
* @since 0.5
|
||||
*/
|
||||
class Ldap extends \yii\base\Component
|
||||
{
|
||||
|
||||
/**
|
||||
* @event event when a ldap user is updated
|
||||
*/
|
||||
const EVENT_UPDATE_USER = 'update_user';
|
||||
|
||||
/**
|
||||
* @var Zend_Ldap instance
|
||||
*/
|
||||
public $ldap = null;
|
||||
|
||||
/**
|
||||
* @var SILDAP instance
|
||||
*/
|
||||
static private $instance = null;
|
||||
|
||||
/**
|
||||
* Returns the current HLdap Instance.
|
||||
*
|
||||
* @return HLdap
|
||||
*/
|
||||
static public function getInstance()
|
||||
{
|
||||
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self;
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var User currently handled user
|
||||
*/
|
||||
public $currentUser = null;
|
||||
|
||||
/**
|
||||
* Creates singleton HLdap Instance which configured Zend_Ldap Class
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
try {
|
||||
$options = array(
|
||||
'host' => Setting::Get('hostname', 'authentication_ldap'),
|
||||
'port' => Setting::Get('port', 'authentication_ldap'),
|
||||
'username' => Setting::Get('username', 'authentication_ldap'),
|
||||
'password' => Setting::Get('password', 'authentication_ldap'),
|
||||
'useStartTls' => (Setting::Get('encryption', 'authentication_ldap') == 'tls'),
|
||||
'useSsl' => (Setting::Get('encryption', 'authentication_ldap') == 'ssl'),
|
||||
'bindRequiresDn' => true,
|
||||
'baseDn' => Setting::Get('baseDn', 'authentication_ldap'),
|
||||
'accountFilterFormat' => Setting::Get('loginFilter', 'authentication_ldap'),
|
||||
);
|
||||
|
||||
$this->ldap = new \Zend\Ldap\Ldap($options);
|
||||
$this->ldap->bind();
|
||||
} catch (\Zend\Ldap\Exception\LdapException $ex) {
|
||||
Yii::error('Cound not bind to LDAP Server. Error: ' . $ex->getMessage());
|
||||
} catch (Exception $ex) {
|
||||
Yii::error('Cound not bind to LDAP Server. Error: ' . $ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates user against LDAP Backend
|
||||
*
|
||||
* @param type $username
|
||||
* @param type $password
|
||||
* @return boolean
|
||||
*/
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
try {
|
||||
$username = $this->ldap->getCanonicalAccountName($username, \Zend\Ldap\Ldap::ACCTNAME_FORM_DN);
|
||||
$this->ldap->bind($username, $password);
|
||||
|
||||
// Update Users Data
|
||||
$node = $this->ldap->getNode($username);
|
||||
$this->handleLdapUser($node);
|
||||
|
||||
return true;
|
||||
} catch (\Zend\Ldap\Exception\LdapException $ex) {
|
||||
return false;
|
||||
} catch (Exception $ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads out all users from configured ldap backend and creates or update
|
||||
* existing users.
|
||||
*
|
||||
* Also disabling deleted ldap users in humhub
|
||||
*/
|
||||
public function refreshUsers()
|
||||
{
|
||||
|
||||
$ldapUserIds = array();
|
||||
|
||||
try {
|
||||
$items = $this->ldap->search(Setting::Get('userFilter', 'authentication_ldap'), Setting::Get('baseDn', 'authentication_ldap'), \Zend\Ldap\Ldap::SEARCH_SCOPE_SUB);
|
||||
foreach ($items as $item) {
|
||||
$node = \Zend\Ldap\Node::fromArray($item);
|
||||
$user = $this->handleLdapUser($node);
|
||||
|
||||
if ($user != null)
|
||||
$ldapUserIds[] = $user->id;
|
||||
}
|
||||
|
||||
|
||||
foreach (User::find()->where(['auth_mode' => User::AUTH_MODE_LDAP])->andWhere(['!=', 'status', User::STATUS_DISABLED])->each() as $user) {
|
||||
if (!in_array($user->id, $ldapUserIds)) {
|
||||
// User no longer available in ldap
|
||||
$user->status = User::STATUS_DISABLED;
|
||||
$user->save();
|
||||
Yii::warning('Disabled user ' . $user->username . ' (' . $user->id . ') - Not found in LDAP!');
|
||||
}
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
Yii::error($ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates or creates user by given ldap node
|
||||
*
|
||||
* @param Zend_Ldap_Node $node
|
||||
* @return User User Object
|
||||
*/
|
||||
public function handleLdapUser($node)
|
||||
{
|
||||
|
||||
$usernameAttribute = Setting::Get('usernameAttribute', 'authentication_ldap');
|
||||
if ($usernameAttribute == '') {
|
||||
$usernameAttribute = 'sAMAccountName';
|
||||
}
|
||||
|
||||
$emailAttribute = Setting::Get('emailAttribute', 'authentication_ldap');
|
||||
if ($emailAttribute == '') {
|
||||
$emailAttribute = 'mail';
|
||||
}
|
||||
|
||||
$username = $node->getAttribute($usernameAttribute, 0);
|
||||
$email = $node->getAttribute($emailAttribute, 0);
|
||||
$guid = $this->binToStrGuid($node->getAttribute('objectGUID', 0));
|
||||
|
||||
// Try to load User:
|
||||
$userChanged = false;
|
||||
$user = null;
|
||||
if ($guid != "") {
|
||||
$user = User::findOne(array('guid' => $guid, 'auth_mode' => User::AUTH_MODE_LDAP));
|
||||
} else {
|
||||
// Fallback use e-mail
|
||||
$user = User::findOne(array('email' => $email, 'auth_mode' => User::AUTH_MODE_LDAP));
|
||||
}
|
||||
|
||||
if ($user === null) {
|
||||
$user = new User();
|
||||
if ($guid != "") {
|
||||
$user->guid = $guid;
|
||||
}
|
||||
$user->status = User::STATUS_ENABLED;
|
||||
$user->auth_mode = User::AUTH_MODE_LDAP;
|
||||
$user->group_id = 1;
|
||||
|
||||
Yii::info('Create ldap user ' . $username . '!');
|
||||
}
|
||||
|
||||
// Update Users Field
|
||||
if ($user->username != $username) {
|
||||
$userChanged = true;
|
||||
$user->username = $username;
|
||||
}
|
||||
if ($user->email != $email) {
|
||||
$userChanged = true;
|
||||
$user->email = $email;
|
||||
}
|
||||
|
||||
if ($user->validate()) {
|
||||
|
||||
// Only Save user when something is changed
|
||||
if ($userChanged || $user->isNewRecord) {
|
||||
$user->save();
|
||||
}
|
||||
|
||||
// Update Profile Fields
|
||||
foreach (ProfileField::find()->andWhere(['!=', 'ldap_attribute', ''])->all() as $profileField) {
|
||||
$ldapAttribute = $profileField->ldap_attribute;
|
||||
$profileFieldName = $profileField->internal_name;
|
||||
$user->profile->$profileFieldName = $node->getAttribute($ldapAttribute, 0);
|
||||
}
|
||||
|
||||
if ($user->profile->validate() && $user->profile->save()) {
|
||||
$this->trigger(self::EVENT_UPDATE_USER, new ParameterEvent(['user' => $user, 'node' => $node]));
|
||||
} else {
|
||||
Yii::error('Could not create or update ldap user profile! (' . print_r($user->profile->getErrors(), true) . ")");
|
||||
}
|
||||
} else {
|
||||
Yii::error('Could not create or update ldap user '.$user->username.'! (' . print_r($user->getErrors(), true) . ")");
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts LDAP Binary GUID to Ascii
|
||||
*
|
||||
* @param type $object_guid
|
||||
* @return type
|
||||
*/
|
||||
private function binToStrGuid($object_guid)
|
||||
{
|
||||
$hex_guid = bin2hex($object_guid);
|
||||
|
||||
if ($hex_guid == "")
|
||||
return "";
|
||||
|
||||
$hex_guid_to_guid_str = '';
|
||||
for ($k = 1; $k <= 4; ++$k) {
|
||||
$hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2);
|
||||
}
|
||||
$hex_guid_to_guid_str .= '-';
|
||||
for ($k = 1; $k <= 2; ++$k) {
|
||||
$hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2);
|
||||
}
|
||||
$hex_guid_to_guid_str .= '-';
|
||||
for ($k = 1; $k <= 2; ++$k) {
|
||||
$hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2);
|
||||
}
|
||||
$hex_guid_to_guid_str .= '-' . substr($hex_guid, 16, 4);
|
||||
$hex_guid_to_guid_str .= '-' . substr($hex_guid, 20);
|
||||
|
||||
return strtolower($hex_guid_to_guid_str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if LDAP is supported
|
||||
*/
|
||||
public static function isAvailable()
|
||||
{
|
||||
if (!class_exists('Zend\Ldap\Ldap')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!function_exists('ldap_bind')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use yii\db\Schema;
|
||||
use yii\db\Migration;
|
||||
|
||||
class m151226_164234_authclient extends Migration
|
||||
{
|
||||
|
||||
public function up()
|
||||
{
|
||||
$this->createTable('user_auth', array(
|
||||
'id' => $this->primaryKey(),
|
||||
'user_id' => $this->integer()->notNull(),
|
||||
'source' => $this->string(255)->notNull(),
|
||||
'source_id' => $this->string(255)->notNull(),
|
||||
));
|
||||
$this->addForeignKey('fk_user_id', 'user_auth', 'user_id', 'user', 'id', 'CASCADE', 'CASCADE');
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
echo "m151226_164234_authclient cannot be reverted.\n";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
// Use safeUp/safeDown to run migration code within a transaction
|
||||
public function safeUp()
|
||||
{
|
||||
}
|
||||
|
||||
public function safeDown()
|
||||
{
|
||||
}
|
||||
*/
|
||||
}
|
59
protected/humhub/modules/user/models/Auth.php
Normal file
59
protected/humhub/modules/user/models/Auth.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace humhub\modules\user\models;
|
||||
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* This is the model class for table "user_auth".
|
||||
*
|
||||
* @property integer $id
|
||||
* @property integer $user_id
|
||||
* @property string $source
|
||||
* @property string $source_id
|
||||
*
|
||||
* @property User $user
|
||||
*/
|
||||
class Auth extends \yii\db\ActiveRecord
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function tableName()
|
||||
{
|
||||
return 'user_auth';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['user_id', 'source', 'source_id'], 'required'],
|
||||
[['user_id'], 'integer'],
|
||||
[['source', 'source_id'], 'string', 'max' => 255]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function attributeLabels()
|
||||
{
|
||||
return [
|
||||
'id' => 'ID',
|
||||
'user_id' => 'User ID',
|
||||
'source' => 'Source',
|
||||
'source_id' => 'Source ID',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \yii\db\ActiveQuery
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->hasOne(User::className(), ['id' => 'user_id']);
|
||||
}
|
||||
}
|
@ -187,4 +187,25 @@ class Group extends \yii\db\ActiveRecord
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns groups which are available in user registration
|
||||
*/
|
||||
public static function getRegistrationGroups()
|
||||
{
|
||||
$groups = [];
|
||||
|
||||
$defaultGroup = \humhub\models\Setting::Get('defaultUserGroup', 'authentication_internal');
|
||||
if ($defaultGroup != '') {
|
||||
$group = self::findOne(['id' => $defaultGroup]);
|
||||
if ($group !== null) {
|
||||
$groups[] = $group;
|
||||
return $groups;
|
||||
}
|
||||
} else {
|
||||
$groups = self::find()->orderBy('name ASC')->all();
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ class Invite extends \yii\db\ActiveRecord
|
||||
|
||||
const SOURCE_SELF = "self";
|
||||
const SOURCE_INVITE = "invite";
|
||||
const TOKEN_LENGTH = 12;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
@ -48,50 +49,61 @@ class Invite extends \yii\db\ActiveRecord
|
||||
{
|
||||
return [
|
||||
[['user_originator_id', 'space_invite_id', 'created_by', 'updated_by'], 'integer'],
|
||||
[['email'], 'required'],
|
||||
[['created_at', 'updated_at', 'firstname', 'lastname'], 'safe'],
|
||||
[['email', 'source', 'token'], 'string', 'max' => 45],
|
||||
[['language'], 'string', 'max' => 10],
|
||||
[['email'], 'unique'],
|
||||
[['token'], 'unique'],
|
||||
[['firstname', 'lastname'], 'string', 'max' => 255],
|
||||
[['email', 'source', 'token'], 'string', 'max' => 45],
|
||||
[['language'], 'string', 'max' => 10],
|
||||
[['email'], 'required'],
|
||||
[['email'], 'unique'],
|
||||
[['email'], 'email'],
|
||||
[['email'], 'unique', 'targetClass' => \humhub\modules\user\models\User::className(), 'message' => Yii::t('UserModule.base', 'E-Mail is already in use! - Try forgot password.')],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function attributeLabels()
|
||||
public function scenarios()
|
||||
{
|
||||
return [
|
||||
'id' => 'ID',
|
||||
'user_originator_id' => 'User Originator ID',
|
||||
'space_invite_id' => 'Space Invite ID',
|
||||
'email' => 'Email',
|
||||
'source' => 'Source',
|
||||
'token' => 'Token',
|
||||
'created_at' => 'Created At',
|
||||
'created_by' => 'Created By',
|
||||
'updated_at' => 'Updated At',
|
||||
'updated_by' => 'Updated By',
|
||||
'language' => 'Language',
|
||||
'firstname' => 'Firstname',
|
||||
'lastname' => 'Lastname'
|
||||
];
|
||||
$scenarios = parent::scenarios();
|
||||
$scenarios['invite'] = ['email'];
|
||||
return $scenarios;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function beforeSave($insert)
|
||||
{
|
||||
if ($insert) {
|
||||
$this->token = uniqid() . mt_rand();
|
||||
if ($insert && $this->token == '') {
|
||||
$this->token = Yii::$app->security->generateRandomString(self::TOKEN_LENGTH);
|
||||
}
|
||||
|
||||
return parent::beforeSave($insert);
|
||||
}
|
||||
|
||||
public function selfInvite()
|
||||
{
|
||||
$this->source = self::SOURCE_SELF;
|
||||
$this->language = Yii::$app->language;
|
||||
|
||||
// Delete existing invite for e-mail - but reuse token
|
||||
$existingInvite = Invite::findOne(['email' => $this->email]);
|
||||
if ($existingInvite !== null) {
|
||||
$this->token = $existingInvite->token;
|
||||
$existingInvite->delete();
|
||||
}
|
||||
|
||||
if ($this->allowSelfInvite() && $this->validate() && $this->save()) {
|
||||
$this->sendInviteMail();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the invite e-mail
|
||||
*
|
||||
*/
|
||||
public function sendInviteMail()
|
||||
{
|
||||
@ -128,14 +140,34 @@ class Invite extends \yii\db\ActiveRecord
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return user which triggered this invite
|
||||
*
|
||||
* @return \yii\db\ActiveQuery
|
||||
*/
|
||||
public function getOriginator()
|
||||
{
|
||||
return $this->hasOne(\humhub\modules\user\models\User::className(), ['id' => 'user_originator_id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return space which is involved in this invite
|
||||
*
|
||||
* @return \yii\db\ActiveQuery
|
||||
*/
|
||||
public function getSpace()
|
||||
{
|
||||
return $this->hasOne(\humhub\modules\space\models\Space::className(), ['id' => 'space_invite_id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow users to invite themself
|
||||
*
|
||||
* @return boolean allow self invite
|
||||
*/
|
||||
public function allowSelfInvite()
|
||||
{
|
||||
return (\humhub\models\Setting::Get('anonymousRegistration', 'authentication_internal'));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -160,10 +160,14 @@ class Profile extends \yii\db\ActiveRecord
|
||||
*/
|
||||
public function getFormDefinition()
|
||||
{
|
||||
|
||||
$definition = array();
|
||||
$definition['elements'] = array();
|
||||
|
||||
$syncAttributes = [];
|
||||
if ($this->user !== null) {
|
||||
$syncAttributes = \humhub\modules\user\authclient\AuthClientHelpers::getSyncAttributesByUser($this->user);
|
||||
}
|
||||
|
||||
foreach (ProfileFieldCategory::find()->orderBy('sort_order')->all() as $profileFieldCategory) {
|
||||
|
||||
$category = array(
|
||||
@ -190,7 +194,7 @@ class Profile extends \yii\db\ActiveRecord
|
||||
}
|
||||
|
||||
// Dont allow editing of ldap syned fields - will be overwritten on next ldap sync.
|
||||
if ($this->user !== null && $this->user->auth_mode == User::AUTH_MODE_LDAP && $profileField->ldap_attribute != "") {
|
||||
if (in_array($profileField->internal_name, $syncAttributes)) {
|
||||
$profileField->editable = false;
|
||||
}
|
||||
|
||||
|
@ -41,12 +41,6 @@ use humhub\modules\user\components\ActiveQueryUser;
|
||||
class User extends ContentContainerActiveRecord implements \yii\web\IdentityInterface, \humhub\modules\search\interfaces\Searchable
|
||||
{
|
||||
|
||||
/**
|
||||
* Authentication Modes
|
||||
*/
|
||||
const AUTH_MODE_LDAP = "ldap";
|
||||
const AUTH_MODE_LOCAL = "local";
|
||||
|
||||
/**
|
||||
* User Status Flags
|
||||
*/
|
||||
@ -90,10 +84,11 @@ class User extends ContentContainerActiveRecord implements \yii\web\IdentityInte
|
||||
[['guid'], 'string', 'max' => 45],
|
||||
[['username'], 'string', 'max' => 25, 'min' => Yii::$app->params['user']['minUsernameLength']],
|
||||
[['time_zone'], 'in', 'range' => \DateTimeZone::listIdentifiers()],
|
||||
[['email'], 'string', 'max' => 100],
|
||||
[['auth_mode'], 'string', 'max' => 10],
|
||||
[['language'], 'string', 'max' => 5],
|
||||
[['email'], 'unique'],
|
||||
[['email'], 'email'],
|
||||
[['email'], 'string', 'max' => 100],
|
||||
[['username'], 'unique'],
|
||||
[['guid'], 'unique'],
|
||||
[['wall_id'], 'unique']
|
||||
@ -122,8 +117,9 @@ class User extends ContentContainerActiveRecord implements \yii\web\IdentityInte
|
||||
{
|
||||
$scenarios = parent::scenarios();
|
||||
$scenarios['login'] = ['username', 'password'];
|
||||
$scenarios['editAdmin'] = ['username', 'email', 'group_id', 'super_admin', 'auth_mode', 'status'];
|
||||
$scenarios['registration'] = ['username', 'email', 'group_id'];
|
||||
$scenarios['editAdmin'] = ['username', 'email', 'group_id', 'super_admin', 'status'];
|
||||
$scenarios['registration_email'] = ['username', 'email', 'group_id'];
|
||||
$scenarios['registration'] = ['username', 'group_id'];
|
||||
return $scenarios;
|
||||
}
|
||||
|
||||
@ -261,11 +257,11 @@ class User extends ContentContainerActiveRecord implements \yii\web\IdentityInte
|
||||
*/
|
||||
public function beforeSave($insert)
|
||||
{
|
||||
|
||||
if ($insert) {
|
||||
|
||||
if ($this->auth_mode == "") {
|
||||
$this->auth_mode = self::AUTH_MODE_LOCAL;
|
||||
if ($this->auth_mode == '') {
|
||||
$passwordAuth = new \humhub\modules\user\authclient\Password();
|
||||
$this->auth_mode = $passwordAuth->getId();
|
||||
}
|
||||
|
||||
if (\humhub\models\Setting::Get('allowGuestAccess', 'authentication_internal')) {
|
||||
@ -277,13 +273,8 @@ class User extends ContentContainerActiveRecord implements \yii\web\IdentityInte
|
||||
|
||||
$this->last_activity_email = new \yii\db\Expression('NOW()');
|
||||
|
||||
// Set Status
|
||||
if ($this->status == "") {
|
||||
if (\humhub\models\Setting::Get('needApproval', 'authentication_internal')) {
|
||||
$this->status = User::STATUS_NEED_APPROVAL;
|
||||
} else {
|
||||
$this->status = User::STATUS_ENABLED;
|
||||
}
|
||||
$this->status = self::STATUS_ENABLED;
|
||||
}
|
||||
|
||||
if ((\humhub\models\Setting::Get('defaultUserGroup', 'authentication_internal'))) {
|
||||
@ -296,8 +287,18 @@ class User extends ContentContainerActiveRecord implements \yii\web\IdentityInte
|
||||
}
|
||||
|
||||
if ($this->group_id == "") {
|
||||
// Try autoset group
|
||||
$availableGroups = Group::getRegistrationGroups();
|
||||
$defaultUserGroup = \humhub\models\Setting::Get('defaultUserGroup', 'authentication_internal');
|
||||
if ($defaultUserGroup != '') {
|
||||
$this->group_id = $defaultUserGroup;
|
||||
} elseif (isset($availableGroups[0])) {
|
||||
// Fallback to first available group
|
||||
$this->group_id = $availableGroups[0]->id;
|
||||
} else {
|
||||
throw new \yii\base\Exception("Could not save user without group!");
|
||||
}
|
||||
}
|
||||
|
||||
return parent::beforeSave($insert);
|
||||
}
|
||||
@ -525,4 +526,12 @@ class User extends ContentContainerActiveRecord implements \yii\web\IdentityInte
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return type
|
||||
*/
|
||||
public function getAuths()
|
||||
{
|
||||
return $this->hasMany(\humhub\modules\user\models\Auth::className(), ['user_id' => 'id']);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,120 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace humhub\modules\user\models\forms;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Model;
|
||||
use humhub\modules\user\models\User;
|
||||
use humhub\modules\user\libs\Ldap;
|
||||
use humhub\models\Setting;
|
||||
use yii\db\Expression;
|
||||
|
||||
/**
|
||||
* LoginForm is the model behind the login form.
|
||||
*/
|
||||
class AccountLogin extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string user's username or email address
|
||||
*/
|
||||
public $username;
|
||||
public $password;
|
||||
public $rememberMe = true;
|
||||
private $_user = false;
|
||||
|
||||
/**
|
||||
* @return array the validation rules.
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['username', 'password'], 'required'],
|
||||
['rememberMe', 'boolean'],
|
||||
['password', 'validatePassword'],
|
||||
['username', 'validateUser'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the password.
|
||||
* This method serves as the inline validation for password.
|
||||
*
|
||||
* @param string $attribute the attribute currently being validated
|
||||
* @param array $params the additional name-value pairs given in the rule
|
||||
*/
|
||||
public function validatePassword($attribute, $params)
|
||||
{
|
||||
if (!$this->hasErrors()) {
|
||||
$user = $this->getUser();
|
||||
if ($user !== null) {
|
||||
if ($user->auth_mode === User::AUTH_MODE_LOCAL && $user->currentPassword->validatePassword($this->password)) {
|
||||
return;
|
||||
} elseif ($user->auth_mode === User::AUTH_MODE_LDAP && Ldap::isAvailable() && Ldap::getInstance()->authenticate($user->username, $this->password)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->addError($attribute, 'Incorrect username or password.');
|
||||
}
|
||||
}
|
||||
|
||||
public function validateUser($attribute, $params)
|
||||
{
|
||||
if (!$this->hasErrors()) {
|
||||
$user = $this->getUser();
|
||||
if ($user !== null) {
|
||||
if ($user->status == User::STATUS_DISABLED) {
|
||||
$this->addError($attribute, 'Your account is disabled!');
|
||||
}
|
||||
if ($user->status == User::STATUS_NEED_APPROVAL) {
|
||||
$this->addError($attribute, 'Your account is not approved yet!');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs in a user using the provided username and password.
|
||||
* @return boolean whether the user is logged in successfully
|
||||
*/
|
||||
public function login()
|
||||
{
|
||||
if ($this->validate() && Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0)) {
|
||||
$this->_user->last_login = new Expression('NOW()');
|
||||
$this->_user->save();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds user by [[username]]
|
||||
*
|
||||
* @return User|null
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
if ($this->_user === false) {
|
||||
$this->_user = User::find()->where(['username' => $this->username])->orWhere(['email' => $this->username])->one();
|
||||
|
||||
// Could not found user -> lookup in LDAP
|
||||
if ($this->_user === null && Ldap::isAvailable() && Setting::Get('enabled', 'authentication_ldap')) {
|
||||
|
||||
try {
|
||||
// Try load/create LDAP user
|
||||
$usernameDn = Ldap::getInstance()->ldap->getCanonicalAccountName($this->username, \Zend\Ldap\Ldap::ACCTNAME_FORM_DN);
|
||||
Ldap::getInstance()->handleLdapUser(Ldap::getInstance()->ldap->getNode($usernameDn));
|
||||
|
||||
// Check if user is availble now
|
||||
$this->_user = User::find()->where(['username' => $this->username])->orWhere(['email' => $this->username])->one();
|
||||
} catch (\Zend\Ldap\Exception\LdapException $ex) {
|
||||
// User not found
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_user;
|
||||
}
|
||||
|
||||
}
|
@ -52,7 +52,9 @@ class AccountRecoverPassword extends \yii\base\Model
|
||||
|
||||
if ($this->email != "") {
|
||||
$user = User::findOne(array('email' => $this->email));
|
||||
if ($user != null && $user->auth_mode != "local") {
|
||||
$passwordAuth = new \humhub\modules\user\authclient\Password();
|
||||
|
||||
if ($user != null && $user->auth_mode !== $passwordAuth->getId()) {
|
||||
$this->addError($attribute, Yii::t('UserModule.forms_AccountRecoverPasswordForm', Yii::t('UserModule.forms_AccountRecoverPasswordForm', "Password recovery is not possible on your account type!")));
|
||||
}
|
||||
}
|
||||
|
@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace humhub\modules\user\models\forms;
|
||||
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* Register Form just collects users e-mail and sends an invite
|
||||
*
|
||||
* @package humhub.modules_core.user.forms
|
||||
* @since 0.5
|
||||
* @author Luke
|
||||
*/
|
||||
class AccountRegister extends \yii\base\Model
|
||||
{
|
||||
|
||||
public $email;
|
||||
|
||||
/**
|
||||
* Declares the validation rules.
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return array(
|
||||
[['email'], 'required'],
|
||||
[['email'], 'email'],
|
||||
[['email'], 'unique', 'targetClass' => \humhub\modules\user\models\User::className(), 'message' => Yii::t('UserModule.forms_AccountRegisterForm', 'E-Mail is already in use! - Try forgot password.')],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares customized attribute labels.
|
||||
* If not declared here, an attribute would have a label that is
|
||||
* the same as its name with the first letter in upper case.
|
||||
*/
|
||||
public function attributeLabels()
|
||||
{
|
||||
return array(
|
||||
'email' => Yii::t('UserModule.forms_AccountRegisterForm', 'E-Mail'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
92
protected/humhub/modules/user/models/forms/Login.php
Normal file
92
protected/humhub/modules/user/models/forms/Login.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace humhub\modules\user\models\forms;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Model;
|
||||
use humhub\modules\user\authclient\BaseFormAuth;
|
||||
use humhub\modules\user\models\User;
|
||||
use humhub\modules\user\libs\Ldap;
|
||||
use humhub\models\Setting;
|
||||
use yii\db\Expression;
|
||||
|
||||
/**
|
||||
* LoginForm is the model behind the login form.
|
||||
*/
|
||||
class Login extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string user's username or email address
|
||||
*/
|
||||
public $username;
|
||||
|
||||
/**
|
||||
* @var string password
|
||||
*/
|
||||
public $password;
|
||||
|
||||
/**
|
||||
* @var boolean remember user
|
||||
*/
|
||||
public $rememberMe = false;
|
||||
|
||||
/**
|
||||
* @var \yii\authclient\BaseClient auth client used to authenticate
|
||||
*/
|
||||
public $authClient = null;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['username', 'password'], 'required'],
|
||||
['rememberMe', 'boolean'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->rememberMe = Yii::$app->getModule('user')->loginRememberMeDefault;
|
||||
|
||||
parent::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation
|
||||
*/
|
||||
public function afterValidate()
|
||||
{
|
||||
$user = null;
|
||||
|
||||
// Loop over enabled authclients
|
||||
foreach (Yii::$app->authClientCollection->getClients() as $authClient) {
|
||||
if ($authClient instanceof BaseFormAuth) {
|
||||
$authClient->login = $this;
|
||||
if ($authClient->auth()) {
|
||||
$this->authClient = $authClient;
|
||||
|
||||
// Delete password after successful auth
|
||||
$this->password = "";
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($user === null) {
|
||||
$this->addError('password', 'User or Password incorrect.');
|
||||
}
|
||||
|
||||
// Delete current password value
|
||||
$this->password = "";
|
||||
|
||||
parent::afterValidate();
|
||||
}
|
||||
|
||||
}
|
291
protected/humhub/modules/user/models/forms/Registration.php
Normal file
291
protected/humhub/modules/user/models/forms/Registration.php
Normal file
@ -0,0 +1,291 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\modules\user\models\forms;
|
||||
|
||||
use Yii;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use humhub\compat\HForm;
|
||||
use humhub\modules\user\models\User;
|
||||
use humhub\modules\user\models\Profile;
|
||||
use humhub\modules\user\models\Password;
|
||||
|
||||
/**
|
||||
* Description of Registration
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
class Registration extends HForm
|
||||
{
|
||||
|
||||
/**
|
||||
* @var boolean show password creation form
|
||||
*/
|
||||
public $enablePasswordForm = true;
|
||||
|
||||
/**
|
||||
* @var boolean show e-mail field
|
||||
*/
|
||||
public $enableEmailField = false;
|
||||
|
||||
/**
|
||||
* @var boolean|null require user approval by admin after registration.
|
||||
*/
|
||||
public $enableUserApproval = false;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
private $_user = null;
|
||||
|
||||
/**
|
||||
* @var Password
|
||||
*/
|
||||
private $_password = null;
|
||||
|
||||
/**
|
||||
* @var Profile
|
||||
*/
|
||||
private $_profile = null;
|
||||
|
||||
public function init()
|
||||
{
|
||||
if (\humhub\models\Setting::Get('needApproval', 'authentication_internal')) {
|
||||
$this->enableUserApproval = true;
|
||||
} else {
|
||||
$this->enableUserApproval = false;
|
||||
}
|
||||
|
||||
return parent::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function render($form)
|
||||
{
|
||||
$this->setFormDefinition();
|
||||
return parent::render($form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds HForm Definition to automatically build form output
|
||||
*/
|
||||
protected function setFormDefinition()
|
||||
{
|
||||
$this->definition = [];
|
||||
$this->definition['elements'] = [];
|
||||
$this->definition['elements']['User'] = $this->getUserFormDefinition();
|
||||
if ($this->enablePasswordForm) {
|
||||
$this->definition['elements']['Password'] = $this->getPasswordFormDefinition();
|
||||
}
|
||||
$this->definition['elements']['Profile'] = array_merge(array('type' => 'form'), $this->getProfile()->getFormDefinition());
|
||||
$this->definition['buttons'] = array(
|
||||
'save' => array(
|
||||
'type' => 'submit',
|
||||
'class' => 'btn btn-primary',
|
||||
'label' => Yii::t('UserModule.controllers_AuthController', 'Create account'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create User Model form fields required for registration
|
||||
*
|
||||
* @return array form definition
|
||||
*/
|
||||
protected function getUserFormDefinition()
|
||||
{
|
||||
$groupModels = \humhub\modules\user\models\Group::find()->orderBy('name ASC')->all();
|
||||
$defaultUserGroup = \humhub\models\Setting::Get('defaultUserGroup', 'authentication_internal');
|
||||
$groupFieldType = "dropdownlist";
|
||||
if ($defaultUserGroup != "") {
|
||||
$groupFieldType = "hidden";
|
||||
} else if (count($groupModels) == 1) {
|
||||
$groupFieldType = "hidden";
|
||||
$defaultUserGroup = $groupModels[0]->id;
|
||||
}
|
||||
if ($groupFieldType == 'hidden') {
|
||||
$this->getUser()->group_id = $defaultUserGroup;
|
||||
}
|
||||
|
||||
$form = array(
|
||||
'type' => 'form',
|
||||
'title' => Yii::t('UserModule.controllers_AuthController', 'Account'),
|
||||
'elements' => [],
|
||||
);
|
||||
|
||||
$form['elements']['username'] = [
|
||||
'type' => 'text',
|
||||
'class' => 'form-control',
|
||||
'maxlength' => 25,
|
||||
];
|
||||
if ($this->enableEmailField) {
|
||||
$form['elements']['email'] = [
|
||||
'type' => 'text',
|
||||
'class' => 'form-control',
|
||||
];
|
||||
}
|
||||
$form['elements']['group_id'] = [
|
||||
'type' => $groupFieldType,
|
||||
'class' => 'form-control',
|
||||
'items' => ArrayHelper::map($groupModels, 'id', 'name'),
|
||||
'value' => $defaultUserGroup,
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Password Model form fields required for registration
|
||||
*
|
||||
* @return array form definition
|
||||
*/
|
||||
protected function getPasswordFormDefinition()
|
||||
{
|
||||
return array(
|
||||
'type' => 'form',
|
||||
'elements' => array(
|
||||
'newPassword' => array(
|
||||
'type' => 'password',
|
||||
'class' => 'form-control',
|
||||
'maxlength' => 255,
|
||||
),
|
||||
'newPasswordConfirm' => array(
|
||||
'type' => 'password',
|
||||
'class' => 'form-control',
|
||||
'maxlength' => 255,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set models User, Profile and Password to Form
|
||||
*/
|
||||
protected function setModels()
|
||||
{
|
||||
// Set Models
|
||||
$this->models['User'] = $this->getUser();
|
||||
$this->models['Profile'] = $this->getProfile();
|
||||
if ($this->enablePasswordForm) {
|
||||
$this->models['Password'] = $this->getPassword();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function validate()
|
||||
{
|
||||
|
||||
// Ensure Models
|
||||
$this->setModels();
|
||||
|
||||
return parent::validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function submitted($buttonName = "")
|
||||
{
|
||||
// Ensure Models
|
||||
$this->setModels();
|
||||
|
||||
return parent::submitted($buttonName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers users
|
||||
*
|
||||
* @return boolean state
|
||||
*/
|
||||
public function register(\yii\authclient\ClientInterface $authClient = null)
|
||||
{
|
||||
$this->models['User']->language = Yii::$app->language;
|
||||
if ($this->enableUserApproval) {
|
||||
$this->models['User']->status = User::STATUS_NEED_APPROVAL;
|
||||
}
|
||||
|
||||
if ($this->models['User']->save()) {
|
||||
|
||||
// Save User Profile
|
||||
$this->models['Profile']->user_id = $this->models['User']->id;
|
||||
$this->models['Profile']->save();
|
||||
|
||||
if ($this->enablePasswordForm) {
|
||||
// Save User Password
|
||||
$this->models['Password']->user_id = $this->models['User']->id;
|
||||
$this->models['Password']->setPassword($this->models['Password']->newPassword);
|
||||
$this->models['Password']->save();
|
||||
}
|
||||
|
||||
if ($authClient !== null) {
|
||||
\humhub\modules\user\authclient\AuthClientHelpers::storeAuthClientForUser($authClient, $this->models['User']);
|
||||
$authClient->trigger(\humhub\modules\user\authclient\BaseClient::EVENT_CREATE_USER, new \yii\web\UserEvent(['identity' => $this->models['User']]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns User model
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
if ($this->_user === null) {
|
||||
$this->_user = new User();
|
||||
if ($this->enableEmailField) {
|
||||
$this->_user->scenario = 'registration_email';
|
||||
} else {
|
||||
$this->_user->scenario = 'registration';
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Profile model
|
||||
*
|
||||
* @return Profile
|
||||
*/
|
||||
public function getProfile()
|
||||
{
|
||||
if ($this->_profile === null) {
|
||||
$this->_profile = $this->getUser()->profile;
|
||||
$this->_profile->scenario = 'registration';
|
||||
}
|
||||
|
||||
return $this->_profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Password model
|
||||
*
|
||||
* @return Password
|
||||
*/
|
||||
public function getPassword()
|
||||
{
|
||||
if ($this->_password === null) {
|
||||
$this->_password = new Password();
|
||||
$this->_password->scenario = 'registration';
|
||||
}
|
||||
|
||||
return $this->_password;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use \yii\bootstrap\Html;
|
||||
use yii\helpers\Url;
|
||||
use yii\widgets\ActiveForm;
|
||||
use \humhub\models\Setting;
|
||||
?>
|
||||
|
||||
<div class="panel-heading">
|
||||
<?php echo Yii::t('UserModule.base', '<strong>Connected</strong> accounts'); ?>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<?= humhub\modules\user\widgets\AccountSettingsMenu::widget(); ?>
|
||||
<br />
|
||||
<p />
|
||||
|
||||
<?php foreach ($authClients as $client) : ?>
|
||||
<div class="media">
|
||||
<div class="media-body">
|
||||
<h4 class="media-heading"><strong><?php echo $client->getTitle(); ?></strong></h4>
|
||||
<?php if ($client->getId() == $currentAuthProviderId): ?>
|
||||
<?php echo Html::a(Yii::t('UserModule.base', 'Current account'), '#', ['class' => 'btn btn-default pull-right', 'data-method' => 'POST', 'disabled' => 'disabled']); ?>
|
||||
<?php elseif (in_array($client->getId(), $activeAuthClientIds)) : ?>
|
||||
<?php echo Html::a(Yii::t('UserModule.base', 'Disconnect account'), ['connected-accounts', 'disconnect' => $client->getId()], ['class' => 'btn btn-danger pull-right', 'data-method' => 'POST']); ?>
|
||||
<?php else: ?>
|
||||
<?php echo Html::a(Yii::t('UserModule.base', 'Connect account'), Url::to(['/user/auth/external-auth', 'authclient' => $client->getId()]), ['class' => 'btn btn-success pull-right']); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php endforeach; ?>
|
||||
|
||||
|
||||
</div>
|
@ -9,6 +9,9 @@ use \humhub\models\Setting;
|
||||
<?php echo Yii::t('UserModule.views_account_editSettings', '<strong>User</strong> settings'); ?>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<?= humhub\modules\user\widgets\AccountSettingsMenu::widget(); ?>
|
||||
<br />
|
||||
<p />
|
||||
<?php $form = ActiveForm::begin(['id' => 'basic-settings-form']); ?>
|
||||
|
||||
<?php echo $form->field($model, 'tags'); ?>
|
||||
@ -19,10 +22,12 @@ use \humhub\models\Setting;
|
||||
|
||||
<?php if (Setting::Get('allowGuestAccess', 'authentication_internal')): ?>
|
||||
|
||||
<?php echo $form->field($model, 'visibility')->dropdownList([
|
||||
<?php
|
||||
echo $form->field($model, 'visibility')->dropdownList([
|
||||
1 => Yii::t('UserModule.views_account_editSettings', 'Registered users only'),
|
||||
2 => Yii::t('UserModule.views_account_editSettings', 'Visible for all (also unregistered users)'),
|
||||
]); ?>
|
||||
]);
|
||||
?>
|
||||
|
||||
|
||||
<?php endif; ?>
|
||||
|
@ -18,6 +18,13 @@ $this->pageTitle = Yii::t('UserModule.views_auth_login', 'Login');
|
||||
|
||||
<div class="panel-body">
|
||||
|
||||
<?php if (Yii::$app->session->hasFlash('error')): ?>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<?= Yii::$app->session->getFlash('error') ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
<?php $form = ActiveForm::begin(['id' => 'account-login-form']); ?>
|
||||
<p><?php echo Yii::t('UserModule.views_auth_login', "If you're already a member, please login with your username/email and password."); ?></p>
|
||||
<?php echo $form->field($model, 'username')->textInput(['id' => 'login_username', 'placeholder' => Yii::t('UserModule.views_auth_login', 'username or email')]); ?>
|
||||
@ -39,6 +46,7 @@ $this->pageTitle = Yii::t('UserModule.views_auth_login', 'Login');
|
||||
</div>
|
||||
|
||||
<?php ActiveForm::end(); ?>
|
||||
<?= humhub\modules\user\widgets\AuthChoice::widget([]) ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -56,9 +64,8 @@ $this->pageTitle = Yii::t('UserModule.views_auth_login', 'Login');
|
||||
|
||||
<p><?php echo Yii::t('UserModule.views_auth_login', "Don't have an account? Join the network by entering your e-mail address."); ?></p>
|
||||
|
||||
<?php $form = ActiveForm::begin(['id' => 'account-register-form']); ?>
|
||||
|
||||
<?php echo $form->field($registerModel, 'email')->textInput(['id' => 'register-email', 'placeholder' => Yii::t('UserModule.views_auth_login', 'email')]); ?>
|
||||
<?php $form = ActiveForm::begin(['id' => 'invite-form']); ?>
|
||||
<?php echo $form->field($invite, 'email')->textInput(['id' => 'register-email', 'placeholder' => Yii::t('UserModule.views_auth_login', 'email')]); ?>
|
||||
<hr>
|
||||
<?php echo CHtml::submitButton(Yii::t('UserModule.views_auth_login', 'Register'), array('class' => 'btn btn-primary')); ?>
|
||||
|
||||
@ -86,7 +93,7 @@ $this->pageTitle = Yii::t('UserModule.views_auth_login', 'Login');
|
||||
<?php } ?>
|
||||
|
||||
// Shake panel after wrong validation
|
||||
<?php if ($registerModel->hasErrors()) { ?>
|
||||
<?php if ($invite->hasErrors()) { ?>
|
||||
$('#register-form').removeClass('bounceInLeft');
|
||||
$('#register-form').addClass('shake');
|
||||
$('#login-form').removeClass('bounceIn');
|
||||
|
@ -16,11 +16,11 @@ use yii\helpers\Url;
|
||||
<?php if ($canRegister) : ?>
|
||||
<div class="text-center">
|
||||
<ul id="tabs" class="nav nav-tabs tabs-center" data-tabs="tabs">
|
||||
<li class="<?php echo (!isset($_POST['AccountRegister'])) ? "active" : ""; ?> tab-login"><a
|
||||
<li class="<?php echo (!isset($_POST['Invite'])) ? "active" : ""; ?> tab-login"><a
|
||||
href="#login"
|
||||
data-toggle="tab"><?php echo Yii::t('SpaceModule.views_space_invite', 'Login'); ?></a>
|
||||
</li>
|
||||
<li class="<?php echo (isset($_POST['AccountRegister'])) ? "active" : ""; ?> tab-register"><a
|
||||
<li class="<?php echo (isset($_POST['Invite'])) ? "active" : ""; ?> tab-register"><a
|
||||
href="#register"
|
||||
data-toggle="tab"><?php echo Yii::t('SpaceModule.views_space_invite', 'New user?'); ?></a>
|
||||
</li>
|
||||
@ -31,18 +31,12 @@ use yii\helpers\Url;
|
||||
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane <?php echo (!isset($_POST['AccountRegister'])) ? "active" : ""; ?>" id="login">
|
||||
<div class="tab-pane <?php echo (!isset($_POST['Invite'])) ? "active" : ""; ?>" id="login">
|
||||
|
||||
<?php $form = ActiveForm::begin(); ?>
|
||||
|
||||
|
||||
<p><?php echo Yii::t('UserModule.views_auth_login', "If you're already a member, please login with your username/email and password."); ?></p>
|
||||
|
||||
<?php echo $form->field($model, 'username')->textInput(['id' => 'login_username', 'placeholder' => Yii::t('UserModule.views_auth_login', 'username or email')]); ?>
|
||||
|
||||
<?php echo $form->field($model, 'password')->passwordInput(['id' => 'login_password', 'placeholder' => Yii::t('UserModule.views_auth_login', 'password')]); ?>
|
||||
|
||||
|
||||
<?php echo $form->field($model, 'rememberMe')->checkbox(); ?>
|
||||
<hr>
|
||||
<div class="row">
|
||||
@ -87,16 +81,17 @@ use yii\helpers\Url;
|
||||
</div>
|
||||
|
||||
<?php ActiveForm::end(); ?>
|
||||
<?= humhub\modules\user\widgets\AuthChoice::widget([]) ?>
|
||||
</div>
|
||||
|
||||
<?php if ($canRegister) : ?>
|
||||
<div class="tab-pane <?php echo (isset($_POST['AccountRegister'])) ? "active" : ""; ?>"
|
||||
<div class="tab-pane <?php echo (isset($_POST['Invite'])) ? "active" : ""; ?>"
|
||||
id="register">
|
||||
|
||||
<p><?php echo Yii::t('UserModule.views_auth_login', "Don't have an account? Join the network by entering your e-mail address."); ?></p>
|
||||
<?php $form = ActiveForm::begin(); ?>
|
||||
|
||||
<?php echo $form->field($registerModel, 'email')->textInput(['id' => 'register-email', 'placeholder' => Yii::t('UserModule.views_auth_login', 'email')]); ?>
|
||||
<?php echo $form->field($invite, 'email')->textInput(['id' => 'register-email', 'placeholder' => Yii::t('UserModule.views_auth_login', 'email')]); ?>
|
||||
<hr>
|
||||
|
||||
<?php
|
||||
|
@ -75,8 +75,8 @@ class AccountMenu extends BaseMenu
|
||||
'isActive' => (Yii::$app->controller->action->id == "emailing"),
|
||||
));
|
||||
|
||||
// LDAP users cannot change their e-mail address
|
||||
if (Yii::$app->user->getIdentity()->auth_mode != User::AUTH_MODE_LDAP) {
|
||||
|
||||
if (Yii::$app->user->canChangeEmail()) {
|
||||
$this->addItem(array(
|
||||
'label' => Yii::t('UserModule.widgets_AccountMenuWidget', 'E-Mail'),
|
||||
'icon' => '<i class="fa fa-paper-plane"></i>',
|
||||
@ -87,8 +87,7 @@ class AccountMenu extends BaseMenu
|
||||
));
|
||||
}
|
||||
|
||||
// LDAP users cannot changes password or delete account
|
||||
if (Yii::$app->user->getIdentity()->auth_mode != User::AUTH_MODE_LDAP) {
|
||||
if (Yii::$app->user->canChangePassword()) {
|
||||
$this->addItem(array(
|
||||
'label' => Yii::t('UserModule.widgets_AccountMenuWidget', 'Password'),
|
||||
'icon' => '<i class="fa fa-key"></i>',
|
||||
@ -97,6 +96,10 @@ class AccountMenu extends BaseMenu
|
||||
'sortOrder' => 500,
|
||||
'isActive' => (Yii::$app->controller->action->id == "change-password"),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
if (Yii::$app->user->canDeleteAccount()) {
|
||||
$this->addItem(array(
|
||||
'label' => Yii::t('UserModule.widgets_AccountMenuWidget', 'Delete account'),
|
||||
'icon' => '<i class="fa fa-trash-o"></i>',
|
||||
|
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\modules\user\widgets;
|
||||
|
||||
use Yii;
|
||||
use yii\helpers\Url;
|
||||
use humhub\models\Setting;
|
||||
|
||||
/**
|
||||
* Account Settings Tab Menu
|
||||
*/
|
||||
class AccountSettingsMenu extends \humhub\widgets\BaseMenu
|
||||
{
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $template = "@humhub/widgets/views/tabMenu";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
|
||||
$this->addItem(array(
|
||||
'label' => Yii::t('UserModule.base', 'Basic Settings'),
|
||||
'url' => Url::toRoute(['/user/account/edit-settings']),
|
||||
'sortOrder' => 100,
|
||||
'isActive' => (Yii::$app->controller->module && Yii::$app->controller->module->id == 'user' && Yii::$app->controller->id == 'account' && Yii::$app->controller->action->id == 'edit-settings'),
|
||||
));
|
||||
|
||||
if (count($this->getSecondoaryAuthProviders()) != 0) {
|
||||
$this->addItem(array(
|
||||
'label' => Yii::t('UserModule.base', 'Connected Accounts'),
|
||||
'url' => Url::toRoute(['/user/account/connected-accounts']),
|
||||
'sortOrder' => 200,
|
||||
'isActive' => (Yii::$app->controller->module && Yii::$app->controller->module->id == 'user' && Yii::$app->controller->id == 'account' && Yii::$app->controller->action->id == 'connected-accounts'),
|
||||
));
|
||||
}
|
||||
|
||||
parent::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns optional authclients
|
||||
*
|
||||
* @return \yii\authclient\ClientInterface[]
|
||||
*/
|
||||
protected function getSecondoaryAuthProviders()
|
||||
{
|
||||
$clients = [];
|
||||
foreach (Yii::$app->get('authClientCollection')->getClients() as $client) {
|
||||
if (!$client instanceof \humhub\modules\user\authclient\BaseFormAuth && !$client instanceof \humhub\modules\user\authclient\interfaces\PrimaryClient) {
|
||||
$clients[] = $client;
|
||||
}
|
||||
}
|
||||
|
||||
return $clients;
|
||||
}
|
||||
|
||||
}
|
83
protected/humhub/modules/user/widgets/AuthChoice.php
Normal file
83
protected/humhub/modules/user/widgets/AuthChoice.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace humhub\modules\user\widgets;
|
||||
|
||||
use yii\base\Widget;
|
||||
use Yii;
|
||||
use yii\authclient\ClientInterface;
|
||||
|
||||
class AuthChoice extends \yii\authclient\widgets\AuthChoice
|
||||
{
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $popupMode = false;
|
||||
|
||||
/**
|
||||
* @var ClientInterface[] auth providers list.
|
||||
*/
|
||||
private $_clients;
|
||||
|
||||
/**
|
||||
* @param ClientInterface[] $clients auth providers
|
||||
*/
|
||||
public function setClients(array $clients)
|
||||
{
|
||||
$this->_clients = $clients;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClientInterface[] auth providers
|
||||
*/
|
||||
public function getClients()
|
||||
{
|
||||
if ($this->_clients === null) {
|
||||
$clients = [];
|
||||
foreach ($this->defaultClients() as $client) {
|
||||
// Don't show clients which need login form
|
||||
if (!$client instanceof \humhub\modules\user\authclient\BaseFormAuth) {
|
||||
$clients[] = $client;
|
||||
}
|
||||
}
|
||||
$this->_clients = $clients;
|
||||
}
|
||||
|
||||
return $this->_clients;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function defaultBaseAuthUrl()
|
||||
{
|
||||
$baseAuthUrl = ['/user/auth/external-auth'];
|
||||
|
||||
$params = $_GET;
|
||||
unset($params[$this->clientIdGetParamName]);
|
||||
$baseAuthUrl = array_merge($baseAuthUrl, $params);
|
||||
|
||||
return $baseAuthUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the main content, which includes all external services links.
|
||||
*/
|
||||
protected function renderMainContent()
|
||||
{
|
||||
if (count($this->getClients()) != 0) {
|
||||
echo \yii\helpers\Html::tag('br');
|
||||
echo \yii\helpers\Html::tag('hr');
|
||||
echo \yii\helpers\Html::tag('strong', Yii::t('UserModule.base', 'Or login by using:'));
|
||||
echo \yii\helpers\Html::tag('p');
|
||||
parent::renderMainContent();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -19,8 +19,8 @@ class LoginPage extends BasePage
|
||||
*/
|
||||
public function login($username, $password)
|
||||
{
|
||||
$this->actor->fillField('input[name="AccountLogin[username]"]', $username);
|
||||
$this->actor->fillField('input[name="AccountLogin[password]"]', $password);
|
||||
$this->actor->fillField('input[name="Login[username]"]', $username);
|
||||
$this->actor->fillField('input[name="Login[password]"]', $password);
|
||||
$this->actor->click('login-button');
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user