Skip to content

Commit db530d1

Browse files
Merge pull request #56921 from nextcloud/fix-caching-routes-by-users-with-an-active-session
2 parents 9350a67 + 51ed61b commit db530d1

File tree

9 files changed

+110
-2
lines changed

9 files changed

+110
-2
lines changed

apps/testing/appinfo/routes.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,10 @@
6363
'type' => null
6464
]
6565
],
66+
[
67+
'name' => 'Routes#getRoutesInRoutesPhp',
68+
'url' => '/api/v1/routes/routesphp/{app}',
69+
'verb' => 'GET',
70+
],
6671
],
6772
];

apps/testing/clean_apcu_cache.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
/**
4+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-License-Identifier: AGPL-3.0-or-later
6+
*/
7+
apcu_clear_cache();

apps/testing/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
'OCA\\Testing\\Controller\\ConfigController' => $baseDir . '/../lib/Controller/ConfigController.php',
1313
'OCA\\Testing\\Controller\\LockingController' => $baseDir . '/../lib/Controller/LockingController.php',
1414
'OCA\\Testing\\Controller\\RateLimitTestController' => $baseDir . '/../lib/Controller/RateLimitTestController.php',
15+
'OCA\\Testing\\Controller\\RoutesController' => $baseDir . '/../lib/Controller/RoutesController.php',
1516
'OCA\\Testing\\Conversion\\ConversionProvider' => $baseDir . '/../lib/Conversion/ConversionProvider.php',
1617
'OCA\\Testing\\HiddenGroupBackend' => $baseDir . '/../lib/HiddenGroupBackend.php',
1718
'OCA\\Testing\\Listener\\GetDeclarativeSettingsValueListener' => $baseDir . '/../lib/Listener/GetDeclarativeSettingsValueListener.php',

apps/testing/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class ComposerStaticInitTesting
2727
'OCA\\Testing\\Controller\\ConfigController' => __DIR__ . '/..' . '/../lib/Controller/ConfigController.php',
2828
'OCA\\Testing\\Controller\\LockingController' => __DIR__ . '/..' . '/../lib/Controller/LockingController.php',
2929
'OCA\\Testing\\Controller\\RateLimitTestController' => __DIR__ . '/..' . '/../lib/Controller/RateLimitTestController.php',
30+
'OCA\\Testing\\Controller\\RoutesController' => __DIR__ . '/..' . '/../lib/Controller/RoutesController.php',
3031
'OCA\\Testing\\Conversion\\ConversionProvider' => __DIR__ . '/..' . '/../lib/Conversion/ConversionProvider.php',
3132
'OCA\\Testing\\HiddenGroupBackend' => __DIR__ . '/..' . '/../lib/HiddenGroupBackend.php',
3233
'OCA\\Testing\\Listener\\GetDeclarativeSettingsValueListener' => __DIR__ . '/..' . '/../lib/Listener/GetDeclarativeSettingsValueListener.php',
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/**
4+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-License-Identifier: AGPL-3.0-or-later
6+
*/
7+
namespace OCA\Testing\Controller;
8+
9+
use OCP\App\AppPathNotFoundException;
10+
use OCP\App\IAppManager;
11+
use OCP\AppFramework\Http;
12+
use OCP\AppFramework\Http\DataResponse;
13+
use OCP\AppFramework\OCSController;
14+
use OCP\IRequest;
15+
16+
class RoutesController extends OCSController {
17+
18+
public function __construct(
19+
string $appName,
20+
IRequest $request,
21+
private IAppManager $appManager,
22+
) {
23+
parent::__construct($appName, $request);
24+
}
25+
26+
public function getRoutesInRoutesPhp(string $app): DataResponse {
27+
try {
28+
$appPath = $this->appManager->getAppPath($app);
29+
} catch (AppPathNotFoundException) {
30+
return new DataResponse([], Http::STATUS_NOT_FOUND);
31+
}
32+
33+
$file = $appPath . '/appinfo/routes.php';
34+
if (!file_exists($file)) {
35+
return new DataResponse();
36+
}
37+
38+
$routes = include $file;
39+
40+
return new DataResponse($routes);
41+
}
42+
}

build/integration/features/bootstrap/Provisioning.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,9 @@ public function getArrayOfSubadminsResponded($resp) {
827827
* @param string $app
828828
*/
829829
public function appEnabledStateWillBeRestoredOnceTheScenarioFinishes($app) {
830+
$previousUser = $this->currentUser;
831+
$this->currentUser = 'admin';
832+
830833
if (in_array($app, $this->getAppsWithFilter('enabled'))) {
831834
$this->appsToEnableAfterScenario[] = $app;
832835
} elseif (in_array($app, $this->getAppsWithFilter('disabled'))) {
@@ -835,6 +838,8 @@ public function appEnabledStateWillBeRestoredOnceTheScenarioFinishes($app) {
835838

836839
// Apps that were not installed before the scenario will not be
837840
// disabled nor uninstalled after the scenario.
841+
842+
$this->currentUser = $previousUser;
838843
}
839844

840845
private function getAppsWithFilter($filter) {

build/integration/features/bootstrap/RoutingContext.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
use Behat\Behat\Context\Context;
88
use Behat\Behat\Context\SnippetAcceptingContext;
9+
use PHPUnit\Framework\Assert;
910

1011
require __DIR__ . '/autoload.php';
1112

@@ -16,4 +17,26 @@ class RoutingContext implements Context, SnippetAcceptingContext {
1617

1718
protected function resetAppConfigs(): void {
1819
}
20+
21+
/**
22+
* @AfterScenario
23+
*/
24+
public function deleteMemcacheSetting(): void {
25+
$this->invokingTheCommand('config:system:delete memcache.local');
26+
}
27+
28+
/**
29+
* @Given /^route "([^"]*)" of app "([^"]*)" is defined in routes.php$/
30+
*/
31+
public function routeOfAppIsDefinedInRoutesPhP(string $route, string $app): void {
32+
$previousUser = $this->currentUser;
33+
$this->currentUser = 'admin';
34+
35+
$this->sendingTo('GET', "/apps/testing/api/v1/routes/routesphp/{$app}");
36+
$this->theHTTPStatusCodeShouldBe('200');
37+
38+
Assert::assertStringContainsString($route, $this->response->getBody()->getContents());
39+
40+
$this->currentUser = $previousUser;
41+
}
1942
}

build/integration/routing_features/apps-and-routes.feature

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,22 @@ Feature: appmanagement
5050
Given As an "admin"
5151
And sending "DELETE" to "/cloud/apps/weather_status"
5252
And app "weather_status" is disabled
53+
54+
Scenario: Cache routes from routes.php with a user in a group without some apps enabled
55+
Given invoking occ with "config:system:set memcache.local --value \OC\Memcache\APCu"
56+
And the command was successful
57+
And route "api/v1/location" of app "weather_status" is defined in routes.php
58+
And app "weather_status" enabled state will be restored once the scenario finishes
59+
And invoking occ with "app:enable weather_status --groups group1"
60+
And the command was successful
61+
When Logging in using web as "user2"
62+
And sending "GET" with exact url to "/apps/testing/clean_apcu_cache.php"
63+
And Sending a "GET" to "/index.php/apps/files" with requesttoken
64+
And the HTTP status code should be "200"
65+
Then As an "user2"
66+
And sending "GET" to "/apps/weather_status/api/v1/location"
67+
And the HTTP status code should be "412"
68+
And As an "user1"
69+
And sending "GET" to "/apps/weather_status/api/v1/location"
70+
And the OCS status code should be "200"
71+
And the HTTP status code should be "200"

lib/private/Route/CachingRouter.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,17 @@ private function serializeRouteCollection(RouteCollection $collection): array {
7474
* @return array
7575
*/
7676
public function findMatchingRoute(string $url): array {
77-
return parent::findMatchingRoute($url);
78-
7977
$this->eventLogger->start('cacheroute:match', 'Match route');
8078
$key = $this->context->getHost() . '#' . $this->context->getBaseUrl() . '#rootCollection';
8179
$cachedRoutes = $this->cache->get($key);
8280
if (!$cachedRoutes) {
81+
// Ensure that all apps are loaded, as for users with an active
82+
// session only the apps that are enabled for that user might have
83+
// been loaded.
84+
$enabledApps = $this->appManager->getEnabledApps();
85+
foreach ($enabledApps as $app) {
86+
$this->appManager->loadApp($app);
87+
}
8388
parent::loadRoutes();
8489
$cachedRoutes = $this->serializeRouteCollection($this->root);
8590
$this->cache->set($key, $cachedRoutes, ($this->config->getSystemValueBool('debug') ? 3 : 3600));

0 commit comments

Comments
 (0)