Skip to content

Commit 7df03bb

Browse files
committed
chores: Updates proper references and reorganizes structs
1 parent 6b3c96a commit 7df03bb

33 files changed

+122
-122
lines changed

src/auth/adapters/email_sender.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import emails
22
import logging
33

4-
from craftship.core.ports.email_sender import AbstractEmailSender
5-
from craftship.auth import config
4+
from src.core.ports.email_sender import AbstractEmailSender
5+
from src.auth import config
66

77

88
class EmailSender(AbstractEmailSender):
@@ -28,5 +28,5 @@ def send_email(
2828
)
2929
logging.info(f"Sending email to {email_to} with subject: {subject}")
3030
response = message.send(to=email_to, smtp=self.smtp_options)
31-
logging.info(f"Email sent, response: {response}")
31+
logging.info(f"Email sent, service response: {response}")
3232
return response.status_code

src/auth/adapters/orm.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
)
1919
from sqlalchemy.orm import events, mapper, relationship
2020

21-
from craftship.auth.domain import model
21+
from src.auth.domain import model
2222

2323

2424
users: Callable[[MetaData], Table] = lambda metadata: Table(

src/auth/bootstrap.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from craftship.core.ports.unit_of_work import AbstractUnitOfWork
2-
from craftship.core.ports.email_sender import AbstractEmailSender
3-
from craftship.auth.services import unit_of_work
4-
from craftship.auth.adapters import email_sender
1+
from src.core.ports.unit_of_work import AbstractUnitOfWork
2+
from src.core.ports.email_sender import AbstractEmailSender
3+
from src.auth.services import unit_of_work
4+
from src.auth.adapters import email_sender
55

66

77
def create(

src/auth/config.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44

55
SCHEMA_PATHS = ("apolo/auth/entrypoint/graphql/schema.graphql",)
66

7+
# [TODO] These should be exported to ENVARs
78
DEFAULT_TOKEN_EXPIRATION = 60
89
DEFAULT_JWT_SECRET_KEY = base64.b64encode(
910
uuid.uuid4().hex[:7].encode("utf-8")
1011
).decode("utf-8")
1112
JWT_ALGORITHM = "HS256"
1213
AUTH_TYPE = "Bearer"
1314
EMAIL_TEMPLATES_DIR = "apolo/auth/services/email-templates"
14-
SUBJECT_PWD_CHANGE = "Troca de Senha Apolo NPL"
15+
SUBJECT_PWD_CHANGE = "Password Change Request"
1516

1617

1718
def get_jwt_secret_key() -> str:

src/auth/domain/model.py

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import jwt
44
from dataclasses import dataclass
55
from typing import Any, Optional, Set, List
6+
# TODO we shouldn't be importing any of these below here
67
from passlib.context import CryptContext
78
from datetime import datetime, timedelta
89
from string import Template
@@ -134,6 +135,7 @@ def generate_password_reset_token(self) -> bytes:
134135
return encoded_jwt.decode("utf-8")
135136

136137
def generate_reset_pwd_email(self, client_url: str) -> str:
138+
# TODO This method should be inside a proper adapter
137139
with open(Path(config.EMAIL_TEMPLATES_DIR) / "reset_pwd.html") as f:
138140
template_str = f.read()
139141

src/auth/entrypoint/graphql/directives.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
)
1313

1414

15-
from craftship.auth.entrypoint import uow
16-
from craftship.auth.services import handlers
15+
from src.auth.entrypoint import uow
16+
from src.auth.services import handlers
1717

1818

1919
class NeedsPermissionDirective(SchemaDirectiveVisitor):

src/auth/entrypoint/graphql/middlewares.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
from ariadne.types import GraphQLError, GraphQLResolveInfo, Resolver
33
from starlette.requests import Headers, HTTPConnection
44

5-
from craftship.auth import utils
6-
from craftship.core.exceptions import resolve_error, ApoloException
5+
from src.auth import utils
6+
from src.core.exceptions import resolve_error, ApoloException
77

88

99
class MissingAuthHeader(ApoloException):

src/auth/entrypoint/graphql/resolvers.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
convert_kwargs_to_snake_case,
88
)
99

10-
from craftship.core.exceptions import resolve_error
11-
from craftship.auth.services import handlers
12-
from craftship.auth.entrypoint import uow, email_sender
13-
from craftship.auth import config, views
14-
from craftship.auth import utils
10+
from src.core.exceptions import resolve_error
11+
from src.auth.services import handlers
12+
from src.auth.entrypoint import uow, email_sender
13+
from src.auth import config, views
14+
from src.auth import utils
1515

1616

1717
query = QueryType()

src/auth/services/handlers.py

+16-13
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,45 @@
11
from typing import Dict, List, Tuple
22

3-
from craftship.auth.domain import model
4-
from craftship.auth.services import unit_of_work
5-
from craftship.auth.adapters import email_sender
6-
from craftship.auth import config
7-
from craftship.auth import utils
8-
from craftship.core.exceptions import ApoloException
3+
from src.auth.domain import model
4+
from src.auth.services import unit_of_work
5+
from src.auth.adapters import email_sender
6+
from src.auth import config
7+
from src.auth import utils
98

9+
from src.core.exceptions import ServerException
1010

11-
class UnknownUser(ApoloException):
11+
12+
class UnknownUser(ServerException):
1213
def __init__(self, access_key: str):
1314
super().__init__(f"Access key {access_key} does not exist")
1415

1516

16-
class UserAlreadyExists(ApoloException):
17+
class UserAlreadyExists(ServerException):
1718
def __init__(self, access_key: str):
1819
super().__init__(f"Access key {access_key} already exists")
1920

2021

21-
class InvalidEmail(ApoloException):
22+
class InvalidEmail(ServerException):
2223
def __init__(self, email: str):
2324
super().__init__(f"Email {email} not valid")
2425

2526

26-
class WrongCredentials(ApoloException):
27+
class WrongCredentials(ServerException):
2728
def __init__(self):
2829
super().__init__("Username or password invalid")
2930

3031

31-
class RoleAlreadyExists(ApoloException):
32+
class RoleAlreadyExists(ServerException):
3233
def __init__(self, code: str):
3334
super().__init__(f"Role with code {code} already exists")
3435

3536

36-
class RoleNotFound(ApoloException):
37+
class RoleNotFound(ServerException):
3738
def __init__(self, code: str):
3839
super().__init__(f"Role with code {code} not found")
3940

4041

41-
class NotAllowed(ApoloException):
42+
class NotAllowed(ServerException):
4243
def __init__(self, access_key: str, action: str, resource: str):
4344
super().__init__(
4445
f"User {access_key} not allowed to perform action {action} on "
@@ -88,6 +89,7 @@ def create_user(
8889
if user:
8990
raise UserAlreadyExists(access_key)
9091

92+
# TODO here we should be passing configs to domain layer
9193
user = model.User(access_key, name, email, password)
9294
if not user.is_email_valid():
9395
raise InvalidEmail(email)
@@ -121,6 +123,7 @@ def reset_password(
121123
user = uow.users.get(access_key)
122124
if not user:
123125
raise UnknownUser(access_key)
126+
# TODO: this should be inside adapters instead of domain
124127
email_html = user.generate_reset_pwd_email(client_url=client_url)
125128
email_sender.send_email(
126129
email_to=user.email,

src/auth/utils.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import jwt
22
from graphql import GraphQLError
33

4-
from craftship.auth import config
5-
from craftship.core.exceptions import ApoloException
4+
from src.auth import config
5+
from src.core.exceptions import ServerException
66

77

8-
class InvalidToken(ApoloException):
8+
class InvalidToken(ServerException):
99
def __init__(self):
1010
super().__init__("Invalid Token")
1111

src/auth/views.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import List, Dict, Optional, Any
22

3-
from craftship.core.utils import group_rows, create_connection
4-
from craftship.auth.services import unit_of_work
3+
from src.core.utils import group_rows, create_connection
4+
from src.auth.services import unit_of_work
55

66

77
def query_role(

src/core/bootstrap.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import Dict
22

3-
from craftship.core import messagebus, utils
4-
from craftship.core.ports.unit_of_work import AbstractUnitOfWork
3+
from src.core import messagebus, utils
4+
from src.core.ports.unit_of_work import AbstractUnitOfWork
55

66

77
def create(

src/core/exceptions.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22
from graphql import GraphQLError
33

44

5-
class ApoloException(Exception):
5+
class ServerException(Exception):
66
def __init__(self, msg: str):
77
self.message = f"{self.__class__.__name__}: {msg}"
88

99

1010
def resolve_error(
11-
error: Union[Exception, ApoloException], error_resolver: Dict
11+
error: Union[Exception, ServerException], error_resolver: Dict
1212
) -> GraphQLError:
1313
message = (
14-
error.message if isinstance(error, ApoloException) else str(error)
14+
error.message if isinstance(error, ServerException) else str(error)
1515
)
1616
status = error_resolver.get(type(error), "UNKNOWN_ERROR")
1717
return GraphQLError(message, extensions=dict(status=status))

src/core/messagebus.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import logging
22
from typing import Any, Callable, Dict, List, Type
33

4-
from craftship.core.ports import unit_of_work
5-
from craftship.core.domain import Command, Event, Message
4+
from src.core.ports import unit_of_work
5+
from src.core.domain import Command, Event, Message
66

77
logger = logging.getLogger("__internal_messagebus__")
88

@@ -12,6 +12,14 @@ class UnknownMessage(Exception):
1212

1313

1414
class MessageBus:
15+
"""A MessageBus has only one responsibility:
16+
- Controlling execution flow in service layer
17+
It is the practical interface between HTTP and service layer.
18+
19+
It does that by operating a few tasks:
20+
1. Maps events to handlers
21+
2. Injects adapters' dependencies in those handlers
22+
3. Chains event execution flow by consuming aggregate's event store"""
1523
def __init__(
1624
self,
1725
uow: unit_of_work.AbstractUnitOfWork,
@@ -35,7 +43,6 @@ async def handle_event(self, event: Event) -> None:
3543
self.queue.extend(self.uow.collect_new_events())
3644
except Exception as ex:
3745
logger.exception("Exception handling event %s: %s", event, ex)
38-
# raise
3946

4047
async def handle_command(self, command: Command) -> None:
4148
logger.info("Handling command %s", command)

src/core/ports/repository.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from sqlalchemy import orm
55

6-
from craftship.core.domain import Aggregate
6+
from src.core.domain import Aggregate
77

88

99
class AbstractRepository(abc.ABC):

src/core/ports/unit_of_work.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
from sqlalchemy import create_engine, orm
55

6-
from apolo import config
7-
from craftship.core.ports import repository
6+
from src import config
7+
from src.core.ports import repository
88

99
DEFAULT_SESSION_FACTORY = orm.sessionmaker(
1010
bind=create_engine(

src/federation.py

+8-15
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,22 @@
22
from typing import Tuple, Optional, Dict
33
from sqlalchemy import MetaData
44

5-
from apolo import orm, config
6-
import craftship.auth.bootstrap
7-
import craftship.auth.entrypoint
8-
import craftship.management.bootstrap
9-
import craftship.management.entrypoint
10-
import craftship.management.entrypoint.lambda_worker
5+
from src import orm, config
6+
import src.auth.bootstrap
7+
import src.auth.entrypoint
118

129

13-
def federation(
10+
def init(
1411
start_orm: bool = True, **dependencies
1512
) -> Tuple[Optional[MetaData], Dict]:
1613
"""Starts-up as a monothilic service federating all aggregated-services
1714
Injecting dependencies as expected"""
1815

19-
lambda_resolver = {
20-
"management": craftship.management.entrypoint.lambda_worker.RESOLVER
21-
}
16+
lambda_resolver = {}
2217

23-
auth_uow, auth_email_sender = craftship.auth.bootstrap.create(**dependencies)
24-
craftship.auth.entrypoint.uow = auth_uow
25-
craftship.auth.entrypoint.email_sender = auth_email_sender
26-
management_bus = craftship.management.bootstrap.create(**dependencies)
27-
craftship.management.entrypoint.messagebus = management_bus
18+
auth_uow, auth_email_sender = src.auth.bootstrap.create(**dependencies)
19+
src.auth.entrypoint.uow = auth_uow
20+
src.auth.entrypoint.email_sender = auth_email_sender
2821

2922
if start_orm:
3023
metadata = orm.start_mappers()

src/orm.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from sqlalchemy import MetaData
2-
import craftship.auth.adapters.orm
3-
import craftship.management.adapters.orm
2+
import src.auth.adapters.orm
43

54

65
def start_mappers() -> MetaData:
@@ -9,7 +8,6 @@ def start_mappers() -> MetaData:
98
Classical way
109
"""
1110
metadata = MetaData()
12-
craftship.auth.adapters.orm.start_mappers(metadata)
13-
craftship.management.adapters.orm.start_mappers(metadata)
11+
src.auth.adapters.orm.start_mappers(metadata)
1412

1513
return metadata

src/server/app.py

+6-10
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
from typing import Dict
66
from logging import getLogger
77

8-
from apolo import config
9-
from craftship.federation import federation
8+
from src import config
9+
from src.federation import init
1010

1111
from tests.fakes import management
1212

@@ -21,10 +21,6 @@ def create_app() -> starlette.applications.Starlette:
2121
origins = [
2222
"http://localhost:3000",
2323
"https://localhost:3000",
24-
"http://apolo-sandbox.nplbrasil.com.br",
25-
"https://apolo-sandbox.nplbrasil.com.br",
26-
"http://apolo-staging.nplbrasil.com.br",
27-
"https://apolo-staging.nplbrasil.com.br",
2824
]
2925

3026
GraphQLApp = create_graphql_asgi_wrapper(debug=False)
@@ -43,15 +39,15 @@ def create_app() -> starlette.applications.Starlette:
4339

4440

4541
params: Dict[str, Dict] = {
46-
"local": dict(start_orm=True, digesto=management.FakeDigestoService),
47-
"sandbox": dict(start_orm=True, digesto=management.FakeDigestoService),
42+
"local": dict(start_orm=True,),
43+
"sandbox": dict(start_orm=True,),
4844
"staging": dict(start_orm=True),
4945
"prod": dict(start_orm=True),
5046
}
5147

5248
ENVIRONMENT = config.current_environment()
5349
logger = getLogger(__name__)
54-
logger.info(f"Apolo Server @ {ENVIRONMENT}")
55-
federation(**params[ENVIRONMENT])
50+
logger.info(f"Kingdom Server @ {ENVIRONMENT}")
51+
init(**params[ENVIRONMENT])
5652

5753
app = create_app()

0 commit comments

Comments
 (0)