Skip to content

Commit

Permalink
Merge pull request #454 from strukturag/webhook-events
Browse files Browse the repository at this point in the history
Implement "IWebhookCompatibleEvent" on Nextcloud 30.
  • Loading branch information
fancycode authored Oct 9, 2024
2 parents aa31f48 + 1217340 commit 0d39ca3
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 35 deletions.
10 changes: 1 addition & 9 deletions lib/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
use OCA\Certificate24\AppInfo\Application;
use OCA\Certificate24\Client;
use OCA\Certificate24\Config;
use OCA\Certificate24\Events\SignEvent;
use OCA\Certificate24\Mails;
use OCA\Certificate24\Manager;
use OCA\Certificate24\Metadata;
Expand All @@ -40,7 +39,6 @@
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\Collaboration\Collaborators\ISearch;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\IRootFolder;
use OCP\IConfig;
use OCP\IL10N;
Expand Down Expand Up @@ -78,7 +76,6 @@ class ApiController extends OCSController {
private IRootFolder $root;
private ISearch $search;
private IMailer $mailer;
private IEventDispatcher $dispatcher;
private IFactory $l10nFactory;
private IL10N $l10n;
private IConfig $systemConfig;
Expand All @@ -101,7 +98,6 @@ public function __construct(string $appName,
IRootFolder $root,
ISearch $search,
IMailer $mailer,
IEventDispatcher $dispatcher,
IFactory $l10nFactory,
IL10N $l10n,
IConfig $systemConfig,
Expand All @@ -122,7 +118,6 @@ public function __construct(string $appName,
$this->root = $root;
$this->search = $search;
$this->mailer = $mailer;
$this->dispatcher = $dispatcher;
$this->l10nFactory = $l10nFactory;
$this->l10n = $l10n;
$this->systemConfig = $systemConfig;
Expand Down Expand Up @@ -1092,10 +1087,7 @@ public function signRequest(string $id): DataResponse {
$signed = new \DateTime();
}

$isLast = $this->requests->markRequestSignedById($id, $type, $value, $signed);

$event = new SignEvent($id, $row, $type, $value, $signed, $user, $isLast);
$this->dispatcher->dispatchTyped($event);
$isLast = $this->requests->markRequestSigned($row, $type, $value, $signed, $user);

if ($isLast) {
$this->manager->saveSignedResult($row, $signed, $user, $account);
Expand Down
44 changes: 44 additions & 0 deletions lib/Events/BaseEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

/**
* @copyright Copyright (c) 2024, struktur AG.
*
* @author Joachim Bauch <[email protected]>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\Certificate24\Events;

use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IWebhookCompatibleEvent;

if (interface_exists(\OCP\EventDispatcher\IWebhookCompatibleEvent::class)) {
// Nextcloud 30 or newer.
abstract class BaseEvent extends Event implements IWebhookCompatibleEvent {
}
} else {
// Compatibility for Nextcloud 29 or older.
abstract class BaseEvent extends Event {

/**
* Return data to be JSON serialized for a Webhook (requires Nextcloud 30).
*/
abstract public function getWebhookSerializable(): array;

}
}
23 changes: 21 additions & 2 deletions lib/Events/ShareEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@
*/
namespace OCA\Certificate24\Events;

use OCP\EventDispatcher\Event;
use OCP\Files\File;
use OCP\IUser;

class ShareEvent extends Event {
class ShareEvent extends BaseEvent {
private File $file;
private IUser $user;
private array $recipients;
Expand Down Expand Up @@ -69,4 +68,24 @@ public function getRecipients(): array {
public function getRequestId(): string {
return $this->request_id;
}

/**
* @inheritDoc
*/
public function getWebhookSerializable(): array {
$file = $this->getFile();
$user = $this->getUser();
return [
'file' => [
'id' => $file->getId(),
'path' => $file->getPath(),
],
'user' => [
'uid' => $user->getUID(),
'displayName' => $user->getDisplayName(),
],
'recipients' => $this->getRecipients(),
'request_id' => $this->getRequestId(),
];
}
}
26 changes: 24 additions & 2 deletions lib/Events/SignEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
*/
namespace OCA\Certificate24\Events;

use OCP\EventDispatcher\Event;
use OCA\Certificate24\Requests;
use OCP\IUser;

class SignEvent extends Event {
class SignEvent extends BaseEvent {
private string $request_id;
private array $request;
private string $type;
Expand Down Expand Up @@ -97,4 +97,26 @@ public function getUser(): ?IUser {
public function isLastSignature(): bool {
return $this->lastSignature;
}

/**
* @inheritDoc
*/
public function getWebhookSerializable(): array {
$request = $this->getRequest();
$user = $this->getUser();
return [
'request_id' => $this->getRequestId(),
'file' => [
'id' => $request['file_id'],
],
'recipient_type' => $this->getRecipientType(),
'recipient' => $this->getRecipient(),
'signed' => $this->getSigned()->format(Requests::ISO8601_EXTENDED),
'user' => $user ? [
'uid' => $user->getUID(),
'displayName' => $user->getDisplayName(),
] : null,
'last_signature' => $this->isLastSignature(),
];
}
}
5 changes: 1 addition & 4 deletions lib/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,9 @@ public function processSignatureDetails(array $request, array $account, string $
return;
}

$isLast = $this->requests->markRequestSignedById($request['id'], $type, $value, $signed);
$isLast = $this->requests->markRequestSigned($request, $type, $value, $signed, null);
$this->logger->info('Request ' . $request['id'] . ' was signed by ' . $type . ' ' . $value . ' on ' . $signed->format(Requests::ISO8601_EXTENDED));

$event = new SignEvent($request['id'], $request, $type, $value, $signed, null, $isLast);
$this->dispatcher->dispatchTyped($event);

if ($isLast) {
$this->saveSignedResult($request, $signed, null, $account);
}
Expand Down
25 changes: 19 additions & 6 deletions lib/Requests.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use OCA\Certificate24\Events\ShareEvent;
use OCA\Certificate24\Events\SignEvent;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\File;
Expand Down Expand Up @@ -458,45 +459,57 @@ public function getRequestsForFile(File $file, bool $include_signed): array {
return $requests;
}

public function markRequestSignedById(string $id, string $type, string $value, \DateTime $now): bool {
public function markRequestSigned(array $request, string $type, string $value, \DateTime $now, ?IUser $user): bool {
$now = clone $now;
$now->setTimezone(new \DateTimeZone('UTC'));

$committed = false;
$this->db->beginTransaction();
try {
$query = $this->db->getQueryBuilder();
$query->update('c24_requests')
->set('signed', $query->createNamedParameter($now, 'datetimetz'))
->where($query->expr()->eq('id', $query->createNamedParameter($id)))
->where($query->expr()->eq('id', $query->createNamedParameter($request['id'])))
->andWhere($query->expr()->eq('recipient_type', $query->createNamedParameter($type)))
->andWhere($query->expr()->eq('recipient', $query->createNamedParameter($value)));
if ($query->executeStatement() === 1) {
// Single recipient for this request.
$this->db->commit();
$committed = true;

$event = new SignEvent($request['id'], $request, $type, $value, $now, $user, true);
$this->dispatcher->dispatchTyped($event);
return true;
}

$query = $this->db->getQueryBuilder();
$query->update('c24_recipients')
->set('signed', $query->createNamedParameter($now, 'datetimetz'))
->where($query->expr()->eq('request_id', $query->createNamedParameter($id)))
->where($query->expr()->eq('request_id', $query->createNamedParameter($request['id'])))
->andWhere($query->expr()->eq('type', $query->createNamedParameter($type)))
->andWhere($query->expr()->eq('value', $query->createNamedParameter($value)));
$query->executeStatement();

$query = $this->db->getQueryBuilder();
$query->select($query->func()->count('*', 'count'))
->from('c24_recipients')
->where($query->expr()->eq('request_id', $query->createNamedParameter($id)))
->where($query->expr()->eq('request_id', $query->createNamedParameter($request['id'])))
->andWhere($query->expr()->isNull('signed'));
$result = $query->executeQuery();
$row = $result->fetch();
$result->closeCursor();
$this->db->commit();
$committed = true;

return ((int)$row['count']) === 0;
$isLast = ((int)$row['count']) === 0;
$event = new SignEvent($request['id'], $request, $type, $value, $now, $user, $isLast);
$this->dispatcher->dispatchTyped($event);

return $isLast;
} catch (Throwable $e) {
$this->db->rollBack();
if (!$committed) {
$this->db->rollBack();
}
throw $e;
}
}
Expand Down
Loading

0 comments on commit 0d39ca3

Please sign in to comment.