You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
nextcloud-server/apps/dav/lib/Controller/CalendarExportController.php

107 lines
4.0 KiB

<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\DAV\Controller;
use OCA\DAV\AppInfo\Application;
use OCA\DAV\CalDAV\Export\ExportService;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\ApiRoute;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\UserRateLimit;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\StreamGeneratorResponse;
use OCP\AppFramework\OCSController;
use OCP\Calendar\CalendarExportOptions;
use OCP\Calendar\ICalendarExport;
use OCP\Calendar\IManager;
use OCP\IGroupManager;
use OCP\IRequest;
use OCP\IUserManager;
use OCP\IUserSession;
class CalendarExportController extends OCSController {
public function __construct(
IRequest $request,
private IUserSession $userSession,
private IUserManager $userManager,
private IGroupManager $groupManager,
private IManager $calendarManager,
private ExportService $exportService,
) {
parent::__construct(Application::APP_ID, $request);
}
/**
* Export calendar data
*
* @param string $target calendar id
* @param string|null $type data format
* @param array{rangeStart:string,rangeCount:positive-int} $options configuration options
* @param string|null $user system user id
*
* @return StreamGeneratorResponse<Http::STATUS_OK, array{Content-Type:'text/calendar; charset=UTF-8'|'application/calendar+json; charset=UTF-8'|'application/calendar+xml; charset=UTF-8'}> | DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_UNAUTHORIZED, array{error?: non-empty-string}, array{}>
*
* 200: data in requested format
* 400: invalid parameters
* 401: user not authorized
*/
#[ApiRoute(verb: 'POST', url: '/export', root: '/calendar')]
#[UserRateLimit(limit: 1, period: 60)]
#[NoAdminRequired]
public function export(string $target, ?string $type = null, ?array $options = null, ?string $user = null) {
$calendarId = $target;
$format = $type ?? 'ical';
$rangeStart = isset($options['rangeStart']) ? (string)$options['rangeStart'] : null;
$rangeCount = isset($options['rangeCount']) ? (int)$options['rangeCount'] : null;
// evaluate if user is logged in and has permissions
if (!$this->userSession->isLoggedIn()) {
return new DataResponse([], Http::STATUS_UNAUTHORIZED);
}
if ($user !== null) {
if ($this->userSession->getUser()->getUID() !== $user
&& $this->groupManager->isAdmin($this->userSession->getUser()->getUID()) === false) {
return new DataResponse([], Http::STATUS_UNAUTHORIZED);
}
if (!$this->userManager->userExists($user)) {
return new DataResponse(['error' => 'user not found'], Http::STATUS_BAD_REQUEST);
}
} else {
$userId = $this->userSession->getUser()->getUID();
}
// retrieve calendar and evaluate if export is supported
$calendars = $this->calendarManager->getCalendarsForPrincipal('principals/users/' . $userId, [$calendarId]);
if ($calendars === []) {
return new DataResponse(['error' => 'calendar not found'], Http::STATUS_BAD_REQUEST);
}
$calendar = $calendars[0];
if (!$calendar instanceof ICalendarExport) {
return new DataResponse(['error' => 'calendar export not supported'], Http::STATUS_BAD_REQUEST);
}
// construct options object
$options = new CalendarExportOptions();
$options->setRangeStart($rangeStart);
$options->setRangeCount($rangeCount);
// evaluate if provided format is supported
if (!in_array($format, ExportService::FORMATS, true)) {
return new DataResponse(['error' => "Format <$format> is not valid."], Http::STATUS_BAD_REQUEST);
}
$options->setFormat($format);
// construct response
$contentType = match (strtolower($options->getFormat())) {
'jcal' => 'application/calendar+json; charset=UTF-8',
'xcal' => 'application/calendar+xml; charset=UTF-8',
default => 'text/calendar; charset=UTF-8'
};
$response = new StreamGeneratorResponse($this->exportService->export($calendar, $options), $contentType, Http::STATUS_OK);
$response->cacheFor(0);
return $response;
}
}