From 0e989fec3504a084515c8eb4c7ce6cebc30263cf Mon Sep 17 00:00:00 2001 From: Alexis Saettler Date: Fri, 8 Oct 2021 22:51:47 +0200 Subject: [PATCH] feat: use queue to update contacts with carddav (#5575) --- .../DAV/Backend/CardDAV/CardDAVBackend.php | 46 +++----------- app/Jobs/Dav/UpdateVCard.php | 63 +++++++++++++++++-- sonar-project.properties | 2 +- tests/Api/DAV/VCardContactTest.php | 2 +- 4 files changed, 69 insertions(+), 44 deletions(-) diff --git a/app/Http/Controllers/DAV/Backend/CardDAV/CardDAVBackend.php b/app/Http/Controllers/DAV/Backend/CardDAV/CardDAVBackend.php index 5fea8768c..13f26d8b8 100644 --- a/app/Http/Controllers/DAV/Backend/CardDAV/CardDAVBackend.php +++ b/app/Http/Controllers/DAV/Backend/CardDAV/CardDAVBackend.php @@ -3,11 +3,11 @@ namespace App\Http\Controllers\DAV\Backend\CardDAV; use Sabre\DAV; -use Illuminate\Support\Arr; +use App\Jobs\Dav\UpdateVCard; use App\Models\Contact\Contact; use App\Models\Account\AddressBook; use App\Services\VCard\ExportVCard; -use App\Services\VCard\ImportVCard; +use Illuminate\Support\Facades\Bus; use Illuminate\Support\Facades\Log; use Sabre\DAV\Server as SabreServer; use Sabre\CardDAV\Backend\SyncSupport; @@ -19,6 +19,7 @@ use App\Services\Contact\Contact\SetMeContact; use App\Http\Controllers\DAV\Backend\IDAVBackend; use App\Http\Controllers\DAV\Backend\SyncDAVBackend; use App\Http\Controllers\DAV\DAVACL\PrincipalBackend; +use App\Services\DavClient\Utils\Model\ContactUpdateDto; class CardDAVBackend extends AbstractBackend implements SyncSupport, IDAVBackend { @@ -185,13 +186,7 @@ class CardDAVBackend extends AbstractBackend implements SyncSupport, IDAVBackend $carddata = $contact->vcard; try { if (empty($carddata)) { - $vcard = app(ExportVCard::class) - ->execute([ - 'account_id' => $this->user->account_id, - 'contact_id' => $contact->id, - ]); - - $carddata = $vcard->serialize(); + $carddata = $this->refreshObject($contact); } return [ @@ -369,36 +364,13 @@ class CardDAVBackend extends AbstractBackend implements SyncSupport, IDAVBackend */ public function updateCard($addressBookId, $cardUri, $cardData): ?string { - $contact_id = null; - if ($cardUri) { - $contact = $this->getObject($addressBookId, $cardUri); + $dto = new ContactUpdateDto($cardUri, '"'.md5($cardData).'"', $cardData); - if ($contact) { - $contact_id = $contact->id; - } - } + $job = new UpdateVCard($this->user, $addressBookId, $dto); - try { - $result = app(ImportVCard::class) - ->execute([ - 'account_id' => $this->user->account_id, - 'user_id' => $this->user->id, - 'contact_id' => $contact_id, - 'entry' => $cardData, - 'behaviour' => ImportVCard::BEHAVIOUR_REPLACE, - 'addressBookName' => $addressBookId == $this->backendUri() ? null : $addressBookId, - ]); - - if (! Arr::has($result, 'error')) { - $contact = Contact::where('account_id', $this->user->account_id) - ->find($result['contact_id']); - - return '"'.md5($contact->vcard).'"'; - } - } catch (\Exception $e) { - Log::debug(__CLASS__.' updateCard: '.(string) $e, [$e]); - throw $e; - } + Bus::batch([$job]) + ->allowFailures() + ->dispatch(); return null; } diff --git a/app/Jobs/Dav/UpdateVCard.php b/app/Jobs/Dav/UpdateVCard.php index 62891231b..747daf43e 100644 --- a/app/Jobs/Dav/UpdateVCard.php +++ b/app/Jobs/Dav/UpdateVCard.php @@ -3,8 +3,11 @@ namespace App\Jobs\Dav; use App\Models\User\User; +use Illuminate\Support\Arr; use Illuminate\Bus\Batchable; use Illuminate\Bus\Queueable; +use App\Models\Contact\Contact; +use App\Services\VCard\ImportVCard; use Illuminate\Support\Facades\Log; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; @@ -57,13 +60,63 @@ class UpdateVCard implements ShouldQueue return; } - Log::info(__CLASS__.' update '.$this->contact->uri); - - $backend = app(CardDAVBackend::class)->init($this->user); - $newtag = $backend->updateCard($this->addressBookName, $this->contact->uri, $this->contact->card); + $newtag = $this->updateCard($this->addressBookName, $this->contact->uri, $this->contact->card); if ($newtag !== $this->contact->etag) { - Log::warning(__CLASS__.' wrong etag when updating contact. Expected '.$this->contact->etag.', get '.$newtag); + Log::warning(__CLASS__.' wrong etag when updating contact. Expected '.$this->contact->etag.', get '.$newtag, [ + 'contacturl' => $this->contact->uri, + 'carddata' => $this->contact->card, + ]); } } + + /** + * Update the contact with the carddata. + * + * @param mixed $addressBookId + * @param string $cardUri + * @param string $cardData + * @return string|null + */ + private function updateCard($addressBookId, $cardUri, $cardData): ?string + { + $backend = app(CardDAVBackend::class)->init($this->user); + + $contact_id = null; + if ($cardUri) { + $contact = $backend->getObject($addressBookId, $cardUri); + + if ($contact) { + $contact_id = $contact->id; + } + } + + try { + $result = app(ImportVCard::class) + ->execute([ + 'account_id' => $this->user->account_id, + 'user_id' => $this->user->id, + 'contact_id' => $contact_id, + 'entry' => $cardData, + 'behaviour' => ImportVCard::BEHAVIOUR_REPLACE, + 'addressBookName' => $addressBookId === $backend->backendUri() ? null : $addressBookId, + ]); + + if (! Arr::has($result, 'error')) { + $contact = Contact::where('account_id', $this->user->account_id) + ->find($result['contact_id']); + + return '"'.md5($contact->vcard).'"'; + } + } catch (\Exception $e) { + Log::debug(__CLASS__.' updateCard: '.(string) $e, [ + $e, + 'contacturl' => $cardUri, + 'carddata' => $cardData, + ]); + throw $e; + } + + return null; + } } diff --git a/sonar-project.properties b/sonar-project.properties index e20d0c8df..53cf751a0 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -8,7 +8,7 @@ sonar.organization=monicahq sonar.sources=app,bootstrap,config,database,public,resources,routes sonar.exclusions=bootstrap/cache/*,public/vendor/**,resources/lang/** sonar.tests=tests -sonar.coverage.exclusions=routes/*.php,config/*.php,bootstrap/**,resources/**/*.php,database/factories/**/*.php,database/migrations/*.php,public/*.php,resources/**/*.vue,resources/**/*.js +sonar.coverage.exclusions=routes/*.php,config/**/*.php,bootstrap/**,resources/**/*.php,database/**/*.php,public/*.php,resources/**/*.vue,resources/**/*.js sonar.cpd.exclusions=routes/*.php,config/*.php,bootstrap/**,resources/**/*.php,database/**/*.php # Encoding of the source code. Default is default system encoding diff --git a/tests/Api/DAV/VCardContactTest.php b/tests/Api/DAV/VCardContactTest.php index d5ea21945..39796da5c 100644 --- a/tests/Api/DAV/VCardContactTest.php +++ b/tests/Api/DAV/VCardContactTest.php @@ -331,7 +331,7 @@ class VCardContactTest extends ApiTestCase $response->assertStatus(204); $response->assertHeader('X-Sabre-Version'); - $response->assertHeader('ETag'); + //$response->assertHeader('ETag'); // etag no more sent } public function test_carddav_contacts_report_version4()