diff --git a/lib/Controller/AccountApiController.php b/lib/Controller/AccountApiController.php new file mode 100644 index 0000000000..1e6fd9c0bb --- /dev/null +++ b/lib/Controller/AccountApiController.php @@ -0,0 +1,70 @@ +|DataResponse + * + * 200: Account list + * 404: User was not logged in + */ + #[ApiRoute(verb: 'GET', url: '/account/list')] + #[NoAdminRequired] + #[NoCSRFRequired] + public function list(): DataResponse { + $userId = $this->userId; + if ($userId === null) { + return new DataResponse([], Http::STATUS_NOT_FOUND); + } + + $accounts = $this->accountService->findByUserId($userId); + return new DataResponse(array_map(function (Account $account) use ($userId) { + $aliases = $this->aliasesService->findAll($account->getId(), $userId); + return [ + 'id' => $account->getId(), + 'email' => $account->getEmail(), + 'aliases' => array_map(static fn (Alias $alias) => [ + 'id' => $alias->getId(), + 'email' => $alias->getAlias(), + 'name' => $alias->getName(), + ], $aliases), + ]; + }, $accounts)); + } +} diff --git a/lib/Db/Alias.php b/lib/Db/Alias.php index a59eb206c9..caba3b3d1f 100644 --- a/lib/Db/Alias.php +++ b/lib/Db/Alias.php @@ -17,8 +17,8 @@ /** * @method void setAccountId(int $accountId) * @method int getAccountId() - * @method void setName(string $name) - * @method string getName() + * @method void setName(string|null $name) + * @method string|null getName() * @method void setAlias(string $alias) * @method string getAlias() * @method void setSignature(string|null $signature) @@ -37,7 +37,7 @@ class Alias extends Entity implements JsonSerializable { /** @var int */ protected $accountId; - /** @var string */ + /** @var string|null */ protected $name; /** @var string */ diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php index 1e5a301a09..9dfd9f7418 100644 --- a/lib/ResponseDefinitions.php +++ b/lib/ResponseDefinitions.php @@ -44,6 +44,16 @@ * } * * @psalm-type MailMessageApiAttachment = array{ name: string, mime: string, size: int<0, max>, content: string} + * + * @psalm-type MailAccountListResponse = array{ + * id: int, + * email: string, + * aliases: array{ + * id: int, + * email: string, + * name: ?string, + * }[] + * } */ class ResponseDefinitions { } diff --git a/tests/Unit/Controller/AccountApiControllerTest.php b/tests/Unit/Controller/AccountApiControllerTest.php new file mode 100644 index 0000000000..c560c8e4f5 --- /dev/null +++ b/tests/Unit/Controller/AccountApiControllerTest.php @@ -0,0 +1,168 @@ +request = $this->createMock(IRequest::class); + $this->accountService = $this->createMock(AccountService::class); + $this->aliasesService = $this->createMock(AliasesService::class); + + $this->controller = new AccountApiController( + 'mail', + $this->request, + self::USER_ID, + $this->accountService, + $this->aliasesService, + ); + } + + public function testListWithoutUser() { + $controller = new AccountApiController( + 'mail', + $this->request, + null, + $this->accountService, + $this->aliasesService, + ); + + $this->accountService->expects(self::never()) + ->method('findByUserId'); + + $this->aliasesService->expects(self::never()) + ->method('findAll'); + + $actual = $controller->list(); + $this->assertEquals(Http::STATUS_NOT_FOUND, $actual->getStatus()); + } + + public function testList() { + $mailAccount = new MailAccount(); + $mailAccount->setId(42); + $mailAccount->setEmail('foo@bar.com'); + + $account = new Account($mailAccount); + $this->accountService->expects(self::once()) + ->method('findByUserId') + ->with(self::USER_ID) + ->willReturn([$account]); + + $alias = new Alias(); + $alias->setId(10); + $alias->setName('Baz'); + $alias->setAlias('baz@bar.com'); + $this->aliasesService->expects(self::once()) + ->method('findAll') + ->with(42, self::USER_ID) + ->willReturn([$alias]); + + $actual = $this->controller->list(); + $this->assertEquals(Http::STATUS_OK, $actual->getStatus()); + $this->assertEquals([ + [ + 'id' => 42, + 'email' => 'foo@bar.com', + 'aliases' => [ + [ + 'id' => 10, + 'email' => 'baz@bar.com', + 'name' => 'Baz', + ], + ], + ] + ], $actual->getData()); + } + + public function testListWithAliasWithoutName() { + $mailAccount = new MailAccount(); + $mailAccount->setId(42); + $mailAccount->setEmail('foo@bar.com'); + + $account = new Account($mailAccount); + $this->accountService->expects(self::once()) + ->method('findByUserId') + ->with(self::USER_ID) + ->willReturn([$account]); + + $alias = new Alias(); + $alias->setId(10); + $alias->setName(null); + $alias->setAlias('baz@bar.com'); + $this->aliasesService->expects(self::once()) + ->method('findAll') + ->with(42, self::USER_ID) + ->willReturn([$alias]); + + $actual = $this->controller->list(); + $this->assertEquals(Http::STATUS_OK, $actual->getStatus()); + $this->assertEquals([ + [ + 'id' => 42, + 'email' => 'foo@bar.com', + 'aliases' => [ + [ + 'id' => 10, + 'email' => 'baz@bar.com', + 'name' => null, + ], + ], + ] + ], $actual->getData()); + } + + public function testListWithoutAliases() { + $mailAccount = new MailAccount(); + $mailAccount->setId(42); + $mailAccount->setEmail('foo@bar.com'); + + $account = new Account($mailAccount); + $this->accountService->expects(self::once()) + ->method('findByUserId') + ->with(self::USER_ID) + ->willReturn([$account]); + + $this->aliasesService->expects(self::once()) + ->method('findAll') + ->with(42, self::USER_ID) + ->willReturn([]); + + $actual = $this->controller->list(); + $this->assertEquals(Http::STATUS_OK, $actual->getStatus()); + $this->assertEquals([ + [ + 'id' => 42, + 'email' => 'foo@bar.com', + 'aliases' => [], + ] + ], $actual->getData()); + } + +}