]> source.dussan.org Git - nextcloud-server.git/commitdiff
feat: allow for ExApps to call Admin endpoints marked with specific attr 46607/head
authorAlexander Piskun <13381981+bigcat88@users.noreply.github.com>
Thu, 18 Jul 2024 12:11:39 +0000 (15:11 +0300)
committerAlexander Piskun <bigcat88@icloud.com>
Thu, 18 Jul 2024 12:11:39 +0000 (15:11 +0300)
Signed-off-by: Alexander Piskun <bigcat88@icloud.com>
lib/composer/composer/autoload_classmap.php
lib/composer/composer/autoload_static.php
lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
lib/public/AppFramework/Http/Attribute/AppApiAdminAccessWithoutUser.php [new file with mode: 0644]

index 4c2c6d8dd0ee1d49532778081793773563ba7c88..fbc61bcb1a695807342cbf3f6c1f8da30aa54f2b 100644 (file)
@@ -44,6 +44,7 @@ return array(
     'OCP\\AppFramework\\Http\\Attribute\\ARateLimit' => $baseDir . '/lib/public/AppFramework/Http/Attribute/ARateLimit.php',
     'OCP\\AppFramework\\Http\\Attribute\\AnonRateLimit' => $baseDir . '/lib/public/AppFramework/Http/Attribute/AnonRateLimit.php',
     'OCP\\AppFramework\\Http\\Attribute\\ApiRoute' => $baseDir . '/lib/public/AppFramework/Http/Attribute/ApiRoute.php',
+    'OCP\\AppFramework\\Http\\Attribute\\AppApiAdminAccessWithoutUser' => $baseDir . '/lib/public/AppFramework/Http/Attribute/AppApiAdminAccessWithoutUser.php',
     'OCP\\AppFramework\\Http\\Attribute\\AuthorizedAdminSetting' => $baseDir . '/lib/public/AppFramework/Http/Attribute/AuthorizedAdminSetting.php',
     'OCP\\AppFramework\\Http\\Attribute\\BruteForceProtection' => $baseDir . '/lib/public/AppFramework/Http/Attribute/BruteForceProtection.php',
     'OCP\\AppFramework\\Http\\Attribute\\CORS' => $baseDir . '/lib/public/AppFramework/Http/Attribute/CORS.php',
index edc94a0cb78a7cce0dec4bbbba3bf8eaaca0bd2c..dd25d62f7e36639ac766204828584e4be4247eac 100644 (file)
@@ -77,6 +77,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
         'OCP\\AppFramework\\Http\\Attribute\\ARateLimit' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/ARateLimit.php',
         'OCP\\AppFramework\\Http\\Attribute\\AnonRateLimit' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/AnonRateLimit.php',
         'OCP\\AppFramework\\Http\\Attribute\\ApiRoute' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/ApiRoute.php',
+        'OCP\\AppFramework\\Http\\Attribute\\AppApiAdminAccessWithoutUser' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/AppApiAdminAccessWithoutUser.php',
         'OCP\\AppFramework\\Http\\Attribute\\AuthorizedAdminSetting' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/AuthorizedAdminSetting.php',
         'OCP\\AppFramework\\Http\\Attribute\\BruteForceProtection' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/BruteForceProtection.php',
         'OCP\\AppFramework\\Http\\Attribute\\CORS' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/CORS.php',
index 603b5d543dc2d3a4c73f7cf5f1bde868f66dbb0d..d7479f674d9524150acd9000c1e4de3a47c16a01 100644 (file)
@@ -21,6 +21,7 @@ use OC\User\Session;
 use OCP\App\AppPathNotFoundException;
 use OCP\App\IAppManager;
 use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\Attribute\AppApiAdminAccessWithoutUser;
 use OCP\AppFramework\Http\Attribute\AuthorizedAdminSetting;
 use OCP\AppFramework\Http\Attribute\ExAppRequired;
 use OCP\AppFramework\Http\Attribute\NoAdminRequired;
@@ -136,11 +137,19 @@ class SecurityMiddleware extends Middleware {
                                throw new ExAppRequiredException();
                        }
                } elseif (!$isPublicPage) {
-                       if (!$this->isLoggedIn) {
+                       $authorized = false;
+                       if ($this->hasAnnotationOrAttribute($reflectionMethod, null, AppApiAdminAccessWithoutUser::class)) {
+                               // this attribute allows ExApp to access admin endpoints only if "userId" is "null"
+                               if ($this->userSession instanceof Session && $this->userSession->getSession()->get('app_api') === true && $this->userSession->getUser() === null) {
+                                       $authorized = true;
+                               }
+                       }
+
+                       if (!$authorized && !$this->isLoggedIn) {
                                throw new NotLoggedInException();
                        }
-                       $authorized = false;
-                       if ($this->hasAnnotationOrAttribute($reflectionMethod, 'AuthorizedAdminSetting', AuthorizedAdminSetting::class)) {
+
+                       if (!$authorized && $this->hasAnnotationOrAttribute($reflectionMethod, 'AuthorizedAdminSetting', AuthorizedAdminSetting::class)) {
                                $authorized = $this->isAdminUser;
 
                                if (!$authorized && $this->hasAnnotationOrAttribute($reflectionMethod, 'SubAdminRequired', SubAdminRequired::class)) {
@@ -233,16 +242,16 @@ class SecurityMiddleware extends Middleware {
         * @template T
         *
         * @param ReflectionMethod $reflectionMethod
-        * @param string $annotationName
+        * @param ?string $annotationName
         * @param class-string<T> $attributeClass
         * @return boolean
         */
-       protected function hasAnnotationOrAttribute(ReflectionMethod $reflectionMethod, string $annotationName, string $attributeClass): bool {
+       protected function hasAnnotationOrAttribute(ReflectionMethod $reflectionMethod, ?string $annotationName, string $attributeClass): bool {
                if (!empty($reflectionMethod->getAttributes($attributeClass))) {
                        return true;
                }
 
-               if ($this->reflector->hasAnnotation($annotationName)) {
+               if ($annotationName && $this->reflector->hasAnnotation($annotationName)) {
                        $this->logger->debug($reflectionMethod->getDeclaringClass()->getName() . '::' . $reflectionMethod->getName() . ' uses the @' . $annotationName . ' annotation and should use the #[' . $attributeClass . '] attribute instead');
                        return true;
                }
diff --git a/lib/public/AppFramework/Http/Attribute/AppApiAdminAccessWithoutUser.php b/lib/public/AppFramework/Http/Attribute/AppApiAdminAccessWithoutUser.php
new file mode 100644 (file)
index 0000000..6b78fee
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCP\AppFramework\Http\Attribute;
+
+use Attribute;
+
+/**
+ * Attribute for (sub)administrator controller methods that allow access for ExApps when the User is not set.
+ *
+ * @since 30.0.0
+ */
+#[Attribute]
+class AppApiAdminAccessWithoutUser {
+}