diff --git a/src/Collection/PermissionSets.php b/src/Collection/PermissionSets.php new file mode 100644 index 0000000000..7511d046fd --- /dev/null +++ b/src/Collection/PermissionSets.php @@ -0,0 +1,10 @@ + $user_id, 'self' => true]); - $acl_yourself['name'] = L10n::t('Yourself'); + $acl_yourself['name'] = DI::l10n()->t('Yourself'); $acl_contacts[] = $acl_yourself; diff --git a/src/DI.php b/src/DI.php index 22c81079b9..e6d9c341b7 100644 --- a/src/DI.php +++ b/src/DI.php @@ -284,6 +284,14 @@ abstract class DI return self::$dice->create(Repository\Introduction::class); } + /** + * @return Repository\PermissionSet + */ + public static function permissionSet() + { + return self::$dice->create(Repository\PermissionSet::class); + } + // // "Protocol" namespace instances // diff --git a/src/Model/PermissionSet.php b/src/Model/PermissionSet.php index fbcc1738d7..9bf2642c8b 100644 --- a/src/Model/PermissionSet.php +++ b/src/Model/PermissionSet.php @@ -5,15 +5,13 @@ namespace Friendica\Model; -use Friendica\Core\L10n; -use Friendica\Database\DBA; +use Friendica\BaseModel; use Friendica\DI; -use Friendica\Network\HTTPException; /** * functions for interacting with the permission set of an object (item, photo, event, ...) */ -class PermissionSet +class PermissionSet extends BaseModel { /** * Fetch the id of a given permission set. Generate a new one when needed @@ -24,7 +22,9 @@ class PermissionSet * @param string|null $deny_cid Disallowed contact IDs - empty = no one * @param string|null $deny_gid Disallowed group IDs - empty = no one * @return int id - * @throws HTTPException\InternalServerErrorException + * @throws \Exception + * @deprecated since 2020.03, use Repository\PermissionSet instead + * @see \Friendica\Repository\PermissionSet->getIdFromACL */ public static function getIdFromACL( int $uid, @@ -33,38 +33,7 @@ class PermissionSet string $deny_cid = null, string $deny_gid = null ) { - $ACLFormatter = DI::aclFormatter(); - - $allow_cid = $ACLFormatter->sanitize($allow_cid); - $allow_gid = $ACLFormatter->sanitize($allow_gid); - $deny_cid = $ACLFormatter->sanitize($deny_cid); - $deny_gid = $ACLFormatter->sanitize($deny_gid); - - // Public permission - if (!$allow_cid && !$allow_gid && !$deny_cid && !$deny_gid) { - return 0; - } - - $condition = [ - 'uid' => $uid, - 'allow_cid' => $allow_cid, - 'allow_gid' => $allow_gid, - 'deny_cid' => $deny_cid, - 'deny_gid' => $deny_gid - ]; - $permissionset = DBA::selectFirst('permissionset', ['id'], $condition); - - if (DBA::isResult($permissionset)) { - $psid = $permissionset['id']; - } else { - if (DBA::insert('permissionset', $condition, true)) { - $psid = DBA::lastInsertId(); - } else { - throw new HTTPException\InternalServerErrorException(L10n::t('Unable to create a new permission set.')); - } - } - - return $psid; + return DI::permissionSet()->getIdFromACL($uid, $allow_cid, $allow_gid, $deny_cid, $deny_gid); } /** @@ -75,31 +44,13 @@ class PermissionSet * * @return array of permission set ids. * @throws \Exception + * @deprecated since 2020.03, use Repository\PermissionSet instead + * @see \Friendica\Repository\PermissionSet->selectByContactId */ - static public function get($uid, $contact_id) + public static function get($uid, $contact_id) { - if (DBA::exists('contact', ['id' => $contact_id, 'uid' => $uid, 'blocked' => false])) { - $groups = Group::getIdsByContactId($contact_id); - } + $permissionSets = DI::permissionSet()->selectByContactId($contact_id, $uid); - $group_str = '<<>>'; // should be impossible to match - foreach ($groups as $group_id) { - $group_str .= '|<' . preg_quote($group_id) . '>'; - } - - $contact_str = '<' . $contact_id . '>'; - - $condition = ["`uid` = ? AND (NOT (`deny_cid` REGEXP ? OR deny_gid REGEXP ?) - AND (allow_cid REGEXP ? OR allow_gid REGEXP ? OR (allow_cid = '' AND allow_gid = '')))", - $uid, $contact_str, $group_str, $contact_str, $group_str]; - - $ret = DBA::select('permissionset', ['id'], $condition); - $set = []; - while ($permission = DBA::fetch($ret)) { - $set[] = $permission['id']; - } - DBA::close($ret); - - return $set; + return $permissionSets->column('id'); } } diff --git a/src/Repository/PermissionSet.php b/src/Repository/PermissionSet.php new file mode 100644 index 0000000000..906dd716e6 --- /dev/null +++ b/src/Repository/PermissionSet.php @@ -0,0 +1,154 @@ +dba, $this->logger, $data); + } + + /** + * @param array $condition + * @return Model\PermissionSet + * @throws \Friendica\Network\HTTPException\NotFoundException + */ + public function selectFirst(array $condition) + { + if (isset($condition['id']) && !$condition['id']) { + return $this->create([ + 'id' => 0, + 'uid' => $condition['uid'] ?? 0, + 'allow_cid' => '', + 'allow_gid' => '', + 'deny_cid' => '', + 'deny_gid' => '', + ]); + } + + return parent::selectFirst($condition); + } + + /** + * @param array $condition + * @param array $params + * @return Collection\PermissionSets + * @throws \Exception + */ + public function select(array $condition = [], array $params = []) + { + return parent::select($condition, $params); + } + + /** + * @param array $condition + * @param array $params + * @param int|null $max_id + * @param int|null $since_id + * @param int $limit + * @return Collection\PermissionSets + * @throws \Exception + */ + public function selectByBoundaries(array $condition = [], array $params = [], int $max_id = null, int $since_id = null, int $limit = self::LIMIT) + { + return parent::selectByBoundaries($condition, $params, $max_id, $since_id, $limit); + } + + /** + * Fetch the id of a given permission set. Generate a new one when needed + * + * @param int $uid + * @param string|null $allow_cid Allowed contact IDs - empty = everyone + * @param string|null $allow_gid Allowed group IDs - empty = everyone + * @param string|null $deny_cid Disallowed contact IDs - empty = no one + * @param string|null $deny_gid Disallowed group IDs - empty = no one + * @return int id + * @throws \Exception + */ + public function getIdFromACL( + int $uid, + string $allow_cid = null, + string $allow_gid = null, + string $deny_cid = null, + string $deny_gid = null + ) { + $ACLFormatter = DI::aclFormatter(); + + $allow_cid = $ACLFormatter->sanitize($allow_cid); + $allow_gid = $ACLFormatter->sanitize($allow_gid); + $deny_cid = $ACLFormatter->sanitize($deny_cid); + $deny_gid = $ACLFormatter->sanitize($deny_gid); + + // Public permission + if (!$allow_cid && !$allow_gid && !$deny_cid && !$deny_gid) { + return 0; + } + + $condition = [ + 'uid' => $uid, + 'allow_cid' => $allow_cid, + 'allow_gid' => $allow_gid, + 'deny_cid' => $deny_cid, + 'deny_gid' => $deny_gid + ]; + + try { + $permissionset = $this->selectFirst($condition); + } catch(HTTPException\NotFoundException $exception) { + $permissionset = $this->insert($condition); + } + + return $permissionset->id; + } + + /** + * Returns a permission set collection for a given contact + * + * @param integer $contact_id Contact id of the visitor + * @param integer $uid User id whom the items belong, used for ownership check. + * + * @return Collection\PermissionSets + * @throws \Exception + */ + public function selectByContactId($contact_id, $uid) + { + $groups = []; + if (DBA::exists('contact', ['id' => $contact_id, 'uid' => $uid, 'blocked' => false])) { + $groups = Group::getIdsByContactId($contact_id); + } + + $group_str = '<<>>'; // should be impossible to match + foreach ($groups as $group_id) { + $group_str .= '|<' . preg_quote($group_id) . '>'; + } + + $contact_str = '<' . $contact_id . '>'; + + $condition = ["`uid` = ? AND (NOT (`deny_cid` REGEXP ? OR deny_gid REGEXP ?) + AND (allow_cid REGEXP ? OR allow_gid REGEXP ? OR (allow_cid = '' AND allow_gid = '')))", + $uid, $contact_str, $group_str, $contact_str, $group_str]; + + return $this->select($condition); + } +}