Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
94.74% |
36 / 38 |
|
50.00% |
2 / 4 |
CRAP | |
0.00% |
0 / 1 |
| DavAccountResolver | |
94.59% |
35 / 37 |
|
50.00% |
2 / 4 |
14.03 | |
0.00% |
0 / 1 |
| __construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| resolveByUserId | |
92.86% |
13 / 14 |
|
0.00% |
0 / 1 |
5.01 | |||
| listActiveAccounts | |
100.00% |
16 / 16 |
|
100.00% |
1 / 1 |
4 | |||
| resolveCredential | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
4.07 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | /** @license For full copyright and license information, please see the LICENSE.md file. */ |
| 6 | |
| 7 | namespace App\Modules\Dav\Application\Service; |
| 8 | |
| 9 | defined('AMMONLY_APP') || exit('Direct script access is forbidden.'); |
| 10 | |
| 11 | use App\Modules\Dav\Domain\Model\DavAccount; |
| 12 | use PDO; |
| 13 | |
| 14 | /** |
| 15 | * DAV Account Resolver Application Service. |
| 16 | * |
| 17 | * Resolves user credentials and CalDAV/CardDAV collection parameters from system user records. |
| 18 | * |
| 19 | * @package App\Modules\Dav\Application\Service |
| 20 | */ |
| 21 | final readonly class DavAccountResolver |
| 22 | { |
| 23 | private const string DEFAULT_BASE_URL = 'https://mail.ammonly.com/SOGo/dav'; |
| 24 | |
| 25 | /** |
| 26 | * DavAccountResolver constructor. |
| 27 | * |
| 28 | * @param PDO $pdo PDO database connection. |
| 29 | * @param string $tablePrefix Optional database table prefix. |
| 30 | * @param string $baseUrl Base DAV endpoint URL. |
| 31 | * @param string $defaultSecret Default mailbox authentication credential fallback. |
| 32 | */ |
| 33 | public function __construct( |
| 34 | private PDO $pdo, |
| 35 | private string $tablePrefix = 'a_', |
| 36 | private string $baseUrl = self::DEFAULT_BASE_URL, |
| 37 | private string $defaultSecret = '' |
| 38 | ) { |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * Resolves a DavAccount for a given user ID. |
| 43 | * |
| 44 | * @param int $userId Local CRM user ID. |
| 45 | * @return DavAccount|null DavAccount object or null if user has no DAV account. |
| 46 | */ |
| 47 | public function resolveByUserId(int $userId): ?DavAccount |
| 48 | { |
| 49 | $table = $this->tablePrefix . 'mod_users_records'; |
| 50 | $sql = sprintf( |
| 51 | 'SELECT `id`, `email`, `dav_account`, `has_dav_account` FROM `%s` WHERE `id` = :id LIMIT 1', |
| 52 | $table |
| 53 | ); |
| 54 | $stmt = $this->pdo->prepare($sql); |
| 55 | $stmt->execute([':id' => $userId]); |
| 56 | $row = $stmt->fetch(PDO::FETCH_ASSOC); |
| 57 | |
| 58 | if (!is_array($row) || ((int) ($row['has_dav_account'] ?? 0)) !== 1) { |
| 59 | return null; |
| 60 | } |
| 61 | |
| 62 | $davEmail = (string) ($row['dav_account'] ?: $row['email']); |
| 63 | if ($davEmail === '') { |
| 64 | return null; |
| 65 | } |
| 66 | |
| 67 | return new DavAccount($userId, $davEmail, $this->resolveCredential(), $this->baseUrl); |
| 68 | } |
| 69 | |
| 70 | /** |
| 71 | * Retrieves all active users configured with an active DAV synchronization account. |
| 72 | * |
| 73 | * @return array<int, DavAccount> List of active DavAccount profiles. |
| 74 | */ |
| 75 | public function listActiveAccounts(): array |
| 76 | { |
| 77 | $table = $this->tablePrefix . 'mod_users_records'; |
| 78 | $sql = sprintf( |
| 79 | 'SELECT `id`, `email`, `dav_account` FROM `%s` ' |
| 80 | . 'WHERE `status` = "active" AND `special_access` = 1 ' |
| 81 | . 'AND `has_dav_account` = 1 AND `dav_account` IS NOT NULL', |
| 82 | $table |
| 83 | ); |
| 84 | $stmt = $this->pdo->query($sql); |
| 85 | $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); |
| 86 | |
| 87 | $accounts = []; |
| 88 | foreach ($rows as $row) { |
| 89 | $userId = (int) $row['id']; |
| 90 | $email = (string) ($row['dav_account'] ?: $row['email']); |
| 91 | if ($email !== '') { |
| 92 | $accounts[] = new DavAccount($userId, $email, $this->resolveCredential(), $this->baseUrl); |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | return $accounts; |
| 97 | } |
| 98 | |
| 99 | /** |
| 100 | * Resolves fallback mailbox credential from property or environment. |
| 101 | * |
| 102 | * @return string Credential string. |
| 103 | */ |
| 104 | private function resolveCredential(): string |
| 105 | { |
| 106 | if ($this->defaultSecret !== '') { |
| 107 | return $this->defaultSecret; |
| 108 | } |
| 109 | |
| 110 | $envSecret = getenv('DAV_MAILBOX_SECRET'); |
| 111 | if (is_string($envSecret) && $envSecret !== '') { |
| 112 | return $envSecret; |
| 113 | } |
| 114 | |
| 115 | return ''; |
| 116 | } |
| 117 | } |