]> source.dussan.org Git - nextcloud-server.git/commitdiff
Allow to do a principal property search based on metadata keys
authorGeorg Ehrke <developer@georgehrke.com>
Thu, 1 Aug 2019 16:37:50 +0000 (18:37 +0200)
committerGeorg Ehrke <developer@georgehrke.com>
Thu, 1 Aug 2019 17:40:27 +0000 (19:40 +0200)
Signed-off-by: Georg Ehrke <developer@georgehrke.com>
apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php
apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTest.php

index bc96041d915fa2724b5555c107ed727cb3da0dc0..aab5fcab8ad862ed5687015b2a95eacb97383ee0 100644 (file)
@@ -184,6 +184,37 @@ abstract class AbstractPrincipalBackend implements BackendInterface {
                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);
+       }
+
        /**
         * Returns the list of members for a group-principal
         *
@@ -296,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;
                        }
                }
@@ -317,6 +356,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
index eb9faa574a1285fdd37b82084fc77004f61e8971..f4019d86e2b6bb5d2794946d778aa125be21ff9d 100644 (file)
@@ -219,6 +219,26 @@ abstract class AbstractPrincipalBackendTest extends TestCase {
                ];
        }
 
+       public function testSearchPrincipalsByMetadataKey() {
+               $user = $this->createMock(IUser::class);
+               $this->userSession->expects($this->once())
+                       ->method('getUser')
+                       ->with()
+                       ->will($this->returnValue($user));
+               $this->groupManager->expects($this->once())
+                       ->method('getUserGroupIds')
+                       ->with($user)
+                       ->will($this->returnValue(['group1', 'group2']));
+
+               $actual = $this->principalBackend->searchPrincipals($this->principalPrefix, [
+                       '{http://nextcloud.com/ns}meta3' => 'value',
+               ]);
+
+               $this->assertEquals([
+                       $this->principalPrefix . '/backend2-res4',
+               ], $actual);
+       }
+
        public function testSearchPrincipalsByCalendarUserAddressSet() {
                $user = $this->createMock(IUser::class);
                $this->userSession->method('getUser')