mirror of
https://github.com/nextcloud/server.git
synced 2026-10-08 20:51:14 +02:00
108 lines
4.0 KiB
PHP
108 lines
4.0 KiB
PHP
<?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\StreamTraversableResponse;
|
|
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 StreamTraversableResponse<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 StreamTraversableResponse($this->exportService->export($calendar, $options), Http::STATUS_OK, ['Content-Type' => $contentType]);
|
|
$response->cacheFor(0);
|
|
|
|
return $response;
|
|
}
|
|
}
|