499 lines
13 KiB
PHP
499 lines
13 KiB
PHP
<?php
|
|
/**
|
|
* Nextcloud - user_sql
|
|
*
|
|
* @copyright 2018 Marcin Łojewski <dev@mlojewski.me>
|
|
* @author Marcin Łojewski <dev@mlojewski.me>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
namespace OCA\UserSQL\Backend;
|
|
|
|
use OCA\UserSQL\Cache;
|
|
use OCA\UserSQL\Constant\DB;
|
|
use OCA\UserSQL\Model\Group;
|
|
use OCA\UserSQL\Properties;
|
|
use OCA\UserSQL\Repository\GroupRepository;
|
|
use OCP\Group\Backend\ABackend;
|
|
use OCP\Group\Backend\IAddToGroupBackend;
|
|
use OCP\Group\Backend\ICountDisabledInGroup;
|
|
use OCP\Group\Backend\ICountUsersBackend;
|
|
use OCP\Group\Backend\ICreateGroupBackend;
|
|
use OCP\Group\Backend\IDeleteGroupBackend;
|
|
use OCP\Group\Backend\IGroupDetailsBackend;
|
|
use OCP\Group\Backend\IIsAdminBackend;
|
|
use OCP\Group\Backend\IRemoveFromGroupBackend;
|
|
use OCP\ILogger;
|
|
|
|
/**
|
|
* The SQL group backend manager.
|
|
*
|
|
* @author Marcin Łojewski <dev@mlojewski.me>
|
|
*/
|
|
final class GroupBackend extends ABackend implements
|
|
IAddToGroupBackend,
|
|
ICountDisabledInGroup,
|
|
ICountUsersBackend,
|
|
ICreateGroupBackend,
|
|
IDeleteGroupBackend,
|
|
IGroupDetailsBackend,
|
|
IIsAdminBackend,
|
|
IRemoveFromGroupBackend
|
|
{
|
|
/**
|
|
* @var string The application name.
|
|
*/
|
|
private $appName;
|
|
/**
|
|
* @var ILogger The logger instance.
|
|
*/
|
|
private $logger;
|
|
/**
|
|
* @var Cache The cache instance.
|
|
*/
|
|
private $cache;
|
|
/**
|
|
* @var GroupRepository The group repository.
|
|
*/
|
|
private $groupRepository;
|
|
/**
|
|
* @var Properties The properties array.
|
|
*/
|
|
private $properties;
|
|
|
|
/**
|
|
* The default constructor.
|
|
*
|
|
* @param string $AppName The application name.
|
|
* @param Cache $cache The cache instance.
|
|
* @param ILogger $logger The logger instance.
|
|
* @param Properties $properties The properties array.
|
|
* @param GroupRepository $groupRepository The group repository.
|
|
*/
|
|
public function __construct(
|
|
$AppName, Cache $cache, ILogger $logger, Properties $properties,
|
|
GroupRepository $groupRepository
|
|
) {
|
|
$this->appName = $AppName;
|
|
$this->cache = $cache;
|
|
$this->logger = $logger;
|
|
$this->properties = $properties;
|
|
$this->groupRepository = $groupRepository;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function getGroups($search = "", $limit = null, $offset = null)
|
|
{
|
|
$this->logger->debug(
|
|
"Entering getGroups($search, $limit, $offset)",
|
|
["app" => $this->appName]
|
|
);
|
|
|
|
$cacheKey = self::class . "groups_" . $search . "_" . $limit . "_"
|
|
. $offset;
|
|
$groups = $this->cache->get($cacheKey);
|
|
|
|
if (!is_null($groups)) {
|
|
$this->logger->debug(
|
|
"Returning from cache getGroups($search, $limit, $offset): count("
|
|
. count($groups) . ")", ["app" => $this->appName]
|
|
);
|
|
return $groups;
|
|
}
|
|
|
|
$groups = $this->groupRepository->findAllBySearchTerm(
|
|
"%" . $search . "%", $limit, $offset
|
|
);
|
|
|
|
if ($groups === false) {
|
|
return [];
|
|
}
|
|
|
|
foreach ($groups as $group) {
|
|
$this->cache->set("group_" . $group->gid, $group);
|
|
}
|
|
|
|
$groups = array_map(
|
|
function ($group) {
|
|
return $group->gid;
|
|
}, $groups
|
|
);
|
|
|
|
$this->cache->set($cacheKey, $groups);
|
|
$this->logger->debug(
|
|
"Returning getGroups($search, $limit, $offset): count(" . count(
|
|
$groups
|
|
) . ")", ["app" => $this->appName]
|
|
);
|
|
|
|
return $groups;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function countUsersInGroup(string $gid, string $search = ""): int
|
|
{
|
|
$this->logger->debug(
|
|
"Entering countUsersInGroup($gid, $search)",
|
|
["app" => $this->appName]
|
|
);
|
|
|
|
$cacheKey = self::class . "users#_" . $gid . "_" . $search;
|
|
$count = $this->cache->get($cacheKey);
|
|
|
|
if (!is_null($count)) {
|
|
$this->logger->debug(
|
|
"Returning from cache countUsersInGroup($gid, $search): $count",
|
|
["app" => $this->appName]
|
|
);
|
|
return $count;
|
|
}
|
|
|
|
$count = $this->groupRepository->countAll($gid, "%" . $search . "%");
|
|
|
|
if ($count === false) {
|
|
return 0;
|
|
}
|
|
|
|
$this->cache->set($cacheKey, $count);
|
|
$this->logger->debug(
|
|
"Returning countUsersInGroup($gid, $search): $count",
|
|
["app" => $this->appName]
|
|
);
|
|
|
|
return $count;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function inGroup($uid, $gid)
|
|
{
|
|
$this->logger->debug(
|
|
"Entering inGroup($uid, $gid)", ["app" => $this->appName]
|
|
);
|
|
|
|
$cacheKey = self::class . "user_group_" . $uid . "_" . $gid;
|
|
$inGroup = $this->cache->get($cacheKey);
|
|
|
|
if (!is_null($inGroup)) {
|
|
$this->logger->debug(
|
|
"Returning from cache inGroup($uid, $gid): " . ($inGroup
|
|
? "true" : "false"), ["app" => $this->appName]
|
|
);
|
|
return $inGroup;
|
|
}
|
|
|
|
$inGroup = in_array($gid, $this->getUserGroups($uid));
|
|
|
|
$this->cache->set($cacheKey, $inGroup);
|
|
$this->logger->debug(
|
|
"Returning inGroup($uid, $gid): " . ($inGroup ? "true" : "false"),
|
|
["app" => $this->appName]
|
|
);
|
|
|
|
return $inGroup;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function getUserGroups($uid)
|
|
{
|
|
$this->logger->debug(
|
|
"Entering getUserGroups($uid)", ["app" => $this->appName]
|
|
);
|
|
|
|
$cacheKey = self::class . "user_groups_" . $uid;
|
|
$groups = $this->cache->get($cacheKey);
|
|
|
|
if (!is_null($groups)) {
|
|
$this->logger->debug(
|
|
"Returning from cache getUserGroups($uid): count(" . count(
|
|
$groups
|
|
) . ")", ["app" => $this->appName]
|
|
);
|
|
return $groups;
|
|
}
|
|
|
|
$groups = $this->groupRepository->findAllByUid($uid);
|
|
|
|
if ($groups === false) {
|
|
return [];
|
|
}
|
|
|
|
foreach ($groups as $group) {
|
|
$this->cache->set("group_" . $group->gid, $group);
|
|
}
|
|
|
|
$groups = array_map(
|
|
function ($group) {
|
|
return $group->gid;
|
|
}, $groups
|
|
);
|
|
|
|
$this->cache->set($cacheKey, $groups);
|
|
$this->logger->debug(
|
|
"Returning getUserGroups($uid): count(" . count(
|
|
$groups
|
|
) . ")", ["app" => $this->appName]
|
|
);
|
|
|
|
return $groups;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function groupExists($gid)
|
|
{
|
|
$this->logger->debug(
|
|
"Entering groupExists($gid)", ["app" => $this->appName]
|
|
);
|
|
|
|
$group = $this->getGroup($gid);
|
|
|
|
if ($group === false) {
|
|
return false;
|
|
}
|
|
|
|
$exists = !is_null($group);
|
|
$this->logger->debug(
|
|
"Returning groupExists($gid): " . ($exists ? "true" : "false"),
|
|
["app" => $this->appName]
|
|
);
|
|
|
|
return $exists;
|
|
}
|
|
|
|
/**
|
|
* Get a group entity object. If it's found value from cache is used.
|
|
*
|
|
* @param $gid $uid The group ID.
|
|
*
|
|
* @return Group The group entity, NULL if it does not exists or
|
|
* FALSE on failure.
|
|
*/
|
|
private function getGroup($gid)
|
|
{
|
|
$cacheKey = self::class . "group_" . $gid;
|
|
$cachedGroup = $this->cache->get($cacheKey);
|
|
|
|
if (!is_null($cachedGroup)) {
|
|
if ($cachedGroup === false) {
|
|
$this->logger->debug(
|
|
"Found null group in cache: $gid", ["app" => $this->appName]
|
|
);
|
|
return null;
|
|
}
|
|
|
|
$group = new Group();
|
|
foreach ($cachedGroup as $key => $value) {
|
|
$group->{$key} = $value;
|
|
}
|
|
|
|
$this->logger->debug(
|
|
"Found group in cache: " . $group->gid,
|
|
["app" => $this->appName]
|
|
);
|
|
|
|
return $group;
|
|
}
|
|
|
|
$group = $this->groupRepository->findByGid($gid);
|
|
|
|
if ($group instanceof Group) {
|
|
$this->cache->set($cacheKey, $group);
|
|
} elseif (is_null($group)) {
|
|
$this->cache->set($cacheKey, false);
|
|
}
|
|
|
|
return $group;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function usersInGroup($gid, $search = "", $limit = -1, $offset = 0)
|
|
{
|
|
$this->logger->debug(
|
|
"Entering usersInGroup($gid, $search, $limit, $offset)",
|
|
["app" => $this->appName]
|
|
);
|
|
|
|
$cacheKey = self::class . "group_users_" . $gid . "_" . $search . "_"
|
|
. $limit . "_" . $offset;
|
|
$users = $this->cache->get($cacheKey);
|
|
|
|
if (!is_null($users)) {
|
|
$this->logger->debug(
|
|
"Returning from cache usersInGroup($gid, $search, $limit, $offset): count("
|
|
. count($users) . ")", ["app" => $this->appName]
|
|
);
|
|
return $users;
|
|
}
|
|
|
|
$uids = $this->groupRepository->findAllUidsBySearchTerm(
|
|
$gid, "%" . $search . "%", $limit, $offset
|
|
);
|
|
|
|
if ($uids === false) {
|
|
return [];
|
|
}
|
|
|
|
$this->cache->set($cacheKey, $uids);
|
|
$this->logger->debug(
|
|
"Returning usersInGroup($gid, $search, $limit, $offset): count("
|
|
. count($uids) . ")", ["app" => $this->appName]
|
|
);
|
|
|
|
return $uids;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function isAdmin(string $uid): bool
|
|
{
|
|
$this->logger->debug(
|
|
"Entering isAdmin($uid)", ["app" => $this->appName]
|
|
);
|
|
|
|
if (empty($this->properties[DB::GROUP_ADMIN_COLUMN])) {
|
|
return false;
|
|
}
|
|
|
|
$cacheKey = self::class . "admin_" . $uid;
|
|
$admin = $this->cache->get($cacheKey);
|
|
|
|
if (!is_null($admin)) {
|
|
$this->logger->debug(
|
|
"Returning from cache isAdmin($uid): " . ($admin ? "true"
|
|
: "false"), ["app" => $this->appName]
|
|
);
|
|
return $admin;
|
|
}
|
|
|
|
$admin = $this->groupRepository->belongsToAdmin($uid);
|
|
|
|
if (is_null($admin)) {
|
|
return false;
|
|
}
|
|
|
|
$this->cache->set($cacheKey, $admin);
|
|
$this->logger->debug(
|
|
"Returning isAdmin($uid): " . ($admin ? "true" : "false"),
|
|
["app" => $this->appName]
|
|
);
|
|
|
|
return $admin;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function getGroupDetails(string $gid): array
|
|
{
|
|
$this->logger->debug(
|
|
"Entering getGroupDetails($gid)", ["app" => $this->appName]
|
|
);
|
|
|
|
if (empty($this->properties[DB::GROUP_NAME_COLUMN])) {
|
|
return [];
|
|
}
|
|
|
|
$group = $this->getGroup($gid);
|
|
|
|
if (!($group instanceof Group)) {
|
|
return [];
|
|
}
|
|
|
|
$details = ["displayName" => $group->name];
|
|
$this->logger->debug(
|
|
"Returning getGroupDetails($gid): " . implode(", ", $details),
|
|
["app" => $this->appName]
|
|
);
|
|
|
|
return $details;
|
|
}
|
|
|
|
/**
|
|
* Check if this backend is correctly set and can be enabled.
|
|
*
|
|
* @return bool TRUE if all necessary options for this backend
|
|
* are configured, FALSE otherwise.
|
|
*/
|
|
public function isConfigured()
|
|
{
|
|
return !empty($this->properties[DB::DATABASE])
|
|
&& !empty($this->properties[DB::DRIVER])
|
|
&& !empty($this->properties[DB::HOSTNAME])
|
|
&& !empty($this->properties[DB::USERNAME])
|
|
&& !empty($this->properties[DB::GROUP_TABLE])
|
|
&& !empty($this->properties[DB::USER_GROUP_TABLE])
|
|
&& !empty($this->properties[DB::GROUP_GID_COLUMN])
|
|
&& !empty($this->properties[DB::USER_GROUP_GID_COLUMN])
|
|
&& !empty($this->properties[DB::USER_GROUP_UID_COLUMN]);
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function addToGroup(string $uid, string $gid): bool
|
|
{
|
|
// TODO: Implement addToGroup() method.
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function countDisabledInGroup(string $gid): int
|
|
{
|
|
// TODO: Implement countDisabledInGroup() method.
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function createGroup(string $gid): bool
|
|
{
|
|
// TODO: Implement createGroup() method.
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function deleteGroup(string $gid): bool
|
|
{
|
|
// TODO: Implement deleteGroup() method.
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
public function removeFromGroup(string $uid, string $gid)
|
|
{
|
|
// TODO: Implement removeFromGroup() method.
|
|
return false;
|
|
}
|
|
}
|