diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ef93a2d7c..e31a6c021d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,11 @@ HumHub Changelog 1.13.2 (Unreleased) ------------------------- - Fix #5965: Suppress log warning 'Invalid session auth key attempted for user' - +- Fix #6084: Automatic LDAP user registration broken when not all req. attributes provided +- Fix #6104: Fix update user with not existing group +- Fix #6103: Fix null passing to parse_str() +- Fix #6108: Fix log time in the `date()` function +- Fix #6122: Fix deleting a content with empty reason 1.13.1 (January 25, 2023) ------------------------- diff --git a/protected/humhub/modules/admin/controllers/SettingController.php b/protected/humhub/modules/admin/controllers/SettingController.php index 3cd8e741c9..7675403b41 100644 --- a/protected/humhub/modules/admin/controllers/SettingController.php +++ b/protected/humhub/modules/admin/controllers/SettingController.php @@ -314,7 +314,7 @@ class SettingController extends Controller // I wish.. if ($dating) { - $dating = date('Y-m-d H:i:s', $dating->log_time); + $dating = date('Y-m-d H:i:s', (int) $dating->log_time); } else { $dating = "the begining of time"; } diff --git a/protected/humhub/modules/admin/controllers/UserController.php b/protected/humhub/modules/admin/controllers/UserController.php index f4ed16e51e..5345f0b8a7 100644 --- a/protected/humhub/modules/admin/controllers/UserController.php +++ b/protected/humhub/modules/admin/controllers/UserController.php @@ -149,7 +149,8 @@ class UserController extends Controller 'items' => UserEditForm::getGroupItems(), 'options' => [ 'data-placeholder' => Yii::t('AdminModule.user', 'Select Groups'), - 'data-placeholder-more' => Yii::t('AdminModule.user', 'Add Groups...') + 'data-placeholder-more' => Yii::t('AdminModule.user', 'Add Groups...'), + 'data-tags' => 'false' ], 'maxSelection' => 250, 'isVisible' => Yii::$app->user->can(new ManageGroups()) diff --git a/protected/humhub/modules/admin/models/forms/UserEditForm.php b/protected/humhub/modules/admin/models/forms/UserEditForm.php index ff436af763..78418f6988 100644 --- a/protected/humhub/modules/admin/models/forms/UserEditForm.php +++ b/protected/humhub/modules/admin/models/forms/UserEditForm.php @@ -2,12 +2,11 @@ namespace humhub\modules\admin\models\forms; -use humhub\libs\Html; -use humhub\modules\user\models\GroupUser; -use Yii; -use humhub\modules\user\models\User; -use humhub\modules\user\models\Group; use humhub\modules\admin\permissions\ManageGroups; +use humhub\modules\user\models\Group; +use humhub\modules\user\models\GroupUser; +use humhub\modules\user\models\User; +use Yii; /** * Description of UserEditForm @@ -18,14 +17,13 @@ class UserEditForm extends User { /** * GroupId selection array of the form. - * @var type + * @var array */ public $groupSelection; /** * Current member groups (models) of the given $user - * @var type - * + * @var Group[] */ public $currentGroups; @@ -103,19 +101,19 @@ class UserEditForm extends User if (!$this->isCurrentlyMemberOf($groupId)) { /* @var $group Group */ $group = Group::findOne(['id' => $groupId]); - if(!$group->is_admin_group || Yii::$app->user->isAdmin()) { + if ($group && (!$group->is_admin_group || Yii::$app->user->isAdmin())) { $group->addUser($this); } } } } - return parent::afterSave($insert, $changedAttributes); + parent::afterSave($insert, $changedAttributes); } /** * Checks if the given group (id or model object) is contained in the form selection - * @param integer $groupId groupId or Group model object + * @param int|Group $groupId groupId or Group model object * @return boolean true if contained in selection else false */ private function isInGroupSelection($groupId) diff --git a/protected/humhub/modules/admin/views/setting/oembed_edit.php b/protected/humhub/modules/admin/views/setting/oembed_edit.php index b84a1fba0a..51306310ef 100644 --- a/protected/humhub/modules/admin/views/setting/oembed_edit.php +++ b/protected/humhub/modules/admin/views/setting/oembed_edit.php @@ -9,7 +9,7 @@ use yii\web\View; /* @var $name string */ /** @var OEmbedProviderForm $model */ -parse_str($model->endpoint, $query); +parse_str($model->endpoint ?? '', $query); $this->registerJs(<<response->format = 'json'; - $this->forcePostRequest(); $model = Yii::$app->request->get('model'); // Due to backward compatibility we use the old delete mechanism in case a model parameter is provided - $id = (int)($model != null) ? Yii::$app->request->get('id') : Yii::$app->request->post('id'); + $id = $model ? Yii::$app->request->get('id') : Yii::$app->request->post('id'); - /* @var $contentObjs Content */ - $contentObj = ($model != null) ? Content::Get($model, $id) : Content::findOne(['id' => $id]); + /* @var $contentObj Content */ + $contentObj = $model ? Content::Get($model, $id) : Content::findOne(['id' => $id]); if (!$contentObj) { throw new NotFoundHttpException(); @@ -77,37 +70,19 @@ class ContentController extends Controller throw new ForbiddenHttpException(); } - if ($contentObj !== null) { - $form = new AdminDeleteContentForm(); + $form = new AdminDeleteContentForm(['content' => $contentObj]); + $form->load(Yii::$app->request->post()); - if ($form->load(Yii::$app->request->post())) { - if (!$form->validate()) { - throw new BadRequestHttpException(); - } - - if ($form->notify) { - $contentDeleted = ContentDeleted::instance() - ->from(Yii::$app->user->getIdentity()) - ->payload(['contentTitle' => (new ContentDeleted)->getContentPlainTextInfo($contentObj), 'reason' => $form->message]); - $contentDeleted->saveRecord($contentObj->createdBy); - - $contentDeleted->record->updateAttributes([ - 'send_web_notifications' => 1 - ]); - } - } - - $json = [ - 'success' => $contentObj->softDelete(), - 'uniqueId' => $contentObj->getUniqueId(), - 'model' => $model, - 'pk' => $id - ]; - } else { - throw new HttpException(500, Yii::t('ContentModule.base', 'Could not delete content!')); + if (!$form->delete()) { + return $this->asJson(['error' => $form->getErrorsAsString()]); } - return $json; + return $this->asJson([ + 'success' => true, + 'uniqueId' => $contentObj->getUniqueId(), + 'model' => $model, + 'pk' => $id + ]); } /** @@ -126,7 +101,7 @@ class ContentController extends Controller } if (!$contentObj->canEdit()) { - throw new HttpException(400); + throw new ForbiddenHttpException(); } return [ @@ -192,9 +167,7 @@ class ContentController extends Controller { $this->forcePostRequest(); - $post = Yii::$app->request->post(); - - $content = Content::findOne(['id' => $post['id']]); + $content = Content::findOne(['id' => Yii::$app->request->post('id')]); if (!$content) { throw new NotFoundHttpException(); @@ -204,26 +177,14 @@ class ContentController extends Controller throw new ForbiddenHttpException(); } - $form = new AdminDeleteContentForm(); + $form = new AdminDeleteContentForm(['content' => $content]); + $form->load(Yii::$app->request->post()); - if ($form->load($post)) { - if (!$form->validate()) { - throw new BadRequestHttpException(); - } - - if ($form->notify) { - $contentDeleted = ContentDeleted::instance() - ->from(Yii::$app->user->getIdentity()) - ->payload(['contentTitle' => (new ContentDeleted)->getContentPlainTextInfo($content), 'reason' => $form->message]); - $contentDeleted->saveRecord($content->createdBy); - - $contentDeleted->record->updateAttributes([ - 'send_web_notifications' => 1 - ]); - } + if (!$form->delete()) { + return $this->asJson(['error' => $form->getErrorsAsString()]); } - return $this->asJson(['success' => $content->softDelete()]); + return $this->asJson(['success' => true]); } public function actionReload($id) @@ -231,11 +192,11 @@ class ContentController extends Controller $content = Content::findOne(['id' => $id]); if (!$content) { - throw new HttpException(400, Yii::t('ContentModule.base', 'Invalid content id given!')); + throw new NotFoundHttpException(Yii::t('ContentModule.base', 'Invalid content id given!')); } if (!$content->canView()) { - throw new HttpException(403); + throw new ForbiddenHttpException(); } return StreamEntryResponse::getAsJson($content); @@ -244,10 +205,9 @@ class ContentController extends Controller /** * Switches the content visibility for the given content. * - * @param type $id content id + * @param int $id content id * @return Response * @throws Exception - * @throws HttpException * @throws InvalidConfigException * @throws \Throwable * @throws \yii\db\IntegrityException @@ -258,11 +218,11 @@ class ContentController extends Controller $content = Content::findOne(['id' => $id]); if (!$content) { - throw new HttpException(400, Yii::t('ContentModule.base', 'Invalid content id given!')); + throw new NotFoundHttpException(Yii::t('ContentModule.base', 'Invalid content id given!')); } elseif (!$content->canEdit()) { - throw new HttpException(403); + throw new ForbiddenHttpException(); } elseif ($content->isPrivate() && !$content->container->permissionManager->can(new CreatePublicContent())) { - throw new HttpException(403); + throw new ForbiddenHttpException(); } if ($content->isPrivate()) { @@ -284,7 +244,6 @@ class ContentController extends Controller * @param bool $lockComments True to lock comments, False to unlock * @return Response * @throws Exception - * @throws HttpException * @throws InvalidConfigException * @throws \Throwable * @throws \yii\db\IntegrityException @@ -295,9 +254,9 @@ class ContentController extends Controller $content = Content::findOne(['id' => $id]); if (!$content) { - throw new HttpException(400, Yii::t('ContentModule.base', 'Invalid content id given!')); + throw new NotFoundHttpException(Yii::t('ContentModule.base', 'Invalid content id given!')); } elseif (!$content->canLockComments()) { - throw new HttpException(403); + throw new ForbiddenHttpException(); } $content->locked_comments = $lockComments; @@ -313,7 +272,6 @@ class ContentController extends Controller * @param int $id Content id * @return Response * @throws Exception - * @throws HttpException * @throws InvalidConfigException * @throws \Throwable * @throws \yii\db\IntegrityException @@ -329,7 +287,6 @@ class ContentController extends Controller * @param int $id Content id * @return Response * @throws Exception - * @throws HttpException * @throws InvalidConfigException * @throws \Throwable * @throws \yii\db\IntegrityException @@ -345,7 +302,6 @@ class ContentController extends Controller * Returns JSON Output. * @return Response * @throws ForbiddenHttpException - * @throws HttpException * @throws NotFoundHttpException * @throws Exception * @throws InvalidConfigException diff --git a/protected/humhub/modules/content/models/forms/AdminDeleteContentForm.php b/protected/humhub/modules/content/models/forms/AdminDeleteContentForm.php index cc469d2899..9d9070fdad 100644 --- a/protected/humhub/modules/content/models/forms/AdminDeleteContentForm.php +++ b/protected/humhub/modules/content/models/forms/AdminDeleteContentForm.php @@ -2,8 +2,8 @@ namespace humhub\modules\content\models\forms; -use humhub\modules\content\components\ContentActiveRecord; use humhub\modules\content\models\Content; +use humhub\modules\content\notifications\ContentDeleted; use Yii; use yii\base\Model; @@ -12,6 +12,11 @@ use yii\base\Model; */ class AdminDeleteContentForm extends Model { + /** + * @var Content + */ + public $content; + /** * @var string */ @@ -43,4 +48,46 @@ class AdminDeleteContentForm extends Model 'notify' => Yii::t('CommentModule.base', 'Send a notification to author') ]; } + + public function delete(): bool + { + if (!$this->validate()) { + return false; + } + + if (!$this->notify()) { + return false; + } + + return (bool) $this->content->softDelete(); + } + + public function notify(): bool + { + if (!$this->notify) { + return true; + } + + $contentDeleted = ContentDeleted::instance() + ->from(Yii::$app->user->getIdentity()) + ->payload([ + 'contentTitle' => (new ContentDeleted)->getContentPlainTextInfo($this->content), + 'reason' => $this->message + ]); + if (!$contentDeleted->saveRecord($this->content->createdBy)) { + $this->addError('message', Yii::t('ContentModule.base', 'Cannot notify the author.')); + return false; + } + + $contentDeleted->record->updateAttributes([ + 'send_web_notifications' => 1 + ]); + + return true; + } + + public function getErrorsAsString(): string + { + return implode(' ', $this->getErrorSummary(true)); + } } diff --git a/protected/humhub/modules/content/resources/js/humhub.content.js b/protected/humhub/modules/content/resources/js/humhub.content.js index 4994434c6a..a07c1e0d6e 100644 --- a/protected/humhub/modules/content/resources/js/humhub.content.js +++ b/protected/humhub/modules/content/resources/js/humhub.content.js @@ -7,12 +7,12 @@ humhub.module('content', function (module, require, $) { var client = require('client'); var util = require('util'); - var object = util.object; var string = util.string; var actions = require('action'); var Component = actions.Component; var event = require('event'); var modal = require('ui.modal'); + var status = require('ui.status'); var DATA_CONTENT_KEY = "content-key"; var DATA_CONTENT_DELETE_URL = "content-delete-url"; @@ -130,9 +130,13 @@ humhub.module('content', function (module, require, $) { client.post(deleteUrl, { data: postData }).then(function (response) { - that.remove().then(function () { - resolve(true); - }); + if (response.response.success) { + that.remove().then(function () { + resolve(true); + }); + } else { + status.error(response.response.error); + } }).catch(function (err) { reject(err); }).finally(function () { diff --git a/protected/humhub/modules/ldap/authclient/LdapAuth.php b/protected/humhub/modules/ldap/authclient/LdapAuth.php index cc9d4aee54..76dc9add95 100644 --- a/protected/humhub/modules/ldap/authclient/LdapAuth.php +++ b/protected/humhub/modules/ldap/authclient/LdapAuth.php @@ -579,4 +579,15 @@ class LdapAuth extends BaseFormAuth implements AutoSyncUsers, SyncAttributes, Ap return $authClient; } + + /** + * @inheridoc + */ + public function beforeSerialize(): void + { + // Make sure we normalized user attributes before put it in session (anonymous functions) + $this->setNormalizeUserAttributeMap([]); + + $this->_ldap = null; + } } diff --git a/protected/humhub/modules/user/authclient/BaseClient.php b/protected/humhub/modules/user/authclient/BaseClient.php index 1dcc906b01..678309e8c5 100644 --- a/protected/humhub/modules/user/authclient/BaseClient.php +++ b/protected/humhub/modules/user/authclient/BaseClient.php @@ -34,7 +34,15 @@ class BaseClient extends \yii\authclient\BaseClient */ protected function initUserAttributes() { - + } + /** + * Workaround for serialization into session during the registration process + * + * @return void + */ + public function beforeSerialize(): void + { + } } diff --git a/protected/humhub/modules/user/controllers/AuthController.php b/protected/humhub/modules/user/controllers/AuthController.php index 50c80a9e99..b236f30158 100644 --- a/protected/humhub/modules/user/controllers/AuthController.php +++ b/protected/humhub/modules/user/controllers/AuthController.php @@ -36,7 +36,7 @@ class AuthController extends Controller * after the response is generated. */ const EVENT_AFTER_LOGIN = 'afterLogin'; - + /** * @event Triggered after an successful login but before checking user status */ @@ -192,8 +192,10 @@ class AuthController extends Controller return $this->login($user, $authClient); } - // Make sure we normalized user attributes before put it in session (anonymous functions) - $authClient->setNormalizeUserAttributeMap([]); + if ($authClient instanceof \humhub\modules\user\authclient\BaseClient) { + /** @var \humhub\modules\user\authclient\BaseClient $authClient */ + $authClient->beforeSerialize(); + } // Store authclient in session - for registration controller Yii::$app->session->set('authClient', $authClient);