diff --git a/ApiServices/IdentityService/initializer/event_clusters.py b/ApiControllers/abstracts/event_clusters.py similarity index 60% rename from ApiServices/IdentityService/initializer/event_clusters.py rename to ApiControllers/abstracts/event_clusters.py index 8337b05..a073dd8 100644 --- a/ApiServices/IdentityService/initializer/event_clusters.py +++ b/ApiControllers/abstracts/event_clusters.py @@ -1,21 +1,22 @@ from typing import Optional, Type - from pydantic import BaseModel class EventCluster: - - def __init__(self, endpoint_uu_id: str): + """ + EventCluster + """ + def __init__(self, endpoint_uu_id: str, name: str): self.endpoint_uu_id = endpoint_uu_id - self.events = [] + self.name = name + self.events: list["Event"] = [] - def add_event(self, list_of_events: list["Event"]): + def add_event(self, event: "Event"): """ Add an event to the cluster """ - for event in list_of_events: + if event.key not in [e.key for e in self.events]: self.events.append(event) - self.events = list(set(self.events)) def get_event(self, event_key: str): """ @@ -31,11 +32,13 @@ class EventCluster: from Schemas import Events, EndpointRestriction with Events.new_session() as db_session: + print(f"Endpoint UUID: {self.endpoint_uu_id}") if to_save_endpoint := EndpointRestriction.filter_one( EndpointRestriction.operation_uu_id == self.endpoint_uu_id, db=db_session, ).data: for event in self.events: + print(f"event:", event.name) event_to_save_database = Events.find_or_create( function_code=event.key, function_class=event.name, @@ -44,8 +47,13 @@ class EventCluster: endpoint_id=to_save_endpoint.id, endpoint_uu_id=str(to_save_endpoint.uu_id), is_confirmed=True, - active=True, db=db_session, + include_args=[ + Events.function_code, + Events.function_class, + Events.endpoint_code, + Events.endpoint_uu_id, + ], ) if event_to_save_database.meta_data.created: event_to_save_database.save(db=db_session) @@ -57,14 +65,9 @@ class EventCluster: """ Match an event by its key """ - # print('set(event_keys)', set(event_keys)) - # print('event.keys', set([event.key for event in self.events])) - # intersection_of_key: set[str] = set(event_key) & set([event.key for event in self.events]) - # if not len(intersection_of_key) == 1: - # raise ValueError( - # f"Event key not found or multiple matches found: {intersection_of_key}" - # ) - return self.get_event(event_key=event_key) + if event := self.get_event(event_key=event_key): + return event + raise ValueError("Event key not found") class Event: @@ -89,3 +92,29 @@ class Event: """ print(self.name) return {} + + +class RouterCluster: + """ + RouterCluster + """ + event_clusters: dict[str, EventCluster] = {} + + def __init__(self, name: str): + self.name = name + + def set_event_cluster(self, event_cluster: EventCluster): + """ + Add an event cluster to the set + """ + if event_cluster.name not in self.event_clusters: + self.event_clusters[event_cluster.name] = event_cluster + + def get_event_cluster(self, event_cluster_name: str) -> EventCluster: + """ + Get an event cluster by its name + """ + if event_cluster_name not in self.event_clusters: + raise ValueError("Event cluster not found") + return self.event_clusters[event_cluster_name] + \ No newline at end of file diff --git a/ApiServices/IdentityService/endpoints/__init__.py b/ApiControllers/handlers/__init__.py similarity index 100% rename from ApiServices/IdentityService/endpoints/__init__.py rename to ApiControllers/handlers/__init__.py diff --git a/ApiServices/IdentityService/exception_handlers/__init__.py b/ApiControllers/initializer/__init__.py similarity index 100% rename from ApiServices/IdentityService/exception_handlers/__init__.py rename to ApiControllers/initializer/__init__.py diff --git a/ApiServices/IdentityService/initializer/create_route.py b/ApiControllers/initializer/create_route.py similarity index 100% rename from ApiServices/IdentityService/initializer/create_route.py rename to ApiControllers/initializer/create_route.py diff --git a/ApiServices/IdentityService/initializer/__init__.py b/ApiControllers/middlewares/__init__.py similarity index 100% rename from ApiServices/IdentityService/initializer/__init__.py rename to ApiControllers/middlewares/__init__.py diff --git a/ApiServices/IdentityService/middlewares/token_middleware.py b/ApiControllers/middlewares/token_middleware.py similarity index 81% rename from ApiServices/IdentityService/middlewares/token_middleware.py rename to ApiControllers/middlewares/token_middleware.py index d165d7e..ed9cf66 100644 --- a/ApiServices/IdentityService/middlewares/token_middleware.py +++ b/ApiControllers/middlewares/token_middleware.py @@ -1,7 +1,8 @@ from fastapi import Request, status from fastapi.responses import JSONResponse -from ApiServices.IdentityService.endpoints.routes import get_safe_endpoint_urls -from ApiServices.IdentityService.config import api_config +from ApiDefaults.config import api_config + +from Endpoints.routes import get_safe_endpoint_urls async def token_middleware(request: Request, call_next): diff --git a/ApiServices/IdentityService/middlewares/__init__.py b/ApiControllers/providers/__init__.py similarity index 100% rename from ApiServices/IdentityService/middlewares/__init__.py rename to ApiControllers/providers/__init__.py diff --git a/ApiServices/IdentityService/providers/token_provider.py b/ApiControllers/providers/token_provider.py similarity index 100% rename from ApiServices/IdentityService/providers/token_provider.py rename to ApiControllers/providers/token_provider.py diff --git a/ApiServices/IdentityService/app.py b/ApiDefaults/app.py similarity index 81% rename from ApiServices/IdentityService/app.py rename to ApiDefaults/app.py index f61d5e5..35e324c 100644 --- a/ApiServices/IdentityService/app.py +++ b/ApiDefaults/app.py @@ -1,7 +1,7 @@ import uvicorn -from config import api_config -from create_app import create_app +from ApiDefaults.config import api_config +from ApiDefaults.create_app import create_app # from prometheus_fastapi_instrumentator import Instrumentator diff --git a/ApiServices/IdentityService/config.py b/ApiDefaults/config.py similarity index 100% rename from ApiServices/IdentityService/config.py rename to ApiDefaults/config.py diff --git a/ApiServices/IdentityService/create_app.py b/ApiDefaults/create_app.py similarity index 54% rename from ApiServices/IdentityService/create_app.py rename to ApiDefaults/create_app.py index 0a44182..bcee2eb 100644 --- a/ApiServices/IdentityService/create_app.py +++ b/ApiDefaults/create_app.py @@ -1,24 +1,33 @@ +from ApiControllers.abstracts.event_clusters import RouterCluster, EventCluster from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import RedirectResponse -from endpoints.routes import get_routes -from open_api_creator import create_openapi_schema -from middlewares.token_middleware import token_middleware -from initializer.create_route import RouteRegisterController - -from config import api_config - def create_events_if_any_cluster_set(): - import events - - for event_str in events.__all__: - if to_set_events := getattr(events, event_str, None): - to_set_events.set_events_to_database() + import Events + if not Events.__all__: + return + + router_cluster_stack: list[RouterCluster] = [getattr(Events, e, None) for e in Events.__all__] + for router_cluster in router_cluster_stack: + event_cluster_stack: list[EventCluster] = list(router_cluster.event_clusters.values()) + for event_cluster in event_cluster_stack: + print(f"Creating event:", event_cluster.name) + try: + event_cluster.set_events_to_database() + except Exception as e: + print(f"Error creating event cluster: {e}") def create_app(): + from ApiDefaults.open_api_creator import create_openapi_schema + from ApiDefaults.config import api_config + + from ApiControllers.middlewares.token_middleware import token_middleware + from ApiControllers.initializer.create_route import RouteRegisterController + + from Endpoints.routes import get_routes application = FastAPI(**api_config.api_info) # application.mount( diff --git a/ApiServices/IdentityService/open_api_creator.py b/ApiDefaults/open_api_creator.py similarity index 96% rename from ApiServices/IdentityService/open_api_creator.py rename to ApiDefaults/open_api_creator.py index e68f9e0..748dc62 100644 --- a/ApiServices/IdentityService/open_api_creator.py +++ b/ApiDefaults/open_api_creator.py @@ -3,8 +3,8 @@ from fastapi import FastAPI from fastapi.routing import APIRoute from fastapi.openapi.utils import get_openapi -from config import api_config as template_api_config -from endpoints.routes import get_safe_endpoint_urls +from ApiDefaults.config import api_config as template_api_config +from Endpoints.routes import get_safe_endpoint_urls class OpenAPISchemaCreator: diff --git a/ApiServices/IdentityService/Dockerfile b/ApiServices/IdentityService/Dockerfile index 1112d65..3627a8f 100644 --- a/ApiServices/IdentityService/Dockerfile +++ b/ApiServices/IdentityService/Dockerfile @@ -3,24 +3,27 @@ FROM python:3.12-slim WORKDIR / # Install system dependencies and Poetry -RUN apt-get update && apt-get install -y --no-install-recommends gcc \ - && rm -rf /var/lib/apt/lists/* && pip install --no-cache-dir poetry +RUN apt-get update && apt-get install -y --no-install-recommends gcc && rm -rf /var/lib/apt/lists/* && pip install --no-cache-dir poetry # Copy Poetry configuration COPY /pyproject.toml ./pyproject.toml # Configure Poetry and install dependencies with optimizations -RUN poetry config virtualenvs.create false \ - && poetry install --no-interaction --no-ansi --no-root --only main \ - && pip cache purge && rm -rf ~/.cache/pypoetry +RUN poetry config virtualenvs.create false && poetry install --no-interaction --no-ansi --no-root --only main \ +&& pip cache purge && rm -rf ~/.cache/pypoetry # Copy application code -COPY /ApiServices/IdentityService /ApiServices/IdentityService +COPY /ApiControllers /ApiControllers +COPY /ApiDefaults /ApiDefaults COPY /Controllers /Controllers COPY /Schemas /Schemas +COPY /ApiServices/IdentityService/Endpoints /ApiDefaults/Endpoints +COPY /ApiServices/IdentityService/Events /ApiDefaults/Events +COPY /ApiServices/IdentityService/Validations /ApiDefaults/Validations + # Set Python path to include app directory ENV PYTHONPATH=/ PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1 # Run the application using the configured uvicorn server -CMD ["poetry", "run", "python", "ApiServices/IdentityService/app.py"] +CMD ["poetry", "run", "python", "ApiDefaults/app.py"] diff --git a/ApiServices/IdentityService/providers/__init__.py b/ApiServices/IdentityService/Endpoints/__init__.py similarity index 100% rename from ApiServices/IdentityService/providers/__init__.py rename to ApiServices/IdentityService/Endpoints/__init__.py diff --git a/ApiServices/IdentityService/endpoints/people/route.py b/ApiServices/IdentityService/Endpoints/people/route.py similarity index 78% rename from ApiServices/IdentityService/endpoints/people/route.py rename to ApiServices/IdentityService/Endpoints/people/route.py index 0e290c6..118d12a 100644 --- a/ApiServices/IdentityService/endpoints/people/route.py +++ b/ApiServices/IdentityService/Endpoints/people/route.py @@ -2,9 +2,9 @@ import uuid from fastapi import APIRouter, Request, Response, Header -from ApiServices.IdentityService.config import api_config -from ApiServices.IdentityService.events.people.event import PeopleCluster -from ApiServices.IdentityService.providers.token_provider import TokenProvider +from ApiDefaults.config import api_config +from Events.people.cluster import PeopleRouterCluster +from ApiControllers.providers.token_provider import TokenProvider from Controllers.Postgres.pagination import PaginateOnly @@ -13,7 +13,7 @@ people_route = APIRouter(prefix="/people", tags=["People"]) @people_route.post( path="/list", - description="Test Template Route", + description="List people endpoint", operation_id="f102db46-031a-43e4-966a-dae6896f985b", ) def people_route_list( @@ -25,7 +25,7 @@ def people_route_list( tz: str = Header(None, alias="timezone"), ): """ - Test Template Route + List people endpoint """ endpoint_code = "f102db46-031a-43e4-966a-dae6896f985b" token = request.headers.get(api_config.ACCESS_TOKEN_TAG, None) @@ -40,10 +40,10 @@ def people_route_list( event_key = TokenProvider.retrieve_event_codes( endpoint_code=endpoint_code, token=token_object ) - event_cluster_matched = PeopleCluster.PeopleListCluster.match_event( + event_cluster_matched = PeopleRouterCluster.get_event_cluster("PeopleList").match_event( event_key=event_key ) - response.headers["X-Header"] = "Test Header GET" + response.headers["X-Header"] = "List Header GET" if runner_callable := event_cluster_matched.event_callable(list_options=data): return runner_callable raise ValueError("Event key not found or multiple matches found") @@ -51,10 +51,10 @@ def people_route_list( @people_route.post( path="/create", - description="Test Template Route with Post Method", + description="Create people endpoint", operation_id="eb465fde-337f-4b81-94cf-28c6d4f2b1b6", ) -def test_template_post( +def people_route_create( request: Request, response: Response, language: str = Header(None, alias="language"), @@ -62,7 +62,7 @@ def test_template_post( tz: str = Header(None, alias="timezone"), ): """ - Test Template Route with Post Method + Create people endpoint """ endpoint_code = "eb465fde-337f-4b81-94cf-28c6d4f2b1b6" token = request.headers.get(api_config.ACCESS_TOKEN_TAG, None) @@ -77,10 +77,10 @@ def test_template_post( event_key = TokenProvider.retrieve_event_codes( endpoint_code=endpoint_code, token=token_object ) - event_cluster_matched = PeopleCluster.PeopleCreateCluster.match_event( + event_cluster_matched = PeopleRouterCluster.get_event_cluster("PeopleCreate").match_event( event_key=event_key ) - response.headers["X-Header"] = "Test Header POST" + response.headers["X-Header"] = "Create Header POST" if runner_callable := event_cluster_matched.event_callable(): return runner_callable raise ValueError("Event key not found or multiple matches found") @@ -88,10 +88,10 @@ def test_template_post( @people_route.post( path="/update", - description="Test Template Route with Post Method", + description="Update people endpoint", operation_id="c9e5ba69-6915-43f5-8f9c-a5c2aa865b89", ) -def test_template_post( +def people_route_update( request: Request, response: Response, language: str = Header(None, alias="language"), @@ -99,7 +99,7 @@ def test_template_post( tz: str = Header(None, alias="timezone"), ): """ - Test Template Route with Post Method + Update people endpoint """ token = request.headers.get(api_config.ACCESS_TOKEN_TAG, None) endpoint_code = "c9e5ba69-6915-43f5-8f9c-a5c2aa865b89" @@ -114,10 +114,10 @@ def test_template_post( event_key = TokenProvider.retrieve_event_codes( endpoint_code=endpoint_code, token=token_object ) - event_cluster_matched = PeopleCluster.PeopleUpdateCluster.match_event( + event_cluster_matched = PeopleRouterCluster.get_event_cluster("PeopleUpdate").match_event( event_key=event_key ) - response.headers["X-Header"] = "Test Header POST" + response.headers["X-Header"] = "Update Header POST" if runner_callable := event_cluster_matched.event_callable(): return runner_callable raise ValueError("Event key not found or multiple matches found") diff --git a/ApiServices/IdentityService/endpoints/routes.py b/ApiServices/IdentityService/Endpoints/routes.py similarity index 76% rename from ApiServices/IdentityService/endpoints/routes.py rename to ApiServices/IdentityService/Endpoints/routes.py index 7b5c122..2125826 100644 --- a/ApiServices/IdentityService/endpoints/routes.py +++ b/ApiServices/IdentityService/Endpoints/routes.py @@ -1,12 +1,11 @@ from fastapi import APIRouter -# from .user.route import user_route -from .people.route import people_route - def get_routes() -> list[APIRouter]: + from .people.route import people_route + from .user.route import user_route return [ - # user_route, + user_route, people_route ] diff --git a/ApiServices/IdentityService/Endpoints/user/route.py b/ApiServices/IdentityService/Endpoints/user/route.py new file mode 100644 index 0000000..f919bfb --- /dev/null +++ b/ApiServices/IdentityService/Endpoints/user/route.py @@ -0,0 +1,107 @@ +import uuid + +from fastapi import APIRouter, Request, Response, Header + +from ApiDefaults.config import api_config +from Events.user.cluster import UserRouterCluster +from ApiControllers.providers.token_provider import TokenProvider + + +user_route = APIRouter(prefix="/user", tags=["User"]) + + +@user_route.post( + path="/list", + description="List users endpoint", + operation_id="5bc09312-d3f2-4f47-baba-17c928706da8", +) +def user_list_route( + request: Request, + response: Response, + language: str = Header(None, alias="language"), + domain: str = Header(None, alias="domain"), + tz: str = Header(None, alias="timezone"), +): + """ + List users endpoint + """ + endpoint_code = "5bc09312-d3f2-4f47-baba-17c928706da8" + token = request.headers.get(api_config.ACCESS_TOKEN_TAG, None) + token_object = TokenProvider.get_dict_from_redis(token=token) + event_key = TokenProvider.retrieve_event_codes(endpoint_code=endpoint_code, token=token_object) + headers = { + "language": language or "", + "domain": domain or "", + "eys-ext": f"{str(uuid.uuid4())}", + "tz": tz or "GMT+3", + "token": token, + } + event_cluster_matched = UserRouterCluster.get_event_cluster("UserList").match_event(event_key=event_key) + response.headers["X-Header"] = "Test Header GET" + if runner_callable := event_cluster_matched.event_callable(): + return runner_callable + raise ValueError("Event key not found or multiple matches found") + + +@user_route.post( + path="/create", + description="Create users endpoint", + operation_id="08d4b572-1584-47bb-aa42-8d068e5514e7", +) +def user_create_route( + request: Request, + response: Response, + language: str = Header(None, alias="language"), + domain: str = Header(None, alias="domain"), + tz: str = Header(None, alias="timezone"), +): + """ + Create users endpoint + """ + endpoint_code = "08d4b572-1584-47bb-aa42-8d068e5514e7" + token = request.headers.get(api_config.ACCESS_TOKEN_TAG, None) + token_object = TokenProvider.get_dict_from_redis(token=token) + event_key = TokenProvider.retrieve_event_codes( + endpoint_code=endpoint_code, token=token_object + ) + headers = { + "language": language or "", + "domain": domain or "", + "eys-ext": f"{str(uuid.uuid4())}", + "tz": tz or "GMT+3", + "token": token, + } + event_cluster_matched = UserRouterCluster.get_event_cluster("UserCreate").match_event(event_key=event_key) + response.headers["X-Header"] = "Test Header POST" + if runner_callable := event_cluster_matched.event_callable(): + return runner_callable + raise ValueError("Event key not found or multiple matches found") + + +@user_route.post( + path="/update", + description="Update users endpoint", + operation_id="b641236a-928d-4f19-a1d2-5edf611d1e56", +) +def user_update_route(request: Request, response: Response): + """ + Update users endpoint + """ + endpoint_code = "b641236a-928d-4f19-a1d2-5edf611d1e56" + token = request.headers.get(api_config.ACCESS_TOKEN_TAG, None) + token_object = TokenProvider.get_dict_from_redis(token=token) + event_key = TokenProvider.retrieve_event_codes( + endpoint_code=endpoint_code, token=token_object + ) + headers = { + "language": language or "", + "domain": domain or "", + "eys-ext": f"{str(uuid.uuid4())}", + "tz": tz or "GMT+3", + "token": token, + } + event_cluster_matched = UserRouterCluster.get_event_cluster("UserUpdate").match_event(event_key=event_key) + response.headers["X-Header"] = "Test Header POST" + if runner_callable := event_cluster_matched.event_callable(): + return runner_callable + raise ValueError("Event key not found or multiple matches found") diff --git a/ApiServices/IdentityService/Events/__init__.py b/ApiServices/IdentityService/Events/__init__.py new file mode 100644 index 0000000..20b9623 --- /dev/null +++ b/ApiServices/IdentityService/Events/__init__.py @@ -0,0 +1,8 @@ +from .people.cluster import PeopleRouterCluster +from .user.cluster import UserRouterCluster + + +__all__ = [ + "PeopleRouterCluster", + "UserRouterCluster", +] diff --git a/ApiServices/IdentityService/Events/people/cluster.py b/ApiServices/IdentityService/Events/people/cluster.py new file mode 100644 index 0000000..92de56f --- /dev/null +++ b/ApiServices/IdentityService/Events/people/cluster.py @@ -0,0 +1,32 @@ +from ApiControllers.abstracts.event_clusters import EventCluster, RouterCluster +from .supers_events import ( + SupersPeopleCreateEvent, + SupersPeopleUpdateEvent, + SupersPeopleListEvent +) + +PeopleRouterCluster = RouterCluster( + name="PeopleRouterCluster" +) + +PeopleEventClusterList = EventCluster( + name="PeopleList", + endpoint_uu_id="f102db46-031a-43e4-966a-dae6896f985b" +) +PeopleEventClusterList.add_event(SupersPeopleListEvent) +PeopleEventClusterCreate = EventCluster( + name="PeopleCreate", + endpoint_uu_id="eb465fde-337f-4b81-94cf-28c6d4f2b1b6" +) +PeopleEventClusterCreate.add_event(SupersPeopleCreateEvent) +PeopleEventClusterUpdate = EventCluster( + name="PeopleUpdate", + endpoint_uu_id="c9e5ba69-6915-43f5-8f9c-a5c2aa865b89" +) +PeopleEventClusterUpdate.add_event(SupersPeopleUpdateEvent) + +PeopleRouterCluster.set_event_cluster(PeopleEventClusterList) +PeopleRouterCluster.set_event_cluster(PeopleEventClusterCreate) +PeopleRouterCluster.set_event_cluster(PeopleEventClusterUpdate) + + diff --git a/ApiServices/IdentityService/events/people/event.py b/ApiServices/IdentityService/Events/people/supers_events.py similarity index 64% rename from ApiServices/IdentityService/events/people/event.py rename to ApiServices/IdentityService/Events/people/supers_events.py index a688326..15a4b14 100644 --- a/ApiServices/IdentityService/events/people/event.py +++ b/ApiServices/IdentityService/Events/people/supers_events.py @@ -1,21 +1,38 @@ -from ApiServices.IdentityService.initializer.event_clusters import EventCluster, Event -from ApiServices.IdentityService.validations.people.validations import ( +from ApiControllers.abstracts.event_clusters import Event +from Validations.people.validations import ( REQUESTAWMXNTKMGPPOJWRCTZUBADNFLQDBDYVQAORFAVCSXUUHEBQHCEPCSKFBADBODFDBPYKOVINV, ) from Controllers.Postgres.pagination import Pagination, PaginationResult, PaginateOnly from Controllers.Postgres.response import EndpointResponse -from Schemas.identity.identity import People +from Schemas import People -# Create endpoint -supers_people_create = Event( - name="supers_people_list", +SupersPeopleCreateEvent = Event( + name="supers_people_create", key="ec4c2404-a61b-46c7-bbdf-ce3357e6cf41", request_validator=None, # TODO: Add request validator response_validator=None, # TODO: Add response validator description="Create events of people endpoint", ) +# Update endpoint +SupersPeopleUpdateEvent = Event( + name="supers_people_update", + key="91e77de4-9f29-4309-b121-4aad256d440c", + request_validator=None, # TODO: Add request validator + response_validator=None, # TODO: Add response validator + description="Update events of people endpoint", +) + +# List endpoint +SupersPeopleListEvent = Event( + name="supers_people_list", + key="6828d280-e587-400d-a622-c318277386c3", + request_validator=None, # TODO: Add request validator + response_validator=None, # TODO: Add response validator + description="List events of people endpoint", +) + def supers_people_create_callable(list_options): """ @@ -32,21 +49,7 @@ def supers_people_create_callable(list_options): } -supers_people_create.event_callable = supers_people_create_callable - -people_event_cluster_create = EventCluster( - endpoint_uu_id="eb465fde-337f-4b81-94cf-28c6d4f2b1b6" -) -people_event_cluster_create.add_event([supers_people_create]) - -# Update endpoint -supers_people_update = Event( - name="supers_people_update", - key="91e77de4-9f29-4309-b121-4aad256d440c", - request_validator=None, # TODO: Add request validator - response_validator=None, # TODO: Add response validator - description="Update events of people endpoint", -) +SupersPeopleCreateEvent.event_callable = supers_people_create_callable def supers_people_update_callable(): @@ -64,21 +67,7 @@ def supers_people_update_callable(): } -supers_people_update.event_callable = supers_people_update_callable -people_event_cluster_update = EventCluster( - endpoint_uu_id="c9e5ba69-6915-43f5-8f9c-a5c2aa865b89" -) -people_event_cluster_update.add_event([supers_people_update]) - - -# List endpoint -supers_people_list = Event( - name="supers_people_list", - key="6828d280-e587-400d-a622-c318277386c3", - request_validator=None, # TODO: Add request validator - response_validator=None, # TODO: Add response validator - description="List events of people endpoint", -) +SupersPeopleUpdateEvent.event_callable = supers_people_update_callable def supers_people_list_callable(list_options: PaginateOnly): @@ -87,10 +76,6 @@ def supers_people_list_callable(list_options: PaginateOnly): """ list_options = PaginateOnly(**list_options.model_dump()) with People.new_session() as db_session: - People.pre_query = People.filter_all( - People.firstname.ilike("%B%"), db=db_session - ).query - if list_options.query: people_list = People.filter_all( *People.convert(list_options.query), db=db_session @@ -110,19 +95,4 @@ def supers_people_list_callable(list_options: PaginateOnly): ).response -supers_people_list.event_callable = supers_people_list_callable -people_event_cluster_list = EventCluster( - endpoint_uu_id="f102db46-031a-43e4-966a-dae6896f985b" -) - -people_event_cluster_list.add_event([supers_people_list]) - - -class PeopleCluster: - """ - People Clusters - """ - - PeopleListCluster = people_event_cluster_list - PeopleCreateCluster = people_event_cluster_create - PeopleUpdateCluster = people_event_cluster_update +SupersPeopleListEvent.event_callable = supers_people_list_callable diff --git a/ApiServices/IdentityService/Events/user/cluster.py b/ApiServices/IdentityService/Events/user/cluster.py new file mode 100644 index 0000000..cc44565 --- /dev/null +++ b/ApiServices/IdentityService/Events/user/cluster.py @@ -0,0 +1,32 @@ +from ApiControllers.abstracts.event_clusters import EventCluster, RouterCluster +from .supers_events import ( + SuperUsersListEvent, + SuperUsersCreateEvent, + SuperUsersUpdateEvent, +) + +UserRouterCluster = RouterCluster( + name="UserRouterCluster" +) + +UserEventClusterList = EventCluster( + name="UserList", + endpoint_uu_id="5bc09312-d3f2-4f47-baba-17c928706da8" +) +UserEventClusterList.add_event(SuperUsersListEvent) + +UserEventClusterCreate = EventCluster( + name="UserCreate", + endpoint_uu_id="08d4b572-1584-47bb-aa42-8d068e5514e7" +) +UserEventClusterCreate.add_event(SuperUsersCreateEvent) + +UserEventClusterUpdate = EventCluster( + name="UserUpdate", + endpoint_uu_id="b641236a-928d-4f19-a1d2-5edf611d1e56" +) +UserEventClusterUpdate.add_event(SuperUsersUpdateEvent) + +UserRouterCluster.set_event_cluster(UserEventClusterList) +UserRouterCluster.set_event_cluster(UserEventClusterCreate) +UserRouterCluster.set_event_cluster(UserEventClusterUpdate) diff --git a/ApiServices/IdentityService/Events/user/supers_events.py b/ApiServices/IdentityService/Events/user/supers_events.py new file mode 100644 index 0000000..e560a5f --- /dev/null +++ b/ApiServices/IdentityService/Events/user/supers_events.py @@ -0,0 +1,99 @@ +from ApiControllers.abstracts.event_clusters import Event +from Controllers.Postgres.pagination import Pagination, PaginationResult, PaginateOnly +from Controllers.Postgres.response import EndpointResponse +from Schemas import ( + Users, +) + +SuperUsersListEvent = Event( + name="supers_users_list", + key="341b394f-9f11-4abb-99e7-4b27fa6bf012", + request_validator=None, # TODO: Add request validator + response_validator=None, # TODO: Add response validator + description="List events of users endpoint", +) + + +def supers_users_list_callable(list_options: PaginateOnly): + """ + Example callable method + """ + list_options = PaginateOnly(**list_options.model_dump()) + with Users.new_session() as db_session: + if list_options.query: + users_list = Users.filter_all( + *Users.convert(list_options.query), db=db_session + ) + else: + users_list = Users.filter_all(db=db_session) + pagination = Pagination(data=users_list) + pagination.change(**list_options.model_dump()) + pagination_result = PaginationResult( + data=users_list, + pagination=pagination, + # response_model="", + ) + return EndpointResponse( + message="MSG0003-LIST", + pagination_result=pagination_result, + ).response + # return { + # "completed": True, + # "message": "Example callable method 2", + # "info": { + # "host": "example_host", + # "user_agent": "example_user_agent", + # }, + # } + + +SuperUsersListEvent.event_callable = supers_users_list_callable + +SuperUsersCreateEvent = Event( + name="supers_users_create", + key="4e7e189e-e015-4ff8-902d-60138cbc77a6", + request_validator=None, # TODO: Add request validator + response_validator=None, # TODO: Add response validator + description="Create events of users endpoint", +) + + +def supers_users_create_callable(): + """ + Example callable method + """ + return { + "completed": True, + "message": "Example callable method 2", + "info": { + "host": "example_host", + "user_agent": "example_user_agent", + }, + } + +SuperUsersCreateEvent.event_callable = supers_users_create_callable + +# Update endpoint +SuperUsersUpdateEvent = Event( + name="supers_users_update", + key="efa4aa4a-d414-4391-91ee-97eb617b7755", + request_validator=None, # TODO: Add request validator + response_validator=None, # TODO: Add response validator + description="Update events of users endpoint", +) + + +def supers_users_update_callable(): + """ + Example callable method + """ + return { + "completed": True, + "message": "Example callable method 2", + "info": { + "host": "example_host", + "user_agent": "example_user_agent", + }, + } + +SuperUsersUpdateEvent.event_callable = supers_users_update_callable diff --git a/ApiServices/IdentityService/schemas/__init__.py b/ApiServices/IdentityService/Validations/__init__.py similarity index 100% rename from ApiServices/IdentityService/schemas/__init__.py rename to ApiServices/IdentityService/Validations/__init__.py diff --git a/ApiServices/IdentityService/validations/lists/validations.py b/ApiServices/IdentityService/Validations/lists/validations.py similarity index 100% rename from ApiServices/IdentityService/validations/lists/validations.py rename to ApiServices/IdentityService/Validations/lists/validations.py diff --git a/ApiServices/IdentityService/Validations/people/validations.py b/ApiServices/IdentityService/Validations/people/validations.py new file mode 100644 index 0000000..7ccfe77 --- /dev/null +++ b/ApiServices/IdentityService/Validations/people/validations.py @@ -0,0 +1,24 @@ +from pydantic import BaseModel + + +class REQUESTAWMXNTKMGPPOJWRCTZUBADNFLQDBDYVQAORFAVCSXUUHEBQHCEPCSKFBADBODFDBPYKOVINV( + BaseModel +): + uu_id: str + created_at: str + updated_at: str + person_tag: str + expiry_starts: str + expiry_ends: str + firstname: str + middle_name: str + surname: str + birth_date: str + birth_place: str + sex_code: str + country_code: str + tax_no: str + active: bool + deleted: bool + is_confirmed: bool + is_notification_send: bool diff --git a/ApiServices/IdentityService/validations/user/validations.py b/ApiServices/IdentityService/Validations/user/validations.py similarity index 100% rename from ApiServices/IdentityService/validations/user/validations.py rename to ApiServices/IdentityService/Validations/user/validations.py diff --git a/ApiServices/IdentityService/endpoints/user/route.py b/ApiServices/IdentityService/endpoints/user/route.py deleted file mode 100644 index cfdc6f0..0000000 --- a/ApiServices/IdentityService/endpoints/user/route.py +++ /dev/null @@ -1,90 +0,0 @@ -import uuid - -from fastapi import APIRouter, Request, Response, Header - -from ApiServices.IdentityService.config import api_config -from ApiServices.IdentityService.events.user.event import supers_users_list - - -user_route = APIRouter(prefix="/user", tags=["User"]) - - -@user_route.post( - path="/list", - description="Test Template Route", - operation_id="5bc09312-d3f2-4f47-baba-17c928706da8", -) -def test_template( - request: Request, - response: Response, - language: str = Header(None, alias="language"), - domain: str = Header(None, alias="domain"), - tz: str = Header(None, alias="timezone"), -): - """ - Test Template Route - """ - event_code = "bb20c8c6-a289-4cab-9da7-34ca8a36c8e5" - token = request.headers.get(api_config.ACCESS_TOKEN_TAG, None) - headers = { - "language": language or "", - "domain": domain or "", - "eys-ext": f"{str(uuid.uuid4())}", - "tz": tz or "GMT+3", - "token": token, - } - event_cluster_matched = supers_users_list.match_event( - event_keys=[ - "3f510dcf-9f84-4eb9-b919-f582f30adab1", - "9f403034-deba-4e1f-b43e-b25d3c808d39", - "b8ec6e64-286a-4f60-8554-7a3865454944", - ] - ) - response.headers["X-Header"] = "Test Header GET" - if runner_callable := event_cluster_matched.example_callable(): - return runner_callable - raise ValueError("Event key not found or multiple matches found") - - -@user_route.post( - path="/create", - description="Test Template Route with Post Method", - operation_id="08d4b572-1584-47bb-aa42-8d068e5514e7", -) -def test_template_post(request: Request, response: Response): - """ - Test Template Route with Post Method - """ - event_cluster_matched = supers_users_list.match_event( - event_keys=[ - "3f510dcf-9f84-4eb9-b919-f582f30adab1", - "9f403034-deba-4e1f-b43e-b25d3c808d39", - "b8ec6e64-286a-4f60-8554-7a3865454944", - ] - ) - response.headers["X-Header"] = "Test Header POST" - if runner_callable := event_cluster_matched.example_callable(): - return runner_callable - raise ValueError("Event key not found or multiple matches found") - - -@user_route.post( - path="/update", - description="Test Template Route with Post Method", - operation_id="b641236a-928d-4f19-a1d2-5edf611d1e56", -) -def test_template_post(request: Request, response: Response): - """ - Test Template Route with Post Method - """ - event_cluster_matched = supers_users_list.match_event( - event_keys=[ - "3f510dcf-9f84-4eb9-b919-f582f30adab1", - "9f403034-deba-4e1f-b43e-b25d3c808d39", - "b8ec6e64-286a-4f60-8554-7a3865454944", - ] - ) - response.headers["X-Header"] = "Test Header POST" - if runner_callable := event_cluster_matched.example_callable(): - return runner_callable - raise ValueError("Event key not found or multiple matches found") diff --git a/ApiServices/IdentityService/events/__init__.py b/ApiServices/IdentityService/events/__init__.py deleted file mode 100644 index 267340c..0000000 --- a/ApiServices/IdentityService/events/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .people.event import ( - people_event_cluster_list, - people_event_cluster_update, - people_event_cluster_create, -) - - -__all__ = [ - "people_event_cluster_list", - "people_event_cluster_update", - "people_event_cluster_create", -] diff --git a/ApiServices/IdentityService/events/user/event.py b/ApiServices/IdentityService/events/user/event.py deleted file mode 100644 index ebd9e44..0000000 --- a/ApiServices/IdentityService/events/user/event.py +++ /dev/null @@ -1,33 +0,0 @@ -from ApiServices.IdentityService.initializer.event_clusters import EventCluster, Event - - -supers_users_list = Event( - name="supers_people_list", - key="341b394f-9f11-4abb-99e7-4b27fa6bf012", - request_validator=None, # TODO: Add request validator - response_validator=None, # TODO: Add response validator - description="Example event description", -) - - -def supers_people_list_callable(): - """ - Example callable method - """ - return { - "completed": True, - "message": "Example callable method 2", - "info": { - "host": "example_host", - "user_agent": "example_user_agent", - }, - } - - -supers_users_list.event_callable = supers_people_list_callable - -people_event_cluster_list = EventCluster( - endpoint_uu_id="f102db46-031a-43e4-966a-dae6896f985b" -) - -people_event_cluster_list.add_event([supers_users_list]) diff --git a/ApiServices/IdentityService/services/__init__.py b/ApiServices/IdentityService/services/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/ApiServices/IdentityService/validations/__init__.py b/ApiServices/IdentityService/validations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/ApiServices/IdentityService/validations/people/validations.py b/ApiServices/IdentityService/validations/people/validations.py deleted file mode 100644 index aa98958..0000000 --- a/ApiServices/IdentityService/validations/people/validations.py +++ /dev/null @@ -1,53 +0,0 @@ -from pydantic import BaseModel - -""" - "sex_code": "M", - "country_code": "TR", - "created_at": "2025-04-13 10:03:32 +00:00", - "father_name": "Father", - "birth_place": "Ankara", - "updated_credentials_token": null, - "cryp_uu_id": null, - "mother_name": "Mother", - "expiry_starts": "2025-04-13 10:03:32 +00:00", - "confirmed_credentials_token": null, - "surname": "Karatay", - "firstname": "Berkay Super User", - "birth_date": "1990-01-07 00:00:00 +00:00", - "expiry_ends": "2099-12-31 00:00:00 +00:00", - "is_confirmed": true, - "is_email_send": false, - "tax_no": "1231231232", - "person_ref": "", - "active": true, - "deleted": false, - "updated_at": "2025-04-13 10:03:32 +00:00", - "uu_id": "b5b6e68f-a4d0-4d64-aa18-634671cb1299", - "middle_name": "", - "created_credentials_token": null, - "person_tag": "BSU-System", - "is_notification_send": false -""" - - -class REQUESTAWMXNTKMGPPOJWRCTZUBADNFLQDBDYVQAORFAVCSXUUHEBQHCEPCSKFBADBODFDBPYKOVINV( - BaseModel -): - uu_id: str - created_at: str - updated_at: str - person_tag: str - expiry_starts: str - expiry_ends: str - firstname: str - middle_name: str - surname: str - birth_date: str - birth_place: str - sex_code: str - country_code: str - tax_no: str - active: bool - deleted: bool - is_confirmed: bool - is_notification_send: bool diff --git a/ApiServices/InitialService/app.py b/ApiServices/InitialService/app.py index d4b8cae..8d7e057 100644 --- a/ApiServices/InitialService/app.py +++ b/ApiServices/InitialService/app.py @@ -9,17 +9,35 @@ from init_services import create_modules_and_services_and_actions from init_address import create_one_address from init_occ_defaults import create_occupant_defaults -set_alembic = bool(os.getenv("set_alembic", 0)) +set_alembic = bool(int(os.getenv("SET_ALEMBIC"), 0)) if __name__ == "__main__": + print(f"Set alembic: {set_alembic}") with get_db() as db_session: if set_alembic: generate_alembic(session=db_session) - - create_one_address(db_session=db_session) - init_api_enums_build_types(db_session=db_session) - create_application_defaults(db_session=db_session) - create_occupant_types_defaults(db_session=db_session) - create_modules_and_services_and_actions(db_session=db_session) - create_occupant_defaults(db_session=db_session) + try: + create_one_address(db_session=db_session) + except Exception as e: + print(f"Error creating address: {e}") + try: + init_api_enums_build_types(db_session=db_session) + except Exception as e: + print(f"Error creating enums: {e}") + try: + create_application_defaults(db_session=db_session) + except Exception as e: + print(f"Error creating application defaults: {e}") + try: + create_occupant_types_defaults(db_session=db_session) + except Exception as e: + print(f"Error creating occupant types defaults: {e}") + try: + create_modules_and_services_and_actions(db_session=db_session) + except Exception as e: + print(f"Error creating modules and services and actions: {e}") + try: + create_occupant_defaults(db_session=db_session) + except Exception as e: + print(f"Error creating occupant defaults: {e}") diff --git a/ApiServices/TemplateService/create_app.py b/ApiServices/TemplateService/create_app.py index 0a44182..46bcebf 100644 --- a/ApiServices/TemplateService/create_app.py +++ b/ApiServices/TemplateService/create_app.py @@ -11,11 +11,11 @@ from config import api_config def create_events_if_any_cluster_set(): - import events + from events import retrieve_all_clusters - for event_str in events.__all__: - if to_set_events := getattr(events, event_str, None): - to_set_events.set_events_to_database() + for event_cluster in retrieve_all_clusters(): + for event in event_cluster.retrieve_all_event_clusters: + event.set_events_to_database() def create_app(): diff --git a/ApiServices/TemplateService/events/__init__.py b/ApiServices/TemplateService/events/__init__.py index 1f67273..3f80219 100644 --- a/ApiServices/TemplateService/events/__init__.py +++ b/ApiServices/TemplateService/events/__init__.py @@ -1,5 +1,10 @@ -from .template.event import template_event_cluster +from .template.cluster import ( + TemplateEventClusterSet +) __all__ = [ - "template_event_cluster", + "TemplateEventClusterSet", ] + +def retrieve_all_clusters(): + return [TemplateEventClusterSet] \ No newline at end of file diff --git a/ApiServices/TemplateService/events/template/cluster.py b/ApiServices/TemplateService/events/template/cluster.py new file mode 100644 index 0000000..6753615 --- /dev/null +++ b/ApiServices/TemplateService/events/template/cluster.py @@ -0,0 +1,15 @@ +from ApiServices.TemplateService.initializer.event_clusters import EventCluster, SetEventCluster + + +TemplateEventCluster = EventCluster( + endpoint_uu_id="bb20c8c6-a289-4cab-9da7-34ca8a36c8e5" +) + +OtherTemplateEventCluster = EventCluster( + endpoint_uu_id="ecb82b7a-317f-469d-a682-ff431f152453" +) + +TemplateEventClusterSet = SetEventCluster() +TemplateEventClusterSet.add_event_cluster(TemplateEventCluster) +TemplateEventClusterSet.add_event_cluster(OtherTemplateEventCluster) + diff --git a/ApiServices/TemplateService/events/template/event.py b/ApiServices/TemplateService/events/template/some_level_event.py similarity index 68% rename from ApiServices/TemplateService/events/template/event.py rename to ApiServices/TemplateService/events/template/some_level_event.py index a0f7205..bdd1f3b 100644 --- a/ApiServices/TemplateService/events/template/event.py +++ b/ApiServices/TemplateService/events/template/some_level_event.py @@ -1,5 +1,8 @@ -from ApiServices.TemplateService.initializer.event_clusters import EventCluster, Event - +from ApiServices.TemplateService.initializer.event_clusters import Event +from .cluster import ( + template_event_cluster, + other_template_event_cluster, +) single_event = Event( name="example_event", @@ -25,10 +28,11 @@ def example_callable(): single_event.event_callable = example_callable +template_event_cluster.add_event([single_event]) other_event = Event( name="example_event-2", - key="176b829c-7622-4cf2-b474-421e5acb637c", + key="36b26d7c-2a9e-4006-a213-f54bc66e5455", request_validator=None, # TODO: Add request validator response_validator=None, # TODO: Add response validator description="Example event 2 description", @@ -50,17 +54,4 @@ def example_callable_other(): other_event.event_callable = example_callable_other - -tokens_in_redis = [ - "3f510dcf-9f84-4eb9-b919-f582f30adab1", - "9f403034-deba-4e1f-b43e-b25d3c808d39", - "b8ec6e64-286a-4f60-8554-7a3865454944", - "176b829c-7622-4cf2-b474-421e5acb637c", -] -template_event_cluster = EventCluster( - endpoint_uu_id="bb20c8c6-a289-4cab-9da7-34ca8a36c8e5" -) -template_event_cluster.add_event([single_event, other_event]) -# matched_event = template_event_cluster.match_event(event_keys=tokens_in_redis) - -# print('event_callable', matched_event.event_callable()) +other_template_event_cluster.add_event([other_event]) diff --git a/ApiServices/TemplateService/initializer/event_clusters.py b/ApiServices/TemplateService/initializer/event_clusters.py index f568e80..63dd576 100644 --- a/ApiServices/TemplateService/initializer/event_clusters.py +++ b/ApiServices/TemplateService/initializer/event_clusters.py @@ -1,5 +1,11 @@ -class EventCluster: +from typing import Optional, Type +from pydantic import BaseModel + +class EventCluster: + """ + EventCluster + """ def __init__(self, endpoint_uu_id: str): self.endpoint_uu_id = endpoint_uu_id self.events = [] @@ -48,20 +54,18 @@ class EventCluster: f"UUID: {event_to_save_database.uu_id} event is saved to {to_save_endpoint.uu_id}" ) - def match_event(self, event_keys: list[str]) -> "Event": + def match_event(self, event_key: str) -> "Event": """ Match an event by its key """ # print('set(event_keys)', set(event_keys)) # print('event.keys', set([event.key for event in self.events])) - intersection_of_key: set[str] = set(event_keys) & set( - [event.key for event in self.events] - ) - if not len(intersection_of_key) == 1: - raise ValueError( - f"Event key not found or multiple matches found: {intersection_of_key}" - ) - return self.get_event(event_key=list(intersection_of_key)[0]) + # intersection_of_key: set[str] = set(event_key) & set([event.key for event in self.events]) + # if not len(intersection_of_key) == 1: + # raise ValueError( + # f"Event key not found or multiple matches found: {intersection_of_key}" + # ) + return self.get_event(event_key=event_key) class Event: @@ -70,8 +74,8 @@ class Event: self, name: str, key: str, - request_validator: str = None, - response_validator: str = None, + request_validator: Optional[Type[BaseModel]] = None, + response_validator: Optional[Type[BaseModel]] = None, description: str = "", ): self.name = name @@ -86,3 +90,25 @@ class Event: """ print(self.name) return {} + + +class SetEventCluster: + """ + SetEventCluster + """ + list_of_event_clusters: list[EventCluster] = [] + + def add_event_cluster(self, event_cluster: EventCluster): + """ + Add an event cluster to the set + """ + endpoint_uu_id_list = [event_cluster_uuid.endpoint_uu_id for event_cluster_uuid in self.list_of_event_clusters] + if event_cluster.endpoint_uu_id not in endpoint_uu_id_list: + self.list_of_event_clusters.append(event_cluster) + + @property + def retrieve_all_event_clusters(self) -> list[EventCluster]: + """ + Retrieve all event clusters + """ + return self.list_of_event_clusters diff --git a/BankServices/SenderService/app.py b/BankServices/SenderService/app.py index a9d509a..4c837ce 100644 --- a/BankServices/SenderService/app.py +++ b/BankServices/SenderService/app.py @@ -96,10 +96,9 @@ def process_unsent_email_records() -> bool: if not account_records: print("No unsent email records found") return False - + # Get the IDs of the records we're processing record_ids = [record.id for record in account_records] - print(f"Found {len(account_records)} unsent email records") # Format rows for the email template diff --git a/docker-compose.yml b/docker-compose.yml index da6ad3f..5c22e69 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -71,7 +71,7 @@ services: context: . dockerfile: ApiServices/InitialService/Dockerfile environment: - - set_alembic=0 + - SET_ALEMBIC=0 networks: - wag-services env_file: