update events via wrapper routers
This commit is contained in:
@@ -20,15 +20,44 @@ from fastapi.openapi.utils import get_openapi
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
"""Create and configure the FastAPI application."""
|
||||
app = FastAPI()
|
||||
|
||||
app = FastAPI(
|
||||
responses={
|
||||
422: {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
},
|
||||
"msg": {"type": "string"},
|
||||
"type": {"type": "string"},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
# Get all routers and protected routes from the new configuration
|
||||
routers, protected_routes = get_all_routers()
|
||||
|
||||
|
||||
# Include all routers
|
||||
for router in routers:
|
||||
app.include_router(router)
|
||||
|
||||
|
||||
# Configure OpenAPI schema with security
|
||||
def custom_openapi():
|
||||
if app.openapi_schema:
|
||||
@@ -47,7 +76,9 @@ def create_app() -> FastAPI:
|
||||
# Configure security for protected routes
|
||||
for path, methods in protected_routes.items():
|
||||
for method in methods:
|
||||
configure_route_security(path, method, openapi_schema, list(protected_routes.keys()))
|
||||
configure_route_security(
|
||||
path, method, openapi_schema, list(protected_routes.keys())
|
||||
)
|
||||
|
||||
app.openapi_schema = openapi_schema
|
||||
return app.openapi_schema
|
||||
|
||||
@@ -18,6 +18,7 @@ from AllConfigs.main import MainConfig as Config
|
||||
|
||||
from create_routes import get_all_routers
|
||||
|
||||
|
||||
def setup_security_schema() -> Dict[str, Any]:
|
||||
"""
|
||||
Configure security schema for the OpenAPI documentation.
|
||||
@@ -32,12 +33,13 @@ def setup_security_schema() -> Dict[str, Any]:
|
||||
"type": "http",
|
||||
"scheme": "bearer",
|
||||
"bearerFormat": "JWT",
|
||||
"description": "Enter the token"
|
||||
"description": "Enter the token",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def configure_route_security(
|
||||
path: str, method: str, schema: Dict[str, Any], protected_paths: List[str]
|
||||
) -> None:
|
||||
@@ -55,6 +57,7 @@ def configure_route_security(
|
||||
if method.lower() in schema["paths"][path]:
|
||||
schema["paths"][path][method.lower()]["security"] = [{"Bearer": []}]
|
||||
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
"""
|
||||
Create and configure a FastAPI application with dynamic route creation.
|
||||
@@ -68,7 +71,7 @@ def create_app() -> FastAPI:
|
||||
description=Config.DESCRIPTION,
|
||||
default_response_class=JSONResponse,
|
||||
)
|
||||
|
||||
|
||||
@app.get("/", include_in_schema=False, summary=str(Config.DESCRIPTION))
|
||||
async def home() -> RedirectResponse:
|
||||
"""Redirect root path to API documentation."""
|
||||
@@ -76,11 +79,11 @@ def create_app() -> FastAPI:
|
||||
|
||||
# Get all routers and protected routes using the dynamic route creation
|
||||
routers, protected_routes = get_all_routers()
|
||||
|
||||
|
||||
# Include all routers
|
||||
for router in routers:
|
||||
app.include_router(router)
|
||||
|
||||
|
||||
# Configure OpenAPI schema with security
|
||||
def custom_openapi():
|
||||
if app.openapi_schema:
|
||||
@@ -100,7 +103,9 @@ def create_app() -> FastAPI:
|
||||
# Configure security for protected routes
|
||||
for path, methods in protected_routes.items():
|
||||
for method in methods:
|
||||
configure_route_security(path, method, openapi_schema, list(protected_routes.keys()))
|
||||
configure_route_security(
|
||||
path, method, openapi_schema, list(protected_routes.keys())
|
||||
)
|
||||
|
||||
app.openapi_schema = openapi_schema
|
||||
return app.openapi_schema
|
||||
|
||||
@@ -5,8 +5,8 @@ Handles dynamic route creation based on configurations.
|
||||
|
||||
from typing import Optional, Dict, Any, List, Callable, TypeVar, ParamSpec
|
||||
|
||||
P = ParamSpec('P') # For function parameters
|
||||
R = TypeVar('R') # For return type
|
||||
P = ParamSpec("P") # For function parameters
|
||||
R = TypeVar("R") # For return type
|
||||
|
||||
from dataclasses import dataclass
|
||||
from functools import wraps
|
||||
@@ -17,7 +17,6 @@ from pydantic import BaseModel
|
||||
from AllConfigs.main import MainConfig as Config
|
||||
|
||||
|
||||
|
||||
@dataclass
|
||||
class EndpointFactoryConfig:
|
||||
endpoint: str
|
||||
@@ -39,17 +38,17 @@ class EndpointFactoryConfig:
|
||||
class EnhancedEndpointFactory:
|
||||
def __init__(self, router_config: dict):
|
||||
self.router = APIRouter(
|
||||
prefix=router_config['prefix'],
|
||||
tags=router_config['tags'],
|
||||
include_in_schema=router_config.get('include_in_schema', True)
|
||||
prefix=router_config["prefix"],
|
||||
tags=router_config["tags"],
|
||||
include_in_schema=router_config.get("include_in_schema", True),
|
||||
)
|
||||
self.endpoints = router_config['endpoints']
|
||||
self.endpoints = router_config["endpoints"]
|
||||
self.protected_routes: Dict[str, List[str]] = {}
|
||||
|
||||
def create_endpoint(self, config: EndpointFactoryConfig):
|
||||
"""
|
||||
Create an endpoint directly from the configuration.
|
||||
|
||||
|
||||
Args:
|
||||
config: EndpointFactoryConfig instance containing endpoint configuration
|
||||
"""
|
||||
@@ -70,7 +69,7 @@ class EnhancedEndpointFactory:
|
||||
response_model=config.response_model,
|
||||
summary=config.summary,
|
||||
description=config.description,
|
||||
**config.extra_options
|
||||
**config.extra_options,
|
||||
)(endpoint_function)
|
||||
|
||||
def get_router(self) -> APIRouter:
|
||||
@@ -94,13 +93,13 @@ async def ping_test(request: Request, service_name: str = "base-router"):
|
||||
|
||||
def get_all_routers() -> tuple[List[APIRouter], Dict[str, List[str]]]:
|
||||
"""
|
||||
Get all configured routers and their protected routes.
|
||||
|
||||
Get all routers and protected routes from route configurations.
|
||||
|
||||
Returns:
|
||||
tuple: (routers, protected_routes)
|
||||
"""
|
||||
from events.route_configs import get_route_configs
|
||||
|
||||
from ApiEvents.route_configs import get_route_configs
|
||||
|
||||
routers = []
|
||||
all_protected_routes = {}
|
||||
|
||||
@@ -109,25 +108,23 @@ def get_all_routers() -> tuple[List[APIRouter], Dict[str, List[str]]]:
|
||||
factory_all = []
|
||||
for config in route_configs:
|
||||
factory = EnhancedEndpointFactory(config)
|
||||
|
||||
|
||||
# Create endpoints from configuration
|
||||
for endpoint_dict in config['endpoints']:
|
||||
for endpoint_dict in config["endpoints"]:
|
||||
endpoint_config = EndpointFactoryConfig(
|
||||
endpoint=endpoint_dict['endpoint'],
|
||||
method=endpoint_dict['method'],
|
||||
summary=endpoint_dict['summary'],
|
||||
description=endpoint_dict['description'],
|
||||
endpoint_function=endpoint_dict['endpoint_function'],
|
||||
is_auth_required=endpoint_dict['is_auth_required'],
|
||||
is_event_required=endpoint_dict['is_event_required'],
|
||||
extra_options=endpoint_dict.get('extra_options', {})
|
||||
endpoint=endpoint_dict["endpoint"],
|
||||
method=endpoint_dict["method"],
|
||||
summary=endpoint_dict["summary"],
|
||||
description=endpoint_dict["description"],
|
||||
endpoint_function=endpoint_dict["endpoint_function"],
|
||||
is_auth_required=endpoint_dict["is_auth_required"],
|
||||
is_event_required=endpoint_dict["is_event_required"],
|
||||
extra_options=endpoint_dict.get("extra_options", {}),
|
||||
)
|
||||
factory.create_endpoint(endpoint_config)
|
||||
factory_all.append(
|
||||
endpoint_config.__dict__
|
||||
)
|
||||
|
||||
factory_all.append(endpoint_config.__dict__)
|
||||
|
||||
# Add router and protected routes
|
||||
routers.append(factory.get_router())
|
||||
all_protected_routes.update(factory.get_protected_routes())
|
||||
return routers, all_protected_routes
|
||||
return routers, all_protected_routes
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
from .token_event_middleware import TokenEventMiddleware
|
||||
from .auth_middleware import RequestTimingMiddleware, MiddlewareModule
|
||||
|
||||
|
||||
__all__ = ["TokenEventMiddleware", "RequestTimingMiddleware", "MiddlewareModule"]
|
||||
|
||||
@@ -6,70 +6,83 @@ and a middleware for request timing measurements.
|
||||
"""
|
||||
|
||||
from time import perf_counter
|
||||
from typing import Callable, Optional, Dict, Any, Tuple
|
||||
from typing import Callable, Optional, Dict, Any, Tuple, Union
|
||||
from functools import wraps
|
||||
from fastapi import Request, Response
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from fastapi import Request, Response
|
||||
from AllConfigs.Token.config import Auth
|
||||
from ApiLibrary.common.line_number import get_line_number_for_error
|
||||
from ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApi
|
||||
from .base_context import BaseContext
|
||||
from ApiServices.Token.token_handler import OccupantTokenObject, EmployeeTokenObject
|
||||
|
||||
|
||||
class AuthContext(BaseContext):
|
||||
"""
|
||||
Context class for authentication middleware.
|
||||
Extends BaseContext to provide authentication-specific functionality.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, token_context: Union[OccupantTokenObject, EmployeeTokenObject]
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.token_context = token_context
|
||||
|
||||
@property
|
||||
def is_employee(self) -> bool:
|
||||
"""Check if authenticated token is for an employee."""
|
||||
return isinstance(self.token_context, EmployeeTokenObject)
|
||||
|
||||
@property
|
||||
def is_occupant(self) -> bool:
|
||||
"""Check if authenticated token is for an occupant."""
|
||||
return isinstance(self.token_context, OccupantTokenObject)
|
||||
|
||||
@property
|
||||
def user_id(self) -> str:
|
||||
"""Get the user's UUID from token context."""
|
||||
return self.token_context.user_uu_id if self.token_context else ""
|
||||
|
||||
def __repr__(self) -> str:
|
||||
user_type = "Employee" if self.is_employee else "Occupant"
|
||||
return f"AuthContext({user_type}Token: {self.user_id})"
|
||||
|
||||
|
||||
class MiddlewareModule:
|
||||
"""
|
||||
Module containing authentication and middleware functionality.
|
||||
|
||||
This class provides:
|
||||
- Token extraction and validation
|
||||
- Authentication decorator for endpoints
|
||||
Middleware module for handling authentication and request timing.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def get_access_token(request: Request) -> Tuple[str, str]:
|
||||
def get_user_from_request(
|
||||
request: Request,
|
||||
) -> AuthContext:
|
||||
"""
|
||||
Extract access token from request headers.
|
||||
Get authenticated token context from request.
|
||||
|
||||
Args:
|
||||
request: FastAPI request object
|
||||
|
||||
Returns:
|
||||
Tuple[str, str]: A tuple containing (scheme, token)
|
||||
AuthContext: Context containing the authenticated token data
|
||||
|
||||
Raises:
|
||||
HTTPExceptionApi: If token is missing or malformed
|
||||
HTTPExceptionApi: If token is missing, invalid, or user not found
|
||||
"""
|
||||
auth_header = request.headers.get(Auth.ACCESS_TOKEN_TAG)
|
||||
if not auth_header:
|
||||
raise HTTPExceptionApi(error_code="HTTP_401_UNAUTHORIZED", lang="tr")
|
||||
from ApiServices.Token.token_handler import TokenService
|
||||
|
||||
try:
|
||||
scheme, token = auth_header.split()
|
||||
if scheme.lower() != "bearer":
|
||||
raise HTTPExceptionApi(error_code="HTTP_401_UNAUTHORIZED", lang="tr")
|
||||
return scheme, token
|
||||
except ValueError:
|
||||
raise HTTPExceptionApi(error_code="HTTP_401_UNAUTHORIZED", lang="tr")
|
||||
# Get token and validate - will raise HTTPExceptionApi if invalid
|
||||
redis_token = TokenService.get_access_token_from_request(request=request)
|
||||
|
||||
@staticmethod
|
||||
async def validate_token(token: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Validate the authentication token.
|
||||
# Get token context - will validate token and raise appropriate errors
|
||||
token_context = TokenService.get_object_via_access_key(access_token=redis_token)
|
||||
if not token_context:
|
||||
raise HTTPExceptionApi(
|
||||
error_code="USER_NOT_FOUND", lang="tr", loc=get_line_number_for_error()
|
||||
)
|
||||
|
||||
Args:
|
||||
token: JWT token to validate
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: User data extracted from token
|
||||
|
||||
Raises:
|
||||
HTTPExceptionApi: If token is invalid
|
||||
"""
|
||||
try:
|
||||
# TODO: Implement your token validation logic
|
||||
# Example:
|
||||
# return jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
|
||||
return {"user_id": "test", "role": "user"} # Placeholder
|
||||
except Exception as e:
|
||||
raise HTTPExceptionApi(error_code="HTTP_401_UNAUTHORIZED", lang="tr")
|
||||
return AuthContext(token_context=token_context)
|
||||
|
||||
@classmethod
|
||||
def auth_required(cls, func: Callable) -> Callable:
|
||||
@@ -80,30 +93,36 @@ class MiddlewareModule:
|
||||
@router.get("/protected")
|
||||
@MiddlewareModule.auth_required
|
||||
async def protected_endpoint(request: Request):
|
||||
user = request.state.user # Access authenticated user data
|
||||
return {"message": "Protected content"}
|
||||
|
||||
@router.get("/public") # No decorator = public endpoint
|
||||
async def public_endpoint():
|
||||
return {"message": "Public content"}
|
||||
auth = protected_endpoint.auth # Access auth context
|
||||
if auth.is_employee:
|
||||
# Handle employee logic
|
||||
employee_id = auth.token_context.employee_id
|
||||
else:
|
||||
# Handle occupant logic
|
||||
occupant_id = auth.token_context.occupant_id
|
||||
return {"user_id": auth.user_id}
|
||||
|
||||
Args:
|
||||
func: The FastAPI route handler function to protect
|
||||
|
||||
Returns:
|
||||
Callable: Wrapped function that checks authentication before execution
|
||||
|
||||
Raises:
|
||||
HTTPExceptionApi: If authentication fails
|
||||
"""
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(request: Request, *args, **kwargs):
|
||||
from ApiServices import TokenService
|
||||
# Get token from header
|
||||
# token = TokenService.get_access_token_from_request(request=request)
|
||||
# print(token)
|
||||
# if not token:
|
||||
# raise HTTPExceptionApi(error_code="NOT_AUTHORIZED", lang="tr")
|
||||
# Get and validate token context from request
|
||||
auth_context = cls.get_user_from_request(request)
|
||||
|
||||
# Attach auth context to function
|
||||
func.auth = auth_context
|
||||
|
||||
# Call the original endpoint function
|
||||
return func(request, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
|
||||
47
DockerApiServices/AllApiNeeds/middleware/base_context.py
Normal file
47
DockerApiServices/AllApiNeeds/middleware/base_context.py
Normal file
@@ -0,0 +1,47 @@
|
||||
"""Base context for middleware."""
|
||||
|
||||
from typing import Optional, Dict, Any, Union, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ApiServices.Token.token_handler import OccupantTokenObject, EmployeeTokenObject
|
||||
|
||||
|
||||
class BaseContext:
|
||||
"""Base context class for middleware."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._token_context: Optional[
|
||||
Union["OccupantTokenObject", "EmployeeTokenObject"]
|
||||
] = None
|
||||
self._function_code: Optional[str] = None
|
||||
|
||||
@property
|
||||
def token_context(
|
||||
self,
|
||||
) -> Optional[Union["OccupantTokenObject", "EmployeeTokenObject"]]:
|
||||
"""Get token context if available."""
|
||||
return self._token_context
|
||||
|
||||
@token_context.setter
|
||||
def token_context(
|
||||
self, value: Union["OccupantTokenObject", "EmployeeTokenObject"]
|
||||
) -> None:
|
||||
"""Set token context."""
|
||||
self._token_context = value
|
||||
|
||||
@property
|
||||
def function_code(self) -> Optional[str]:
|
||||
"""Get function code if available."""
|
||||
return self._function_code
|
||||
|
||||
@function_code.setter
|
||||
def function_code(self, value: str) -> None:
|
||||
"""Set function code."""
|
||||
self._function_code = value
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""Convert context to dictionary."""
|
||||
return {
|
||||
"token_context": self._token_context,
|
||||
"function_code": self._function_code,
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
"""
|
||||
Token event middleware for handling authentication and event tracking.
|
||||
"""
|
||||
|
||||
from functools import wraps
|
||||
from typing import Callable, Dict, Any
|
||||
from .auth_middleware import MiddlewareModule
|
||||
from .base_context import BaseContext
|
||||
|
||||
|
||||
class TokenEventHandler(BaseContext):
|
||||
"""Handler for token events with authentication context."""
|
||||
|
||||
def __init__(self, func: Callable, url_of_endpoint: str):
|
||||
"""Initialize the handler with function and URL."""
|
||||
super().__init__()
|
||||
self.func = func
|
||||
self.url_of_endpoint = url_of_endpoint
|
||||
|
||||
def update_context(self, function_code: str):
|
||||
"""Update the event context with function code."""
|
||||
self.function_code = function_code
|
||||
|
||||
|
||||
class TokenEventMiddleware:
|
||||
"""
|
||||
Module containing token and event handling functionality.
|
||||
|
||||
This class provides:
|
||||
- Token and event context management
|
||||
- Event validation decorator for endpoints
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def event_required(
|
||||
func: Callable[..., Dict[str, Any]]
|
||||
) -> Callable[..., Dict[str, Any]]:
|
||||
"""
|
||||
Decorator for endpoints with token and event requirements.
|
||||
This decorator:
|
||||
1. First validates authentication using MiddlewareModule.auth_required
|
||||
2. Then adds event tracking context
|
||||
|
||||
Args:
|
||||
func: The function to be decorated
|
||||
|
||||
Returns:
|
||||
Callable: The wrapped function with both auth and event handling
|
||||
"""
|
||||
# First apply authentication
|
||||
authenticated_func = MiddlewareModule.auth_required(func)
|
||||
|
||||
@wraps(authenticated_func)
|
||||
def wrapper(*args, **kwargs) -> Dict[str, Any]:
|
||||
# Create handler with context
|
||||
handler = TokenEventHandler(
|
||||
func=authenticated_func,
|
||||
url_of_endpoint=authenticated_func.url_of_endpoint,
|
||||
)
|
||||
|
||||
# Update event-specific context
|
||||
handler.update_context(
|
||||
function_code="7192c2aa-5352-4e36-98b3-dafb7d036a3d" # Keep function_code as URL
|
||||
)
|
||||
|
||||
# Copy auth context from authenticated function
|
||||
if hasattr(authenticated_func, "auth"):
|
||||
handler.token_context = authenticated_func.auth.token_context
|
||||
|
||||
# Make handler available to the function
|
||||
authenticated_func.handler = handler
|
||||
|
||||
# Call the authenticated function
|
||||
return authenticated_func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
@@ -19,7 +19,7 @@ RUN poetry config virtualenvs.create false \
|
||||
&& rm -rf ~/.cache/pypoetry
|
||||
|
||||
# Copy application code
|
||||
COPY DockerApiServices/AllApiNeeds /app/
|
||||
COPY DockerApiServices/AllApiNeeds /app
|
||||
COPY ErrorHandlers /app/ErrorHandlers
|
||||
COPY LanguageModels /app/LanguageModels
|
||||
COPY ApiLibrary /app/ApiLibrary
|
||||
@@ -28,6 +28,15 @@ COPY AllConfigs /app/AllConfigs
|
||||
COPY ErrorHandlers /app/ErrorHandlers
|
||||
COPY Schemas /app/Schemas
|
||||
COPY Services /app/Services
|
||||
COPY ApiServices /app/ApiServices
|
||||
|
||||
# Copy Events structure with consistent naming
|
||||
COPY ApiEvents/AuthServiceApi /app/ApiEvents
|
||||
COPY ApiEvents/abstract_class.py /app/ApiEvents/abstract_class.py
|
||||
COPY ApiEvents/base_request_model.py /app/ApiEvents/base_request_model.py
|
||||
|
||||
# Create empty __init__.py files to make directories into Python packages
|
||||
RUN touch /app/ApiEvents/__init__.py
|
||||
|
||||
# Set Python path to include app directory
|
||||
ENV PYTHONPATH=/app \
|
||||
|
||||
@@ -19,7 +19,7 @@ RUN poetry config virtualenvs.create false \
|
||||
&& rm -rf ~/.cache/pypoetry
|
||||
|
||||
# Copy application code
|
||||
COPY DockerApiServices/AllApiNeeds /app/
|
||||
COPY DockerApiServices/AllApiNeeds /app
|
||||
COPY ErrorHandlers /app/ErrorHandlers
|
||||
COPY LanguageModels /app/LanguageModels
|
||||
COPY ApiLibrary /app/ApiLibrary
|
||||
@@ -31,9 +31,12 @@ COPY Services /app/Services
|
||||
COPY ApiServices /app/ApiServices
|
||||
|
||||
# Copy Events structure with consistent naming
|
||||
COPY ApiEvents/EventServiceApi /app/events
|
||||
COPY ApiEvents/utils.py /app/events/utils.py
|
||||
COPY ApiEvents/abstract_class.py /app/events/abstract_class.py
|
||||
COPY ApiEvents/EventServiceApi /app/ApiEvents
|
||||
COPY ApiEvents/abstract_class.py /app/ApiEvents/abstract_class.py
|
||||
COPY ApiEvents/base_request_model.py /app/ApiEvents/base_request_model.py
|
||||
|
||||
# Create empty __init__.py files to make directories into Python packages
|
||||
RUN touch /app/ApiEvents/__init__.py
|
||||
|
||||
# Set Python path to include app directory
|
||||
ENV PYTHONPATH=/app \
|
||||
|
||||
@@ -35,11 +35,9 @@ docker compose -f docker-compose-services.yml build --no-cache && docker compose
|
||||
```
|
||||
|
||||
## Service Ports
|
||||
- Auth Service: `http://localhost:8000`
|
||||
- `/test/health` - Protected health check endpoint (requires authentication)
|
||||
- `/test/ping` - Public ping endpoint
|
||||
- Event Service: `http://localhost:8001`
|
||||
- Validation Service: `http://localhost:8002`
|
||||
- Auth Service: http://localhost:41575
|
||||
- Event Service: http://localhost:41576
|
||||
- Validation Service: http://localhost:41577
|
||||
|
||||
## Development Notes
|
||||
- Use clean build (--no-cache) when:
|
||||
|
||||
@@ -19,13 +19,21 @@ RUN poetry config virtualenvs.create false \
|
||||
&& rm -rf ~/.cache/pypoetry
|
||||
|
||||
# Copy application code
|
||||
COPY DockerApiServices/AllApiNeeds /app/
|
||||
COPY DockerApiServices/AllApiNeeds /app
|
||||
COPY ErrorHandlers /app/ErrorHandlers
|
||||
COPY LanguageModels /app/LanguageModels
|
||||
COPY ApiLibrary /app/ApiLibrary
|
||||
COPY ApiValidations /app/ApiValidations
|
||||
COPY AllConfigs /app/AllConfigs
|
||||
COPY ErrorHandlers /app/ErrorHandlers
|
||||
COPY Schemas /app/Schemas
|
||||
COPY Services /app/Services
|
||||
COPY ApiServices /app/ApiServices
|
||||
|
||||
# Copy Events structure with consistent naming
|
||||
COPY ApiEvents/EventServiceApi /app/ApiEvents
|
||||
COPY ApiEvents/abstract_class.py /app/ApiEvents/abstract_class.py
|
||||
COPY ApiEvents/base_request_model.py /app/ApiEvents/base_request_model.py
|
||||
|
||||
# Set Python path to include app directory
|
||||
ENV PYTHONPATH=/app \
|
||||
|
||||
Reference in New Issue
Block a user