summaryrefslogtreecommitdiffstats
path: root/apps/dav/lib/CalDAV/ResourceBooking
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dav/lib/CalDAV/ResourceBooking')
-rw-r--r--apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php137
-rw-r--r--apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php2
-rw-r--r--apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php2
3 files changed, 130 insertions, 11 deletions
diff --git a/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php b/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php
index 90d147f6741..aab5fcab8ad 100644
--- a/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php
+++ b/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php
@@ -1,6 +1,6 @@
<?php
/**
- * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
+ * @copyright 2019, Georg Ehrke <oc.list@georgehrke.com>
*
* @author Georg Ehrke <oc.list@georgehrke.com>
*
@@ -51,6 +51,12 @@ abstract class AbstractPrincipalBackend implements BackendInterface {
private $dbTableName;
/** @var string */
+ private $dbMetaDataTableName;
+
+ /** @var string */
+ private $dbForeignKeyName;
+
+ /** @var string */
private $cuType;
/**
@@ -74,7 +80,9 @@ abstract class AbstractPrincipalBackend implements BackendInterface {
$this->groupManager = $groupManager;
$this->logger = $logger;
$this->principalPrefix = $principalPrefix;
- $this->dbTableName = 'calendar_' . $dbPrefix;
+ $this->dbTableName = 'calendar_' . $dbPrefix . 's';
+ $this->dbMetaDataTableName = $this->dbTableName . '_md';
+ $this->dbForeignKeyName = $dbPrefix . '_id';
$this->cuType = $cuType;
}
@@ -100,8 +108,31 @@ abstract class AbstractPrincipalBackend implements BackendInterface {
->from($this->dbTableName);
$stmt = $query->execute();
+ $metaDataQuery = $this->db->getQueryBuilder();
+ $metaDataQuery->select([$this->dbForeignKeyName, 'key', 'value'])
+ ->from($this->dbMetaDataTableName);
+ $metaDataStmt = $metaDataQuery->execute();
+ $metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
+
+ $metaDataById = [];
+ foreach($metaDataRows as $metaDataRow) {
+ if (!isset($metaDataById[$metaDataRow[$this->dbForeignKeyName]])) {
+ $metaDataById[$metaDataRow[$this->dbForeignKeyName]] = [];
+ }
+
+ $metaDataById[$metaDataRow[$this->dbForeignKeyName]][$metaDataRow['key']] =
+ $metaDataRow['value'];
+ }
+
while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
- $principals[] = $this->rowToPrincipal($row);
+ $id = $row['id'];
+
+ if (isset($metaDataById[$id])) {
+ $principals[] = $this->rowToPrincipal($row, $metaDataById[$id]);
+ } else {
+ $principals[] = $this->rowToPrincipal($row);
+ }
+
}
$stmt->closeCursor();
@@ -138,7 +169,50 @@ abstract class AbstractPrincipalBackend implements BackendInterface {
return null;
}
- return $this->rowToPrincipal($row);
+ $metaDataQuery = $this->db->getQueryBuilder();
+ $metaDataQuery->select(['key', 'value'])
+ ->from($this->dbMetaDataTableName)
+ ->where($metaDataQuery->expr()->eq($this->dbForeignKeyName, $metaDataQuery->createNamedParameter($row['id'])));
+ $metaDataStmt = $metaDataQuery->execute();
+ $metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
+ $metadata = [];
+
+ foreach($metaDataRows as $metaDataRow) {
+ $metadata[$metaDataRow['key']] = $metaDataRow['value'];
+ }
+
+ return $this->rowToPrincipal($row, $metadata);
+ }
+
+ /**
+ * @param int $id
+ * @return array|null
+ */
+ public function getPrincipalById($id):?array {
+ $query = $this->db->getQueryBuilder();
+ $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
+ ->from($this->dbTableName)
+ ->where($query->expr()->eq('id', $query->createNamedParameter($id)));
+ $stmt = $query->execute();
+ $row = $stmt->fetch(\PDO::FETCH_ASSOC);
+
+ if(!$row) {
+ return null;
+ }
+
+ $metaDataQuery = $this->db->getQueryBuilder();
+ $metaDataQuery->select(['key', 'value'])
+ ->from($this->dbMetaDataTableName)
+ ->where($metaDataQuery->expr()->eq($this->dbForeignKeyName, $metaDataQuery->createNamedParameter($row['id'])));
+ $metaDataStmt = $metaDataQuery->execute();
+ $metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
+ $metadata = [];
+
+ foreach($metaDataRows as $metaDataRow) {
+ $metadata[$metaDataRow['key']] = $metaDataRow['value'];
+ }
+
+ return $this->rowToPrincipal($row, $metadata);
}
/**
@@ -253,7 +327,15 @@ abstract class AbstractPrincipalBackend implements BackendInterface {
break;
default:
- $results[] = [];
+ $rowsByMetadata = $this->searchPrincipalsByMetadataKey($prop, $value);
+ $filteredRows = array_filter($rowsByMetadata, function($row) use ($usersGroups) {
+ return $this->isAllowedToAccessResource($row, $usersGroups);
+ });
+
+ $results[] = array_map(function($row) {
+ return $row['uri'];
+ }, $filteredRows);
+
break;
}
}
@@ -275,6 +357,39 @@ abstract class AbstractPrincipalBackend implements BackendInterface {
}
/**
+ * Searches principals based on their metadata keys.
+ * This allows to search for all principals with a specific key.
+ * e.g.:
+ * '{http://nextcloud.com/ns}room-building-address' => 'ABC Street 123, ...'
+ *
+ * @param $key
+ * @param $value
+ * @return array
+ */
+ private function searchPrincipalsByMetadataKey($key, $value):array {
+ $query = $this->db->getQueryBuilder();
+ $query->select([$this->dbForeignKeyName])
+ ->from($this->dbMetaDataTableName)
+ ->where($query->expr()->eq('key', $query->createNamedParameter($key)))
+ ->andWhere($query->expr()->iLike('value', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
+ $stmt = $query->execute();
+
+ $rows = [];
+ while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
+ $id = $row[$this->dbForeignKeyName];
+
+ $principalRow = $this->getPrincipalById($id);
+ if (!$principalRow) {
+ continue;
+ }
+
+ $rows[] = $principalRow;
+ }
+
+ return $rows;
+ }
+
+ /**
* @param string $uri
* @param string $principalPrefix
* @return null|string
@@ -338,14 +453,18 @@ abstract class AbstractPrincipalBackend implements BackendInterface {
/**
* convert database row to principal
+ *
+ * @param String[] $row
+ * @param String[] $metadata
+ * @return Array
*/
- private function rowToPrincipal($row) {
- return [
+ private function rowToPrincipal(array $row, array $metadata=[]):array {
+ return array_merge([
'uri' => $this->principalPrefix . '/' . $row['backend_id'] . '-' . $row['resource_id'],
'{DAV:}displayname' => $row['displayname'],
'{http://sabredav.org/ns}email-address' => $row['email'],
'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->cuType,
- ];
+ ], $metadata);
}
/**
@@ -353,7 +472,7 @@ abstract class AbstractPrincipalBackend implements BackendInterface {
* @param $userGroups
* @return bool
*/
- private function isAllowedToAccessResource($row, $userGroups) {
+ private function isAllowedToAccessResource(array $row, array $userGroups):bool {
if (!isset($row['group_restrictions']) ||
$row['group_restrictions'] === null ||
$row['group_restrictions'] === '') {
diff --git a/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php b/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php
index f8f10e78f94..0f6e6e7b4fd 100644
--- a/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php
+++ b/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php
@@ -40,6 +40,6 @@ class ResourcePrincipalBackend extends AbstractPrincipalBackend {
IGroupManager $groupManager,
ILogger $logger) {
parent::__construct($dbConnection, $userSession, $groupManager, $logger,
- 'principals/calendar-resources', 'resources', 'RESOURCE');
+ 'principals/calendar-resources', 'resource', 'RESOURCE');
}
}
diff --git a/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php b/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php
index 3059ed80ea6..68a344aa0ca 100644
--- a/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php
+++ b/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php
@@ -40,6 +40,6 @@ class RoomPrincipalBackend extends AbstractPrincipalBackend {
IGroupManager $groupManager,
ILogger $logger) {
parent::__construct($dbConnection, $userSession, $groupManager, $logger,
- 'principals/calendar-rooms', 'rooms', 'ROOM');
+ 'principals/calendar-rooms', 'room', 'ROOM');
}
}