diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 140d93c92..7a8211569 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -90,7 +90,7 @@ jobs: persist-credentials: false submodules: true repository: nextcloud/server - ref: ${{ matrix.server-versions }} + ref: feat/noid/app-password-route-gate - name: Checkout app uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 diff --git a/lib/Controller/EndpointController.php b/lib/Controller/EndpointController.php index d21fc08b0..f18c05bd0 100644 --- a/lib/Controller/EndpointController.php +++ b/lib/Controller/EndpointController.php @@ -10,11 +10,13 @@ namespace OCA\Notifications\Controller; +use NCU\AppFramework\Http\Attribute\TokenScope; use OCA\Notifications\Exceptions\NotificationNotFoundException; use OCA\Notifications\Handler; use OCA\Notifications\Push; use OCA\Notifications\ResponseDefinitions; use OCA\Notifications\Service\ClientService; +use OCA\Notifications\TokenScopes; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\ApiRoute; use OCP\AppFramework\Http\Attribute\NoAdminRequired; @@ -38,6 +40,7 @@ * @psalm-import-type NotificationsNotification from ResponseDefinitions * @psalm-import-type NotificationsNotificationAction from ResponseDefinitions */ +#[TokenScope(scope: TokenScopes::NOTIFICATIONS_READ)] class EndpointController extends OCSController { public function __construct( string $appName, diff --git a/lib/Controller/PushController.php b/lib/Controller/PushController.php index 3fd9d829a..964f792b4 100644 --- a/lib/Controller/PushController.php +++ b/lib/Controller/PushController.php @@ -9,9 +9,11 @@ namespace OCA\Notifications\Controller; +use NCU\AppFramework\Http\Attribute\TokenScope; use OC\Authentication\Token\IProvider; use OC\Security\IdentityProof\Manager; use OCA\Notifications\ResponseDefinitions; +use OCA\Notifications\TokenScopes; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\ApiRoute; use OCP\AppFramework\Http\Attribute\NoAdminRequired; @@ -32,6 +34,7 @@ * @psalm-import-type NotificationsPushDevice from ResponseDefinitions */ #[OpenAPI(scope: 'push')] +#[TokenScope(scope: TokenScopes::NOTIFICATIONS_READ)] class PushController extends OCSController { public function __construct( string $appName, diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index d3523612a..11790ef55 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -9,9 +9,11 @@ namespace OCA\Notifications\Controller; +use NCU\AppFramework\Http\Attribute\TokenScope; use OCA\Notifications\AppInfo\Application; use OCA\Notifications\Model\Settings; use OCA\Notifications\Model\SettingsMapper; +use OCA\Notifications\TokenScopes; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\ApiRoute; use OCP\AppFramework\Http\Attribute\NoAdminRequired; @@ -48,6 +50,7 @@ public function __construct( #[NoAdminRequired] #[OpenAPI] #[ApiRoute(verb: 'POST', url: '/api/{apiVersion}/settings', requirements: ['apiVersion' => '(v2)'])] + #[TokenScope(scope: TokenScopes::NOTIFICATIONS_READ)] public function personal(int $batchSetting, string $soundNotification, string $soundTalk): DataResponse { $this->settingsMapper->setBatchSettingForUser($this->settingsMapper->getSettingsByUser($this->userId), $batchSetting); diff --git a/lib/Controller/WebPushController.php b/lib/Controller/WebPushController.php index 844bbf4b5..32217b161 100644 --- a/lib/Controller/WebPushController.php +++ b/lib/Controller/WebPushController.php @@ -9,8 +9,10 @@ namespace OCA\Notifications\Controller; +use NCU\AppFramework\Http\Attribute\TokenScope; use OC\Authentication\Token\IProvider; use OC\Security\IdentityProof\Manager; +use OCA\Notifications\TokenScopes; use OCA\Notifications\WebPush\ActivationSubStatus; use OCA\Notifications\WebPush\NewSubStatus; use OCA\Notifications\WebPushClient; @@ -35,6 +37,7 @@ use Symfony\Component\Uid\Uuid; #[OpenAPI(scope: 'webpush')] +#[TokenScope(scope: TokenScopes::NOTIFICATIONS_READ)] class WebPushController extends OCSController { public function __construct( string $appName, diff --git a/lib/TokenScopes.php b/lib/TokenScopes.php new file mode 100644 index 000000000..aaf6aead1 --- /dev/null +++ b/lib/TokenScopes.php @@ -0,0 +1,17 @@ + [EndpointController::class], + 'push registration' => [PushController::class], + 'web push registration' => [WebPushController::class], + ]; + } + + #[DataProvider('openControllers')] + public function testOpenControllers(string $class): void { + $attribute = (new \ReflectionClass($class))->getAttributes(TokenScope::class)[0]; + $this->assertSame(TokenScopes::NOTIFICATIONS_READ, $attribute->getArguments()['scope']); + } + + public function testPersonalSettingsOnly(): void { + $personal = (new \ReflectionMethod(SettingsController::class, 'personal'))->getAttributes(TokenScope::class)[0]; + $this->assertSame(TokenScopes::NOTIFICATIONS_READ, $personal->getArguments()['scope']); + $this->assertSame([], (new \ReflectionMethod(SettingsController::class, 'admin'))->getAttributes(TokenScope::class)); + $this->assertSame([], (new \ReflectionClass(SettingsController::class))->getAttributes(TokenScope::class)); + } + + public static function closedControllers(): array { + return [ + 'admin' => [APIController::class], + ]; + } + + #[DataProvider('closedControllers')] + public function testClosedControllers(string $class): void { + $class = new \ReflectionClass($class); + $this->assertSame([], $class->getAttributes(TokenScope::class)); + foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { + $this->assertSame([], $method->getAttributes(TokenScope::class), $method->getName()); + } + } +}