Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/mail.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Wurst <ChristophWurst@users.noreply.github.com>2021-02-26 20:06:51 +0300
committerGitHub <noreply@github.com>2021-02-26 20:06:51 +0300
commit6ab26aa3a66afc4d58b3ee9eb5b03a468f052577 (patch)
tree3edc34eaecfb04ff4917076c34d4ed8a8f57f779
parent06842c1ad4fc1b73218d7a49b72343ce6ac92b48 (diff)
parent5677ea6d1a234060466c34b181bf86f9fd8b8200 (diff)
Merge pull request #4513 from nextcloud/add/trusted_domain
Add trusted domain
-rw-r--r--appinfo/info.xml2
-rw-r--r--lib/Contracts/ITrustedSenderService.php2
-rw-r--r--lib/Controller/TrustedSendersController.php12
-rw-r--r--lib/Db/TrustedSender.php6
-rw-r--r--lib/Db/TrustedSenderMapper.php23
-rw-r--r--lib/Migration/Version1090Date20210216154409.php34
-rw-r--r--lib/Service/TrustedSenderService.php8
-rw-r--r--src/components/MessageHTMLBody.vue40
-rw-r--r--src/components/TrustedSenders.vue12
-rw-r--r--src/service/TrustedSenderService.js5
-rw-r--r--tests/Integration/Db/TrustedSenderMapperTest.php78
-rw-r--r--tests/Unit/Service/TrustedSenderServiceTest.php7
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
);
}