fix(dav): Handle GenericFileException when reading default contact file

Assisted-by: ClaudeCode:claude-sonnet-4-6

Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
This commit is contained in:
Daniel Kesselberg 2026-06-21 21:30:48 +02:00
parent 522d3ee476
commit 64608f23ce
No known key found for this signature in database
GPG key ID: 4A81C29F63464E8F
4 changed files with 73 additions and 6 deletions

View file

@ -13,9 +13,12 @@ use OCA\DAV\AppInfo\Application;
use OCA\DAV\CardDAV\CardDavBackend;
use OCP\AppFramework\Services\IAppConfig;
use OCP\Files\AppData\IAppDataFactory;
use OCP\Files\GenericFileException;
use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\IL10N;
use OCP\Lock\LockedException;
use Psr\Log\LoggerInterface;
use Symfony\Component\Uid\Uuid;
@ -47,11 +50,14 @@ class ExampleContactService {
return null;
}
if (!$folder->fileExists('defaultContact.vcf')) {
try {
return $folder->getFile('defaultContact.vcf')->getContent();
} catch (NotFoundException $e) {
return null;
} catch (GenericFileException|NotPermittedException|LockedException $e) {
$this->logger->error('Could not read default contact file', ['exception' => $e]);
return null;
}
return $folder->getFile('defaultContact.vcf')->getContent();
}
private function createInitialDefaultContact(): void {

View file

@ -14,6 +14,7 @@ use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\Exception\ExampleEventException;
use OCA\DAV\Model\ExampleEvent;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Files\GenericFileException;
use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
@ -105,7 +106,7 @@ EOF);
try {
return $icsFile->getContent();
} catch (NotFoundException|NotPermittedException $e) {
} catch (NotFoundException|NotPermittedException|GenericFileException $e) {
throw new ExampleEventException(
'Failed to read custom example event',
0,

View file

@ -11,9 +11,9 @@ namespace OCA\DAV\Tests\unit\Service;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\Service\ExampleContactService;
use OCP\App\IAppManager;
use OCP\AppFramework\Services\IAppConfig;
use OCP\Files\AppData\IAppDataFactory;
use OCP\Files\GenericFileException;
use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile;
@ -27,7 +27,6 @@ use Test\TestCase;
class ExampleContactServiceTest extends TestCase {
protected ExampleContactService $service;
protected CardDavBackend&MockObject $cardDav;
protected IAppManager&MockObject $appManager;
protected IAppDataFactory&MockObject $appDataFactory;
protected LoggerInterface&MockObject $logger;
protected IAppConfig&MockObject $appConfig;
@ -161,6 +160,42 @@ class ExampleContactServiceTest extends TestCase {
$this->assertTrue(Uuid::isValid($vcard->UID->getValue()));
}
public function testGetCardReturnsNullWhenFolderNotFound(): void {
$this->appData->method('getFolder')->willThrowException(new NotFoundException());
$this->assertNull($this->service->getCard());
}
public function testGetCardReturnsNullWhenFileNotFound(): void {
$folder = $this->createMock(ISimpleFolder::class);
$this->appData->method('getFolder')->willReturn($folder);
$folder->method('getFile')->willThrowException(new NotFoundException());
$this->assertNull($this->service->getCard());
}
public function testGetCardReturnsNullOnReadError(): void {
$folder = $this->createMock(ISimpleFolder::class);
$file = $this->createMock(ISimpleFile::class);
$this->appData->method('getFolder')->willReturn($folder);
$folder->method('getFile')->willReturn($file);
$file->method('getContent')->willThrowException(new GenericFileException());
$this->logger->expects($this->once())
->method('error')
->with('Could not read default contact file', $this->anything());
$this->assertNull($this->service->getCard());
}
public function testGetCardReturnsContent(): void {
$folder = $this->createMock(ISimpleFolder::class);
$file = $this->createMock(ISimpleFile::class);
$this->appData->method('getFolder')->willReturn($folder);
$folder->method('getFile')->willReturn($file);
$file->method('getContent')->willReturn('vcarddata');
$this->assertEquals('vcarddata', $this->service->getCard());
}
public function testDefaultContactIsNotCreatedIfEnabled(): void {
$this->appConfig->method('getAppValueBool')
->with('enableDefaultContact', true)

View file

@ -10,8 +10,10 @@ declare(strict_types=1);
namespace OCA\DAV\Tests\unit\Service;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\Exception\ExampleEventException;
use OCA\DAV\Service\ExampleEventService;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Files\GenericFileException;
use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile;
@ -173,6 +175,29 @@ class ExampleEventServiceTest extends TestCase {
$this->assertEquals($expectedIcs, $actualIcs);
}
public function testGetExampleEventThrowsOnReadError(): void {
$exampleEventFolder = $this->createMock(ISimpleFolder::class);
$this->appData->expects(self::once())
->method('getFolder')
->with('example_event')
->willReturn($exampleEventFolder);
$exampleEventFile = $this->createMock(ISimpleFile::class);
$exampleEventFolder->expects(self::once())
->method('getFile')
->with('example_event.ics')
->willReturn($exampleEventFile);
$exampleEventFile->expects(self::once())
->method('getContent')
->willThrowException(new GenericFileException());
$this->random->expects(self::once())
->method('generate')
->willReturn('RANDOM-UID');
$this->expectException(ExampleEventException::class);
$this->service->getExampleEvent();
}
public function testGetExampleEventWithDefault(): void {
$this->appData->expects(self::once())
->method('getFolder')