Merge branch 'develop' of github.com:humhub/humhub into develop

This commit is contained in:
Lucas Bartholemy 2021-10-11 22:15:03 +02:00
commit 1820a734fd
11 changed files with 213 additions and 8 deletions

View File

@ -35,3 +35,4 @@
- Enh #5080: Show available module updates directly in admin menu
- Fix #5331: Fix js error on pjax open "Directory" page
- Enh #5333: Module's events handlers registration: check if method exists
- Enh #5300: Blocking users for space

View File

@ -9,6 +9,8 @@ namespace humhub\modules\content\models;
use humhub\components\ActiveRecord;
use humhub\modules\content\components\ContentContainerActiveRecord;
use humhub\modules\friendship\models\Friendship;
use humhub\modules\space\models\Space;
use humhub\modules\user\models\User;
use humhub\modules\user\Module;
use Yii;
@ -38,9 +40,32 @@ class ContentContainerBlockedUsers extends ActiveRecord
return [
[['contentcontainer_id', 'user_id'], 'required'],
[['contentcontainer_id', 'user_id'], 'integer'],
[['user_id'], 'validateUser'],
];
}
public function validateUser()
{
$blockingUser = $this->getUser();
$contentContainer = $this->getContentContainer();
if (!$blockingUser || !$contentContainer) {
$this->addError('user_id', 'User and container ids should be specified!');
}
if ($blockingUser->is($contentContainer)) {
$this->addError('user_id', Yii::t('ContentModule.base', 'You cannot block the user of the same container!'));
}
if (!Yii::$app->user->isGuest && $blockingUser->is(Yii::$app->user->getIdentity())) {
$this->addError('user_id', Yii::t('ContentModule.base', 'You cannot block yourself!'));
}
if (($contentContainer instanceof Space) && $contentContainer->isSpaceOwner($blockingUser)) {
$this->addError('user_id', Yii::t('ContentModule.base', 'You cannot block the space owner!'));
}
}
/**
* Get blocked user guids of the Content Container
*
@ -81,9 +106,6 @@ class ContentContainerBlockedUsers extends ActiveRecord
$newBlockedUserIds = [];
foreach ($newBlockedUsers as $newBlockedUser) {
/* @var User $newBlockedUser */
if ($newBlockedUser->is($contentContainer)) {
continue;
}
$newBlockedUserRelation = new ContentContainerBlockedUsers();
$newBlockedUserRelation->contentcontainer_id = $contentContainer->contentcontainer_id;
$newBlockedUserRelation->user_id = $newBlockedUser->id;
@ -95,6 +117,60 @@ class ContentContainerBlockedUsers extends ActiveRecord
$contentContainer->settings->set(self::BLOCKED_USERS_SETTING, empty($newBlockedUserIds) ? null : implode(',', $newBlockedUserIds));
}
/**
* @inheritdoc
*/
public function save($runValidation = true, $attributeNames = null)
{
if (!$this->validate()) {
return false;
}
return parent::save($runValidation, $attributeNames);
}
/**
* @inheritdoc
*/
public function afterSave($insert, $changedAttributes)
{
$this->afterBlockUserForUser();
$this->afterBlockUserForSpace();
parent::afterSave($insert, $changedAttributes);
}
/**
* Call additional actions after save a blocked user for a User container
*/
public function afterBlockUserForUser()
{
$containerUser = $this->getContentContainer();
if (!($containerUser instanceof User)) {
return;
}
if ($blockedUser = $this->getUser()) {
Friendship::cancel($containerUser, $blockedUser);
$containerUser->unfollow($blockedUser->id);
}
}
/**
* Call additional actions after save a blocked user for a Space container
*/
public function afterBlockUserForSpace()
{
$space = $this->getContentContainer();
if (!($space instanceof Space)) {
return;
}
if ($blockedUser = $this->getUser()) {
$space->removeMember($blockedUser->id);
$space->unfollow($blockedUser->id);
}
}
/**
* Delete blocked user relations of the Content Container
*
@ -110,4 +186,30 @@ class ContentContainerBlockedUsers extends ActiveRecord
$contentContainer->settings->delete(self::BLOCKED_USERS_SETTING);
}
/**
* Get Content Container(Space/User) of this relation
*
* @return ContentContainerActiveRecord|null
*/
public function getContentContainer(): ?ContentContainerActiveRecord
{
if (empty($this->contentcontainer_id)) {
return null;
}
$contentContainer = ContentContainer::findOne($this->contentcontainer_id);
return $contentContainer ? $contentContainer->getPolymorphicRelation() : null;
}
/**
* Get blocked User of this relation
*
* @return User|null
*/
public function getUser(): ?User
{
return empty($this->user_id) ? null : User::findOne($this->user_id);
}
}

View File

@ -14,9 +14,9 @@ use humhub\modules\space\models\Membership;
use humhub\modules\space\models\Space;
use humhub\modules\user\components\ActiveQueryUser;
use humhub\modules\user\models\User;
use humhub\modules\user\Module;
use Yii;
use yii\db\ActiveQuery;
use yii\db\Expression;
/**
@ -96,4 +96,32 @@ class ActiveQuerySpace extends ActiveQuery
return $this;
}
/**
* Exclude blocked spaces for the given $user or for the current User
*
* @param User $user
* @return ActiveQueryUser the query
*/
public function filterBlockedSpaces(?User $user = null): ActiveQuerySpace
{
if ($user === null && !Yii::$app->user->isGuest) {
$user = Yii::$app->user->getIdentity();
}
if (!($user instanceof User)) {
return $this;
}
/* @var Module $userModule */
$userModule = Yii::$app->getModule('user');
if (!$userModule->allowBlockUsers()) {
return $this;
}
$this->leftJoin('contentcontainer_blocked_users', 'contentcontainer_blocked_users.contentcontainer_id=space.contentcontainer_id AND contentcontainer_blocked_users.user_id=:blockedUserId', [':blockedUserId' => $user->id]);
$this->andWhere('contentcontainer_blocked_users.user_id IS NULL');
return $this;
}
}

View File

@ -48,6 +48,7 @@ class SpaceDirectoryQuery extends ActiveQuerySpace
$this->visible();
$this->filterBlockedSpaces();
$this->filterByKeyword();
$this->filterByConnection();

View File

@ -48,7 +48,7 @@ class BrowseController extends Controller
{
Yii::$app->response->format = 'json';
$query = Space::find()->visible();
$query = Space::find()->visible()->filterBlockedSpaces();
$query->search(Yii::$app->request->get('keyword'));
$countQuery = clone $query;

View File

@ -119,7 +119,7 @@ class Space extends ContentContainerActiveRecord implements Searchable
[['join_policy', 'visibility', 'status', 'auto_add_new_members', 'default_content_visibility'], 'integer'],
[['name'], 'required'],
[['description', 'about', 'color'], 'string'],
[['tagsField'], 'safe'],
[['tagsField', 'blockedUsersField'], 'safe'],
[['description'], 'string', 'max' => 100],
[['join_policy'], 'in', 'range' => [0, 1, 2]],
[['visibility'], 'in', 'range' => [0, 1, 2]],
@ -146,7 +146,7 @@ class Space extends ContentContainerActiveRecord implements Searchable
{
$scenarios = parent::scenarios();
$scenarios[static::SCENARIO_EDIT] = ['name', 'color', 'description', 'about', 'tagsField', 'join_policy', 'visibility', 'default_content_visibility', 'url'];
$scenarios[static::SCENARIO_EDIT] = ['name', 'color', 'description', 'about', 'tagsField', 'blockedUsersField', 'join_policy', 'visibility', 'default_content_visibility', 'url'];
$scenarios[static::SCENARIO_CREATE] = ['name', 'color', 'description', 'join_policy', 'visibility'];
$scenarios[static::SCENARIO_SECURITY_SETTINGS] = ['default_content_visibility', 'join_policy', 'visibility'];
@ -173,7 +173,8 @@ class Space extends ContentContainerActiveRecord implements Searchable
'updated_at' => Yii::t('SpaceModule.base', 'Updated At'),
'updated_by' => Yii::t('SpaceModule.base', 'Updated by'),
'ownerUsernameSearch' => Yii::t('SpaceModule.base', 'Owner'),
'default_content_visibility' => Yii::t('SpaceModule.base', 'Default content visibility')
'default_content_visibility' => Yii::t('SpaceModule.base', 'Default content visibility'),
'blockedUsersField' => Yii::t('SpaceModule.base', 'Blocked users'),
];
}
@ -360,6 +361,10 @@ class Space extends ContentContainerActiveRecord implements Searchable
return false;
}
if ($this->isBlockedForUser(User::findOne($userId))) {
return false;
}
return true;
}

View File

@ -49,6 +49,7 @@ class DefaultController extends Controller
{
$space = $this->contentContainer;
$space->scenario = 'edit';
$space->blockedUsersField = $space->getBlockedUserGuids();
if ($space->load(Yii::$app->request->post()) && $space->validate() && $space->save()) {
RichText::postProcess($space->about, $space);

View File

@ -6,6 +6,7 @@ use humhub\modules\space\models\Space;
use humhub\modules\space\modules\manage\widgets\DefaultMenu;
use humhub\modules\space\widgets\SpaceNameColorInput;
use humhub\modules\ui\form\widgets\ActiveForm;
use humhub\modules\user\widgets\UserPickerField;
use humhub\widgets\Button;
/* @var $this \humhub\modules\ui\view\components\View
@ -31,6 +32,9 @@ use humhub\widgets\Button;
<?= $form->field($model, 'description')->textInput(['maxlength' => 100]); ?>
<?= $form->field($model, 'about')->widget(RichTextField::class); ?>
<?= $form->field($model, 'tagsField')->widget(ContainerTagPicker::class, ['minInput' => 2]); ?>
<?php if (Yii::$app->getModule('user')->allowBlockUsers()) : ?>
<?= $form->field($model, 'blockedUsersField')->widget(UserPickerField::class, ['minInput' => 2]); ?>
<?php endif; ?>
<?= Button::save()->submit() ?>

View File

@ -0,0 +1,58 @@
<?php
namespace space\acceptance;
use space\AcceptanceTester;
class BlockSpacesCest
{
public function testBlockUsers(AcceptanceTester $I)
{
$I->wantTo('test users blocking for space');
$I->amGoingTo('check the users blocking is enabled in system by default');
$I->amAdmin();
$this->isUsersBlockingEnabled($I);
$I->amGoingTo('block some users for the space "Sara Tester"');
$I->selectUserFromPicker('#space-blockedusersfield', 'Peter Tester');
$I->click('Save');
$I->seeSuccess('Saved');
$I->see('Peter Tester', '.field-space-blockedusersfield');
$I->amGoingTo('check the current user "Peter Tester" is blocked for the space "Space 1"');
$I->amUser1(true);
$I->amOnSpace1();
$I->see('You are blocked for this page!');
$I->amGoingTo('disable the users blocking');
$I->amAdmin(true);
$this->disableUsersBlocking($I);
$I->amUser1(true);
$this->isUsersBlockingDisabled($I);
$I->amGoingTo('be sure the Space 1 is viewable for the user "Peter Tester"');
$I->amOnSpace1();
$I->see('Space 1');
}
private function disableUsersBlocking(AcceptanceTester $I)
{
$I->amOnPage('/admin/authentication');
$I->click('[for="authenticationsettingsform-blockusers"]');
$I->wait(1);
$I->click('Save');
}
private function isUsersBlockingDisabled(AcceptanceTester $I)
{
$I->amOnPage('/user/account/edit-settings');
$I->dontSee('Blocked users');
}
private function isUsersBlockingEnabled(AcceptanceTester $I)
{
$I->amOnSpace1('/space/manage/default/index');
$I->see('Blocked users');
}
}

View File

@ -130,6 +130,10 @@ class MembershipButton extends Widget
*/
public function run()
{
if ($this->space->isBlockedForUser()) {
return '';
}
$options = $this->getOptions();
if ($options['becomeMember']['mode'] == 'link') {

View File

@ -56,6 +56,7 @@ class PeopleQuery extends ActiveQueryUser
$this->visible();
$this->filterBlockedUsers();
$this->filterByKeyword();
$this->filterByGroup();
$this->filterByConnection();