BTHLABS-61: Service layer refactoring

A journey to fix `ValidationError` in Pocket imports turned service
layer refactoring :D
This commit is contained in:
2025-10-12 18:37:32 +00:00
parent ac7a8dd90e
commit 8b86145519
45 changed files with 1023 additions and 337 deletions

View File

@@ -6,6 +6,7 @@ import hmac
import logging
import uuid
from django.core.exceptions import ValidationError
from django.db import models
import uuid6
@@ -15,6 +16,10 @@ from hotpocket_soa.dto.accounts import (
AccessTokenMetaUpdateIn,
AccessTokensQuery,
)
from hotpocket_soa.exceptions.backend import (
Invalid as InvalidError,
NotFound as NotFoundError,
)
LOGGER = logging.getLogger(__name__)
@@ -23,7 +28,10 @@ class AccessTokensService:
class AccessTokensServiceError(Exception):
pass
class AccessTokenNotFound(AccessTokensServiceError):
class Invalid(InvalidError, AccessTokensServiceError):
pass
class NotFound(NotFoundError, AccessTokensServiceError):
pass
def create(self,
@@ -32,20 +40,23 @@ class AccessTokensService:
origin: str,
meta: dict,
) -> AccessToken:
pk = uuid6.uuid7()
key = hmac.new(
settings.SECRET_KEY.encode('ascii'),
msg=pk.bytes,
digestmod=hashlib.sha256,
)
try:
pk = uuid6.uuid7()
key = hmac.new(
settings.SECRET_KEY.encode('ascii'),
msg=pk.bytes,
digestmod=hashlib.sha256,
)
return AccessToken.objects.create(
pk=pk,
account_uuid=account_uuid,
key=key.hexdigest(),
origin=origin,
meta=meta,
)
return AccessToken.objects.create(
pk=pk,
account_uuid=account_uuid,
key=key.hexdigest(),
origin=origin,
meta=meta,
)
except ValidationError as exception:
raise self.Invalid.from_django_validation_error(exception)
def get(self, *, pk: uuid.UUID) -> AccessToken:
try:
@@ -53,7 +64,7 @@ class AccessTokensService:
return query_set.get(pk=pk)
except AccessToken.DoesNotExist as exception:
raise self.AccessTokenNotFound(
raise self.NotFound(
f'Access Token not found: pk=`{pk}`',
) from exception
@@ -63,7 +74,7 @@ class AccessTokensService:
return query_set.get(key=key)
except AccessToken.DoesNotExist as exception:
raise self.AccessTokenNotFound(
raise self.NotFound(
f'Access Token not found: key=`{key}`',
) from exception
@@ -98,7 +109,7 @@ class AccessTokensService:
pk: uuid.UUID,
update: AccessTokenMetaUpdateIn,
) -> AccessToken:
access_token = AccessToken.active_objects.get(pk=pk)
access_token = self.get(pk=pk)
next_meta = {
**(access_token.meta or {}),

View File

@@ -5,6 +5,7 @@ import logging
import uuid
from hotpocket_backend.apps.accounts.models import Account
from hotpocket_soa.exceptions.backend import NotFound as NotFoundError
LOGGER = logging.getLogger(__name__)
@@ -13,7 +14,7 @@ class AccountsService:
class AccountsServiceError(Exception):
pass
class AccountNotFound(AccountsServiceError):
class NotFound(NotFoundError, AccountsServiceError):
pass
def get(self, *, pk: uuid.UUID) -> Account:
@@ -22,6 +23,6 @@ class AccountsService:
return query_set.get(pk=pk)
except Account.DoesNotExist as exception:
raise self.AccountNotFound(
raise self.NotFound(
f'Account not found: pk=`{pk}`',
) from exception

View File

@@ -5,11 +5,17 @@ import datetime
import logging
import uuid
from django.core.exceptions import ValidationError
from django.utils.timezone import now
import uuid6
from hotpocket_backend.apps.accounts.models import AuthKey
from hotpocket_backend.apps.core.conf import settings
from hotpocket_soa.exceptions.backend import (
InternalError,
Invalid as InvalidError,
NotFound as NotFoundError,
)
LOGGER = logging.getLogger(__name__)
@@ -18,22 +24,25 @@ class AuthKeysService:
class AuthKeysServiceError(Exception):
pass
class AuthKeyNotFound(AuthKeysServiceError):
class Invalid(InvalidError, AuthKeysServiceError):
pass
class AuthKeyExpired(AuthKeysServiceError):
class NotFound(NotFoundError, AuthKeysServiceError):
pass
class AuthKeyAccessDenied(AuthKeysServiceError):
class Expired(InternalError, AuthKeysServiceError):
pass
def create(self, *, account_uuid: uuid.UUID) -> AuthKey:
key = str(uuid6.uuid7())
try:
key = str(uuid6.uuid7())
return AuthKey.objects.create(
account_uuid=account_uuid,
key=key,
)
return AuthKey.objects.create(
account_uuid=account_uuid,
key=key,
)
except ValidationError as exception:
raise self.Invalid.from_django_validation_error(exception)
def get(self, *, pk: uuid.UUID) -> AuthKey:
try:
@@ -41,7 +50,7 @@ class AuthKeysService:
return query_set.get(pk=pk)
except AuthKey.DoesNotExist as exception:
raise self.AuthKeyNotFound(
raise self.NotFound(
f'Auth Key not found: pk=`{pk}`',
) from exception
@@ -56,17 +65,17 @@ class AuthKeysService:
if ttl > 0:
if result.created_at < now() - datetime.timedelta(seconds=ttl):
raise self.AuthKeyExpired(
raise self.Expired(
f'Auth Key expired: pk=`{key}`',
)
if result.consumed_at is not None:
raise self.AuthKeyExpired(
raise self.Expired(
f'Auth Key already consumed: pk=`{key}`',
)
return result
except AuthKey.DoesNotExist as exception:
raise self.AuthKeyNotFound(
raise self.NotFound(
f'Auth Key not found: key=`{key}`',
) from exception