Improve content permissions

This commit is contained in:
Yuriy Bakhtin 2023-01-13 14:08:48 +04:00
parent 9c3226f53b
commit b340db9881
5 changed files with 49 additions and 30 deletions

View File

@ -613,7 +613,7 @@ class ContentActiveRecord extends ActiveRecord implements ContentOwner, Movable
{
if ($user && !$user->is(Yii::$app->user->getIdentity())) {
return new ContentPermissionManager([
'content' => $this,
'model' => $this,
'subject' => $user
]);
}
@ -623,7 +623,7 @@ class ContentActiveRecord extends ActiveRecord implements ContentOwner, Movable
}
return $this->permissionManager = new ContentPermissionManager([
'content' => $this
'model' => $this
]);
}
}

View File

@ -9,10 +9,7 @@ use yii\base\InvalidArgumentException;
class ContentPermissionManager extends AbstractPermissionManager
{
/**
* @var ContentActiveRecord
*/
public $content;
public ContentActiveRecord $model;
protected function verify(BasePermission $permission)
{
@ -21,6 +18,10 @@ class ContentPermissionManager extends AbstractPermissionManager
throw new InvalidArgumentException(get_class($permission) . ' must be instance of ' . AbstractContentPermission::class);
}
return $permission->verify($this->content, $this->getSubject());
if (!isset($permission->model)) {
$permission->model = $this->model;
}
return $permission->verify($this->getSubject());
}
}

View File

@ -4,9 +4,27 @@ namespace humhub\modules\content\permissions;
use humhub\components\permission\BasePermission;
use humhub\modules\content\components\ContentActiveRecord;
use humhub\modules\content\components\ContentContainerActiveRecord;
use humhub\modules\content\models\Content;
use humhub\modules\user\models\User;
/**
* @property-read Content $content
* @property-read ContentContainerActiveRecord $container
*/
abstract class AbstractContentPermission extends BasePermission
{
abstract public function verify(ContentActiveRecord $content, ?User $user): bool;
public ContentActiveRecord $model;
abstract public function verify(?User $user = null): bool;
public function getContent(): ?Content
{
return $this->model instanceof ContentActiveRecord ? $this->model->content : null;
}
public function getContainer(): ?ContentContainerActiveRecord
{
return $this->content instanceof Content ? $this->content->container : null;
}
}

View File

@ -21,14 +21,14 @@ use Yii;
class CanEditContent extends AbstractContentPermission
{
public function verify(ContentActiveRecord $content, ?User $user): bool
public function verify(?User $user = null): bool
{
if ($user === null) {
return false;
}
// Only owner can edit his content
if ($content->content->created_by == $user->id) {
if ($this->content->created_by == $user->id) {
return true;
}
@ -38,18 +38,18 @@ class CanEditContent extends AbstractContentPermission
}
// Check additional manage permission for the given container
if ($content->content->container) {
if ($content->isNewRecord && $content->hasCreatePermission() && $content->content->container->getPermissionManager($user)->can($content->getCreatePermission())) {
if ($this->container) {
if ($this->model->isNewRecord && $this->model->hasCreatePermission() && $this->container->getPermissionManager($user)->can($this->model->getCreatePermission())) {
return true;
}
if (!$content->isNewRecord && $content->hasManagePermission() && $content->content->container->getPermissionManager($user)->can($content->getManagePermission())) {
if (!$this->model->isNewRecord && $this->model->hasManagePermission() && $this->container->getPermissionManager($user)->can($this->model->getManagePermission())) {
return true;
}
}
// Check if underlying models canEdit implementation
// ToDo: Implement this as interface
if (method_exists($content, 'canEdit') && $content->canEdit($user)) {
if (method_exists($this->model, 'canEdit') && $this->model->canEdit($user)) {
return true;
}

View File

@ -13,26 +13,26 @@ use humhub\modules\user\models\User;
class CanViewContent extends AbstractContentPermission
{
public function verify(ContentActiveRecord $content, ?User $user): bool
public function verify(?User $user = null): bool
{
// Check global content visibility, private global content is visible for all users
if (empty($content->content->contentcontainer_id) && $user !== null) {
if (empty($this->content->contentcontainer_id) && $user !== null) {
return true;
}
// Check Guest Visibility
if (!$user) {
return $this->checkGuestAccess($content);
return $this->checkGuestAccess();
}
// User can access own content
if ($content->content->created_by == $user->id) {
if ($this->content->created_by == $user->id) {
return true;
}
// Public visible content
if ($content->content->isPublic()) {
if ($this->content->isPublic()) {
return true;
}
@ -41,9 +41,9 @@ class CanViewContent extends AbstractContentPermission
return true;
}
return $content->content->isPrivate() &&
$content->content->container !== null &&
$content->content->container->canAccessPrivateContent($user);
return $this->content->isPrivate() &&
$this->container !== null &&
$this->container->canAccessPrivateContent($user);
}
/**
@ -56,23 +56,23 @@ class CanViewContent extends AbstractContentPermission
*
* @return bool
*/
private function checkGuestAccess(ContentActiveRecord $content): bool
private function checkGuestAccess(): bool
{
if (!$content->content->isPublic() || !AuthHelper::isGuestAccessEnabled()) {
if (!$this->content->isPublic() || !AuthHelper::isGuestAccessEnabled()) {
return false;
}
// Global content
if (!$content->content->container) {
return $content->content->isPublic();
if (!$this->container) {
return true;
}
if ($content->content->container instanceof Space) {
return $content->content->isPublic() && $content->content->container->visibility == Space::VISIBILITY_ALL;
if ($this->container instanceof Space) {
return $this->container->visibility == Space::VISIBILITY_ALL;
}
if ($content->content->container instanceof User) {
return $content->content->isPublic() && $content->content->container->visibility == User::VISIBILITY_ALL;
if ($this->container instanceof User) {
return $this->container->visibility == User::VISIBILITY_ALL;
}
return false;