-
Notifications
You must be signed in to change notification settings - Fork 263
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9891 from nextcloud/feat/trusted-senders
feat: add internal addresses
- Loading branch information
Showing
20 changed files
with
925 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
namespace OCA\Mail\Contracts; | ||
|
||
use OCA\Mail\Db\InternalAddress; | ||
|
||
interface IInternalAddressService { | ||
public function isInternal(string $uid, string $address): bool; | ||
|
||
public function add(string $uid, string $address, string $type, ?bool $trust = true); | ||
|
||
/** | ||
* @param string $uid | ||
* @return InternalAddress[] | ||
*/ | ||
public function getInternalAddresses(string $uid): array; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
namespace OCA\Mail\Controller; | ||
|
||
use OCA\Mail\AppInfo\Application; | ||
use OCA\Mail\Http\JsonResponse; | ||
use OCA\Mail\Http\TrapError; | ||
use OCA\Mail\Service\InternalAddressService; | ||
use OCP\AppFramework\Controller; | ||
use OCP\AppFramework\Http; | ||
use OCP\AppFramework\Http\Attribute\NoAdminRequired; | ||
use OCP\IRequest; | ||
|
||
class InternalAddressController extends Controller { | ||
private ?string $uid; | ||
|
||
public function __construct(IRequest $request, | ||
?string $userId, | ||
private InternalAddressService $internalAddressService) { | ||
parent::__construct(Application::APP_ID, $request); | ||
|
||
$this->internalAddressService = $internalAddressService; | ||
$this->uid = $userId; | ||
} | ||
|
||
/** | ||
* @NoAdminRequired | ||
* | ||
* @param string $address | ||
* @param string $type | ||
* @return JsonResponse | ||
*/ | ||
#[TrapError] | ||
public function setAddress(string $address, string $type): JsonResponse { | ||
$address = $this->internalAddressService->add( | ||
$this->uid, | ||
$address, | ||
$type | ||
)->jsonSerialize(); | ||
|
||
return JsonResponse::success($address, Http::STATUS_CREATED); | ||
} | ||
|
||
/** | ||
* @NoAdminRequired | ||
* | ||
* @param string $address | ||
* @param string $type | ||
* @return JsonResponse | ||
*/ | ||
#[TrapError] | ||
public function removeAddress(string $address, string $type): JsonResponse { | ||
if($this->uid === null) { | ||
return JsonResponse::error('User not found', Http::STATUS_UNAUTHORIZED); | ||
} | ||
|
||
$this->internalAddressService->add( | ||
$this->uid, | ||
$address, | ||
$type, | ||
false | ||
); | ||
|
||
return JsonResponse::success(); | ||
} | ||
|
||
/** | ||
* @NoAdminRequired | ||
* | ||
* @return JsonResponse | ||
*/ | ||
#[TrapError] | ||
public function list(): JsonResponse { | ||
if($this->uid === null) { | ||
return JsonResponse::error('User not found', Http::STATUS_UNAUTHORIZED); | ||
} | ||
$list = $this->internalAddressService->getInternalAddresses( | ||
$this->uid | ||
); | ||
|
||
return JsonResponse::success($list); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
namespace OCA\Mail\Db; | ||
|
||
use JsonSerializable; | ||
use OCP\AppFramework\Db\Entity; | ||
use ReturnTypeWillChange; | ||
|
||
/** | ||
* @method setAddress(string $address): void | ||
* @method getAddress(): string | ||
* @method setUserId(string $userId): void | ||
* @method getUserId(): string | ||
* @method setType(string $type): void | ||
* @method getType(): string | ||
*/ | ||
class InternalAddress extends Entity implements JsonSerializable { | ||
|
||
protected $address ; | ||
protected $userId; | ||
protected $type; | ||
|
||
#[ReturnTypeWillChange] | ||
public function jsonSerialize() { | ||
return [ | ||
'id' => $this->id, | ||
'address' => $this->address, | ||
'uid' => $this->userId, | ||
'type' => $this->type, | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
namespace OCA\Mail\Db; | ||
|
||
use OCP\AppFramework\Db\DoesNotExistException; | ||
use OCP\AppFramework\Db\QBMapper; | ||
use OCP\IDBConnection; | ||
|
||
/** | ||
* @template-extends QBMapper<InternalAddress> | ||
*/ | ||
class InternalAddressMapper extends QBMapper { | ||
public function __construct(IDBConnection $db) { | ||
parent::__construct($db, 'mail_internal_address'); | ||
} | ||
|
||
public function exists(string $uid, string $address): bool { | ||
|
||
$emailObject = new \Horde_Mail_Rfc822_Address($address); | ||
$host = $emailObject->host; | ||
$qb = $this->db->getQueryBuilder(); | ||
|
||
$select = $qb->select('*') | ||
->from($this->getTableName()) | ||
->where( | ||
$qb->expr()->orX( | ||
$qb->expr()->andX( | ||
$qb->expr()->eq('address', $qb->createNamedParameter($address)), | ||
$qb->expr()->eq('type', $qb->createNamedParameter('individual')) | ||
), | ||
$qb->expr()->andX( | ||
$qb->expr()->eq('address', $qb->createNamedParameter($host)), | ||
$qb->expr()->eq('type', $qb->createNamedParameter('domain')) | ||
) | ||
), | ||
$qb->expr()->eq('user_id', $qb->createNamedParameter($uid)) | ||
); | ||
|
||
$rows = $this->findEntities($select); | ||
|
||
return $rows !== []; | ||
} | ||
|
||
public function create(string $uid, string $address, string $type): int { | ||
|
||
$address = InternalAddress::fromParams([ | ||
'userId' => $uid, | ||
'address' => $address, | ||
'type' => $type, | ||
]); | ||
|
||
$result = $this->insert($address); | ||
|
||
return $result->getId(); | ||
} | ||
|
||
public function remove(string $uid, string $address, string $type): void { | ||
$qb = $this->db->getQueryBuilder(); | ||
|
||
$delete = $qb->delete($this->getTableName()) | ||
->where( | ||
$qb->expr()->eq('user_id', $qb->createNamedParameter($uid)), | ||
$qb->expr()->eq('address', $qb->createNamedParameter($address)), | ||
$qb->expr()->eq('type', $qb->createNamedParameter($type)) | ||
); | ||
|
||
$delete->executeStatement(); | ||
} | ||
|
||
/** | ||
* @param string $uid | ||
* @return InternalAddress[] | ||
*/ | ||
public function findAll(string $uid): array { | ||
$qb = $this->db->getQueryBuilder(); | ||
$select = $qb->select('*') | ||
->from($this->getTableName()) | ||
->where($qb->expr()->eq('user_id', $qb->createNamedParameter($uid))); | ||
return $this->findEntities($select); | ||
} | ||
|
||
public function find(string $uid, string $address): ?InternalAddress { | ||
$qb = $this->db->getQueryBuilder(); | ||
$select = $qb->select('*') | ||
->from($this->getTableName()) | ||
->where( | ||
$qb->expr()->eq('user_id', $qb->createNamedParameter($uid)), | ||
$qb->expr()->eq('address', $qb->createNamedParameter($address)) | ||
); | ||
try { | ||
return $this->findEntity($select); | ||
} catch (DoesNotExistException $e) { | ||
return null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
namespace OCA\Mail\Migration; | ||
|
||
use Closure; | ||
use OCP\DB\ISchemaWrapper; | ||
use OCP\DB\Types; | ||
use OCP\Migration\IOutput; | ||
use OCP\Migration\SimpleMigrationStep; | ||
|
||
class Version4000Date20240716172702 extends SimpleMigrationStep { | ||
/** | ||
* @param IOutput $output | ||
* @param Closure(): ISchemaWrapper $schemaClosure | ||
* @param array $options | ||
* @return ISchemaWrapper | ||
*/ | ||
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { | ||
/** @var ISchemaWrapper $schema */ | ||
$schema = $schemaClosure(); | ||
$table = $schema->createTable('mail_internal_address'); | ||
|
||
$table->addColumn('id', Types::INTEGER, [ | ||
'autoincrement' => true, | ||
'notnull' => true, | ||
'length' => 4, | ||
]); | ||
$table->addColumn('address', Types::STRING, [ | ||
'notnull' => true, | ||
'length' => 255, | ||
]); | ||
$table->addColumn('type', Types::STRING, [ | ||
'notnull' => true, | ||
'length' => 64, | ||
]); | ||
$table->addColumn('user_id', Types::STRING, [ | ||
'notnull' => true, | ||
'length' => 64, | ||
]); | ||
$table->setPrimaryKey(['id']); | ||
$table->addUniqueIndex(['address', 'user_id'], 'mail_internal_address_uniq'); | ||
|
||
return $schema; | ||
} | ||
|
||
|
||
} |
Oops, something went wrong.