Merge branch 'master' into develop

This commit is contained in:
Lucas Bartholemy 2024-09-05 17:08:15 +02:00
commit f5eb868663
13 changed files with 116 additions and 68 deletions

View File

@ -28,8 +28,8 @@ HumHub Changelog
- Enh #7167: Disable DEBUG mode automatically after successful humhub installation. Add `.env` support
- Enh #7202: Increased minimum PHP version to 8.1
1.16.2 (Unreleased)
---------------------
1.16.2 (September 5, 2024)
--------------------------
- Fix #7102: Fix content search with word ending with hyphen
- Fix #7104: Missing `--text-color-default` CSS variable
- Enh #7105: Add an external link icon to the "Install Updates" button to avoid thinking it updates the modules directly
@ -47,11 +47,15 @@ HumHub Changelog
- Fix #324: Focus on active and selected nav page after reload on mobile
- Fix #7170: Fix rendering of new line on email messages
- Fix #7178: Highlight only words with 3 or more characters
- Fix #7180: Fix active form on user edit form for correct working of widget inputs
- Fix #7180: Fix active form on registration and user edit forms for correct working of widget inputs
- Fix #7181: Fix duplicated label of checkbox profile field
- Fix #7182: Fix initialization of several select2 inputs on the same page
- Fix #7187: Fix search reindexing after content deletion
- Fix #7152: Fix search starting with special characters
- Enh #7148: Improve rendering of meta search content
- Fix #7192: Deny deleting user from single group
- Fix #7200: Fix module description for space and user
- Enh #7204: Make "Invite new people" always possible for user with permission "Manage Users"
1.16.1 (July 1, 2024)
---------------------

View File

@ -151,11 +151,29 @@ class GroupController extends Controller
$group = Group::findOne(['id' => $request->get('id')]);
$this->checkGroupAccess($group);
$group->removeUser($request->get('userId'));
$userGroupsCount = GroupUser::find()
->where(['user_id' => $request->get('userId')])
->count();
$error = '';
if ($userGroupsCount > 1) {
if (!$group->removeUser($request->get('userId'))) {
$error = Yii::t('AdminModule.user', 'The user cannot be removed from this Group!');
}
} else {
$error = Yii::t('AdminModule.user', 'The user cannot be removed from this Group, as users are required to be assigned to at least one Group.');
}
if ($request->isAjax) {
Yii::$app->response->format = 'json';
return ['success' => true];
return [
'success' => $error === '',
'error' => $error,
];
}
if ($error) {
$this->view->error($error);
}
return $this->redirect([

View File

@ -268,14 +268,12 @@ class UserController extends Controller
return $this->redirect(['edit', 'id' => $registration->getUser()->id]);
}
$adminIsAlwaysAllowed = Yii::$app->user->isAdmin();
$invite = new InviteForm();
return $this->render('add', [
'hForm' => $registration,
'canInviteByEmail' => $invite->canInviteByEmail($adminIsAlwaysAllowed),
'canInviteByLink' => $invite->canInviteByLink($adminIsAlwaysAllowed),
'adminIsAlwaysAllowed' => $adminIsAlwaysAllowed,
'canInviteByEmail' => $invite->canInviteByEmail(),
'canInviteByLink' => $invite->canInviteByLink(),
]);
}

View File

@ -1,6 +1,7 @@
humhub.module('admin.group', function (module, require, $) {
var client = require('client');
var loader = require('ui.loader');
var status = require('ui.status');
var setManagerRole = function (evt) {
var options = {
@ -36,6 +37,8 @@ humhub.module('admin.group', function (module, require, $) {
$controls.closest('tr').fadeOut('slow', function () {
$(this).remove();
});
} else if (response.error) {
status.error(response.error);
} else {
module.log.error(response, true);
}

View File

@ -55,9 +55,7 @@ AdminGroupAsset::register($this);
</div>
<div class="table-responsive">
<?php
$actionUrl = Url::to(['edit-manager-role']);
echo GridView::widget(
<?= GridView::widget(
[
'dataProvider' => $dataProvider,
#'filterModel' => $searchModel,
@ -76,15 +74,15 @@ AdminGroupAsset::register($this);
'visible' => $isManagerApprovalSetting,
'label' => Yii::t('AdminModule.user', 'Group Manager'),
'format' => 'raw',
'value' => function ($data) use ($group, $actionUrl) {
'value' => function ($data) use ($group) {
$isManager = $group->isManager($data);
$yesSelected = ($isManager) ? 'selected' : '';
$noSelected = ($isManager) ? '' : 'selected';
$result = '<select class="editableCell form-control" data-action-change="admin.group.setManagerRole" data-action-url="' . $actionUrl . '" data-userid="' . $data->id . '" data-groupid="' . $group->id . '">';
$result = '<select class="editableCell form-control" data-action-change="admin.group.setManagerRole" data-action-url="' . Url::to(['edit-manager-role']) . '" data-userid="' . $data->id . '" data-groupid="' . $group->id . '">';
$result .= '<option value="0" ' . $noSelected . '>' . Yii::t('AdminModule.user', 'No') . '</option>';
$result .= '<option value="1" ' . $yesSelected . '>' . Yii::t('AdminModule.user', 'Yes') . '</option>';
return $result;
}
},
],
[
'class' => 'yii\grid\ActionColumn',
@ -97,18 +95,25 @@ AdminGroupAsset::register($this);
return false;
},
'delete' => function ($url, $model) use ($group) {
return Button::danger()
->tooltip(Yii::t('AdminModule.user', 'Remove from group'))
->action('admin.group.removeMember', Url::to(['remove-group-user', 'id' => $group->id, 'userId' => $model->id]))
->icon('remove')->xs()
->confirm();
}
return $model->getGroups()->count() > 1
? Button::danger()
->tooltip(Yii::t('AdminModule.user', 'Remove from group'))
->action('admin.group.removeMember', Url::to(['remove-group-user', 'id' => $group->id, 'userId' => $model->id]))
->icon('remove')
->xs()
->confirm()
: Button::danger()
->tooltip(Yii::t('AdminModule.user', 'The user cannot be removed from this Group, as users are required to be assigned to at least one Group.'))
->icon('remove')
->options(['disabled' => true])
->xs()
->loader(false);
},
],
],
],
]
);
?>
) ?>
</div>
</div>
<?php $this->endContent(); ?>

View File

@ -9,7 +9,6 @@ use humhub\modules\ui\form\widgets\ActiveForm;
* @var $hForm HForm
* @var $canInviteByEmail bool
* @var $canInviteByLink bool
* @var $adminIsAlwaysAllowed bool
*/
?>
@ -21,7 +20,7 @@ use humhub\modules\ui\form\widgets\ActiveForm;
<?php if ($canInviteByEmail || $canInviteByLink): ?>
<?= ModalButton::success(Yii::t('AdminModule.user', 'Invite new people'))
->load(['/user/invite', 'adminIsAlwaysAllowed' => $adminIsAlwaysAllowed])->icon('invite')->sm() ?>
->load(['/user/invite'])->icon('invite')->sm() ?>
<?php endif; ?>
</div>

View File

@ -10,7 +10,7 @@ namespace humhub\modules\content\search;
use humhub\interfaces\MetaSearchResultInterface;
use humhub\modules\content\components\ContentContainerActiveRecord;
use humhub\modules\content\models\Content;
use humhub\modules\content\widgets\richtext\RichText;
use humhub\modules\content\widgets\richtext\converter\RichTextToHtmlConverter;
use humhub\modules\ui\icon\widgets\Icon;
use humhub\modules\user\models\User;
use Yii;
@ -46,7 +46,37 @@ class SearchRecord implements MetaSearchResultInterface
*/
public function getTitle(): string
{
return RichText::output($this->content->getContentDescription(), ['record' => $this->content->getModel()]);
$title = RichTextToHtmlConverter::process($this->content->getContentDescription());
$title = preg_replace('/[\r\n\s]+/', ' ', strip_tags($title));
return $this->cutStringToKeyword($title);
}
/**
* Cut string to a word before first word contained the searched keyword
*
* @param string $string
* @param int $maxWordNumberBeforeKeyword
* @return string
*/
private function cutStringToKeyword(string $string, int $maxWordNumberBeforeKeyword = 1): string
{
$index = stripos($string, $this->keyword);
if ($index === false || $index < 40) {
// Don't cut if the keyword is almost at the beginning
return $string;
}
$wordNumber = 0;
do {
$index--;
$subString = substr($string, $index);
if ($subString[0] === ' ') {
$wordNumber++;
}
} while ($index > 0 && $wordNumber <= $maxWordNumberBeforeKeyword);
return ($index > 0 ? '...' : '') . trim($subString);
}
/**

View File

@ -7,9 +7,9 @@
namespace humhub\modules\content\widgets;
use humhub\components\Module;
use humhub\components\Widget;
use humhub\modules\content\components\ContentContainerActiveRecord;
use humhub\modules\content\components\ContentContainerModule;
/**
* ModuleCard shows a card with module data of Content Container
@ -19,12 +19,8 @@ use humhub\modules\content\components\ContentContainerActiveRecord;
*/
class ContainerModule extends Widget
{
public Module $module;
/**
* @var ContentContainerActiveRecord
*/
public $contentContainer;
public ContentContainerModule $module;
public ContentContainerActiveRecord $contentContainer;
/**
* @inheritdoc

View File

@ -5,12 +5,12 @@
* @license https://www.humhub.com/licences
*/
use humhub\components\Module;
use humhub\libs\Html;
use humhub\modules\content\components\ContentContainerActiveRecord;
use humhub\modules\content\components\ContentContainerModule;
use humhub\modules\content\widgets\ContainerModuleActionButtons;
/* @var Module $module */
/* @var ContentContainerModule $module */
/* @var ContentContainerActiveRecord $contentContainer */
?>
<div class="module-row row">
@ -26,7 +26,7 @@ use humhub\modules\content\widgets\ContainerModuleActionButtons;
<?= $module->getContentContainerName($contentContainer) ?>
<br><small><?= Yii::t('AdminModule.base', 'Version') . ' ' . $module->getVersion() ?></small>
</div>
<div class="col-xs-6 col-sm-5 col-md-6"><?= $module->getDescription() ?></div>
<div class="col-xs-6 col-sm-5 col-md-6"><?= $module->getContentContainerDescription($contentContainer) ?></div>
<div class="col-xs-5 col-sm-3 module-actions">
<?= ContainerModuleActionButtons::widget([
'module' => $module,

View File

@ -8,19 +8,18 @@
namespace humhub\modules\user\controllers;
use humhub\modules\user\Module;
use Throwable;
use Yii;
use yii\base\Exception;
use yii\base\InvalidConfigException;
use yii\web\Controller;
use yii\web\HttpException;
use humhub\components\behaviors\AccessControl;
use humhub\modules\admin\permissions\ManageGroups;
use humhub\modules\admin\permissions\ManageUsers;
use humhub\modules\user\models\Invite;
use humhub\modules\user\models\forms\Invite as InviteForm;
use humhub\widgets\ModalClose;
use Throwable;
use Yii;
use yii\base\Exception;
use yii\base\InvalidConfigException;
use yii\web\Controller;
use yii\web\HttpException;
/**
* InviteController for new user invites
@ -47,12 +46,12 @@ class InviteController extends Controller
* @return string the action result
* @throws HttpException
*/
public function actionIndex($adminIsAlwaysAllowed = false)
public function actionIndex()
{
$model = new InviteForm();
$canInviteByEmail = $model->canInviteByEmail($adminIsAlwaysAllowed);
$canInviteByLink = $model->canInviteByLink($adminIsAlwaysAllowed);
$canInviteByEmail = $model->canInviteByEmail();
$canInviteByLink = $model->canInviteByLink();
if (!$canInviteByEmail && !$canInviteByLink) {
throw new HttpException(403, 'Invite denied!');
}
@ -71,7 +70,6 @@ class InviteController extends Controller
'model' => $model,
'canInviteByEmail' => $canInviteByEmail,
'canInviteByLink' => $canInviteByLink,
'adminIsAlwaysAllowed' => $adminIsAlwaysAllowed,
]);
}
@ -98,13 +96,12 @@ class InviteController extends Controller
}
/**
* @param $adminIsAlwaysAllowed
* @return string
* @throws Throwable
* @throws Exception
* @throws InvalidConfigException
*/
public function actionResetInviteLink($adminIsAlwaysAllowed = false)
public function actionResetInviteLink()
{
$model = new InviteForm();
@ -118,9 +115,8 @@ class InviteController extends Controller
return $this->renderAjax('index', [
'model' => $model,
'canInviteByEmail' => $model->canInviteByEmail($adminIsAlwaysAllowed),
'canInviteByLink' => $model->canInviteByLink($adminIsAlwaysAllowed),
'adminIsAlwaysAllowed' => $adminIsAlwaysAllowed,
'canInviteByEmail' => $model->canInviteByEmail(),
'canInviteByLink' => $model->canInviteByLink(),
]);
}
}

View File

@ -10,6 +10,7 @@ namespace humhub\modules\user\models\forms;
use humhub\modules\admin\permissions\ManageGroups;
use humhub\modules\admin\permissions\ManageUsers;
use humhub\modules\user\models\User;
use humhub\modules\user\Module;
use humhub\modules\user\services\LinkRegistrationService;
use Throwable;
@ -17,7 +18,6 @@ use Yii;
use yii\base\Exception;
use yii\base\InvalidConfigException;
use yii\base\Model;
use humhub\modules\user\models\User;
use yii\helpers\Url;
use yii\validators\EmailValidator;
@ -87,35 +87,35 @@ class Invite extends Model
/**
* Checks if external user invitation setting is enabled
*
* @param bool $adminIsAlwaysAllowed
* @return bool
* @throws InvalidConfigException
* @throws Throwable
*/
public function canInviteByEmail(bool $adminIsAlwaysAllowed = false)
public function canInviteByEmail()
{
/** @var Module $module */
$module = Yii::$app->getModule('user');
return
(!Yii::$app->user->isGuest && $module->settings->get('auth.internalUsersCanInviteByEmail'))
|| ($adminIsAlwaysAllowed && Yii::$app->user->can([ManageUsers::class, ManageGroups::class]));
return (!Yii::$app->user->isGuest && $module->settings->get('auth.internalUsersCanInviteByEmail'))
|| Yii::$app->user->isAdmin()
|| Yii::$app->user->can([ManageUsers::class, ManageGroups::class]);
}
/**
* Checks if external user invitation setting is enabled
*
* @param bool $adminIsAlwaysAllowed
* @return bool
* @throws Throwable
* @throws InvalidConfigException
*/
public function canInviteByLink(bool $adminIsAlwaysAllowed = false)
public function canInviteByLink()
{
/** @var Module $module */
$module = Yii::$app->getModule('user');
return
(!Yii::$app->user->isGuest && $module->settings->get('auth.internalUsersCanInviteByLink'))
|| ($adminIsAlwaysAllowed && Yii::$app->user->can([ManageUsers::class, ManageGroups::class]));
return (!Yii::$app->user->isGuest && $module->settings->get('auth.internalUsersCanInviteByLink'))
|| Yii::$app->user->isAdmin()
|| Yii::$app->user->can([ManageUsers::class, ManageGroups::class]);
}
/**

View File

@ -16,7 +16,6 @@ use yii\bootstrap\ActiveForm;
* @var $model Invite
* @var $canInviteByEmail bool
* @var $canInviteByLink bool
* @var $adminIsAlwaysAllowed bool
*/
?>
@ -49,7 +48,7 @@ use yii\bootstrap\ActiveForm;
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'emails')->textarea(['rows' => '3', 'placeholder' => Yii::t('UserModule.invite', 'Email address(es)'), 'id' => 'emails'])->label(false)->hint(Yii::t('UserModule.invite', 'Separate multiple email addresses by comma.')); ?>
<a href="#" class="btn btn-primary" data-action-click="ui.modal.submit"
data-action-url="<?= Url::to(['/user/invite', 'adminIsAlwaysAllowed' => $adminIsAlwaysAllowed]) ?>" data-ui-loader>
data-action-url="<?= Url::to(['/user/invite']) ?>" data-ui-loader>
<?= Yii::t('UserModule.invite', 'Send invite') ?>
</a>
<?php ActiveForm::end(); ?>
@ -73,7 +72,7 @@ use yii\bootstrap\ActiveForm;
data-action-confirm-header="<?= Yii::t('SpaceModule.base', 'Create new link') ?>" ,
data-action-confirm="<?= Yii::t('SpaceModule.base', 'Please note that any links you have previously created will become invalid as soon as you create a new one. Would you like to proceed?') ?>"
data-action-click="ui.modal.load"
data-action-click-url="<?= Url::to(['/user/invite/reset-invite-link', 'adminIsAlwaysAllowed' => $adminIsAlwaysAllowed]) ?>">
data-action-click-url="<?= Url::to(['/user/invite/reset-invite-link']) ?>">
<small><?= Yii::t('SpaceModule.base', 'Create new link'); ?></small>
</a>
<?php endif; ?>

View File

@ -1,10 +1,10 @@
<?php
use humhub\libs\Html;
use humhub\modules\ui\form\widgets\ActiveForm;
use humhub\modules\user\models\forms\Registration;
use humhub\modules\user\widgets\AuthChoice;
use humhub\widgets\SiteLogo;
use yii\bootstrap\ActiveForm;
/**
* @var $hForm Registration