Skip to content

Commit

Permalink
Merge branch 'master' into fix/select-groups-display
Browse files Browse the repository at this point in the history
  • Loading branch information
yannicklescure authored Oct 2, 2024
2 parents 258cb1a + 004d7da commit 1abd28d
Show file tree
Hide file tree
Showing 56 changed files with 615 additions and 161 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\AdminAudit\Tests\Actions;

use OCA\AdminAudit\IAuditLogger;
use OCA\AdminAudit\Listener\UserManagementEventListener;
use OCP\IUser;
use OCP\User\Events\UserChangedEvent;
use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;

class UserManagementEventListenerTest extends TestCase {
private IAuditLogger&MockObject $logger;

private UserManagementEventListener $listener;

private MockObject&IUser $user;

protected function setUp(): void {
parent::setUp();

$this->logger = $this->createMock(IAuditLogger::class);
$this->listener = new UserManagementEventListener($this->logger);

$this->user = $this->createMock(IUser::class);
$this->user->method('getUID')->willReturn('alice');
$this->user->method('getDisplayName')->willReturn('Alice');
}

public function testSkipUnsupported(): void {
$this->logger->expects($this->never())
->method('info');

$event = new UserChangedEvent(
$this->user,
'unsupported',
'value',
);

$this->listener->handle($event);
}

public function testUserEnabled(): void {
$this->logger->expects($this->once())
->method('info')
->with('User enabled: "alice"', ['app' => 'admin_audit']);

$event = new UserChangedEvent(
$this->user,
'enabled',
true,
false,
);

$this->listener->handle($event);
}

public function testUserDisabled(): void {
$this->logger->expects($this->once())
->method('info')
->with('User disabled: "alice"', ['app' => 'admin_audit']);

$event = new UserChangedEvent(
$this->user,
'enabled',
false,
true,
);

$this->listener->handle($event);
}

public function testEmailChanged(): void {
$this->logger->expects($this->once())
->method('info')
->with('Email address changed for user alice', ['app' => 'admin_audit']);

$event = new UserChangedEvent(
$this->user,
'eMailAddress',
'[email protected]',
'',
);

$this->listener->handle($event);
}
}
1 change: 1 addition & 0 deletions apps/dav/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@

<commands>
<command>OCA\DAV\Command\CreateAddressBook</command>
<command>OCA\DAV\Command\ListAddressbooks</command>
<command>OCA\DAV\Command\CreateCalendar</command>
<command>OCA\DAV\Command\CreateSubscription</command>
<command>OCA\DAV\Command\DeleteCalendar</command>
Expand Down
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 @@ -156,6 +156,7 @@
'OCA\\DAV\\Command\\CreateSubscription' => $baseDir . '/../lib/Command/CreateSubscription.php',
'OCA\\DAV\\Command\\DeleteCalendar' => $baseDir . '/../lib/Command/DeleteCalendar.php',
'OCA\\DAV\\Command\\FixCalendarSyncCommand' => $baseDir . '/../lib/Command/FixCalendarSyncCommand.php',
'OCA\\DAV\\Command\\ListAddressbooks' => $baseDir . '/../lib/Command/ListAddressbooks.php',
'OCA\\DAV\\Command\\ListCalendars' => $baseDir . '/../lib/Command/ListCalendars.php',
'OCA\\DAV\\Command\\MoveCalendar' => $baseDir . '/../lib/Command/MoveCalendar.php',
'OCA\\DAV\\Command\\RemoveInvalidShares' => $baseDir . '/../lib/Command/RemoveInvalidShares.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 @@ -171,6 +171,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Command\\CreateSubscription' => __DIR__ . '/..' . '/../lib/Command/CreateSubscription.php',
'OCA\\DAV\\Command\\DeleteCalendar' => __DIR__ . '/..' . '/../lib/Command/DeleteCalendar.php',
'OCA\\DAV\\Command\\FixCalendarSyncCommand' => __DIR__ . '/..' . '/../lib/Command/FixCalendarSyncCommand.php',
'OCA\\DAV\\Command\\ListAddressbooks' => __DIR__ . '/..' . '/../lib/Command/ListAddressbooks.php',
'OCA\\DAV\\Command\\ListCalendars' => __DIR__ . '/..' . '/../lib/Command/ListCalendars.php',
'OCA\\DAV\\Command\\MoveCalendar' => __DIR__ . '/..' . '/../lib/Command/MoveCalendar.php',
'OCA\\DAV\\Command\\RemoveInvalidShares' => __DIR__ . '/..' . '/../lib/Command/RemoveInvalidShares.php',
Expand Down
1 change: 1 addition & 0 deletions apps/dav/l10n/uk.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ OC.L10N.register(
"Accounts" : "Облікові записи",
"System address book which holds all accounts" : "Системна адресна книга, в якій містяться всі облікові записи",
"File is not updatable: %1$s" : "Файл не оновлюється: %1$s",
"Failed to get storage for file" : "Не вдалося отримати дані про сховище для файлу",
"Could not write to final file, canceled by hook" : "Не вдалося записати в остаточний файл, скасовано перехопленням",
"Could not write file contents" : "Не вдалося записати вміст файлу",
"_%n byte_::_%n bytes_" : ["%n байт","%n байтів","%n байтів","%n байтів"],
Expand Down
1 change: 1 addition & 0 deletions apps/dav/l10n/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
"Accounts" : "Облікові записи",
"System address book which holds all accounts" : "Системна адресна книга, в якій містяться всі облікові записи",
"File is not updatable: %1$s" : "Файл не оновлюється: %1$s",
"Failed to get storage for file" : "Не вдалося отримати дані про сховище для файлу",
"Could not write to final file, canceled by hook" : "Не вдалося записати в остаточний файл, скасовано перехопленням",
"Could not write file contents" : "Не вдалося записати вміст файлу",
"_%n byte_::_%n bytes_" : ["%n байт","%n байтів","%n байтів","%n байтів"],
Expand Down
145 changes: 58 additions & 87 deletions apps/dav/lib/CalDAV/WebcalCaching/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,11 @@
namespace OCA\DAV\CalDAV\WebcalCaching;

use Exception;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\RequestOptions;
use OCP\Http\Client\IClientService;
use OCP\Http\Client\LocalServerException;
use OCP\IAppConfig;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Xml\Property\Href;
use Sabre\VObject\Reader;

class Connection {
Expand All @@ -31,107 +27,82 @@ public function __construct(
/**
* gets webcal feed from remote server
*/
public function queryWebcalFeed(array $subscription, array &$mutations): ?string {
$client = $this->clientService->newClient();

$didBreak301Chain = false;
$latestLocation = null;

$handlerStack = HandlerStack::create();
$handlerStack->push(Middleware::mapRequest(function (RequestInterface $request) {
return $request
->withHeader('Accept', 'text/calendar, application/calendar+json, application/calendar+xml')
->withHeader('User-Agent', 'Nextcloud Webcal Service');
}));
$handlerStack->push(Middleware::mapResponse(function (ResponseInterface $response) use (&$didBreak301Chain, &$latestLocation) {
if (!$didBreak301Chain) {
if ($response->getStatusCode() !== 301) {
$didBreak301Chain = true;
} else {
$latestLocation = $response->getHeader('Location');
}
}
return $response;
}));

$allowLocalAccess = $this->config->getValueString('dav', 'webcalAllowLocalAccess', 'no');
public function queryWebcalFeed(array $subscription): ?string {
$subscriptionId = $subscription['id'];
$url = $this->cleanURL($subscription['source']);
if ($url === null) {
return null;
}

try {
$params = [
'allow_redirects' => [
'redirects' => 10
],
'handler' => $handlerStack,
'nextcloud' => [
'allow_local_address' => $allowLocalAccess === 'yes',
]
];

$user = parse_url($subscription['source'], PHP_URL_USER);
$pass = parse_url($subscription['source'], PHP_URL_PASS);
if ($user !== null && $pass !== null) {
$params['auth'] = [$user, $pass];
}
$allowLocalAccess = $this->config->getValueString('dav', 'webcalAllowLocalAccess', 'no');

$params = [
'nextcloud' => [
'allow_local_address' => $allowLocalAccess === 'yes',
],
RequestOptions::HEADERS => [
'User-Agent' => 'Nextcloud Webcal Service',
'Accept' => 'text/calendar, application/calendar+json, application/calendar+xml',
],
];

$user = parse_url($subscription['source'], PHP_URL_USER);
$pass = parse_url($subscription['source'], PHP_URL_PASS);
if ($user !== null && $pass !== null) {
$params[RequestOptions::AUTH] = [$user, $pass];
}

try {
$client = $this->clientService->newClient();
$response = $client->get($url, $params);
$body = $response->getBody();

if ($latestLocation !== null) {
$mutations['{http://calendarserver.org/ns/}source'] = new Href($latestLocation);
}

$contentType = $response->getHeader('Content-Type');
$contentType = explode(';', $contentType, 2)[0];
switch ($contentType) {
case 'application/calendar+json':
try {
$jCalendar = Reader::readJson($body, Reader::OPTION_FORGIVING);
} catch (Exception $ex) {
// In case of a parsing error return null
$this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
return null;
}
return $jCalendar->serialize();

case 'application/calendar+xml':
try {
$xCalendar = Reader::readXML($body);
} catch (Exception $ex) {
// In case of a parsing error return null
$this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
return null;
}
return $xCalendar->serialize();

case 'text/calendar':
default:
try {
$vCalendar = Reader::read($body);
} catch (Exception $ex) {
// In case of a parsing error return null
$this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
return null;
}
return $vCalendar->serialize();
}
} catch (LocalServerException $ex) {
$this->logger->warning("Subscription $subscriptionId was not refreshed because it violates local access rules", [
'exception' => $ex,
]);

return null;
} catch (Exception $ex) {
$this->logger->warning("Subscription $subscriptionId could not be refreshed due to a network error", [
'exception' => $ex,
]);

return null;
}

$body = $response->getBody();

$contentType = $response->getHeader('Content-Type');
$contentType = explode(';', $contentType, 2)[0];
switch ($contentType) {
case 'application/calendar+json':
try {
$jCalendar = Reader::readJson($body, Reader::OPTION_FORGIVING);
} catch (Exception $ex) {
// In case of a parsing error return null
$this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
return null;
}
return $jCalendar->serialize();

case 'application/calendar+xml':
try {
$xCalendar = Reader::readXML($body);
} catch (Exception $ex) {
// In case of a parsing error return null
$this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
return null;
}
return $xCalendar->serialize();

case 'text/calendar':
default:
try {
$vCalendar = Reader::read($body);
} catch (Exception $ex) {
// In case of a parsing error return null
$this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
return null;
}
return $vCalendar->serialize();
}
}

/**
Expand Down
13 changes: 10 additions & 3 deletions apps/dav/lib/CalDAV/WebcalCaching/RefreshWebcalService.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use OCP\AppFramework\Utility\ITimeFactory;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\BadRequest;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\PropPatch;
use Sabre\VObject\Component;
use Sabre\VObject\DateTimeParser;
Expand Down Expand Up @@ -57,7 +58,7 @@ public function refreshSubscription(string $principalUri, string $uri) {
}


$webcalData = $this->connection->queryWebcalFeed($subscription, $mutations);
$webcalData = $this->connection->queryWebcalFeed($subscription);
if (!$webcalData) {
return;
}
Expand Down Expand Up @@ -101,7 +102,13 @@ public function refreshSubscription(string $principalUri, string $uri) {
continue;
}

$denormalized = $this->calDavBackend->getDenormalizedData($vObject->serialize());
try {
$denormalized = $this->calDavBackend->getDenormalizedData($vObject->serialize());
} catch (InvalidDataException|Forbidden $ex) {
$this->logger->warning('Unable to denormalize calendar object from subscription {subscriptionId}', ['exception' => $ex, 'subscriptionId' => $subscription['id'], 'source' => $subscription['source']]);
continue;
}

// Find all identical sets and remove them from the update
if (isset($localData[$uid]) && $denormalized['etag'] === $localData[$uid]['etag']) {
unset($localData[$uid]);
Expand All @@ -127,7 +134,7 @@ public function refreshSubscription(string $principalUri, string $uri) {
$objectUri = $this->getRandomCalendarObjectUri();
$this->calDavBackend->createCalendarObject($subscription['id'], $objectUri, $vObject->serialize(), CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION);
} catch (NoInstancesException|BadRequest $ex) {
$this->logger->error('Unable to create calendar object from subscription {subscriptionId}', ['exception' => $ex, 'subscriptionId' => $subscription['id'], 'source' => $subscription['source']]);
$this->logger->warning('Unable to create calendar object from subscription {subscriptionId}', ['exception' => $ex, 'subscriptionId' => $subscription['id'], 'source' => $subscription['source']]);
}
}

Expand Down
Loading

0 comments on commit 1abd28d

Please sign in to comment.