From c57c3c15734c153d541247cc5fca198cb0e4f7b6 Mon Sep 17 00:00:00 2001 From: provokateurin Date: Thu, 25 Jul 2024 13:24:59 +0200 Subject: [PATCH] refactor(core): Replace security annotations with respective attributes Signed-off-by: provokateurin --- core/Controller/AppPasswordController.php | 19 +++++----- core/Controller/AutoCompleteController.php | 4 +- core/Controller/AvatarController.php | 28 ++++++-------- core/Controller/CSRFTokenController.php | 8 ++-- core/Controller/ClientFlowLoginController.php | 20 +++++----- .../ClientFlowLoginV2Controller.php | 37 ++++++++----------- .../CollaborationResourcesController.php | 22 ++++------- core/Controller/ContactsMenuController.php | 7 ++-- core/Controller/CssController.php | 6 ++- core/Controller/ErrorController.php | 14 +++---- core/Controller/GuestAvatarController.php | 12 +++--- core/Controller/HoverCardController.php | 4 +- core/Controller/JsController.php | 6 ++- core/Controller/LoginController.php | 23 ++++++------ core/Controller/LostController.php | 29 +++++++-------- core/Controller/NavigationController.php | 12 +++--- core/Controller/OCJSController.php | 6 ++- core/Controller/OCMController.php | 6 ++- core/Controller/OCSController.php | 19 ++++------ core/Controller/PreviewController.php | 12 +++--- core/Controller/ProfileApiController.php | 9 +++-- core/Controller/ProfilePageController.php | 10 ++--- core/Controller/RecommendedAppsController.php | 3 +- core/Controller/ReferenceApiController.php | 26 +++++-------- core/Controller/ReferenceController.php | 7 ++-- core/Controller/SearchController.php | 5 +-- core/Controller/TranslationApiController.php | 13 ++++--- .../TwoFactorChallengeController.php | 31 +++++++--------- core/Controller/UnifiedSearchController.php | 12 +++--- .../UnsupportedBrowserController.php | 7 ++-- core/Controller/UserController.php | 4 +- core/Controller/WalledGardenController.php | 8 ++-- core/Controller/WebAuthnController.php | 11 ++---- core/Controller/WellKnownController.php | 7 ++-- core/Controller/WhatsNewController.php | 7 ++-- core/Controller/WipeController.php | 21 +++++------ .../testapp/lib/Controller/PageController.php | 8 ++-- lib/public/AppFramework/ApiController.php | 5 +-- .../AuthPublicShareController.php | 7 ---- 39 files changed, 225 insertions(+), 270 deletions(-) diff --git a/core/Controller/AppPasswordController.php b/core/Controller/AppPasswordController.php index c36b34cce1f5c..c72d352441925 100644 --- a/core/Controller/AppPasswordController.php +++ b/core/Controller/AppPasswordController.php @@ -14,6 +14,9 @@ use OC\User\Session; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\ApiRoute; +use OCP\AppFramework\Http\Attribute\BruteForceProtection; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired; use OCP\AppFramework\Http\Attribute\UseSession; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSForbiddenException; @@ -45,9 +48,6 @@ public function __construct( } /** - * @NoAdminRequired - * @PasswordConfirmationRequired - * * Create app password * * @return DataResponse @@ -55,6 +55,8 @@ public function __construct( * * 200: App password returned */ + #[NoAdminRequired] + #[PasswordConfirmationRequired] #[ApiRoute(verb: 'GET', url: '/getapppassword', root: '/core')] public function getAppPassword(): DataResponse { // We do not allow the creation of new tokens if this is an app password @@ -98,8 +100,6 @@ public function getAppPassword(): DataResponse { } /** - * @NoAdminRequired - * * Delete app password * * @return DataResponse, array{}> @@ -107,6 +107,7 @@ public function getAppPassword(): DataResponse { * * 200: App password deleted successfully */ + #[NoAdminRequired] #[ApiRoute(verb: 'DELETE', url: '/apppassword', root: '/core')] public function deleteAppPassword(): DataResponse { if (!$this->session->exists('app_password')) { @@ -126,8 +127,6 @@ public function deleteAppPassword(): DataResponse { } /** - * @NoAdminRequired - * * Rotate app password * * @return DataResponse @@ -135,6 +134,7 @@ public function deleteAppPassword(): DataResponse { * * 200: App password returned */ + #[NoAdminRequired] #[ApiRoute(verb: 'POST', url: '/apppassword/rotate', root: '/core')] public function rotateAppPassword(): DataResponse { if (!$this->session->exists('app_password')) { @@ -160,9 +160,6 @@ public function rotateAppPassword(): DataResponse { /** * Confirm the user password * - * @NoAdminRequired - * @BruteForceProtection(action=sudo) - * * @param string $password The password of the user * * @return DataResponse|DataResponse, array{}> @@ -170,6 +167,8 @@ public function rotateAppPassword(): DataResponse { * 200: Password confirmation succeeded * 403: Password confirmation failed */ + #[NoAdminRequired] + #[BruteForceProtection('sudo')] #[UseSession] #[ApiRoute(verb: 'PUT', url: '/apppassword/confirm', root: '/core')] public function confirmUserPassword(string $password): DataResponse { diff --git a/core/Controller/AutoCompleteController.php b/core/Controller/AutoCompleteController.php index 02d525e1f7ad4..6a5071aed16bb 100644 --- a/core/Controller/AutoCompleteController.php +++ b/core/Controller/AutoCompleteController.php @@ -11,6 +11,7 @@ use OC\Core\ResponseDefinitions; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\ApiRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\Collaboration\AutoComplete\AutoCompleteEvent; @@ -36,8 +37,6 @@ public function __construct( } /** - * @NoAdminRequired - * * Autocomplete a query * * @param string $search Text to search for @@ -51,6 +50,7 @@ public function __construct( * * 200: Autocomplete results returned */ + #[NoAdminRequired] #[ApiRoute(verb: 'GET', url: '/autocomplete/get', root: '/core')] public function get(string $search, ?string $itemType, ?string $itemId, ?string $sorter = null, array $shareTypes = [IShare::TYPE_USER], int $limit = 10): DataResponse { // if enumeration/user listings are disabled, we'll receive an empty diff --git a/core/Controller/AvatarController.php b/core/Controller/AvatarController.php index dac2df37ac357..3126b2600d975 100644 --- a/core/Controller/AvatarController.php +++ b/core/Controller/AvatarController.php @@ -11,6 +11,9 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\DataDisplayResponse; use OCP\AppFramework\Http\FileDisplayResponse; use OCP\AppFramework\Http\JSONResponse; @@ -47,10 +50,7 @@ public function __construct( } /** - * @NoAdminRequired - * @NoCSRFRequired * @NoSameSiteCookieRequired - * @PublicPage * * Get the dark avatar * @@ -63,6 +63,8 @@ public function __construct( * 201: Avatar returned * 404: Avatar not found */ + #[NoCSRFRequired] + #[PublicPage] #[FrontpageRoute(verb: 'GET', url: '/avatar/{userId}/{size}/dark')] public function getAvatarDark(string $userId, int $size, bool $guestFallback = false) { if ($size <= 64) { @@ -99,10 +101,7 @@ public function getAvatarDark(string $userId, int $size, bool $guestFallback = f /** - * @NoAdminRequired - * @NoCSRFRequired * @NoSameSiteCookieRequired - * @PublicPage * * Get the avatar * @@ -115,6 +114,8 @@ public function getAvatarDark(string $userId, int $size, bool $guestFallback = f * 201: Avatar returned * 404: Avatar not found */ + #[NoCSRFRequired] + #[PublicPage] #[FrontpageRoute(verb: 'GET', url: '/avatar/{userId}/{size}')] public function getAvatar(string $userId, int $size, bool $guestFallback = false) { if ($size <= 64) { @@ -149,9 +150,7 @@ public function getAvatar(string $userId, int $size, bool $guestFallback = false return $response; } - /** - * @NoAdminRequired - */ + #[NoAdminRequired] #[FrontpageRoute(verb: 'POST', url: '/avatar/')] public function postAvatar(?string $path = null): JSONResponse { $files = $this->request->getUploadedFile('files'); @@ -271,9 +270,7 @@ public function postAvatar(?string $path = null): JSONResponse { } } - /** - * @NoAdminRequired - */ + #[NoAdminRequired] #[FrontpageRoute(verb: 'DELETE', url: '/avatar/')] public function deleteAvatar(): JSONResponse { try { @@ -287,10 +284,9 @@ public function deleteAvatar(): JSONResponse { } /** - * @NoAdminRequired - * * @return JSONResponse|DataDisplayResponse */ + #[NoAdminRequired] #[FrontpageRoute(verb: 'GET', url: '/avatar/tmp')] public function getTmpAvatar() { $tmpAvatar = $this->cache->get('tmpAvatar'); @@ -315,9 +311,7 @@ public function getTmpAvatar() { return $resp; } - /** - * @NoAdminRequired - */ + #[NoAdminRequired] #[FrontpageRoute(verb: 'POST', url: '/avatar/cropped')] public function postCroppedAvatar(?array $crop = null): JSONResponse { if (is_null($crop)) { diff --git a/core/Controller/CSRFTokenController.php b/core/Controller/CSRFTokenController.php index c4e7b81279ffb..c3d1a7f842b28 100644 --- a/core/Controller/CSRFTokenController.php +++ b/core/Controller/CSRFTokenController.php @@ -12,6 +12,8 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\JSONResponse; use OCP\IRequest; @@ -27,15 +29,13 @@ public function __construct( /** * Returns a new CSRF token. * - * @NoAdminRequired - * @NoCSRFRequired - * @PublicPage - * * @return JSONResponse|JSONResponse, array{}> * * 200: CSRF token returned * 403: Strict cookie check failed */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/csrftoken')] public function index(): JSONResponse { if (!$this->request->passesStrictCookieCheck()) { diff --git a/core/Controller/ClientFlowLoginController.php b/core/Controller/ClientFlowLoginController.php index 38aeb785b3bb2..ccf70cc9d30c3 100644 --- a/core/Controller/ClientFlowLoginController.php +++ b/core/Controller/ClientFlowLoginController.php @@ -15,7 +15,10 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\Attribute\UseSession; use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\StandaloneTemplateResponse; @@ -82,10 +85,8 @@ private function stateTokenForbiddenResponse(): StandaloneTemplateResponse { return $response; } - /** - * @PublicPage - * @NoCSRFRequired - */ + #[PublicPage] + #[NoCSRFRequired] #[UseSession] #[FrontpageRoute(verb: 'GET', url: '/login/flow')] public function showAuthPickerPage(string $clientIdentifier = '', string $user = '', int $direct = 0): StandaloneTemplateResponse { @@ -150,10 +151,10 @@ public function showAuthPickerPage(string $clientIdentifier = '', string $user = } /** - * @NoAdminRequired - * @NoCSRFRequired * @NoSameSiteCookieRequired */ + #[NoAdminRequired] + #[NoCSRFRequired] #[UseSession] #[FrontpageRoute(verb: 'GET', url: '/login/flow/grant')] public function grantPage(string $stateToken = '', @@ -203,10 +204,9 @@ public function grantPage(string $stateToken = '', } /** - * @NoAdminRequired - * * @return Http\RedirectResponse|Response */ + #[NoAdminRequired] #[UseSession] #[FrontpageRoute(verb: 'POST', url: '/login/flow')] public function generateAppPassword(string $stateToken, @@ -297,9 +297,7 @@ public function generateAppPassword(string $stateToken, return new Http\RedirectResponse($redirectUri); } - /** - * @PublicPage - */ + #[PublicPage] #[FrontpageRoute(verb: 'POST', url: '/login/flow/apptoken')] public function apptokenRedirect(string $stateToken, string $user, string $password): Response { if (!$this->isValidToken($stateToken)) { diff --git a/core/Controller/ClientFlowLoginV2Controller.php b/core/Controller/ClientFlowLoginV2Controller.php index bfa455ebe925e..76c8ed2921a9f 100644 --- a/core/Controller/ClientFlowLoginV2Controller.php +++ b/core/Controller/ClientFlowLoginV2Controller.php @@ -15,7 +15,10 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\Attribute\UseSession; use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\RedirectResponse; @@ -55,9 +58,6 @@ public function __construct( } /** - * @NoCSRFRequired - * @PublicPage - * * Poll the login flow credentials * * @param string $token Token of the flow @@ -66,6 +66,8 @@ public function __construct( * 200: Login flow credentials returned * 404: Login flow not found or completed */ + #[NoCSRFRequired] + #[PublicPage] #[FrontpageRoute(verb: 'POST', url: '/login/v2/poll')] public function poll(string $token): JSONResponse { try { @@ -77,10 +79,8 @@ public function poll(string $token): JSONResponse { return new JSONResponse($creds->jsonSerialize()); } - /** - * @NoCSRFRequired - * @PublicPage - */ + #[NoCSRFRequired] + #[PublicPage] #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] #[UseSession] #[FrontpageRoute(verb: 'GET', url: '/login/v2/flow/{token}')] @@ -96,10 +96,8 @@ public function landing(string $token, $user = ''): Response { ); } - /** - * @NoCSRFRequired - * @PublicPage - */ + #[NoCSRFRequired] + #[PublicPage] #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] #[UseSession] #[FrontpageRoute(verb: 'GET', url: '/login/v2/flow')] @@ -131,10 +129,10 @@ public function showAuthPickerPage($user = ''): StandaloneTemplateResponse { } /** - * @NoAdminRequired - * @NoCSRFRequired * @NoSameSiteCookieRequired */ + #[NoAdminRequired] + #[NoCSRFRequired] #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] #[UseSession] #[FrontpageRoute(verb: 'GET', url: '/login/v2/grant')] @@ -170,9 +168,7 @@ public function grantPage(?string $stateToken): StandaloneTemplateResponse { ); } - /** - * @PublicPage - */ + #[PublicPage] #[FrontpageRoute(verb: 'POST', url: '/login/v2/apptoken')] public function apptokenRedirect(?string $stateToken, string $user, string $password) { if ($stateToken === null) { @@ -217,9 +213,7 @@ public function apptokenRedirect(?string $stateToken, string $user, string $pass return $this->handleFlowDone($result); } - /** - * @NoAdminRequired - */ + #[NoAdminRequired] #[UseSession] #[FrontpageRoute(verb: 'POST', url: '/login/v2/grant')] public function generateAppPassword(?string $stateToken): Response { @@ -270,15 +264,14 @@ private function handleFlowDone(bool $result): StandaloneTemplateResponse { } /** - * @NoCSRFRequired - * @PublicPage - * * Init a login flow * * @return JSONResponse * * 200: Login flow init returned */ + #[NoCSRFRequired] + #[PublicPage] #[FrontpageRoute(verb: 'POST', url: '/login/v2')] public function init(): JSONResponse { // Get client user agent diff --git a/core/Controller/CollaborationResourcesController.php b/core/Controller/CollaborationResourcesController.php index 6cc351d9cdccc..6f27789c56633 100644 --- a/core/Controller/CollaborationResourcesController.php +++ b/core/Controller/CollaborationResourcesController.php @@ -13,6 +13,7 @@ use OC\Core\ResponseDefinitions; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\ApiRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\Collaboration\Resources\CollectionException; @@ -55,8 +56,6 @@ protected function getCollection(int $collectionId): ICollection { } /** - * @NoAdminRequired - * * Get a collection * * @param int $collectionId ID of the collection @@ -65,6 +64,7 @@ protected function getCollection(int $collectionId): ICollection { * 200: Collection returned * 404: Collection not found */ + #[NoAdminRequired] #[ApiRoute(verb: 'GET', url: '/resources/collections/{collectionId}', root: '/collaboration')] public function listCollection(int $collectionId): DataResponse { try { @@ -77,8 +77,6 @@ public function listCollection(int $collectionId): DataResponse { } /** - * @NoAdminRequired - * * Search for collections * * @param string $filter Filter collections @@ -87,6 +85,7 @@ public function listCollection(int $collectionId): DataResponse { * 200: Collections returned * 404: Collection not found */ + #[NoAdminRequired] #[ApiRoute(verb: 'GET', url: '/resources/collections/search/{filter}', root: '/collaboration')] public function searchCollections(string $filter): DataResponse { try { @@ -99,8 +98,6 @@ public function searchCollections(string $filter): DataResponse { } /** - * @NoAdminRequired - * * Add a resource to a collection * * @param int $collectionId ID of the collection @@ -111,6 +108,7 @@ public function searchCollections(string $filter): DataResponse { * 200: Collection returned * 404: Collection not found or resource inaccessible */ + #[NoAdminRequired] #[ApiRoute(verb: 'POST', url: '/resources/collections/{collectionId}', root: '/collaboration')] public function addResource(int $collectionId, string $resourceType, string $resourceId): DataResponse { try { @@ -134,8 +132,6 @@ public function addResource(int $collectionId, string $resourceType, string $res } /** - * @NoAdminRequired - * * Remove a resource from a collection * * @param int $collectionId ID of the collection @@ -146,6 +142,7 @@ public function addResource(int $collectionId, string $resourceType, string $res * 200: Collection returned * 404: Collection or resource not found */ + #[NoAdminRequired] #[ApiRoute(verb: 'DELETE', url: '/resources/collections/{collectionId}', root: '/collaboration')] public function removeResource(int $collectionId, string $resourceType, string $resourceId): DataResponse { try { @@ -166,8 +163,6 @@ public function removeResource(int $collectionId, string $resourceType, string $ } /** - * @NoAdminRequired - * * Get collections by resource * * @param string $resourceType Type of the resource @@ -177,6 +172,7 @@ public function removeResource(int $collectionId, string $resourceType, string $ * 200: Collections returned * 404: Resource not accessible */ + #[NoAdminRequired] #[ApiRoute(verb: 'GET', url: '/resources/{resourceType}/{resourceId}', root: '/collaboration')] public function getCollectionsByResource(string $resourceType, string $resourceId): DataResponse { try { @@ -193,8 +189,6 @@ public function getCollectionsByResource(string $resourceType, string $resourceI } /** - * @NoAdminRequired - * * Create a collection for a resource * * @param string $baseResourceType Type of the base resource @@ -206,6 +200,7 @@ public function getCollectionsByResource(string $resourceType, string $resourceI * 400: Creating collection is not possible * 404: Resource inaccessible */ + #[NoAdminRequired] #[ApiRoute(verb: 'POST', url: '/resources/{baseResourceType}/{baseResourceId}', root: '/collaboration')] public function createCollectionOnResource(string $baseResourceType, string $baseResourceId, string $name): DataResponse { if (!isset($name[0]) || isset($name[64])) { @@ -229,8 +224,6 @@ public function createCollectionOnResource(string $baseResourceType, string $bas } /** - * @NoAdminRequired - * * Rename a collection * * @param int $collectionId ID of the collection @@ -240,6 +233,7 @@ public function createCollectionOnResource(string $baseResourceType, string $bas * 200: Collection returned * 404: Collection not found */ + #[NoAdminRequired] #[ApiRoute(verb: 'PUT', url: '/resources/collections/{collectionId}', root: '/collaboration')] public function renameCollection(int $collectionId, string $collectionName): DataResponse { try { diff --git a/core/Controller/ContactsMenuController.php b/core/Controller/ContactsMenuController.php index 6f4e026c5589e..f4ded1ed42b00 100644 --- a/core/Controller/ContactsMenuController.php +++ b/core/Controller/ContactsMenuController.php @@ -10,6 +10,7 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\JSONResponse; use OCP\IRequest; use OCP\IUserSession; @@ -24,22 +25,20 @@ public function __construct( } /** - * @NoAdminRequired - * * @return \JsonSerializable[] * @throws Exception */ + #[NoAdminRequired] #[FrontpageRoute(verb: 'POST', url: '/contactsmenu/contacts')] public function index(?string $filter = null): array { return $this->manager->getEntries($this->userSession->getUser(), $filter); } /** - * @NoAdminRequired - * * @return JSONResponse|\JsonSerializable * @throws Exception */ + #[NoAdminRequired] #[FrontpageRoute(verb: 'POST', url: '/contactsmenu/findOne')] public function findOne(int $shareType, string $shareWith) { $contact = $this->manager->findOne($this->userSession->getUser(), $shareType, $shareWith); diff --git a/core/Controller/CssController.php b/core/Controller/CssController.php index c6a2478428651..345b70fe2d332 100644 --- a/core/Controller/CssController.php +++ b/core/Controller/CssController.php @@ -12,7 +12,9 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\FileDisplayResponse; use OCP\AppFramework\Http\NotFoundResponse; use OCP\AppFramework\Http\Response; @@ -39,14 +41,14 @@ public function __construct( } /** - * @PublicPage - * @NoCSRFRequired * @NoSameSiteCookieRequired * * @param string $fileName css filename with extension * @param string $appName css folder name * @return FileDisplayResponse|NotFoundResponse */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/css/{appName}/{fileName}')] public function getCss(string $fileName, string $appName): Response { try { diff --git a/core/Controller/ErrorController.php b/core/Controller/ErrorController.php index 573ac4e218f73..55925ffc941f2 100644 --- a/core/Controller/ErrorController.php +++ b/core/Controller/ErrorController.php @@ -11,15 +11,15 @@ use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\TemplateResponse; #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] class ErrorController extends \OCP\AppFramework\Controller { - /** - * @PublicPage - * @NoCSRFRequired - */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: 'error/403')] public function error403(): TemplateResponse { $response = new TemplateResponse( @@ -32,10 +32,8 @@ public function error403(): TemplateResponse { return $response; } - /** - * @PublicPage - * @NoCSRFRequired - */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: 'error/404')] public function error404(): TemplateResponse { $response = new TemplateResponse( diff --git a/core/Controller/GuestAvatarController.php b/core/Controller/GuestAvatarController.php index 3121abc2ca1e7..6a7edc9cfcc44 100644 --- a/core/Controller/GuestAvatarController.php +++ b/core/Controller/GuestAvatarController.php @@ -8,6 +8,8 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\FileDisplayResponse; use OCP\AppFramework\Http\Response; use OCP\IAvatarManager; @@ -33,9 +35,6 @@ public function __construct( /** * Returns a guest avatar image response * - * @PublicPage - * @NoCSRFRequired - * * @param string $guestName The guest name, e.g. "Albert" * @param string $size The desired avatar size, e.g. 64 for 64x64px * @param bool|null $darkTheme Return dark avatar @@ -44,6 +43,8 @@ public function __construct( * 200: Custom avatar returned * 201: Avatar returned */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/avatar/guest/{guestName}/{size}')] public function getAvatar(string $guestName, string $size, ?bool $darkTheme = false) { $size = (int) $size; @@ -87,9 +88,6 @@ public function getAvatar(string $guestName, string $size, ?bool $darkTheme = fa /** * Returns a dark guest avatar image response * - * @PublicPage - * @NoCSRFRequired - * * @param string $guestName The guest name, e.g. "Albert" * @param string $size The desired avatar size, e.g. 64 for 64x64px * @return FileDisplayResponse|Response @@ -97,6 +95,8 @@ public function getAvatar(string $guestName, string $size, ?bool $darkTheme = fa * 200: Custom avatar returned * 201: Avatar returned */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/avatar/guest/{guestName}/{size}/dark')] public function getAvatarDark(string $guestName, string $size) { return $this->getAvatar($guestName, $size, true); diff --git a/core/Controller/HoverCardController.php b/core/Controller/HoverCardController.php index 89ca3576dbe04..588cef2a72d09 100644 --- a/core/Controller/HoverCardController.php +++ b/core/Controller/HoverCardController.php @@ -11,6 +11,7 @@ use OC\Core\ResponseDefinitions; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\ApiRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\DataResponse; use OCP\IRequest; use OCP\IUserSession; @@ -29,8 +30,6 @@ public function __construct( } /** - * @NoAdminRequired - * * Get the account details for a hovercard * * @param string $userId ID of the user @@ -39,6 +38,7 @@ public function __construct( * 200: Account details returned * 404: Account not found */ + #[NoAdminRequired] #[ApiRoute(verb: 'GET', url: '/v1/{userId}', root: '/hovercard')] public function getUser(string $userId): DataResponse { $contact = $this->manager->findOne($this->userSession->getUser(), IShare::TYPE_USER, $userId); diff --git a/core/Controller/JsController.php b/core/Controller/JsController.php index ef54e7e9ee9d9..f5fe381688d51 100644 --- a/core/Controller/JsController.php +++ b/core/Controller/JsController.php @@ -12,7 +12,9 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\FileDisplayResponse; use OCP\AppFramework\Http\NotFoundResponse; use OCP\AppFramework\Http\Response; @@ -39,14 +41,14 @@ public function __construct( } /** - * @PublicPage - * @NoCSRFRequired * @NoSameSiteCookieRequired * * @param string $fileName js filename with extension * @param string $appName js folder name * @return FileDisplayResponse|NotFoundResponse */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/js/{appName}/{fileName}')] public function getJs(string $fileName, string $appName): Response { try { diff --git a/core/Controller/LoginController.php b/core/Controller/LoginController.php index 87a02e8af8e70..a84f28a52d558 100644 --- a/core/Controller/LoginController.php +++ b/core/Controller/LoginController.php @@ -20,9 +20,12 @@ use OCP\App\IAppManager; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\BruteForceProtection; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\Attribute\UseSession; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\RedirectResponse; @@ -65,10 +68,9 @@ public function __construct( } /** - * @NoAdminRequired - * * @return RedirectResponse */ + #[NoAdminRequired] #[UseSession] #[FrontpageRoute(verb: 'GET', url: '/logout')] public function logout() { @@ -97,14 +99,13 @@ public function logout() { } /** - * @PublicPage - * @NoCSRFRequired - * * @param string $user * @param string $redirect_url * * @return TemplateResponse|RedirectResponse */ + #[NoCSRFRequired] + #[PublicPage] #[UseSession] #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] #[FrontpageRoute(verb: 'GET', url: '/login')] @@ -269,12 +270,11 @@ private function generateRedirect(?string $redirectUrl): RedirectResponse { } /** - * @PublicPage - * @NoCSRFRequired - * @BruteForceProtection(action=login) - * * @return RedirectResponse */ + #[NoCSRFRequired] + #[PublicPage] + #[BruteForceProtection('login')] #[UseSession] #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] #[FrontpageRoute(verb: 'POST', url: '/login')] @@ -377,9 +377,6 @@ private function createLoginFailedResponse( /** * Confirm the user password * - * @NoAdminRequired - * @BruteForceProtection(action=sudo) - * * @license GNU AGPL version 3 or any later version * * @param string $password The password of the user @@ -389,6 +386,8 @@ private function createLoginFailedResponse( * 200: Password confirmation succeeded * 403: Password confirmation failed */ + #[NoAdminRequired] + #[BruteForceProtection('sudo')] #[UseSession] #[NoCSRFRequired] #[FrontpageRoute(verb: 'POST', url: '/login/confirm')] diff --git a/core/Controller/LostController.php b/core/Controller/LostController.php index d6f5ccd8da83f..a40624e814ac0 100644 --- a/core/Controller/LostController.php +++ b/core/Controller/LostController.php @@ -15,8 +15,12 @@ use OC\Security\RateLimiting\Exception\RateLimitExceededException; use OC\Security\RateLimiting\Limiter; use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\Attribute\AnonRateLimit; +use OCP\AppFramework\Http\Attribute\BruteForceProtection; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; @@ -74,12 +78,11 @@ public function __construct( /** * Someone wants to reset their password: - * - * @PublicPage - * @NoCSRFRequired - * @BruteForceProtection(action=passwordResetEmail) - * @AnonRateThrottle(limit=10, period=300) */ + #[PublicPage] + #[NoCSRFRequired] + #[BruteForceProtection('passwordResetEmail')] + #[AnonRateLimit(10, 300)] #[FrontpageRoute(verb: 'GET', url: '/lostpassword/reset/form/{token}/{userId}')] public function resetform(string $token, string $userId): TemplateResponse { try { @@ -140,11 +143,9 @@ private function success(array $data = []): array { return array_merge($data, ['status' => 'success']); } - /** - * @PublicPage - * @BruteForceProtection(action=passwordResetEmail) - * @AnonRateThrottle(limit=10, period=300) - */ + #[PublicPage] + #[BruteForceProtection('passwordResetEmail')] + #[AnonRateLimit(10, 300)] #[FrontpageRoute(verb: 'POST', url: '/lostpassword/email')] public function email(string $user): JSONResponse { if ($this->config->getSystemValue('lost_password_link', '') !== '') { @@ -178,11 +179,9 @@ public function email(string $user): JSONResponse { return $response; } - /** - * @PublicPage - * @BruteForceProtection(action=passwordResetEmail) - * @AnonRateThrottle(limit=10, period=300) - */ + #[PublicPage] + #[BruteForceProtection('passwordResetEmail')] + #[AnonRateLimit(10, 300)] #[FrontpageRoute(verb: 'POST', url: '/lostpassword/set/{token}/{userId}')] public function setPassword(string $token, string $userId, string $password, bool $proceed): JSONResponse { if ($this->encryptionManager->isEnabled() && !$proceed) { diff --git a/core/Controller/NavigationController.php b/core/Controller/NavigationController.php index 856561161447c..44c8ef0880b20 100644 --- a/core/Controller/NavigationController.php +++ b/core/Controller/NavigationController.php @@ -8,6 +8,8 @@ use OC\Core\ResponseDefinitions; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\ApiRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\INavigationManager; @@ -28,9 +30,6 @@ public function __construct( } /** - * @NoAdminRequired - * @NoCSRFRequired - * * Get the apps navigation * * @param bool $absolute Rewrite URLs to absolute ones @@ -39,6 +38,8 @@ public function __construct( * 200: Apps navigation returned * 304: No apps navigation changed */ + #[NoAdminRequired] + #[NoCSRFRequired] #[ApiRoute(verb: 'GET', url: '/navigation/apps', root: '/core')] public function getAppsNavigation(bool $absolute = false): DataResponse { $navigation = $this->navigationManager->getAll(); @@ -56,9 +57,6 @@ public function getAppsNavigation(bool $absolute = false): DataResponse { } /** - * @NoAdminRequired - * @NoCSRFRequired - * * Get the settings navigation * * @param bool $absolute Rewrite URLs to absolute ones @@ -67,6 +65,8 @@ public function getAppsNavigation(bool $absolute = false): DataResponse { * 200: Apps navigation returned * 304: No apps navigation changed */ + #[NoAdminRequired] + #[NoCSRFRequired] #[ApiRoute(verb: 'GET', url: '/navigation/settings', root: '/core')] public function getSettingsNavigation(bool $absolute = false): DataResponse { $navigation = $this->navigationManager->getAll('settings'); diff --git a/core/Controller/OCJSController.php b/core/Controller/OCJSController.php index 8a6193d2e5341..3a0922c9344d0 100644 --- a/core/Controller/OCJSController.php +++ b/core/Controller/OCJSController.php @@ -14,7 +14,9 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\DataDisplayResponse; use OCP\Defaults; use OCP\IConfig; @@ -67,10 +69,10 @@ public function __construct( } /** - * @NoCSRFRequired * @NoTwoFactorRequired - * @PublicPage */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/core/js/oc.js')] public function getConfig(): DataDisplayResponse { $data = $this->helper->getConfig(); diff --git a/core/Controller/OCMController.php b/core/Controller/OCMController.php index f8110278b2093..d79b5b1669e43 100644 --- a/core/Controller/OCMController.php +++ b/core/Controller/OCMController.php @@ -13,6 +13,8 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\DataResponse; use OCP\Capabilities\ICapability; use OCP\IConfig; @@ -39,8 +41,6 @@ public function __construct( * generate a OCMProvider with local data and send it as DataResponse. * This replaces the old PHP file ocm-provider/index.php * - * @PublicPage - * @NoCSRFRequired * @psalm-suppress MoreSpecificReturnType * @psalm-suppress LessSpecificReturnStatement * @return DataResponse|DataResponse @@ -48,6 +48,8 @@ public function __construct( * 200: OCM Provider details returned * 500: OCM not supported */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/ocm-provider/')] public function discovery(): DataResponse { try { diff --git a/core/Controller/OCSController.php b/core/Controller/OCSController.php index d4da85752d8a5..450b8205fd3c5 100644 --- a/core/Controller/OCSController.php +++ b/core/Controller/OCSController.php @@ -9,7 +9,9 @@ use OC\Security\IdentityProof\Manager; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\ApiRoute; +use OCP\AppFramework\Http\Attribute\BruteForceProtection; use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\DataResponse; use OCP\IRequest; use OCP\IUserManager; @@ -27,9 +29,7 @@ public function __construct( parent::__construct($appName, $request); } - /** - * @PublicPage - */ + #[PublicPage] #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] #[ApiRoute(verb: 'GET', url: '/config', root: '')] public function getConfig(): DataResponse { @@ -45,14 +45,13 @@ public function getConfig(): DataResponse { } /** - * @PublicPage - * * Get the capabilities * * @return DataResponse}, array{}> * * 200: Capabilities returned */ + #[PublicPage] #[ApiRoute(verb: 'GET', url: '/capabilities', root: '/cloud')] public function getCapabilities(): DataResponse { $result = []; @@ -77,10 +76,8 @@ public function getCapabilities(): DataResponse { return $response; } - /** - * @PublicPage - * @BruteForceProtection(action=login) - */ + #[PublicPage] + #[BruteForceProtection('login')] #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] #[ApiRoute(verb: 'POST', url: '/check', root: '/person')] public function personCheck(string $login = '', string $password = ''): DataResponse { @@ -100,9 +97,7 @@ public function personCheck(string $login = '', string $password = ''): DataResp return new DataResponse([], 101); } - /** - * @PublicPage - */ + #[PublicPage] #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] #[ApiRoute(verb: 'GET', url: '/key/{cloudId}', root: '/identityproof')] public function getIdentityProof(string $cloudId): DataResponse { diff --git a/core/Controller/PreviewController.php b/core/Controller/PreviewController.php index 4ace295a6aa9c..a3b826c19e64d 100644 --- a/core/Controller/PreviewController.php +++ b/core/Controller/PreviewController.php @@ -12,6 +12,8 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\FileDisplayResponse; use OCP\AppFramework\Http\RedirectResponse; @@ -36,9 +38,6 @@ public function __construct( } /** - * @NoAdminRequired - * @NoCSRFRequired - * * Get a preview by file path * * @param string $file Path of the file @@ -56,6 +55,8 @@ public function __construct( * 403: Getting preview is not allowed * 404: Preview not found */ + #[NoAdminRequired] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/core/preview.png')] public function getPreview( string $file = '', @@ -80,9 +81,6 @@ public function getPreview( } /** - * @NoAdminRequired - * @NoCSRFRequired - * * Get a preview by file ID * * @param int $fileId ID of the file @@ -100,6 +98,8 @@ public function getPreview( * 403: Getting preview is not allowed * 404: Preview not found */ + #[NoAdminRequired] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/core/preview')] public function getPreviewByFileId( int $fileId = -1, diff --git a/core/Controller/ProfileApiController.php b/core/Controller/ProfileApiController.php index f8f7e77db0db4..cc36a486afcd5 100644 --- a/core/Controller/ProfileApiController.php +++ b/core/Controller/ProfileApiController.php @@ -13,6 +13,9 @@ use OC\Profile\ProfileManager; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\ApiRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired; +use OCP\AppFramework\Http\Attribute\UserRateLimit; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSBadRequestException; use OCP\AppFramework\OCS\OCSForbiddenException; @@ -34,10 +37,7 @@ public function __construct( } /** - * @NoAdminRequired * @NoSubAdminRequired - * @PasswordConfirmationRequired - * @UserRateThrottle(limit=40, period=600) * * Update the visibility of a parameter * @@ -51,6 +51,9 @@ public function __construct( * * 200: Visibility updated successfully */ + #[NoAdminRequired] + #[PasswordConfirmationRequired] + #[UserRateLimit(40, 600)] #[ApiRoute(verb: 'PUT', url: '/{targetUserId}', root: '/profile')] public function setVisibility(string $targetUserId, string $paramId, string $visibility): DataResponse { $requestingUser = $this->userSession->getUser(); diff --git a/core/Controller/ProfilePageController.php b/core/Controller/ProfilePageController.php index 73a6be5f65c4c..7463173e906d8 100644 --- a/core/Controller/ProfilePageController.php +++ b/core/Controller/ProfilePageController.php @@ -14,7 +14,9 @@ use OCP\AppFramework\Http\Attribute\AnonRateLimit; use OCP\AppFramework\Http\Attribute\BruteForceProtection; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\Attribute\UserRateLimit; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; @@ -44,12 +46,8 @@ public function __construct( parent::__construct($appName, $request); } - /** - * @PublicPage - * @NoCSRFRequired - * @NoAdminRequired - * @NoSubAdminRequired - */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/u/{targetUserId}')] #[BruteForceProtection(action: 'user')] #[UserRateLimit(limit: 30, period: 120)] diff --git a/core/Controller/RecommendedAppsController.php b/core/Controller/RecommendedAppsController.php index 9d14cc5327896..ba35bc8705e4a 100644 --- a/core/Controller/RecommendedAppsController.php +++ b/core/Controller/RecommendedAppsController.php @@ -10,6 +10,7 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\StandaloneTemplateResponse; @@ -28,9 +29,9 @@ public function __construct( } /** - * @NoCSRFRequired * @return Response */ + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/core/apps/recommended')] public function index(): Response { $defaultPageUrl = $this->urlGenerator->linkToDefaultPageUrl(); diff --git a/core/Controller/ReferenceApiController.php b/core/Controller/ReferenceApiController.php index e12cedfe927f3..cba91b976e261 100644 --- a/core/Controller/ReferenceApiController.php +++ b/core/Controller/ReferenceApiController.php @@ -12,6 +12,8 @@ use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\AnonRateLimit; use OCP\AppFramework\Http\Attribute\ApiRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\DataResponse; use OCP\Collaboration\Reference\IDiscoverableReferenceProvider; use OCP\Collaboration\Reference\IReferenceManager; @@ -35,8 +37,6 @@ public function __construct( } /** - * @NoAdminRequired - * * Extract references from a text * * @param string $text Text to extract from @@ -46,6 +46,7 @@ public function __construct( * * 200: References returned */ + #[NoAdminRequired] #[ApiRoute(verb: 'POST', url: '/extract', root: '/references')] public function extract(string $text, bool $resolve = false, int $limit = 1): DataResponse { $references = $this->referenceManager->extractReferences($text); @@ -66,8 +67,6 @@ public function extract(string $text, bool $resolve = false, int $limit = 1): Da } /** - * @PublicPage - * * Extract references from a text * * @param string $text Text to extract from @@ -79,6 +78,7 @@ public function extract(string $text, bool $resolve = false, int $limit = 1): Da * 200: References returned */ #[ApiRoute(verb: 'POST', url: '/extractPublic', root: '/references')] + #[PublicPage] #[AnonRateLimit(limit: 10, period: 120)] public function extractPublic(string $text, string $sharingToken, bool $resolve = false, int $limit = 1): DataResponse { $references = $this->referenceManager->extractReferences($text); @@ -99,8 +99,6 @@ public function extractPublic(string $text, string $sharingToken, bool $resolve } /** - * @NoAdminRequired - * * Resolve a reference * * @param string $reference Reference to resolve @@ -108,6 +106,7 @@ public function extractPublic(string $text, string $sharingToken, bool $resolve * * 200: Reference returned */ + #[NoAdminRequired] #[ApiRoute(verb: 'GET', url: '/resolve', root: '/references')] public function resolveOne(string $reference): DataResponse { /** @var ?CoreReference $resolvedReference */ @@ -119,8 +118,6 @@ public function resolveOne(string $reference): DataResponse { } /** - * @PublicPage - * * Resolve from a public page * * @param string $reference Reference to resolve @@ -130,6 +127,7 @@ public function resolveOne(string $reference): DataResponse { * 200: Reference returned */ #[ApiRoute(verb: 'GET', url: '/resolvePublic', root: '/references')] + #[PublicPage] #[AnonRateLimit(limit: 10, period: 120)] public function resolveOnePublic(string $reference, string $sharingToken): DataResponse { /** @var ?CoreReference $resolvedReference */ @@ -141,8 +139,6 @@ public function resolveOnePublic(string $reference, string $sharingToken): DataR } /** - * @NoAdminRequired - * * Resolve multiple references * * @param string[] $references References to resolve @@ -151,6 +147,7 @@ public function resolveOnePublic(string $reference, string $sharingToken): DataR * * 200: References returned */ + #[NoAdminRequired] #[ApiRoute(verb: 'POST', url: '/resolve', root: '/references')] public function resolve(array $references, int $limit = 1): DataResponse { $result = []; @@ -169,8 +166,6 @@ public function resolve(array $references, int $limit = 1): DataResponse { } /** - * @PublicPage - * * Resolve multiple references from a public page * * @param string[] $references References to resolve @@ -181,6 +176,7 @@ public function resolve(array $references, int $limit = 1): DataResponse { * 200: References returned */ #[ApiRoute(verb: 'POST', url: '/resolvePublic', root: '/references')] + #[PublicPage] #[AnonRateLimit(limit: 10, period: 120)] public function resolvePublic(array $references, string $sharingToken, int $limit = 1): DataResponse { $result = []; @@ -199,14 +195,13 @@ public function resolvePublic(array $references, string $sharingToken, int $limi } /** - * @NoAdminRequired - * * Get the providers * * @return DataResponse * * 200: Providers returned */ + #[NoAdminRequired] #[ApiRoute(verb: 'GET', url: '/providers', root: '/references')] public function getProvidersInfo(): DataResponse { $providers = $this->referenceManager->getDiscoverableProviders(); @@ -217,8 +212,6 @@ public function getProvidersInfo(): DataResponse { } /** - * @NoAdminRequired - * * Touch a provider * * @param string $providerId ID of the provider @@ -227,6 +220,7 @@ public function getProvidersInfo(): DataResponse { * * 200: Provider touched */ + #[NoAdminRequired] #[ApiRoute(verb: 'PUT', url: '/provider/{providerId}', root: '/references')] public function touchProvider(string $providerId, ?int $timestamp = null): DataResponse { if ($this->userId !== null) { diff --git a/core/Controller/ReferenceController.php b/core/Controller/ReferenceController.php index 523edcdbbfafc..b4c88562bc900 100644 --- a/core/Controller/ReferenceController.php +++ b/core/Controller/ReferenceController.php @@ -11,6 +11,8 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\DataDownloadResponse; use OCP\AppFramework\Http\DataResponse; use OCP\Collaboration\Reference\IReferenceManager; @@ -30,9 +32,6 @@ public function __construct( } /** - * @PublicPage - * @NoCSRFRequired - * * Get a preview for a reference * * @param string $referenceId the reference cache key @@ -41,6 +40,8 @@ public function __construct( * 200: Preview returned * 404: Reference not found */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/core/references/preview/{referenceId}')] public function preview(string $referenceId): DataDownloadResponse|DataResponse { $reference = $this->referenceManager->getReferenceByCacheKey($referenceId); diff --git a/core/Controller/SearchController.php b/core/Controller/SearchController.php index 1ca8dd5dae490..166e2bad53bec 100644 --- a/core/Controller/SearchController.php +++ b/core/Controller/SearchController.php @@ -10,6 +10,7 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\JSONResponse; use OCP\IRequest; use OCP\ISearch; @@ -26,9 +27,7 @@ public function __construct( parent::__construct($appName, $request); } - /** - * @NoAdminRequired - */ + #[NoAdminRequired] #[FrontpageRoute(verb: 'GET', url: '/core/search')] public function search(string $query, array $inApps = [], int $page = 1, int $size = 30): JSONResponse { $results = $this->searcher->searchPaged($query, $inApps, $page, $size); diff --git a/core/Controller/TranslationApiController.php b/core/Controller/TranslationApiController.php index 3cccaadc7c18b..3a919e1f79ad3 100644 --- a/core/Controller/TranslationApiController.php +++ b/core/Controller/TranslationApiController.php @@ -12,7 +12,10 @@ use InvalidArgumentException; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\AnonRateLimit; use OCP\AppFramework\Http\Attribute\ApiRoute; +use OCP\AppFramework\Http\Attribute\PublicPage; +use OCP\AppFramework\Http\Attribute\UserRateLimit; use OCP\AppFramework\Http\DataResponse; use OCP\IL10N; use OCP\IRequest; @@ -31,14 +34,13 @@ public function __construct( } /** - * @PublicPage - * * Get the list of supported languages * * @return DataResponse * * 200: Supported languages returned */ + #[PublicPage] #[ApiRoute(verb: 'GET', url: '/languages', root: '/translation')] public function languages(): DataResponse { return new DataResponse([ @@ -48,10 +50,6 @@ public function languages(): DataResponse { } /** - * @PublicPage - * @UserRateThrottle(limit=25, period=120) - * @AnonRateThrottle(limit=10, period=120) - * * Translate a text * * @param string $text Text to be translated @@ -63,6 +61,9 @@ public function languages(): DataResponse { * 400: Language not detected or unable to translate * 412: Translating is not possible */ + #[PublicPage] + #[UserRateLimit(25, 120)] + #[AnonRateLimit(10, 120)] #[ApiRoute(verb: 'POST', url: '/translate', root: '/translation')] public function translate(string $text, ?string $fromLanguage, string $toLanguage): DataResponse { try { diff --git a/core/Controller/TwoFactorChallengeController.php b/core/Controller/TwoFactorChallengeController.php index ee84cbd2aa983..153e1e7559a6a 100644 --- a/core/Controller/TwoFactorChallengeController.php +++ b/core/Controller/TwoFactorChallengeController.php @@ -11,6 +11,8 @@ use OC_User; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; use OCP\AppFramework\Http\Attribute\UseSession; use OCP\AppFramework\Http\RedirectResponse; @@ -64,13 +66,13 @@ private function splitProvidersAndBackupCodes(array $providers): array { } /** - * @NoAdminRequired - * @NoCSRFRequired * @TwoFactorSetUpDoneRequired * * @param string $redirect_url * @return StandaloneTemplateResponse */ + #[NoAdminRequired] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/login/selectchallenge')] public function selectChallenge($redirect_url) { $user = $this->userSession->getUser(); @@ -91,14 +93,14 @@ public function selectChallenge($redirect_url) { } /** - * @NoAdminRequired - * @NoCSRFRequired * @TwoFactorSetUpDoneRequired * * @param string $challengeProviderId * @param string $redirect_url * @return StandaloneTemplateResponse|RedirectResponse */ + #[NoAdminRequired] + #[NoCSRFRequired] #[UseSession] #[FrontpageRoute(verb: 'GET', url: '/login/challenge/{challengeProviderId}')] public function showChallenge($challengeProviderId, $redirect_url) { @@ -143,8 +145,6 @@ public function showChallenge($challengeProviderId, $redirect_url) { } /** - * @NoAdminRequired - * @NoCSRFRequired * @TwoFactorSetUpDoneRequired * * @UserRateThrottle(limit=5, period=100) @@ -154,6 +154,8 @@ public function showChallenge($challengeProviderId, $redirect_url) { * @param string $redirect_url * @return RedirectResponse */ + #[NoAdminRequired] + #[NoCSRFRequired] #[UseSession] #[FrontpageRoute(verb: 'POST', url: '/login/challenge/{challengeProviderId}')] public function solveChallenge($challengeProviderId, $challenge, $redirect_url = null) { @@ -189,10 +191,8 @@ public function solveChallenge($challengeProviderId, $challenge, $redirect_url = ])); } - /** - * @NoAdminRequired - * @NoCSRFRequired - */ + #[NoAdminRequired] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: 'login/setupchallenge')] public function setupProviders(?string $redirect_url = null): StandaloneTemplateResponse { $user = $this->userSession->getUser(); @@ -207,10 +207,8 @@ public function setupProviders(?string $redirect_url = null): StandaloneTemplate return new StandaloneTemplateResponse($this->appName, 'twofactorsetupselection', $data, 'guest'); } - /** - * @NoAdminRequired - * @NoCSRFRequired - */ + #[NoAdminRequired] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: 'login/setupchallenge/{providerId}')] public function setupProvider(string $providerId, ?string $redirect_url = null) { $user = $this->userSession->getUser(); @@ -241,11 +239,10 @@ public function setupProvider(string $providerId, ?string $redirect_url = null) } /** - * @NoAdminRequired - * @NoCSRFRequired - * * @todo handle the extreme edge case of an invalid provider ID and redirect to the provider selection page */ + #[NoAdminRequired] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'POST', url: 'login/setupchallenge/{providerId}')] public function confirmProviderSetup(string $providerId, ?string $redirect_url = null) { return new RedirectResponse($this->urlGenerator->linkToRoute( diff --git a/core/Controller/UnifiedSearchController.php b/core/Controller/UnifiedSearchController.php index 236ca845da6a0..20d6fb5e59c23 100644 --- a/core/Controller/UnifiedSearchController.php +++ b/core/Controller/UnifiedSearchController.php @@ -15,6 +15,8 @@ use OC\Search\UnsupportedFilter; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\ApiRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\IRequest; @@ -40,9 +42,6 @@ public function __construct( } /** - * @NoAdminRequired - * @NoCSRFRequired - * * Get the providers for unified search * * @param string $from the url the user is currently at @@ -50,6 +49,8 @@ public function __construct( * * 200: Providers returned */ + #[NoAdminRequired] + #[NoCSRFRequired] #[ApiRoute(verb: 'GET', url: '/providers', root: '/search')] public function getProviders(string $from = ''): DataResponse { [$route, $parameters] = $this->getRouteInformation($from); @@ -61,9 +62,6 @@ public function getProviders(string $from = ''): DataResponse { } /** - * @NoAdminRequired - * @NoCSRFRequired - * * Launch a search for a specific search provider. * * Additional filters are available for each provider. @@ -81,6 +79,8 @@ public function getProviders(string $from = ''): DataResponse { * 200: Search entries returned * 400: Searching is not possible */ + #[NoAdminRequired] + #[NoCSRFRequired] #[ApiRoute(verb: 'GET', url: '/providers/{providerId}/search', root: '/search')] public function search( string $providerId, diff --git a/core/Controller/UnsupportedBrowserController.php b/core/Controller/UnsupportedBrowserController.php index b8efe2539f1b1..2877e2e90472f 100644 --- a/core/Controller/UnsupportedBrowserController.php +++ b/core/Controller/UnsupportedBrowserController.php @@ -11,7 +11,9 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\TemplateResponse; use OCP\IRequest; @@ -24,11 +26,10 @@ public function __construct(IRequest $request) { } /** - * @PublicPage - * @NoCSRFRequired - * * @return Response */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: 'unsupported')] public function index(): Response { Util::addScript('core', 'unsupported-browser'); diff --git a/core/Controller/UserController.php b/core/Controller/UserController.php index 4031f9b1e5f16..b6e464d9a95c9 100644 --- a/core/Controller/UserController.php +++ b/core/Controller/UserController.php @@ -9,6 +9,7 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\JSONResponse; use OCP\IRequest; use OCP\IUserManager; @@ -25,12 +26,11 @@ public function __construct( /** * Lookup user display names * - * @NoAdminRequired - * * @param array $users * * @return JSONResponse */ + #[NoAdminRequired] #[FrontpageRoute(verb: 'POST', url: '/displaynames')] public function getDisplayNames($users) { $result = []; diff --git a/core/Controller/WalledGardenController.php b/core/Controller/WalledGardenController.php index ffb30d30277e5..b55e90675a14a 100644 --- a/core/Controller/WalledGardenController.php +++ b/core/Controller/WalledGardenController.php @@ -8,15 +8,15 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\Response; #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] class WalledGardenController extends Controller { - /** - * @PublicPage - * @NoCSRFRequired - */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '/204')] public function get(): Response { $resp = new Response(); diff --git a/core/Controller/WebAuthnController.php b/core/Controller/WebAuthnController.php index a9d929e5f2ebc..d7255831e88de 100644 --- a/core/Controller/WebAuthnController.php +++ b/core/Controller/WebAuthnController.php @@ -15,6 +15,7 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\Attribute\UseSession; use OCP\AppFramework\Http\JSONResponse; use OCP\IRequest; @@ -39,10 +40,7 @@ public function __construct( parent::__construct($appName, $request); } - /** - * @NoAdminRequired - * @PublicPage - */ + #[PublicPage] #[UseSession] #[FrontpageRoute(verb: 'POST', url: 'login/webauthn/start')] public function startAuthentication(string $loginName): JSONResponse { @@ -64,10 +62,7 @@ public function startAuthentication(string $loginName): JSONResponse { return new JSONResponse($publicKeyCredentialRequestOptions); } - /** - * @NoAdminRequired - * @PublicPage - */ + #[PublicPage] #[UseSession] #[FrontpageRoute(verb: 'POST', url: 'login/webauthn/finish')] public function finishAuthentication(string $data): JSONResponse { diff --git a/core/Controller/WellKnownController.php b/core/Controller/WellKnownController.php index 0e6c440d57018..89a648d6bef53 100644 --- a/core/Controller/WellKnownController.php +++ b/core/Controller/WellKnownController.php @@ -12,7 +12,9 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\Response; use OCP\IRequest; @@ -27,11 +29,10 @@ public function __construct( } /** - * @PublicPage - * @NoCSRFRequired - * * @return Response */ + #[PublicPage] + #[NoCSRFRequired] #[FrontpageRoute(verb: 'GET', url: '.well-known/{service}')] public function handle(string $service): Response { $response = $this->requestManager->process( diff --git a/core/Controller/WhatsNewController.php b/core/Controller/WhatsNewController.php index 1218e2d1f68c5..06b27b0d30228 100644 --- a/core/Controller/WhatsNewController.php +++ b/core/Controller/WhatsNewController.php @@ -11,6 +11,7 @@ use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\ApiRoute; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\DataResponse; use OCP\Defaults; use OCP\IConfig; @@ -36,8 +37,6 @@ public function __construct( } /** - * @NoAdminRequired - * * Get the changes * * @return DataResponse|DataResponse, array{}> @@ -45,6 +44,7 @@ public function __construct( * 200: Changes returned * 204: No changes */ + #[NoAdminRequired] #[ApiRoute(verb: 'GET', url: '/whatsnew', root: '/core')] public function get():DataResponse { $user = $this->userSession->getUser(); @@ -81,8 +81,6 @@ public function get():DataResponse { } /** - * @NoAdminRequired - * * Dismiss the changes * * @param string $version Version to dismiss the changes for @@ -93,6 +91,7 @@ public function get():DataResponse { * * 200: Changes dismissed */ + #[NoAdminRequired] #[ApiRoute(verb: 'POST', url: '/whatsnew', root: '/core')] public function dismiss(string $version):DataResponse { $user = $this->userSession->getUser(); diff --git a/core/Controller/WipeController.php b/core/Controller/WipeController.php index 44f80dc55103e..089e9792a7eb5 100644 --- a/core/Controller/WipeController.php +++ b/core/Controller/WipeController.php @@ -11,7 +11,10 @@ use OC\Authentication\Token\RemoteWipe; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\AnonRateLimit; use OCP\AppFramework\Http\Attribute\FrontpageRoute; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\JSONResponse; use OCP\Authentication\Exceptions\InvalidTokenException; use OCP\IRequest; @@ -26,12 +29,6 @@ public function __construct( } /** - * @NoAdminRequired - * @NoCSRFRequired - * @PublicPage - * - * @AnonRateThrottle(limit=10, period=300) - * * Check if the device should be wiped * * @param string $token App password @@ -41,6 +38,9 @@ public function __construct( * 200: Device should be wiped * 404: Device should not be wiped */ + #[PublicPage] + #[NoCSRFRequired] + #[AnonRateLimit(10, 300)] #[FrontpageRoute(verb: 'POST', url: '/core/wipe/check')] public function checkWipe(string $token): JSONResponse { try { @@ -58,12 +58,6 @@ public function checkWipe(string $token): JSONResponse { /** - * @NoAdminRequired - * @NoCSRFRequired - * @PublicPage - * - * @AnonRateThrottle(limit=10, period=300) - * * Finish the wipe * * @param string $token App password @@ -73,6 +67,9 @@ public function checkWipe(string $token): JSONResponse { * 200: Wipe finished successfully * 404: Device should not be wiped */ + #[PublicPage] + #[NoCSRFRequired] + #[AnonRateLimit(10, 300)] #[FrontpageRoute(verb: 'POST', url: '/core/wipe/success')] public function wipeDone(string $token): JSONResponse { try { diff --git a/cypress/fixtures/testapp/lib/Controller/PageController.php b/cypress/fixtures/testapp/lib/Controller/PageController.php index d32e0277ee043..e7812fa1046f1 100644 --- a/cypress/fixtures/testapp/lib/Controller/PageController.php +++ b/cypress/fixtures/testapp/lib/Controller/PageController.php @@ -9,6 +9,8 @@ use OCA\TestApp\AppInfo\Application; use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\TemplateResponse; use OCP\IRequest; @@ -17,10 +19,8 @@ public function __construct(IRequest $request) { parent::__construct(Application::APP_ID, $request); } - /** - * @NoAdminRequired - * @NoCSRFRequired - */ + #[NoAdminRequired] + #[NoCSRFRequired] public function index(): TemplateResponse { return new TemplateResponse(Application::APP_ID, 'main'); } diff --git a/lib/public/AppFramework/ApiController.php b/lib/public/AppFramework/ApiController.php index da1152090c620..d3c83005ad1bf 100644 --- a/lib/public/AppFramework/ApiController.php +++ b/lib/public/AppFramework/ApiController.php @@ -7,6 +7,7 @@ */ namespace OCP\AppFramework; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\Response; @@ -51,13 +52,11 @@ public function __construct($appName, * This method implements a preflighted cors response for you that you can * link to for the options request * - * @NoAdminRequired - * @NoCSRFRequired - * @PublicPage * @since 7.0.0 */ #[NoCSRFRequired] #[PublicPage] + #[NoAdminRequired] public function preflightedCors() { if (isset($this->request->server['HTTP_ORIGIN'])) { $origin = $this->request->server['HTTP_ORIGIN']; diff --git a/lib/public/AppFramework/AuthPublicShareController.php b/lib/public/AppFramework/AuthPublicShareController.php index d6c088d4a0c5f..9c912d0e9a670 100644 --- a/lib/public/AppFramework/AuthPublicShareController.php +++ b/lib/public/AppFramework/AuthPublicShareController.php @@ -46,9 +46,6 @@ public function __construct(string $appName, } /** - * @PublicPage - * @NoCSRFRequired - * * Show the authentication page * The form has to submit to the authenticate method route * @@ -125,10 +122,6 @@ protected function authSucceeded() { } /** - * @UseSession - * @PublicPage - * @BruteForceProtection(action=publicLinkAuth) - * * Authenticate the share * * @since 14.0.0