Commit 3b020fa8 authored by Brian Hatchet's avatar Brian Hatchet :speech_balloon:

Feature complete, role parsing for groups and channels.

1 merge request!290(feat) permissions rbac 600
Pipeline #75293318 running with stages
<?php
namespace Minds\Core\Permissions\Delegates;
use Minds\Core\Permissions\Roles\Roles;
use Minds\Entities\User;
abstract class BaseRoleCalculator
{
/** @var Roles */
protected $roles;
/** @var User */
protected $user;
public function __construct(User $user, Roles $roles = null)
{
$this->roles = $roles ?: new Roles();
$this->user = $user;
}
abstract public function calculate($entity);
}
<?php
namespace Minds\Core\Permissions\Delegates;
use Minds\Traits\MagicAttributes;
use Minds\Core\Permissions\Roles\Roles;
class ChannelRoleCalculator extends BaseRoleCalculator
{
use MagicAttributes;
private $channels = [];
/**
* @param $entity an entity from a channel
* Retrieves permissions for an entity relative to the user's role in a channel
* Retrieves the role from the in memory cache if we've seen this channel before during this request
* Else checks the user's membership against the channel
*
* @return Role
*/
public function calculate($entity)
{
if (isset($this->channels[$entity->getOwnerGUID()])) {
return $this->channels[$entity->getOwnerGUID()];
}
$role = null;
if ($entity->getOwnerGUID() === $this->user->getGUID()) {
$role = $this->roles->getRole(Roles::ROLE_CHANNEL_OWNER);
} elseif ($this->user->isSubscribed($entity->getOwnerGUID())) {
$role = $this->roles->getRole(Roles::ROLE_CHANNEL_SUBSCRIBER);
} else {
$role = $this->roles->getRole(Roles::ROLE_CHANNEL_NON_SUBSCRIBER);
}
$this->channels[$entity->getOwnerGUID()] = $role;
return $role;
}
}
<?php
namespace Minds\Core\Permissions\Delegates;
use Minds\Traits\MagicAttributes;
use Minds\Core\Di\Di;
use Minds\Core\Permissions\Roles\Roles;
use Minds\Core\EntitiesBuilder;
use Minds\Entities\User;
class GroupRoleCalculator extends BaseRoleCalculator
{
use MagicAttributes;
/** @var EntitiesBuilder */
private $entitiesBuilder;
/** @var array */
private $groups = [];
public function __construct(User $user, Roles $roles, EntitiesBuilder $entitiesBuilder = null)
{
parent::__construct($user, $roles);
$this->entitiesBuilder = $entitiesBuilder ?: Di::_()->get('EntitiesBuilder');
}
/**
* @param $entity an entity belonging to a group
* Retrieves permissions for an entity relative to the user's role in a group
* Retrieves the role from the in memory cache if we've seen this group before during this request
* Else gets the group and checks the user's membership
*
* @return Role
*/
public function calculate($entity)
{
if (isset($this->groups[$entity->getAccessId()])) {
return $this->groups[$entity->getAccessId()];
}
$group = $this->entitiesBuilder->single($entity->getAccessId());
$role = null;
if ($group->isCreator($this->user)) {
$role = $this->roles->getRole(Roles::ROLE_GROUP_OWNER);
} elseif ($group->isOwner($this->user)) {
$role = $this->roles->getRole(Roles::ROLE_GROUP_ADMIN);
} elseif ($group->isBanned($this->user)) {
$role = $this->roles->getRole(Roles::ROLE_BANNED);
} elseif ($group->isModerator($this->user)) {
$role = $this->roles->getRole(Roles::ROLE_GROUP_MODERATOR);
} elseif ($group->isMember($this->user)) {
$role = $this->roles->getRole(Roles::ROLE_GROUP_SUBSCRIBER);
} else {
$role = $this->roles->getRole(Roles::ROLE_GROUP_NON_SUBSCRIBER);
}
$this->groups[$entity->getAccessId()] = $role;
return $role;
}
}
......@@ -31,9 +31,7 @@ class Manager {
$user = $this->entitiesBuilder->single($opts['user_guid']);
$entities = $this->entitiesBuilder->get($opts);
foreach($entities as $entity) {
error_log(var_export($entity, true));
}
error_log(var_export($user->getGroupMembership(), true));
if ($user->getType() !== 'user') {
throw new \InvalidArgumentException('Entity is not a user');
}
......
......@@ -5,9 +5,12 @@ namespace Minds\Core\Permissions;
use Minds\Core\Di\Di;
use Minds\Traits\MagicAttributes;
use Minds\Entities\User;
use Minds\Entities\Group;
use Minds\Core\Permissions\Roles\Roles;
use Minds\Core\EntitiesBuilder;
use Minds\Core\Permissions\Roles\Roles;
use Minds\Core\Permissions\Delegates\ChannelRoleCalculator;
use Minds\Core\Permissions\Delegates\GroupRoleCalculator;
use Minds\Common\Access;
class Permissions implements \JsonSerializable
{
......@@ -22,17 +25,14 @@ class Permissions implements \JsonSerializable
/** @var Roles */
private $roles;
/** @var array */
private $channels;
/** @var array */
private $groups;
/** @var array */
private $entities;
/** @var EntitiesBuilder */
private $entitiesBuilder;
/** @var ChannelRoleCalculator */
private $channelRoleCalculator;
/** @var GroupRoleCalculator */
private $groupRoleCalculator;
public function __construct(User $user, EntitiesBuilder $entitiesBuilder = null, Roles $roles = null)
public function __construct(User $user, Roles $roles = null, EntitiesBuilder $entitiesBuilder)
{
$this->entitiesBuilder = $entitiesBuilder ?: Di::_()->get('EntitiesBuilder');
$this->roles = $roles ?: new Roles();
$this->user = $user;
$this->isAdmin = $user->isAdmin();
......@@ -40,30 +40,42 @@ class Permissions implements \JsonSerializable
$this->groups = [];
$this->channels = [];
$this->entities = [];
$this->channels[$user->guid] = $user;
$this->channels[$user->getGUID()] = $user;
$this->channelRoleCalculator = new ChannelRoleCalculator($this->user, $this->roles);
$this->groupRoleCalculator = new GroupRoleCalculator($this->user, $this->roles, $entitiesBuilder);
}
/**
* @param array entities an array of entities for calculating permissions
* Takes an array of entities and checks their permissions
* Builds up collections of permissions based on the user's relationships to the entity
* Any found channels and their roles are accessible in the channelRoleCalculator
* Any found groups and their roles are in the groupRoleCalculator
* All requested entities and the user's role is available in $this->entities
* @return void
*/
public function calculate(array $entities = [])
{
foreach ($entities as $entity) {
$role = $this->getRoleForEntity($entity);
$this->entities[$entity->guid] = $role;
$this->entities[$entity->getGUID()] = $this->getRoleForEntity($entity);
}
}
private function getRoleForEntity($entity)
{
$role = null;
error_log("get role for entity");
error_log(var_export($entity->getContainerEntity() instanceof User, true));
if ($entity->getContainerEntity() instanceof User) {
$role = $this->getChannelRole($entity->getContainerEntity());
}
if ($entity->getContainerEntity() instanceof Group) {
$role = $this->getGroupRole($entity->getContainerEntity());
//Access id is the best way to determine what the parent entity is
//Any of the access flags are a channel
//Anything else is a group guid
switch ($entity->getAccessId()) {
case Access::UNLISTED:
case Access::LOGGED_IN:
case Access::PUBLIC:
case Access::UNKNOWN:
$role = $this->channelRoleCalculator->calculate($entity);
break;
default:
$role = $this->groupRoleCalculator->calculate($entity);
}
//Apply global overrides
if ($this->isAdmin) {
......@@ -76,34 +88,26 @@ class Permissions implements \JsonSerializable
return $role;
}
private function getChannelRole(User $channel)
{
error_log("Getting channel role");
$this->channels[$channel->guid] = $channel;
if($channel->guid === $this->user->guid) {
return $this->roles->getRole(Roles::ROLE_CHANNEL_OWNER);
}
if ($this->user->isSubscribed($owner->guid)) {
return $this->roles->getRole(Roles::ROLE_CHANNEL_SUBSCRIBER);
} else {
return $this->roles->getRole(Roles::ROLE_CHANNEL_NON_SUBSCRIBER);
}
}
private function getGroupOwner(Group $group)
{
$this->groups[$group->guid] = $group;
}
/* Export the nested objects */
public function export()
{
$export = [];
$export['user'] = $this->user->export();
$export['channels'] = $this->getChannels();
$export['groups'] = $this->getGroups();
$export['entities'] = $this->entities;
return $export;
}
public function getChannels() {
return $this->channelRoleCalculator->getChannels();
}
public function getGroups() {
return $this->groupRoleCalculator->getGroups();
}
public function jsonSerialize()
{
return $this->export();
......
......@@ -541,7 +541,7 @@ class Group extends NormalizedEntity
*/
public function isBanned($user = null)
{
return (new Membership($this))->isInvited($user);
return Membership::_($this)->isBanned($user);
}
/**
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment