Skip to content

Commit

Permalink
Add action for listing the attachments of a melding (#92)
Browse files Browse the repository at this point in the history
  • Loading branch information
4c0n authored Oct 24, 2024
1 parent 3dbfb33 commit c82c7d0
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 14 deletions.
30 changes: 24 additions & 6 deletions meldingen_core/actions/attachment.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from collections.abc import Collection
from typing import AsyncIterator, Generic, TypeVar
from uuid import uuid4

Expand All @@ -12,13 +13,14 @@
from meldingen_core.validators import BaseMediaTypeIntegrityValidator, BaseMediaTypeValidator

A = TypeVar("A", bound=Attachment)
A_co = TypeVar("A_co", bound=Attachment, covariant=True)
M = TypeVar("M", bound=Melding)
M_co = TypeVar("M_co", bound=Melding, covariant=True)


class UploadAttachmentAction(Generic[A, M, M_co]):
class UploadAttachmentAction(Generic[A, A_co, M, M_co]):
_create_attachment: BaseAttachmentFactory[A, M]
_attachment_repository: BaseAttachmentRepository
_attachment_repository: BaseAttachmentRepository[A, A_co]
_filesystem: Filesystem
_verify_token: TokenVerifier[M, M_co]
_base_directory: str
Expand All @@ -28,7 +30,7 @@ class UploadAttachmentAction(Generic[A, M, M_co]):
def __init__(
self,
attachment_factory: BaseAttachmentFactory[A, M],
attachment_repository: BaseAttachmentRepository,
attachment_repository: BaseAttachmentRepository[A, A_co],
filesystem: Filesystem,
token_verifier: TokenVerifier[M, M_co],
media_type_validator: BaseMediaTypeValidator,
Expand Down Expand Up @@ -69,15 +71,15 @@ async def __call__(
return attachment


class DownloadAttachmentAction(Generic[M, M_co]):
class DownloadAttachmentAction(Generic[A, A_co, M, M_co]):
_verify_token: TokenVerifier[M, M_co]
_attachment_repository: BaseAttachmentRepository
_attachment_repository: BaseAttachmentRepository[A, A_co]
_filesystem: Filesystem

def __init__(
self,
token_verifier: TokenVerifier[M, M_co],
attachment_repository: BaseAttachmentRepository,
attachment_repository: BaseAttachmentRepository[A, A_co],
filesystem: Filesystem,
):
self._verify_token = token_verifier
Expand All @@ -99,3 +101,19 @@ async def __call__(self, melding_id: int, attachment_id: int, token: str) -> Asy
return await file.get_iterator()
except filesystem.NotFoundException as exception:
raise NotFoundException("File not found") from exception


class ListAttachmentsAction(Generic[A, A_co, M, M_co]):
_verify_token: TokenVerifier[M, M_co]
_attachment_repository: BaseAttachmentRepository[A, A_co]

def __init__(
self, token_verifier: TokenVerifier[M, M_co], attachment_repository: BaseAttachmentRepository[A, A_co]
):
self._verify_token = token_verifier
self._attachment_repository = attachment_repository

async def __call__(self, melding_id: int, token: str) -> Collection[A_co]:
await self._verify_token(melding_id, token)

return await self._attachment_repository.find_by_melding(melding_id)
8 changes: 7 additions & 1 deletion meldingen_core/repositories.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,10 @@ class BaseQuestionRepository(BaseRepository[Question, Question], metaclass=ABCMe
class BaseAnswerRepository(BaseRepository[Answer, Answer], metaclass=ABCMeta): ...


class BaseAttachmentRepository(BaseRepository[Attachment, Attachment], metaclass=ABCMeta): ...
A = TypeVar("A", bound=Attachment)
A_co = TypeVar("A_co", covariant=True, bound=Attachment)


class BaseAttachmentRepository(BaseRepository[A, A_co], metaclass=ABCMeta):
@abstractmethod
async def find_by_melding(self, melding_id: int) -> Collection[A_co]: ...
34 changes: 27 additions & 7 deletions tests/test_actions/test_attachment.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from plugfs import filesystem
from plugfs.filesystem import File, Filesystem

from meldingen_core.actions.attachment import DownloadAttachmentAction, UploadAttachmentAction
from meldingen_core.actions.attachment import DownloadAttachmentAction, ListAttachmentsAction, UploadAttachmentAction
from meldingen_core.exceptions import NotFoundException
from meldingen_core.factories import BaseAttachmentFactory
from meldingen_core.models import Attachment, Melding
Expand All @@ -28,9 +28,9 @@ async def test_can_handle_attachment(self) -> None:

filesystem = Mock(Filesystem)

attachment_repository = Mock(BaseAttachmentRepository)
attachment_repository = Mock(BaseAttachmentRepository[Attachment, Attachment])

action: UploadAttachmentAction[Attachment, Melding, Melding] = UploadAttachmentAction(
action: UploadAttachmentAction[Attachment, Attachment, Melding, Melding] = UploadAttachmentAction(
Mock(BaseAttachmentFactory),
attachment_repository,
filesystem,
Expand All @@ -55,7 +55,7 @@ async def test_attachment_not_found(self) -> None:
attachment_repository = Mock(BaseAttachmentRepository)
attachment_repository.retrieve.return_value = None

action: DownloadAttachmentAction[Melding, Melding] = DownloadAttachmentAction(
action: DownloadAttachmentAction[Attachment, Attachment, Melding, Melding] = DownloadAttachmentAction(
AsyncMock(TokenVerifier),
attachment_repository,
Mock(Filesystem),
Expand All @@ -74,7 +74,7 @@ async def test_attachment_does_not_belong_to_melding(self) -> None:
attachment_repository = Mock(BaseAttachmentRepository)
attachment_repository.retrieve.return_value = attachment

action: DownloadAttachmentAction[Melding, Melding] = DownloadAttachmentAction(
action: DownloadAttachmentAction[Attachment, Attachment, Melding, Melding] = DownloadAttachmentAction(
AsyncMock(TokenVerifier),
attachment_repository,
Mock(Filesystem),
Expand All @@ -97,7 +97,7 @@ async def test_can_handle_attachment_download(self) -> None:
attachment_repository = Mock(BaseAttachmentRepository)
attachment_repository.retrieve.return_value = attachment

action: DownloadAttachmentAction[Melding, Melding] = DownloadAttachmentAction(
action: DownloadAttachmentAction[Attachment, Attachment, Melding, Melding] = DownloadAttachmentAction(
token_verifier,
attachment_repository,
Mock(Filesystem),
Expand All @@ -123,7 +123,7 @@ async def test_file_not_found(self) -> None:
filesystem_mock = Mock(Filesystem)
filesystem_mock.get_file.return_value = file

action: DownloadAttachmentAction[Melding, Melding] = DownloadAttachmentAction(
action: DownloadAttachmentAction[Attachment, Attachment, Melding, Melding] = DownloadAttachmentAction(
token_verifier,
attachment_repository,
filesystem_mock,
Expand All @@ -133,3 +133,23 @@ async def test_file_not_found(self) -> None:
await action(123, 456, "supersecrettoken")

assert str(exception_info.value) == "File not found"


class TestListAttachmentsAction:
@pytest.mark.anyio
async def test_can_list_attachments(self) -> None:
token = "supersecrettoken"
melding_id = 123
repo_attachments: list[Attachment] = []
token_verifier = AsyncMock(TokenVerifier)
repository = Mock(BaseAttachmentRepository)
repository.find_by_melding.return_value = repo_attachments

action: ListAttachmentsAction[Attachment, Attachment, Melding, Melding] = ListAttachmentsAction(
token_verifier, repository
)
attachments = await action(melding_id, token)

assert repo_attachments == attachments
token_verifier.assert_awaited_once()
repository.find_by_melding.assert_awaited_once_with(melding_id)

0 comments on commit c82c7d0

Please sign in to comment.