mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-11-15 12:50:15 +00:00
[Web] API: complete the OpenAPI docs, add route tests for json_api.php
This commit is contained in:
47 files changed
+18848
-7491
No files matched your search
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mailcow\Tests\Api\Routing;
|
||||
|
||||
use Mailcow\Tests\Api\ApiTestCase;
|
||||
|
||||
/** add/edit/delete/get alias */
|
||||
class AliasRoutesTest extends ApiTestCase
|
||||
{
|
||||
private const SALES = ['id' => 12, 'address' => 'sales@example.org', 'goto' => 'anna@example.org,ben@example.org', 'active' => 1];
|
||||
private const INFO = ['id' => 13, 'address' => 'info@example.org', 'goto' => 'anna@example.org', 'active' => 1];
|
||||
private const SHOP = ['id' => 20, 'address' => 'shop@example.net', 'goto' => 'ben@example.org', 'active' => 0];
|
||||
|
||||
public function testAddPassesTheBody(): void
|
||||
{
|
||||
$attr = [
|
||||
'address' => "sales@example.org, info@example.org",
|
||||
'goto' => 'anna@example.org,ben@example.org',
|
||||
'active' => '1',
|
||||
'sogo_visible' => 1,
|
||||
'internal' => '0',
|
||||
'sender_allowed' => true,
|
||||
'public_comment' => 'Sales team',
|
||||
];
|
||||
|
||||
$result = $this->post('add/alias', $attr + ['csrf_token' => 'x']);
|
||||
|
||||
$this->assertSame([['add', 'alias', $attr]], $result->callsTo('mailbox'));
|
||||
}
|
||||
|
||||
public function testEditMergesItemsAndAttributes(): void
|
||||
{
|
||||
$list = $this->post('edit/alias', ['items' => [12, 'info@example.org'], 'attr' => ['goto_null' => '1', 'active' => '0']]);
|
||||
$this->assertCalled($list, 'mailbox', ['edit', 'alias', ['id' => [12, 'info@example.org'], 'goto_null' => '1', 'active' => '0']]);
|
||||
|
||||
$single = $this->post('edit/alias', ['items' => 12, 'attr' => ['expand_alias' => true]]);
|
||||
$this->assertCalled($single, 'mailbox', ['edit', 'alias', ['id' => [12], 'expand_alias' => true]]);
|
||||
}
|
||||
|
||||
public function testDeleteTakesIdsOrAddresses(): void
|
||||
{
|
||||
$result = $this->post('delete/alias', [12, 'info@example.org']);
|
||||
|
||||
$this->assertSame([['delete', 'alias', ['id' => [12, 'info@example.org']]]], $result->callsTo('mailbox'));
|
||||
}
|
||||
|
||||
public function testGetOneAliasByIdOrAddress(): void
|
||||
{
|
||||
$byId = $this->get('get/alias/12', ['script' => [self::answer('mailbox', ['get', 'alias_details', '12'], self::SALES)]]);
|
||||
$this->assertSame(self::SALES, $byId->json());
|
||||
|
||||
$byAddress = $this->get('get/alias/sales@example.org');
|
||||
$this->assertSame([['get', 'alias_details', 'sales@example.org']], $byAddress->callsTo('mailbox'));
|
||||
$this->assertSame('{}', $byAddress->body);
|
||||
}
|
||||
|
||||
public function testGetAllWalksTheDomainsAndAliasDomains(): void
|
||||
{
|
||||
$result = $this->get('get/alias/all', ['script' => [
|
||||
self::answer('mailbox', ['get', 'domains'], ['example.org', 'example.com']),
|
||||
self::answer('mailbox', ['get', 'alias_domains'], ['example.net']),
|
||||
self::answer('mailbox', ['get', 'aliases', 'example.org'], [12, 13, 14]),
|
||||
self::answer('mailbox', ['get', 'aliases', 'example.com'], []),
|
||||
self::answer('mailbox', ['get', 'aliases', 'example.net'], [20]),
|
||||
self::answer('mailbox', ['get', 'alias_details', 12], self::SALES),
|
||||
self::answer('mailbox', ['get', 'alias_details', 13], self::INFO),
|
||||
self::answer('mailbox', ['get', 'alias_details', 14], false),
|
||||
self::answer('mailbox', ['get', 'alias_details', 20], self::SHOP),
|
||||
]]);
|
||||
|
||||
$this->assertSame([self::SALES, self::INFO, self::SHOP], $result->json());
|
||||
$this->assertSame([
|
||||
['get', 'domains'],
|
||||
['get', 'alias_domains'],
|
||||
['get', 'aliases', 'example.org'],
|
||||
['get', 'alias_details', 12],
|
||||
['get', 'alias_details', 13],
|
||||
['get', 'alias_details', 14],
|
||||
['get', 'aliases', 'example.com'],
|
||||
['get', 'aliases', 'example.net'],
|
||||
['get', 'alias_details', 20],
|
||||
], $result->callsTo('mailbox'));
|
||||
}
|
||||
|
||||
public function testGetAllOfTheNamedDomains(): void
|
||||
{
|
||||
$result = $this->get('get/alias/all/example.org,example.net', ['script' => [
|
||||
self::answer('mailbox', ['get', 'aliases', 'example.org'], [12]),
|
||||
self::answer('mailbox', ['get', 'aliases', 'example.net'], [20]),
|
||||
self::answer('mailbox', ['get', 'alias_details', 12], self::SALES),
|
||||
self::answer('mailbox', ['get', 'alias_details', 20], self::SHOP),
|
||||
]]);
|
||||
|
||||
$this->assertSame([self::SALES, self::SHOP], $result->json());
|
||||
$this->assertSame([
|
||||
['get', 'aliases', 'example.org'],
|
||||
['get', 'alias_details', 12],
|
||||
['get', 'aliases', 'example.net'],
|
||||
['get', 'alias_details', 20],
|
||||
], $result->callsTo('mailbox'));
|
||||
}
|
||||
|
||||
public function testGetAllWithoutAliases(): void
|
||||
{
|
||||
$noDomains = $this->get('get/alias/all', ['script' => [
|
||||
self::answer('mailbox', ['get', 'domains'], []),
|
||||
self::answer('mailbox', ['get', 'alias_domains'], []),
|
||||
]]);
|
||||
$this->assertSame('{}', $noDomains->body);
|
||||
|
||||
$noAliases = $this->get('get/alias/all/example.org', ['script' => [self::answer('mailbox', ['get', 'aliases'], false)]]);
|
||||
$this->assertSame('{}', $noAliases->body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mailcow\Tests\Api\Routing;
|
||||
|
||||
use Mailcow\Tests\Api\ApiTestCase;
|
||||
|
||||
/** add/edit/delete/get fwdhost */
|
||||
class ForwardingHostRoutesTest extends ApiTestCase
|
||||
{
|
||||
private const HOSTS = [
|
||||
['host' => '192.0.2.25', 'source' => 'relay.example.com', 'keep_spam' => 'yes'],
|
||||
['host' => '2001:db8::25', 'source' => 'relay.example.com', 'keep_spam' => 'yes'],
|
||||
];
|
||||
|
||||
public function testAddPassesTheBody(): void
|
||||
{
|
||||
$result = $this->post('add/fwdhost', ['hostname' => 'relay.example.com', 'filter_spam' => '1']);
|
||||
|
||||
$this->assertSame([['add', ['hostname' => 'relay.example.com', 'filter_spam' => '1']]], $result->callsTo('fwdhost'));
|
||||
}
|
||||
|
||||
public function testEditNamesTheHostsFwdhost(): void
|
||||
{
|
||||
$result = $this->post('edit/fwdhost', ['items' => ['192.0.2.25', '198.51.100.0/24'], 'attr' => ['keep_spam' => '0']]);
|
||||
|
||||
$this->assertSame([['edit', ['fwdhost' => ['192.0.2.25', '198.51.100.0/24'], 'keep_spam' => '0']]], $result->callsTo('fwdhost'));
|
||||
}
|
||||
|
||||
public function testDeleteNamesTheHostsForwardinghost(): void
|
||||
{
|
||||
$result = $this->post('delete/fwdhost', ['192.0.2.25', '2001:db8::25']);
|
||||
|
||||
$this->assertSame([['delete', ['forwardinghost' => ['192.0.2.25', '2001:db8::25']]]], $result->callsTo('fwdhost'));
|
||||
}
|
||||
|
||||
public function testGetAllPassesTheList(): void
|
||||
{
|
||||
$result = $this->get('get/fwdhost/all', ['script' => [self::answer('fwdhost', ['get'], self::HOSTS)]]);
|
||||
|
||||
$this->assertSame(self::HOSTS, $result->json());
|
||||
$this->assertSame([['get']], $result->callsTo('fwdhost'));
|
||||
|
||||
$this->assertSame('{}', $this->get('get/fwdhost/all', ['script' => [self::answer('fwdhost', ['get'], [])]])->body);
|
||||
}
|
||||
|
||||
public function testGetOneHost(): void
|
||||
{
|
||||
$found = $this->get('get/fwdhost/192.0.2.25', ['script' => [self::answer('fwdhost', ['details', '192.0.2.25'], self::HOSTS[0])]]);
|
||||
$this->assertSame(self::HOSTS[0], $found->json());
|
||||
|
||||
$this->assertSame('{}', $this->get('get/fwdhost/192.0.2.99', ['script' => [self::answer('fwdhost', ['details'], [])]])->body);
|
||||
}
|
||||
|
||||
public function testGetOneNetworkIsCutAtTheSlash(): void
|
||||
{
|
||||
$result = $this->get('get/fwdhost/198.51.100.0/24');
|
||||
|
||||
$this->assertSame([['details', '198.51.100.0']], $result->callsTo('fwdhost'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mailcow\Tests\Api\Routing;
|
||||
|
||||
use Mailcow\Tests\Api\ApiTestCase;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
|
||||
/** bcc, recipient_map and tls-policy-map: json_api.php handles the three alike */
|
||||
class MapRoutesTest extends ApiTestCase
|
||||
{
|
||||
public static function maps(): array
|
||||
{
|
||||
return [
|
||||
'bcc' => ['bcc', 'bcc',
|
||||
['local_dest' => 'example.org', 'bcc_dest' => 'archive@example.com', 'type' => 'rcpt', 'active' => '1'],
|
||||
['id' => 3, 'local_dest' => '@example.org', 'bcc_dest' => 'archive@example.com', 'active' => 1, 'type' => 'rcpt', 'domain' => 'example.org']],
|
||||
'recipient_map' => ['recipient_map', 'recipient_map',
|
||||
['recipient_map_old' => 'old@example.org', 'recipient_map_new' => 'new@example.org', 'active' => 1],
|
||||
['id' => 3, 'recipient_map_old' => 'old@example.org', 'recipient_map_new' => 'new@example.org', 'active' => 1]],
|
||||
'tls-policy-map' => ['tls-policy-map', 'tls_policy_maps',
|
||||
['dest' => 'example.com', 'policy' => 'encrypt', 'parameters' => 'protocols=>=TLSv1.2', 'active' => '1'],
|
||||
['id' => 3, 'dest' => 'example.com', 'policy' => 'encrypt', 'parameters' => '', 'active' => 1]],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('maps')]
|
||||
public function testAddPassesTheBody(string $category, string $function, array $attr): void
|
||||
{
|
||||
$result = $this->post("add/$category", $attr);
|
||||
|
||||
$this->assertSame([['add', $attr]], $result->callsTo($function));
|
||||
}
|
||||
|
||||
#[DataProvider('maps')]
|
||||
public function testEditMergesItemsAndAttributes(string $category, string $function): void
|
||||
{
|
||||
$list = $this->post("edit/$category", ['items' => [3, '4'], 'attr' => ['active' => '0']]);
|
||||
$this->assertSame([['edit', ['id' => [3, '4'], 'active' => '0']]], $list->callsTo($function));
|
||||
|
||||
$single = $this->post("edit/$category", ['items' => 3, 'attr' => ['active' => '1']]);
|
||||
$this->assertSame([['edit', ['id' => [3], 'active' => '1']]], $single->callsTo($function));
|
||||
}
|
||||
|
||||
#[DataProvider('maps')]
|
||||
public function testDeleteTakesIds(string $category, string $function): void
|
||||
{
|
||||
$result = $this->post("delete/$category", [3, 4]);
|
||||
|
||||
$this->assertSame([['delete', ['id' => [3, 4]]]], $result->callsTo($function));
|
||||
}
|
||||
|
||||
#[DataProvider('maps')]
|
||||
public function testGetAllCollectsTheDetailsOfEveryId(string $category, string $function, array $attr, array $details): void
|
||||
{
|
||||
$result = $this->get("get/$category/all", ['script' => [
|
||||
self::answer($function, ['get'], [3, 4, 5]),
|
||||
self::answer($function, ['details', 3], $details),
|
||||
self::answer($function, ['details', 4], false),
|
||||
self::answer($function, ['details', 5], ['id' => 5] + $details),
|
||||
]]);
|
||||
|
||||
$this->assertSame([$details, ['id' => 5] + $details], $result->json());
|
||||
$this->assertSame([['get'], ['details', 3], ['details', 4], ['details', 5]], $result->callsTo($function));
|
||||
}
|
||||
|
||||
#[DataProvider('maps')]
|
||||
public function testGetAllWithoutEntries(string $category, string $function): void
|
||||
{
|
||||
$result = $this->get("get/$category/all", ['script' => [self::answer($function, ['get'], [])]]);
|
||||
|
||||
$this->assertSame('{}', $result->body);
|
||||
}
|
||||
|
||||
#[DataProvider('maps')]
|
||||
public function testGetOneAddsANullMember(string $category, string $function, array $attr, array $details): void
|
||||
{
|
||||
// json_api.php appends the undefined $details to the answer
|
||||
$found = $this->get("get/$category/3", ['script' => [self::answer($function, ['details', '3'], $details)]]);
|
||||
$this->assertSame($details + [0 => null], $found->json());
|
||||
|
||||
$missing = $this->get("get/$category/9", ['script' => [self::answer($function, ['details', '9'], false)]]);
|
||||
$this->assertSame('{}', $missing->body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mailcow\Tests\Api\Routing;
|
||||
|
||||
use Mailcow\Tests\Api\ApiTestCase;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
|
||||
/** relayhost (sender-dependent transports) and transport (transport maps): json_api.php handles both alike */
|
||||
class TransportRoutesTest extends ApiTestCase
|
||||
{
|
||||
public static function transports(): array
|
||||
{
|
||||
return [
|
||||
'relayhost' => ['relayhost',
|
||||
['hostname' => '[smtp.example.com]:587', 'username' => 'relay-user', 'password' => 'secret'],
|
||||
['id' => 1, 'hostname' => '[smtp.example.com]:587', 'username' => 'relay-user', 'active' => 1, 'used_by_domains' => 'example.org']],
|
||||
'transport' => ['transport',
|
||||
['destination' => 'example.com, .example.com', 'nexthop' => '[mx.example.com]:25', 'is_mx_based' => '0', 'active' => '1'],
|
||||
['id' => 1, 'is_mx_based' => 0, 'destination' => 'example.com', 'nexthop' => '[mx.example.com]:25', 'active' => 1]],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('transports')]
|
||||
public function testAddPassesTheBody(string $category, array $attr): void
|
||||
{
|
||||
$result = $this->post("add/$category", $attr);
|
||||
|
||||
$this->assertSame([['add', $attr]], $result->callsTo($category));
|
||||
}
|
||||
|
||||
#[DataProvider('transports')]
|
||||
public function testEditMergesItemsAndAttributes(string $category): void
|
||||
{
|
||||
$result = $this->post("edit/$category", ['items' => [1, 2], 'attr' => ['active' => '0', 'password' => '']]);
|
||||
|
||||
$this->assertSame([['edit', ['id' => [1, 2], 'active' => '0', 'password' => '']]], $result->callsTo($category));
|
||||
}
|
||||
|
||||
#[DataProvider('transports')]
|
||||
public function testDeleteTakesIds(string $category): void
|
||||
{
|
||||
$result = $this->post("delete/$category", ['1', 2]);
|
||||
|
||||
$this->assertSame([['delete', ['id' => ['1', 2]]]], $result->callsTo($category));
|
||||
}
|
||||
|
||||
#[DataProvider('transports')]
|
||||
public function testGetAllCollectsTheDetailsOfEveryRow(string $category, array $attr, array $details): void
|
||||
{
|
||||
$result = $this->get("get/$category/all", ['script' => [
|
||||
self::answer($category, ['get'], [['id' => 1, 'active' => 1], ['id' => 2, 'active' => 1], ['id' => 3, 'active' => 0]]),
|
||||
self::answer($category, ['details', 1], $details),
|
||||
self::answer($category, ['details', 2], false),
|
||||
self::answer($category, ['details', 3], ['id' => 3] + $details),
|
||||
]]);
|
||||
|
||||
$this->assertSame([$details, ['id' => 3] + $details], $result->json());
|
||||
$this->assertSame([['get'], ['details', 1], ['details', 2], ['details', 3]], $result->callsTo($category));
|
||||
}
|
||||
|
||||
#[DataProvider('transports')]
|
||||
public function testGetAllWithoutEntries(string $category): void
|
||||
{
|
||||
$none = $this->get("get/$category/all", ['script' => [self::answer($category, ['get'], [])]]);
|
||||
$this->assertSame('{}', $none->body);
|
||||
|
||||
$noDetails = $this->get("get/$category/all", ['script' => [
|
||||
self::answer($category, ['get'], [['id' => 1]]),
|
||||
self::answer($category, ['details'], false),
|
||||
]]);
|
||||
$this->assertSame('{}', $noDetails->body);
|
||||
}
|
||||
|
||||
#[DataProvider('transports')]
|
||||
public function testGetOne(string $category, array $attr, array $details): void
|
||||
{
|
||||
$found = $this->get("get/$category/1", ['script' => [self::answer($category, ['details', '1'], $details)]]);
|
||||
$this->assertSame($details, $found->json());
|
||||
|
||||
$missing = $this->get("get/$category/9", ['script' => [self::answer($category, ['details', '9'], false)]]);
|
||||
$this->assertSame('{}', $missing->body);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user