You've already forked hotpocket
A journey to fix `ValidationError` in Pocket imports turned service layer refactoring :D
175 lines
5.3 KiB
Python
175 lines
5.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
from __future__ import annotations
|
|
|
|
import datetime
|
|
import http
|
|
import uuid
|
|
|
|
from hotpocket_backend.apps.saves.services import (
|
|
AssociationsService as BackendAssociationsService,
|
|
)
|
|
from hotpocket_soa.dto.associations import (
|
|
AssociationOut,
|
|
AssociationsQuery,
|
|
AssociationUpdateIn,
|
|
AssociationWithTargetOut,
|
|
)
|
|
from hotpocket_soa.dto.saves import SaveOut
|
|
from hotpocket_soa.exceptions.backend import NotFound
|
|
|
|
from .base import ProxyService, SOAError
|
|
|
|
|
|
class AssociationsService(ProxyService):
|
|
class AssociationsServiceError(SOAError):
|
|
pass
|
|
|
|
class NotFound(AssociationsServiceError):
|
|
pass
|
|
|
|
class AccessDenied(AssociationsServiceError):
|
|
pass
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.backend_associations_service = BackendAssociationsService()
|
|
|
|
def get_error_class(self) -> type[SOAError]:
|
|
return self.AssociationsServiceError
|
|
|
|
def create(self,
|
|
*,
|
|
account_uuid: uuid.UUID,
|
|
target: SaveOut,
|
|
pk: uuid.UUID | None = None,
|
|
created_at: datetime.datetime | None = None,
|
|
) -> AssociationOut:
|
|
return AssociationOut.model_validate(
|
|
self.call(
|
|
self.backend_associations_service,
|
|
'create',
|
|
account_uuid=account_uuid,
|
|
save_uuid=target.pk,
|
|
pk=pk,
|
|
created_at=created_at,
|
|
),
|
|
from_attributes=True,
|
|
)
|
|
|
|
def get(self,
|
|
*,
|
|
account_uuid: uuid.UUID | None,
|
|
pk: uuid.UUID,
|
|
with_target: bool = False,
|
|
allow_archived: bool = False,
|
|
) -> AssociationOut | AssociationWithTargetOut:
|
|
try:
|
|
model: type[AssociationOut] = AssociationOut
|
|
if with_target is True:
|
|
model = AssociationWithTargetOut
|
|
|
|
result = model.model_validate(
|
|
self.call(
|
|
self.backend_associations_service,
|
|
'get',
|
|
pk=pk,
|
|
with_target=with_target,
|
|
),
|
|
from_attributes=True,
|
|
)
|
|
|
|
if allow_archived is False and result.archived_at is not None:
|
|
raise self.NotFound(
|
|
http.HTTPStatus.NOT_FOUND.value, f'pk=`{pk}`',
|
|
)
|
|
|
|
if account_uuid is not None and result.account_uuid != account_uuid:
|
|
raise self.AccessDenied(
|
|
http.HTTPStatus.FORBIDDEN.value,
|
|
f'account_uuid=`{account_uuid}` pk=`{pk}`',
|
|
)
|
|
|
|
return result
|
|
except NotFound as exception:
|
|
raise self.NotFound.from_backend_error(exception)
|
|
|
|
def search(self,
|
|
*,
|
|
query: AssociationsQuery,
|
|
limit: int,
|
|
) -> list[AssociationWithTargetOut]:
|
|
return [
|
|
AssociationWithTargetOut.model_validate(row, from_attributes=True)
|
|
for row
|
|
in self.call(
|
|
self.backend_associations_service,
|
|
'search',
|
|
query=query,
|
|
limit=limit,
|
|
)
|
|
]
|
|
|
|
def archive(self, *, association: AssociationOut) -> bool:
|
|
try:
|
|
return self.call(
|
|
self.backend_associations_service,
|
|
'archive',
|
|
pk=association.pk,
|
|
)
|
|
except NotFound as exception:
|
|
raise self.NotFound.from_backend_error(exception)
|
|
|
|
def star(self, *, association: AssociationOut) -> AssociationOut:
|
|
try:
|
|
return AssociationOut.model_validate(
|
|
self.call(
|
|
self.backend_associations_service,
|
|
'star',
|
|
pk=association.pk,
|
|
),
|
|
from_attributes=True,
|
|
)
|
|
except NotFound as exception:
|
|
raise self.NotFound.from_backend_error(exception)
|
|
|
|
def unstar(self, *, association: AssociationOut) -> AssociationOut:
|
|
try:
|
|
return AssociationOut.model_validate(
|
|
self.call(
|
|
self.backend_associations_service,
|
|
'unstar',
|
|
pk=association.pk,
|
|
),
|
|
from_attributes=True,
|
|
)
|
|
except NotFound as exception:
|
|
raise self.NotFound.from_backend_error(exception)
|
|
|
|
def update(self,
|
|
*,
|
|
association: AssociationOut,
|
|
update: AssociationUpdateIn,
|
|
) -> AssociationOut:
|
|
try:
|
|
return AssociationOut.model_validate(
|
|
self.call(
|
|
self.backend_associations_service,
|
|
'update',
|
|
pk=association.pk,
|
|
update=update,
|
|
),
|
|
from_attributes=True,
|
|
)
|
|
except NotFound as exception:
|
|
raise self.NotFound.from_backend_error(exception)
|
|
|
|
def delete(self, *, association: AssociationOut) -> bool:
|
|
try:
|
|
return self.call(
|
|
self.backend_associations_service,
|
|
'delete',
|
|
pk=association.pk,
|
|
)
|
|
except NotFound as exception:
|
|
raise self.NotFound.from_backend_error(exception)
|