Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/dav/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@
'OCA\\DAV\\SystemTag\\SystemTagsObjectMappingCollection' => $baseDir . '/../lib/SystemTag/SystemTagsObjectMappingCollection.php',
'OCA\\DAV\\SystemTag\\SystemTagsObjectTypeCollection' => $baseDir . '/../lib/SystemTag/SystemTagsObjectTypeCollection.php',
'OCA\\DAV\\SystemTag\\SystemTagsRelationsCollection' => $baseDir . '/../lib/SystemTag/SystemTagsRelationsCollection.php',
'OCA\\DAV\\TokenScopes' => $baseDir . '/../lib/TokenScopes.php',
'OCA\\DAV\\Traits\\PrincipalProxyTrait' => $baseDir . '/../lib/Traits/PrincipalProxyTrait.php',
'OCA\\DAV\\Upload\\AssemblyStream' => $baseDir . '/../lib/Upload/AssemblyStream.php',
'OCA\\DAV\\Upload\\ChunkingPlugin' => $baseDir . '/../lib/Upload/ChunkingPlugin.php',
Expand Down
1 change: 1 addition & 0 deletions apps/dav/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\SystemTag\\SystemTagsObjectMappingCollection' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagsObjectMappingCollection.php',
'OCA\\DAV\\SystemTag\\SystemTagsObjectTypeCollection' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagsObjectTypeCollection.php',
'OCA\\DAV\\SystemTag\\SystemTagsRelationsCollection' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagsRelationsCollection.php',
'OCA\\DAV\\TokenScopes' => __DIR__ . '/..' . '/../lib/TokenScopes.php',
'OCA\\DAV\\Traits\\PrincipalProxyTrait' => __DIR__ . '/..' . '/../lib/Traits/PrincipalProxyTrait.php',
'OCA\\DAV\\Upload\\AssemblyStream' => __DIR__ . '/..' . '/../lib/Upload/AssemblyStream.php',
'OCA\\DAV\\Upload\\ChunkingPlugin' => __DIR__ . '/..' . '/../lib/Upload/ChunkingPlugin.php',
Expand Down
3 changes: 3 additions & 0 deletions apps/dav/lib/Controller/CalendarExportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

namespace OCA\DAV\Controller;

use NCU\AppFramework\Http\Attribute\TokenScope;
use OCA\DAV\AppInfo\Application;
use OCA\DAV\CalDAV\Export\ExportService;
use OCA\DAV\TokenScopes;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\ApiRoute;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
Expand Down Expand Up @@ -55,6 +57,7 @@ public function __construct(
#[ApiRoute(verb: 'POST', url: '/export', root: '/calendar')]
#[UserRateLimit(limit: 1, period: 60)]
#[NoAdminRequired]
#[TokenScope(scope: TokenScopes::CALENDAR_READ)]
public function export(string $target, ?string $type = null, ?array $options = null, ?string $user = null) {
$calendarId = $target;
$format = $type ?? 'ical';
Expand Down
3 changes: 3 additions & 0 deletions apps/dav/lib/Controller/CalendarImportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
namespace OCA\DAV\Controller;

use InvalidArgumentException;
use NCU\AppFramework\Http\Attribute\TokenScope;
/**
* @psalm-type CalendarImportResult = array{items: list<string>, total: non-negative-int}
*/
use OCA\DAV\AppInfo\Application;
use OCA\DAV\CalDAV\CalendarImpl;
use OCA\DAV\CalDAV\Import\ImportService;
use OCA\DAV\TokenScopes;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\ApiRoute;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
Expand Down Expand Up @@ -62,6 +64,7 @@ public function __construct(
#[ApiRoute(verb: 'POST', url: '/import', root: '/calendar')]
#[UserRateLimit(limit: 10, period: 3600)]
#[NoAdminRequired]
#[TokenScope(scope: TokenScopes::CALENDAR_WRITE)]
public function import(string $transaction, string $target, array $options, string $data, ?string $user = null): DataResponse|StreamTraversableResponse {
$calendarId = $target;
$format = isset($options['format']) ? $options['format'] : null;
Expand Down
3 changes: 3 additions & 0 deletions apps/dav/lib/Controller/ContactsImportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
namespace OCA\DAV\Controller;

use InvalidArgumentException;
use NCU\AppFramework\Http\Attribute\TokenScope;
/**
* @psalm-type ContactsImportResult = array{items: list<string>, total: non-negative-int}
*/
use OCA\DAV\AppInfo\Application;
use OCA\DAV\CardDAV\Import\ImportService;
use OCA\DAV\TokenScopes;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\ApiRoute;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
Expand Down Expand Up @@ -62,6 +64,7 @@ public function __construct(
#[ApiRoute(verb: 'POST', url: '/import', root: '/contacts')]
#[UserRateLimit(limit: 10, period: 3600)]
#[NoAdminRequired]
#[TokenScope(scope: TokenScopes::CONTACTS_WRITE)]
public function import(string $transaction, string $target, array $options, string $data, ?string $user = null): DataResponse|StreamTraversableResponse {
$addressBookId = $target;
$format = isset($options['format']) ? $options['format'] : null;
Expand Down
3 changes: 3 additions & 0 deletions apps/dav/lib/Controller/DirectController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace OCA\DAV\Controller;

use NCU\AppFramework\Http\Attribute\TokenScope;
use OCA\DAV\Db\Direct;
use OCA\DAV\Db\DirectMapper;
use OCP\AppFramework\Http;
Expand Down Expand Up @@ -58,6 +59,8 @@ public function __construct(
* 200: Direct link returned
*/
#[NoAdminRequired]
// Not OCA\Files_Sharing\TokenScopes::SHARES_WRITE: files_sharing can be disabled, and its classes don't load then
#[TokenScope(scope: 'files_sharing:shares:write')]
public function getUrl(int $fileId, int $expirationTime = 60 * 60 * 8): DataResponse {
if (!$this->shareManager->shareApiAllowLinks()) {
throw new OCSForbiddenException('Creating direct links is disabled');
Expand Down
5 changes: 5 additions & 0 deletions apps/dav/lib/Controller/FederatedCalendarController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@

namespace OCA\DAV\Controller;

use NCU\AppFramework\Http\Attribute\TokenScope;
use OCA\DAV\AppInfo\Application;
use OCA\DAV\CalDAV\Federation\FederatedCalendarEntity;
use OCA\DAV\CalDAV\Federation\FederatedCalendarInvitationService;
use OCA\DAV\CalDAV\Federation\FederatedCalendarMapper;
use OCA\DAV\ResponseDefinitions;
use OCA\DAV\TokenScopes;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
Expand Down Expand Up @@ -44,6 +46,7 @@ public function __construct(
* 401: When the user is not logged in
*/
#[NoAdminRequired]
#[TokenScope(scope: TokenScopes::CALENDAR_READ)]
public function getPending(): DataResponse {
if ($this->userId === null) {
return new DataResponse(null, Http::STATUS_UNAUTHORIZED);
Expand Down Expand Up @@ -76,6 +79,7 @@ public function getPending(): DataResponse {
* 200: Invitation accepted successfully
*/
#[NoAdminRequired]
#[TokenScope(scope: TokenScopes::CALENDAR_WRITE)]
public function accept(int $id): DataResponse {
$this->invitationService->accept($this->getPendingCalendar($id));
return new DataResponse(null);
Expand All @@ -91,6 +95,7 @@ public function accept(int $id): DataResponse {
* 200: Invitation declined successfully
*/
#[NoAdminRequired]
#[TokenScope(scope: TokenScopes::CALENDAR_WRITE)]
public function decline(int $id): DataResponse {
$this->invitationService->decline($this->getPendingCalendar($id));
return new DataResponse(null);
Expand Down
6 changes: 6 additions & 0 deletions apps/dav/lib/Controller/OutOfOfficeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
namespace OCA\DAV\Controller;

use DateTimeImmutable;
use NCU\AppFramework\Http\Attribute\TokenScope;
use OCA\DAV\ResponseDefinitions;
use OCA\DAV\Service\AbsenceService;
use OCA\DAV\TokenScopes;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
Expand Down Expand Up @@ -50,6 +52,7 @@ public function __construct(
* 404: No out-of-office data was found
*/
#[NoAdminRequired]
#[TokenScope(scope: TokenScopes::CALENDAR_READ)]
public function getCurrentOutOfOfficeData(string $userId): DataResponse {
$user = $this->userManager->get($userId);
if ($user === null) {
Expand Down Expand Up @@ -77,6 +80,7 @@ public function getCurrentOutOfOfficeData(string $userId): DataResponse {
* 404: No out-of-office data was found
*/
#[NoAdminRequired]
#[TokenScope(scope: TokenScopes::CALENDAR_READ)]
public function getOutOfOffice(string $userId): DataResponse {
try {
$data = $this->absenceService->getAbsence($userId);
Expand Down Expand Up @@ -115,6 +119,7 @@ public function getOutOfOffice(string $userId): DataResponse {
* 404: When the replacementUserId was provided but replacement user was not found
*/
#[NoAdminRequired]
#[TokenScope(scope: TokenScopes::CALENDAR_WRITE)]
public function setOutOfOffice(
string $firstDay,
string $lastDay,
Expand Down Expand Up @@ -176,6 +181,7 @@ public function setOutOfOffice(
* 401: When the user is not logged in
*/
#[NoAdminRequired]
#[TokenScope(scope: TokenScopes::CALENDAR_WRITE)]
public function clearOutOfOffice(): DataResponse {
$user = $this->userSession?->getUser();
if ($user === null) {
Expand Down
3 changes: 3 additions & 0 deletions apps/dav/lib/Controller/UpcomingEventsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@

namespace OCA\DAV\Controller;

use NCU\AppFramework\Http\Attribute\TokenScope;
use OCA\DAV\AppInfo\Application;
use OCA\DAV\CalDAV\UpcomingEvent;
use OCA\DAV\CalDAV\UpcomingEventsService;
use OCA\DAV\ResponseDefinitions;
use OCA\DAV\TokenScopes;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\DataResponse;
Expand Down Expand Up @@ -41,6 +43,7 @@ public function __construct(
* 401: When not authenticated
*/
#[NoAdminRequired]
#[TokenScope(scope: TokenScopes::CALENDAR_READ)]
public function getEvents(?string $location = null): DataResponse {
if ($this->userId === null) {
return new DataResponse(null, Http::STATUS_UNAUTHORIZED);
Expand Down
20 changes: 20 additions & 0 deletions apps/dav/lib/TokenScopes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\DAV;

/**
* App password scopes for calendars and address books
*/
class TokenScopes {
public const CALENDAR_READ = 'dav:calendar:read';
public const CALENDAR_WRITE = 'dav:calendar:write';
public const CONTACTS_READ = 'dav:contacts:read';
public const CONTACTS_WRITE = 'dav:contacts:write';
}
3 changes: 3 additions & 0 deletions apps/files/lib/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@

namespace OCA\Files\Controller;

use NCU\AppFramework\Http\Attribute\TokenScope;
use OC\Files\Node\Node;
use OCA\Files\Helper;
use OCA\Files\ResponseDefinitions;
use OCA\Files\Service\TagService;
use OCA\Files\Service\UserConfig;
use OCA\Files\Service\ViewConfig;
use OCA\Files\TokenScopes;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\ApiRoute;
Expand Down Expand Up @@ -53,6 +55,7 @@
*
* @package OCA\Files\Controller
*/
#[TokenScope(scope: TokenScopes::FILES_WRITE)]
class ApiController extends Controller {
private ?Folder $userFolder = null;

Expand Down
3 changes: 3 additions & 0 deletions apps/files/lib/Controller/OpenLocalEditorController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@

namespace OCA\Files\Controller;

use NCU\AppFramework\Http\Attribute\TokenScope;
use OCA\Files\Db\OpenLocalEditor;
use OCA\Files\Db\OpenLocalEditorMapper;
use OCA\Files\TokenScopes;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\BruteForceProtection;
Expand All @@ -25,6 +27,7 @@
use OCP\Security\ISecureRandom;
use Psr\Log\LoggerInterface;

#[TokenScope(scope: TokenScopes::FILES_WRITE)]
final class OpenLocalEditorController extends OCSController {
public const int TOKEN_LENGTH = 128;

Expand Down
3 changes: 3 additions & 0 deletions apps/files/lib/Controller/TransferOwnershipController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@

namespace OCA\Files\Controller;

use NCU\AppFramework\Http\Attribute\TokenScope;
use OCA\Files\BackgroundJob\TransferOwnership;
use OCA\Files\Db\TransferOwnership as TransferOwnershipEntity;
use OCA\Files\Db\TransferOwnershipMapper;
use OCA\Files\TokenScopes;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
Expand All @@ -26,6 +28,7 @@
use OCP\IUserManager;
use OCP\Notification\IManager as NotificationManager;

#[TokenScope(scope: TokenScopes::FILES_WRITE)]
final class TransferOwnershipController extends OCSController {

public function __construct(
Expand Down
3 changes: 3 additions & 0 deletions apps/files_sharing/lib/Controller/AcceptController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

namespace OCA\Files_Sharing\Controller;

use NCU\AppFramework\Http\Attribute\TokenScope;
use OCA\Files\TokenScopes;
use OCA\Files_Sharing\AppInfo\Application;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
Expand Down Expand Up @@ -78,6 +80,7 @@ public function showAccept(string $shareId): Response {
}

#[NoAdminRequired]
#[TokenScope(scope: TokenScopes::FILES_WRITE)]
public function accept(string $shareId): Response {
try {
$share = $this->shareManager->getShareById($shareId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

namespace OCA\Files_Sharing\Controller;

use NCU\AppFramework\Http\Attribute\TokenScope;
use OCA\Deck\Sharing\ShareAPIHelper;
use OCA\Files\TokenScopes;
use OCA\Files_Sharing\ResponseDefinitions;
use OCP\App\IAppManager;
use OCP\AppFramework\Http;
Expand All @@ -35,6 +37,7 @@
/**
* @psalm-import-type Files_SharingDeletedShare from ResponseDefinitions
*/
#[TokenScope(scope: TokenScopes::FILES_WRITE)]
class DeletedShareAPIController extends OCSController {

public function __construct(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

namespace OCA\Files_Sharing\Controller;

use NCU\AppFramework\Http\Attribute\TokenScope;
use OCA\Files\TokenScopes;
use OCA\Files_Sharing\BackgroundJob\ExternalShareScanJob;
use OCA\Files_Sharing\External\Manager;
use OCP\AppFramework\Controller;
Expand All @@ -24,6 +26,7 @@
*
* @package OCA\Files_Sharing\Controller
*/
#[TokenScope(scope: TokenScopes::FILES_WRITE)]
class ExternalSharesController extends Controller {
public function __construct(
string $appName,
Expand Down
3 changes: 3 additions & 0 deletions apps/files_sharing/lib/Controller/PublicPreviewController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

namespace OCA\Files_Sharing\Controller;

use NCU\AppFramework\Http\Attribute\TokenScope;
use OCA\Files\TokenScopes;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\AppFramework\Http\Attribute\NoSameSiteCookieRequired;
Expand All @@ -29,6 +31,7 @@
use OCP\Share\IManager as ShareManager;
use OCP\Share\IShare;

#[TokenScope(scope: TokenScopes::FILES_READ)]
class PublicPreviewController extends PublicShareController {

private IShare $share;
Expand Down
3 changes: 3 additions & 0 deletions apps/files_sharing/lib/Controller/RemoteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

namespace OCA\Files_Sharing\Controller;

use NCU\AppFramework\Http\Attribute\TokenScope;
use OCA\Files\TokenScopes;
use OCA\Files_Sharing\External\ExternalShare;
use OCA\Files_Sharing\External\Manager;
use OCA\Files_Sharing\ResponseDefinitions;
Expand All @@ -28,6 +30,7 @@
* @psalm-import-type Files_SharingRemoteShare from ResponseDefinitions
* @api
*/
#[TokenScope(scope: TokenScopes::FILES_WRITE)]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldnt this be allowing to write shares?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accepting mounts the share into your own files, so I decided to go with files write. The sharing write scope is for creating shares only, and a client without it should still be able to accept incoming shares. Happy to change it if you disagree?

class RemoteController extends OCSController {
/**
* Remote controller constructor.
Expand Down
3 changes: 3 additions & 0 deletions apps/files_sharing/lib/Controller/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@

namespace OCA\Files_Sharing\Controller;

use NCU\AppFramework\Http\Attribute\TokenScope;
use OCA\Files\TokenScopes;
use OCA\Files_Sharing\AppInfo\Application;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\JSONResponse;
use OCP\IConfig;
use OCP\IRequest;

#[TokenScope(scope: TokenScopes::FILES_WRITE)]
class SettingsController extends Controller {

public function __construct(
Expand Down
Loading
Loading