diff --git a/lib/Controller/IdentifyAccountController.php b/lib/Controller/IdentifyAccountController.php index cd370524a2..620bc78b85 100644 --- a/lib/Controller/IdentifyAccountController.php +++ b/lib/Controller/IdentifyAccountController.php @@ -19,8 +19,10 @@ use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\DataResponse; use OCP\Collaboration\Collaborators\ISearch; +use OCP\IConfig; use OCP\IRequest; use OCP\IURLGenerator; +use OCP\IUserManager; use OCP\IUserSession; use OCP\Share\IShare; @@ -36,6 +38,8 @@ public function __construct( private IURLGenerator $urlGenerator, private Email $identifyEmailMethod, private Account $identifyAccountMethod, + private IUserManager $userManager, + private IConfig $config, ) { parent::__construct(Application::APP_ID, $request); } @@ -76,6 +80,7 @@ public function search(string $search = '', string $method = '', int $page = 1, $return = $this->addHerselfAccount($return, $search); $return = $this->addHerselfEmail($return, $search); $return = $this->replaceShareTypeByMethod($return); + $return = $this->addEmailNotificationPreference($return); $return = $this->excludeNotAllowed($return); return new DataResponse($return); @@ -239,4 +244,62 @@ private function replaceShareTypeByMethod(array $list): array { } return $list; } + + private function addEmailNotificationPreference(array $list): array { + foreach ($list as $key => $item) { + if ($item['method'] !== 'account') { + continue; + } + + $user = $this->userManager->get($item['id']); + if ($user === null) { + $list[$key]['acceptsEmailNotifications'] = false; + continue; + } + + $email = $user->getEMailAddress(); + if (empty($email)) { + $list[$key]['acceptsEmailNotifications'] = false; + continue; + } + + if ($this->isNotificationDisabledAtActivity($user->getUID(), 'libresign_file_to_sign')) { + $list[$key]['acceptsEmailNotifications'] = false; + continue; + } + + $list[$key]['acceptsEmailNotifications'] = true; + } + return $list; + } + + private function isNotificationDisabledAtActivity(string $userId, string $type): bool { + if (!class_exists(\OCA\Activity\UserSettings::class)) { + return false; + } + $activityUserSettings = \OCP\Server::get(\OCA\Activity\UserSettings::class); + if ($activityUserSettings) { + $manager = \OCP\Server::get(\OCP\Activity\IManager::class); + try { + $manager->getSettingById($type); + } catch (\Exception $e) { + return false; + } + + $adminSetting = $activityUserSettings->getAdminSetting('email', $type); + if (!$adminSetting) { + return true; + } + + $notificationSetting = $activityUserSettings->getUserSetting( + $userId, + 'email', + $type + ); + if (!$notificationSetting) { + return true; + } + } + return false; + } } diff --git a/lib/Db/IdentifyMethodMapper.php b/lib/Db/IdentifyMethodMapper.php index bba1db2efd..c7203c6471 100644 --- a/lib/Db/IdentifyMethodMapper.php +++ b/lib/Db/IdentifyMethodMapper.php @@ -125,6 +125,7 @@ public function searchByIdentifierValue(string $search, string $userId, string $ ->join('im', 'libresign_sign_request', 'sr', $qb->expr()->eq('sr.id', 'im.sign_request_id'), ) + ->where($qb->expr()->neq('im.identifier_value', $qb->createNamedParameter('deleted_users'))) ->setMaxResults($limit) ->setFirstResult($offset); diff --git a/lib/Db/SignRequestMapper.php b/lib/Db/SignRequestMapper.php index 30745d6ec2..adad246ce7 100644 --- a/lib/Db/SignRequestMapper.php +++ b/lib/Db/SignRequestMapper.php @@ -60,10 +60,17 @@ public function incrementNotificationCounter(SignRequest $signRequest, string $m if (!isset($metadata['notify'])) { $this->firstNotification = true; } - $metadata['notify'][] = [ + + $notificationEntry = [ 'method' => $method, 'date' => time(), ]; + + if (!empty($fromDatabase->getDescription())) { + $notificationEntry['description'] = $fromDatabase->getDescription(); + } + + $metadata['notify'][] = $notificationEntry; $fromDatabase->setMetadata($metadata); $this->update($fromDatabase); $this->db->commit(); diff --git a/lib/Listener/MailNotifyListener.php b/lib/Listener/MailNotifyListener.php index 8ba2db6afc..db07391552 100644 --- a/lib/Listener/MailNotifyListener.php +++ b/lib/Listener/MailNotifyListener.php @@ -88,10 +88,10 @@ protected function sendSignMailNotification( $isFirstNotification = $this->signRequestMapper->incrementNotificationCounter($signRequest, 'mail'); if ($isFirstNotification) { - $this->mail->notifyUnsignedUser($signRequest, $email); + $this->mail->notifyUnsignedUser($signRequest, $email, $signRequest->getDescription()); return; } - $this->mail->notifySignDataUpdated($signRequest, $email); + $this->mail->notifySignDataUpdated($signRequest, $email, $signRequest->getDescription()); } catch (\InvalidArgumentException $e) { $this->logger->error($e->getMessage(), ['exception' => $e]); return; @@ -173,6 +173,17 @@ private function isNotificationDisabledAtActivity(string $userId, string $type): } $activityUserSettings = \OCP\Server::get(\OCA\Activity\UserSettings::class); if ($activityUserSettings) { + $manager = \OCP\Server::get(\OCP\Activity\IManager::class); + try { + $manager->getSettingById($type); + } catch (\Exception $e) { + return false; + } + + $adminSetting = $activityUserSettings->getAdminSetting('email', $type); + if (!$adminSetting) { + return true; + } $notificationSetting = $activityUserSettings->getUserSetting( $userId, 'email', diff --git a/lib/Listener/NotificationListener.php b/lib/Listener/NotificationListener.php index 05cd3e1e10..e7bb9a74ef 100644 --- a/lib/Listener/NotificationListener.php +++ b/lib/Listener/NotificationListener.php @@ -209,13 +209,23 @@ private function isNotificationDisabledAtActivity(string $userId, string $type): } $activityUserSettings = \OCP\Server::get(\OCA\Activity\UserSettings::class); if ($activityUserSettings) { + $manager = \OCP\Server::get(\OCP\Activity\IManager::class); + try { + $manager->getSettingById($type); + } catch (\Exception $e) { + return false; + } + + $adminSetting = $activityUserSettings->getAdminSetting('notification', $type); + if (!$adminSetting) { + return true; + } + $notificationSetting = $activityUserSettings->getUserSetting( $userId, 'notification', $type ); - // If setting is explicitly false, notifications are disabled - // If setting is null/not configured, notifications are enabled by default if ($notificationSetting === false) { return true; } diff --git a/lib/Listener/TwofactorGatewayListener.php b/lib/Listener/TwofactorGatewayListener.php index 5581c209f1..f8ebddf498 100644 --- a/lib/Listener/TwofactorGatewayListener.php +++ b/lib/Listener/TwofactorGatewayListener.php @@ -80,10 +80,16 @@ protected function sendSignNotification( } $isFirstNotification = $this->signRequestMapper->incrementNotificationCounter($signRequest, $entity->getIdentifierKey()); + + $message = ''; + if (!empty($signRequest->getDescription())) { + $message = $signRequest->getDescription() . "\n\n"; + } + if ($isFirstNotification) { - $message = $this->l10n->t('There is a document for you to sign. Access the link below:'); + $message .= $this->l10n->t('There is a document for you to sign. Access the link below:'); } else { - $message = $this->l10n->t('Changes have been made in a file that you have to sign. Access the link below:'); + $message .= $this->l10n->t('Changes have been made in a file that you have to sign. Access the link below:'); } $message .= "\n"; $link = $this->urlGenerator->linkToRouteAbsolute('libresign.page.sign', ['uuid' => $signRequest->getUuid()]); diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php index a8b88477ff..aabe88d612 100644 --- a/lib/ResponseDefinitions.php +++ b/lib/ResponseDefinitions.php @@ -28,6 +28,9 @@ * email?: string, * account?: string, * }, + * displayName?: string, + * description?: string, + * notify?: non-negative-int, * signingOrder?: non-negative-int, * } * @psalm-type LibresignNewFile = array{ @@ -55,6 +58,7 @@ * subname: string, * shareType: 0|4, * icon?: 'icon-mail'|'icon-user', + * acceptsEmailNotifications?: boolean, * } * @psalm-type LibresignPagination = array{ * total: non-negative-int, diff --git a/lib/Service/MailService.php b/lib/Service/MailService.php index bb100e5f4e..5f24ff1d04 100644 --- a/lib/Service/MailService.php +++ b/lib/Service/MailService.php @@ -45,12 +45,18 @@ private function getFileById(int $fileId): File { /** * @psalm-suppress MixedMethodCall */ - public function notifySignDataUpdated(SignRequest $data, string $email): void { + public function notifySignDataUpdated(SignRequest $data, string $email, ?string $description = null): void { $emailTemplate = $this->mailer->createEMailTemplate('settings.TestEmail'); // TRANSLATORS The subject of the email that is sent after changes are made to the signature request that may affect something for the signer who will sign the document. Some possible reasons: URL for signature changed (when the URL expires), the person who requested the signature sent a notification $emailTemplate->setSubject($this->l10n->t('LibreSign: Changes into a file for you to sign')); $emailTemplate->addHeader(); $emailTemplate->addHeading($this->l10n->t('File to sign'), false); + + if (!empty($description)) { + $emailTemplate->addBodyText($description); + $emailTemplate->addBodyText(''); + } + $emailTemplate->addBodyText($this->l10n->t('Changes have been made in a file that you have to sign. Access the link below:')); $link = $this->urlGenerator->linkToRouteAbsolute('libresign.page.sign', ['uuid' => $data->getUuid()]); $file = $this->getFileById($data->getFileId()); @@ -76,11 +82,17 @@ public function notifySignDataUpdated(SignRequest $data, string $email): void { /** * @psalm-suppress MixedMethodCall */ - public function notifyUnsignedUser(SignRequest $data, string $email): void { + public function notifyUnsignedUser(SignRequest $data, string $email, ?string $description = null): void { $emailTemplate = $this->mailer->createEMailTemplate('settings.TestEmail'); $emailTemplate->setSubject($this->l10n->t('LibreSign: There is a file for you to sign')); $emailTemplate->addHeader(); $emailTemplate->addHeading($this->l10n->t('File to sign'), false); + + if (!empty($description)) { + $emailTemplate->addBodyText($description); + $emailTemplate->addBodyText(''); + } + $emailTemplate->addBodyText($this->l10n->t('There is a document for you to sign. Access the link below:')); $link = $this->urlGenerator->linkToRouteAbsolute('libresign.page.sign', ['uuid' => $data->getUuid()]); $file = $this->getFileById($data->getFileId()); diff --git a/openapi-full.json b/openapi-full.json index 410bdc6f7e..4c065cb325 100644 --- a/openapi-full.json +++ b/openapi-full.json @@ -453,6 +453,9 @@ "icon-mail", "icon-user" ] + }, + "acceptsEmailNotifications": { + "type": "boolean" } } }, @@ -514,6 +517,17 @@ } } }, + "displayName": { + "type": "string" + }, + "description": { + "type": "string" + }, + "notify": { + "type": "integer", + "format": "int64", + "minimum": 0 + }, "signingOrder": { "type": "integer", "format": "int64", diff --git a/openapi.json b/openapi.json index 217121894d..0eb99d6307 100644 --- a/openapi.json +++ b/openapi.json @@ -383,6 +383,9 @@ "icon-mail", "icon-user" ] + }, + "acceptsEmailNotifications": { + "type": "boolean" } } }, @@ -444,6 +447,17 @@ } } }, + "displayName": { + "type": "string" + }, + "description": { + "type": "string" + }, + "notify": { + "type": "integer", + "format": "int64", + "minimum": 0 + }, "signingOrder": { "type": "integer", "format": "int64", diff --git a/src/Components/Request/IdentifySigner.vue b/src/Components/Request/IdentifySigner.vue index d34f6071fc..40d575ed4e 100644 --- a/src/Components/Request/IdentifySigner.vue +++ b/src/Components/Request/IdentifySigner.vue @@ -26,6 +26,23 @@ :error="nameHaveError" :helper-text="nameHelperText" @update:value="onNameChange" /> + +
+ + {{ t('libresign', 'Add custom message') }} + + +
+