diff options
author | GretaD <gretadoci@gmail.com> | 2021-02-11 20:32:08 +0300 |
---|---|---|
committer | Christoph Wurst <christoph@winzerhof-wurst.at> | 2021-02-26 19:59:39 +0300 |
commit | 5677ea6d1a234060466c34b181bf86f9fd8b8200 (patch) | |
tree | 3edc34eaecfb04ff4917076c34d4ed8a8f57f779 | |
parent | 06842c1ad4fc1b73218d7a49b72343ce6ac92b48 (diff) |
Add trusted domain
Signed-off-by: GretaD <gretadoci@gmail.com>
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
-rw-r--r-- | appinfo/info.xml | 2 | ||||
-rw-r--r-- | lib/Contracts/ITrustedSenderService.php | 2 | ||||
-rw-r--r-- | lib/Controller/TrustedSendersController.php | 12 | ||||
-rw-r--r-- | lib/Db/TrustedSender.php | 6 | ||||
-rw-r--r-- | lib/Db/TrustedSenderMapper.php | 23 | ||||
-rw-r--r-- | lib/Migration/Version1090Date20210216154409.php | 34 | ||||
-rw-r--r-- | lib/Service/TrustedSenderService.php | 8 | ||||
-rw-r--r-- | src/components/MessageHTMLBody.vue | 40 | ||||
-rw-r--r-- | src/components/TrustedSenders.vue | 12 | ||||
-rw-r--r-- | src/service/TrustedSenderService.js | 5 | ||||
-rw-r--r-- | tests/Integration/Db/TrustedSenderMapperTest.php | 78 | ||||
-rw-r--r-- | tests/Unit/Service/TrustedSenderServiceTest.php | 7 |
12 files changed, 194 insertions, 35 deletions
diff --git a/appinfo/info.xml b/appinfo/info.xml index 3b4d9c5cb..6fcd6c4c7 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -12,7 +12,7 @@ - **🙈 We’re not reinventing the wheel!** Based on the great [Horde](http://horde.org) libraries. - **📬 Want to host your own mail server?** We don’t have to reimplement this as you could set up [Mail-in-a-Box](https://mailinabox.email)! ]]></description> - <version>1.9.0-alpha.2</version> + <version>1.9.0-alpha.3</version> <licence>agpl</licence> <author>Christoph Wurst</author> <author>Greta Doçi</author> diff --git a/lib/Contracts/ITrustedSenderService.php b/lib/Contracts/ITrustedSenderService.php index 7f0de8aab..1f25e93d4 100644 --- a/lib/Contracts/ITrustedSenderService.php +++ b/lib/Contracts/ITrustedSenderService.php @@ -30,7 +30,7 @@ use OCA\Mail\Db\TrustedSender; interface ITrustedSenderService { public function isTrusted(string $uid, string $email): bool; - public function trust(string $uid, string $email, ?bool $trust = true); + public function trust(string $uid, string $email, string $type, ?bool $trust = true); /** * @param string $uid diff --git a/lib/Controller/TrustedSendersController.php b/lib/Controller/TrustedSendersController.php index 552101d8d..54c5d930c 100644 --- a/lib/Controller/TrustedSendersController.php +++ b/lib/Controller/TrustedSendersController.php @@ -54,13 +54,14 @@ class TrustedSendersController extends Controller { * @TrapError * * @param string $email - * + * @param string $type * @return JsonResponse */ - public function setTrusted(string $email): JsonResponse { + public function setTrusted(string $email, string $type): JsonResponse { $this->trustedSenderService->trust( $this->uid, - $email + $email, + $type ); return JsonResponse::success(null, Http::STATUS_CREATED); @@ -71,13 +72,14 @@ class TrustedSendersController extends Controller { * @TrapError * * @param string $email - * + * @param string $type * @return JsonResponse */ - public function removeTrust(string $email): JsonResponse { + public function removeTrust(string $email, string $type): JsonResponse { $this->trustedSenderService->trust( $this->uid, $email, + $type, false ); diff --git a/lib/Db/TrustedSender.php b/lib/Db/TrustedSender.php index d02313f7c..3425c056a 100644 --- a/lib/Db/TrustedSender.php +++ b/lib/Db/TrustedSender.php @@ -33,6 +33,8 @@ use OCP\AppFramework\Db\Entity; * @method getEmail(): string * @method setUserId(string $userId): void * @method getUserId(): string + * @method setType(string $type): void + * @method getType(): string */ class TrustedSender extends Entity implements JsonSerializable { @@ -42,11 +44,15 @@ class TrustedSender extends Entity implements JsonSerializable { /** @var string */ protected $userId; + /** @var string */ + protected $type; + public function jsonSerialize() { return [ 'id' => $this->id, 'email' => $this->email, 'uid' => $this->userId, + 'type' => $this->type, ]; } } diff --git a/lib/Db/TrustedSenderMapper.php b/lib/Db/TrustedSenderMapper.php index 5d29f224a..b8b8eeae3 100644 --- a/lib/Db/TrustedSenderMapper.php +++ b/lib/Db/TrustedSenderMapper.php @@ -34,13 +34,24 @@ class TrustedSenderMapper extends QBMapper { } public function exists(string $uid, string $email): bool { + $emailObject = new \Horde_Mail_Rfc822_Address($email); + $host = $emailObject->host; $qb = $this->db->getQueryBuilder(); $select = $qb->select('*') ->from($this->getTableName()) ->where( - $qb->expr()->eq('user_id', $qb->createNamedParameter($uid)), - $qb->expr()->eq('email', $qb->createNamedParameter($email)) + $qb->expr()->orX( + $qb->expr()->andX( + $qb->expr()->eq('email', $qb->createNamedParameter($email)), + $qb->expr()->eq('type', $qb->createNamedParameter('individual')) + ), + $qb->expr()->andX( + $qb->expr()->eq('email', $qb->createNamedParameter($host)), + $qb->expr()->eq('type', $qb->createNamedParameter('domain')) + ) + ), + $qb->expr()->eq('user_id', $qb->createNamedParameter($uid)) ); /** @var TrustedSender[] $rows */ @@ -49,25 +60,27 @@ class TrustedSenderMapper extends QBMapper { return !empty($rows); } - public function create(string $uid, string $email): void { + public function create(string $uid, string $email, string $type): void { $qb = $this->db->getQueryBuilder(); $insert = $qb->insert($this->getTableName()) ->values([ 'user_id' => $qb->createNamedParameter($uid), 'email' => $qb->createNamedParameter($email), + 'type' => $qb->createNamedParameter($type), ]); $insert->execute(); } - public function remove(string $uid, string $email): void { + public function remove(string $uid, string $email, string $type): void { $qb = $this->db->getQueryBuilder(); $delete = $qb->delete($this->getTableName()) ->where( $qb->expr()->eq('user_id', $qb->createNamedParameter($uid)), - $qb->expr()->eq('email', $qb->createNamedParameter($email)) + $qb->expr()->eq('email', $qb->createNamedParameter($email)), + $qb->expr()->eq('type', $qb->createNamedParameter($type)) ); $delete->execute(); diff --git a/lib/Migration/Version1090Date20210216154409.php b/lib/Migration/Version1090Date20210216154409.php new file mode 100644 index 000000000..4a793a142 --- /dev/null +++ b/lib/Migration/Version1090Date20210216154409.php @@ -0,0 +1,34 @@ +<?php + +declare(strict_types=1); + +namespace OCA\Mail\Migration; + +use Closure; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + +class Version1090Date20210216154409 extends SimpleMigrationStep { + + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * @return null|ISchemaWrapper + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + $table = $schema->getTable('mail_trusted_senders'); + $table->addColumn('type', 'string', [ + 'notnull' => true, + 'default' => 'individual', + ]); + $table->addIndex(['type'], 'mail_trusted_senders_type'); + + return $schema; + } +} diff --git a/lib/Service/TrustedSenderService.php b/lib/Service/TrustedSenderService.php index 8210be686..57cebbfa6 100644 --- a/lib/Service/TrustedSenderService.php +++ b/lib/Service/TrustedSenderService.php @@ -44,7 +44,7 @@ class TrustedSenderService implements ITrustedSenderService { ); } - public function trust(string $uid, string $email, ?bool $trust = true): void { + public function trust(string $uid, string $email, string $type, ?bool $trust = true): void { if ($trust && $this->isTrusted($uid, $email)) { // Nothing to do return; @@ -53,12 +53,14 @@ class TrustedSenderService implements ITrustedSenderService { if ($trust) { $this->mapper->create( $uid, - $email + $email, + $type ); } else { $this->mapper->remove( $uid, - $email + $email, + $type ); } } diff --git a/src/components/MessageHTMLBody.vue b/src/components/MessageHTMLBody.vue index 1837fee39..0393b2f69 100644 --- a/src/components/MessageHTMLBody.vue +++ b/src/components/MessageHTMLBody.vue @@ -3,9 +3,16 @@ <MdnRequest :message="message" /> <div v-if="hasBlockedContent" id="mail-message-has-blocked-content" style="color: #000000"> {{ t('mail', 'The images have been blocked to protect your privacy.') }} - <button @click="onShowBlockedContent"> - {{ t('mail', 'Show images from this sender') }} - </button> + <Actions default-icon="icon-toggle"> + <ActionButton icon="icon-toggle" + @click="onShowBlockedContent"> + {{ t('mail', 'Always show images from {sender}', {sender: message.from[0].email}) }} + </ActionButton> + <ActionButton icon="icon-toggle" + @click="onShowBlockedContentForDomain"> + {{ t('mail', 'Always show images from {domain}', {domain: getDomain()}) }} + </ActionButton> + </Actions> </div> <div v-if="loading" class="icon-loading" /> <div id="message-container" :class="{hidden: loading, scroll: !fullHeight}"> @@ -23,6 +30,8 @@ import { iframeResizer } from 'iframe-resizer' import PrintScout from 'printscout' import { trustSender } from '../service/TrustedSenderService' +import ActionButton from '@nextcloud/vue/dist/Components/ActionButton' +import Actions from '@nextcloud/vue/dist/Components/Actions' import logger from '../logger' import MdnRequest from './MdnRequest' @@ -30,7 +39,11 @@ const scout = new PrintScout() export default { name: 'MessageHTMLBody', - components: { MdnRequest }, + components: { + MdnRequest, + Actions, + ActionButton, + }, props: { url: { type: String, @@ -78,7 +91,7 @@ export default { this.loading = false if (this.isSenderTrusted) { - this.onShowBlockedContent() + this.displayIframe() } }, onAfterPrint() { @@ -87,7 +100,7 @@ export default { onBeforePrint() { this.$refs.iframe.style.setProperty('height', `${this.getIframeDoc().body.scrollHeight}px`, 'important') }, - async onShowBlockedContent() { + displayIframe() { const iframeDoc = this.getIframeDoc() logger.debug('showing external images') iframeDoc.querySelectorAll('[data-original-src]').forEach((node) => { @@ -97,10 +110,19 @@ export default { iframeDoc .querySelectorAll('[data-original-style]') .forEach((node) => node.setAttribute('style', node.getAttribute('data-original-style'))) - this.hasBlockedContent = false - await trustSender(this.message.from[0].email, true) - + }, + async onShowBlockedContent() { + this.displayIframe() + await trustSender(this.message.from[0].email, 'individual', true) + }, + getDomain() { + return this.message.from[0].email.split('@').pop() + }, + async onShowBlockedContentForDomain() { + this.displayIframe() + // TODO: there might be more than one @ in an email address + await trustSender(this.getDomain(), 'domain', true) }, }, } diff --git a/src/components/TrustedSenders.vue b/src/components/TrustedSenders.vue index b4833e3e4..c92a3973f 100644 --- a/src/components/TrustedSenders.vue +++ b/src/components/TrustedSenders.vue @@ -24,7 +24,7 @@ <div v-for="sender in sortedSenders" :key="sender.email"> {{ sender.email }} - + {{ senderType(sender.type) }} <button class="button" @click="removeSender(sender)"> {{ t('mail','Remove') }} @@ -67,6 +67,7 @@ export default { try { await trustSender( sender.email, + sender.type, false ) } catch (error) { @@ -80,6 +81,15 @@ export default { this.list.push(sender) } }, + senderType(type) { + switch (type) { + case 'individual': + return t('mail', 'individual') + case 'domain': + return t('mail', 'domain') + } + return type + }, }, } </script> diff --git a/src/service/TrustedSenderService.js b/src/service/TrustedSenderService.js index c93bf1350..7d6d6fda8 100644 --- a/src/service/TrustedSenderService.js +++ b/src/service/TrustedSenderService.js @@ -1,9 +1,10 @@ import { generateUrl } from '@nextcloud/router' import axios from '@nextcloud/axios' -export async function trustSender(email, trustFlag) { - const url = generateUrl('/apps/mail/api/trustedsenders/{email}', { +export async function trustSender(email, type, trustFlag) { + const url = generateUrl('/apps/mail/api/trustedsenders/{email}?type={type}', { email, + type, }) if (trustFlag) { diff --git a/tests/Integration/Db/TrustedSenderMapperTest.php b/tests/Integration/Db/TrustedSenderMapperTest.php index c5bbbe845..058f8cc66 100644 --- a/tests/Integration/Db/TrustedSenderMapperTest.php +++ b/tests/Integration/Db/TrustedSenderMapperTest.php @@ -62,7 +62,7 @@ class TrustedSenderMapperTest extends TestCase { $this->assertFalse($exists); } - public function testExists(): void { + public function testIndividualExists(): void { $uid = $this->user->getUID(); $qb = $this->db->getQueryBuilder(); $qb->insert('mail_trusted_senders') @@ -77,11 +77,29 @@ class TrustedSenderMapperTest extends TestCase { $this->assertTrue($exists); } - public function testCreate(): void { + public function testDomainExists(): void { + $uid = $this->user->getUID(); + $qb = $this->db->getQueryBuilder(); + $qb->insert('mail_trusted_senders') + ->values([ + 'user_id' => $qb->createNamedParameter($uid), + 'email' => $qb->createNamedParameter('next.cloud'), + 'type' => $qb->createNamedParameter('domain'), + + ]) + ->execute(); + + $exists = $this->mapper->exists($uid, "christoph@next.cloud"); + + $this->assertTrue($exists); + } + + public function testCreateIndividual(): void { $uid = $this->user->getUID(); $this->mapper->create( $uid, - "christoph@next.cloud" + "christoph@next.cloud", + 'individual' ); $qb = $this->db->getQueryBuilder(); @@ -97,19 +115,28 @@ class TrustedSenderMapperTest extends TestCase { $this->assertCount(1, $rows); } - public function testRemove(): void { + public function testRemoveIndividual(): void { $uid = $this->user->getUID(); $qb = $this->db->getQueryBuilder(); $qb->insert('mail_trusted_senders') ->values([ 'user_id' => $qb->createNamedParameter($uid), 'email' => $qb->createNamedParameter('christoph@next.cloud'), + 'type' => $qb->createNamedParameter('individual'), + ]) + ->execute(); + $qb->insert('mail_trusted_senders') + ->values([ + 'user_id' => $qb->createNamedParameter($uid), + 'email' => $qb->createNamedParameter('next.cloud'), + 'type' => $qb->createNamedParameter('domain'), ]) ->execute(); $this->mapper->remove( $uid, - "christoph@next.cloud" + "christoph@next.cloud", + 'individual' ); $qb = $this->db->getQueryBuilder(); @@ -117,7 +144,46 @@ class TrustedSenderMapperTest extends TestCase { ->from('mail_trusted_senders') ->where( $qb->expr()->eq('user_id', $qb->createNamedParameter($uid)), - $qb->expr()->eq('email', $qb->createNamedParameter("christoph@next.cloud")) + $qb->expr()->eq('email', $qb->createNamedParameter("christoph@next.cloud")), + $qb->expr()->eq('type', $qb->createNamedParameter("individual")) + ); + $result = $qb->execute(); + $rows = $result->fetchAll(); + $result->closeCursor(); + $this->assertEmpty($rows); + } + + public function testRemoveDomain(): void { + $uid = $this->user->getUID(); + $qb = $this->db->getQueryBuilder(); + $qb->insert('mail_trusted_senders') + ->values([ + 'user_id' => $qb->createNamedParameter($uid), + 'email' => $qb->createNamedParameter('christoph@next.cloud'), + 'type' => $qb->createNamedParameter('individual'), + ]) + ->execute(); + $qb->insert('mail_trusted_senders') + ->values([ + 'user_id' => $qb->createNamedParameter($uid), + 'email' => $qb->createNamedParameter('next.cloud'), + 'type' => $qb->createNamedParameter('domain'), + ]) + ->execute(); + + $this->mapper->remove( + $uid, + "next.cloud", + 'domain' + ); + + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from('mail_trusted_senders') + ->where( + $qb->expr()->eq('user_id', $qb->createNamedParameter($uid)), + $qb->expr()->eq('email', $qb->createNamedParameter("next.cloud")), + $qb->expr()->eq('type', $qb->createNamedParameter("domain")) ); $result = $qb->execute(); $rows = $result->fetchAll(); diff --git a/tests/Unit/Service/TrustedSenderServiceTest.php b/tests/Unit/Service/TrustedSenderServiceTest.php index e37b80387..005018e26 100644 --- a/tests/Unit/Service/TrustedSenderServiceTest.php +++ b/tests/Unit/Service/TrustedSenderServiceTest.php @@ -92,7 +92,8 @@ class TrustedSenderServiceTest extends TestCase { $this->service->trust( $uid, - $email + $email, + 'individual' ); } @@ -109,7 +110,8 @@ class TrustedSenderServiceTest extends TestCase { $this->service->trust( $uid, - $email + $email, + 'individual' ); } @@ -127,6 +129,7 @@ class TrustedSenderServiceTest extends TestCase { $this->service->trust( $uid, $email, + 'individual', false ); } |