Skip to content

Commit 8d0feed

Browse files
author
Max Azatian
committed
v2: added kafka instead of polling, more details to add sooner
1 parent 904b452 commit 8d0feed

File tree

236 files changed

+44935
-1335
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

236 files changed

+44935
-1335
lines changed

backend/.env

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,66 @@
11
PROJECT_NAME=integr8scode
2-
SECRET_KEY=CHANGE_ME_this_is_a_dev_key_min_32_chars_required
2+
SECRET_KEY=-5c_AyfH64NL9g39JbpsOsGUoLTQPA4fGsEGQhTDja8
33
ALGORITHM=HS256
4-
ACCESS_TOKEN_EXPIRE_MINUTES=30
5-
MONGODB_URL=mongodb://mongo:27017/integr8scode
4+
ACCESS_TOKEN_EXPIRE_MINUTES=1440
5+
MONGODB_URL=mongodb://root:rootpassword@mongo:27017/integr8scode?authSource=admin
6+
MONGO_ROOT_USER=root
7+
MONGO_ROOT_PASSWORD=rootpassword
68
KUBERNETES_CONFIG_PATH=/app/kubeconfig.yaml
79
KUBERNETES_CA_CERTIFICATE_PATH=/app/certs/k8s-ca.pem
810
K8S_POD_CPU_LIMIT=1000m
911
K8S_POD_MEMORY_LIMIT=128Mi
1012
K8S_POD_CPU_REQUEST=200m
1113
K8S_POD_MEMORY_REQUEST=128Mi
1214
K8S_POD_EXECUTION_TIMEOUT=5
13-
RATE_LIMITS=100/minute
15+
RATE_LIMITS=100/minute
16+
17+
# Event-Driven Design Configuration
18+
KAFKA_BOOTSTRAP_SERVERS=kafka:29092
19+
SCHEMA_REGISTRY_URL=http://schema-registry:8081
20+
ENABLE_EVENT_STREAMING=true
21+
EVENT_RETENTION_DAYS=30
22+
KAFKA_CONSUMER_GROUP_ID=integr8scode-backend
23+
KAFKA_AUTO_OFFSET_RESET=earliest
24+
KAFKA_ENABLE_AUTO_COMMIT=true
25+
KAFKA_SESSION_TIMEOUT_MS=30000
26+
KAFKA_MAX_POLL_RECORDS=500
27+
28+
# Feature Flags
29+
FEATURE_EVENT_DRIVEN_EXECUTION=true
30+
FEATURE_SSE_STREAMING=true
31+
FEATURE_WEBSOCKET_UPDATES=true
32+
FEATURE_DISTRIBUTED_TRACING=true
33+
FEATURE_EVENT_STORE_ENABLED=true
34+
FEATURE_CIRCUIT_BREAKER_ENABLED=true
35+
FEATURE_KAFKA_EVENTS=true
36+
37+
# WebSocket Configuration
38+
WEBSOCKET_PING_INTERVAL=30
39+
WEBSOCKET_PING_TIMEOUT=10
40+
WEBSOCKET_MAX_CONNECTIONS_PER_USER=5
41+
WEBSOCKET_STALE_CONNECTION_TIMEOUT=300
42+
43+
# Distributed Tracing
44+
ENABLE_TRACING=true
45+
JAEGER_AGENT_HOST=jaeger
46+
JAEGER_AGENT_PORT=6831
47+
TRACING_SERVICE_NAME=integr8scode-backend
48+
TRACING_SERVICE_VERSION=1.0.0
49+
TRACING_SAMPLING_RATE=1.0
50+
51+
# Dead Letter Queue Configuration
52+
KAFKA_DLQ_TOPIC=dead-letter-queue
53+
DLQ_RETRY_MAX_ATTEMPTS=5
54+
DLQ_RETRY_BASE_DELAY_SECONDS=60.0
55+
DLQ_RETRY_MAX_DELAY_SECONDS=3600.0
56+
DLQ_RETENTION_DAYS=7
57+
DLQ_WARNING_THRESHOLD=100
58+
DLQ_CRITICAL_THRESHOLD=1000
59+
60+
61+
# App URL for notification links
62+
APP_URL=https://localhost
63+
64+
# Service Configuration
65+
SERVICE_NAME=integr8scode-backend
66+
SERVICE_VERSION=1.0.0

backend/Dockerfile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
FROM python:3.9
1+
FROM python:3.12
22
WORKDIR /app
33

44
# Install required packages
55
RUN apt-get update && apt-get upgrade -y liblzma-dev liblzma5 xz-utils && \
6+
apt-get install -y libsnappy-dev && \
67
rm -rf /var/lib/apt/lists/*
78

89
# Install kubectl (latest stable version)
@@ -16,6 +17,8 @@ RUN pip install --no-cache-dir --upgrade pip setuptools>=70.0.0 wheel && \
1617

1718
# Copy application files and configuration
1819
COPY ./app /app/app
20+
COPY ./workers /app/workers
21+
COPY ./scripts /app/scripts
1922
COPY .env /app/.env
2023
COPY openssl.cnf /app/openssl.cnf
2124

@@ -28,4 +31,5 @@ CMD bash -c "\
2831
while [ ! -f /app/kubeconfig.yaml ]; do echo 'Waiting for kubeconfig...'; sleep 2; done && \
2932
echo 'Certs and kubeconfig found. Starting application...' && \
3033
export KUBECONFIG=/app/kubeconfig.yaml && \
34+
PYTHONPATH=/app python /app/scripts/create_topics.py || true && \
3135
uvicorn app.main:app --host 0.0.0.0 --port 443 --ssl-keyfile /app/certs/server.key --ssl-certfile /app/certs/server.crt"

backend/alertmanager/alertmanager.yml

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -37,51 +37,18 @@ receivers:
3737
webhook_configs:
3838
- url: 'http://backend:443/api/v1/health'
3939
send_resolved: true
40-
title: 'Integr8sCode Alert: {{ .GroupLabels.alertname }}'
41-
text: |
42-
{{ range .Alerts }}
43-
Alert: {{ .Annotations.summary }}
44-
Description: {{ .Annotations.description }}
45-
Severity: {{ .Labels.severity }}
46-
{{ end }}
4740

4841
- name: 'critical-security'
4942
webhook_configs:
5043
- url: 'http://backend:443/api/v1/health'
5144
send_resolved: true
52-
title: '🚨 CRITICAL SECURITY ALERT: {{ .GroupLabels.alertname }}'
53-
text: |
54-
IMMEDIATE ATTENTION REQUIRED - Security incident detected!
55-
56-
{{ range .Alerts }}
57-
Alert: {{ .Annotations.summary }}
58-
Description: {{ .Annotations.description }}
59-
Labels: {{ range .Labels.SortedPairs }}{{ .Name }}={{ .Value }} {{ end }}
60-
{{ end }}
6145

6246
- name: 'critical-infrastructure'
6347
webhook_configs:
6448
- url: 'http://backend:443/api/v1/health'
6549
send_resolved: true
66-
title: '🔥 CRITICAL INFRASTRUCTURE ALERT: {{ .GroupLabels.alertname }}'
67-
text: |
68-
Critical system issue requiring immediate attention!
69-
70-
{{ range .Alerts }}
71-
Alert: {{ .Annotations.summary }}
72-
Description: {{ .Annotations.description }}
73-
Severity: {{ .Labels.severity }}
74-
{{ end }}
7550

7651
- name: 'warning'
7752
webhook_configs:
7853
- url: 'http://backend:443/api/v1/health'
79-
send_resolved: true
80-
title: '⚠️ WARNING: {{ .GroupLabels.alertname }}'
81-
text: |
82-
Warning condition detected - monitoring recommended.
83-
84-
{{ range .Alerts }}
85-
Alert: {{ .Annotations.summary }}
86-
Description: {{ .Annotations.description }}
87-
{{ end }}
54+
send_resolved: true

backend/app/api/dependencies.py

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,78 @@
1-
# app/api/dependencies.py
1+
from fastapi import Depends, HTTPException, Request, status
2+
from motor.motor_asyncio import AsyncIOMotorDatabase
3+
24
from app.config import Settings, get_settings
35
from app.core.logging import logger
6+
from app.core.security import security_service
47
from app.db.mongodb import DatabaseManager
5-
from fastapi import HTTPException, Request, status
6-
from motor.motor_asyncio import AsyncIOMotorDatabase
8+
from app.db.repositories.user_repository import UserRepository, get_user_repository
9+
from app.schemas_pydantic.user import UserResponse, UserRole
710

811

912
def get_settings_dependency() -> Settings:
1013
return get_settings()
1114

15+
1216
def get_db_dependency(request: Request) -> AsyncIOMotorDatabase:
13-
"""
14-
Dependency function to get the database handle from the DatabaseManager
15-
stored in the application state.
16-
"""
1717
try:
1818
db_manager: DatabaseManager = request.app.state.db_manager
19-
return db_manager.get_database() # type: ignore
19+
return db_manager.get_database()
2020
except AttributeError as e:
21-
# This signifies a critical setup error: lifespan didn't set the state.
2221
logger.critical("DatabaseManager not found in app state. Application startup likely failed.")
2322
raise HTTPException(
2423
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
2524
detail="Internal server error: Database service not available.",
2625
) from e
2726
except RuntimeError as e:
28-
# This signifies get_database was called when db is None (shouldn't happen if connect succeeded)
29-
logger.error(f"Error retrieving database handle: {e}")
30-
raise HTTPException(
31-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
32-
detail="Internal server error: Database connection issue.",
33-
) from e
27+
logger.error(f"Error retrieving database handle: {e}")
28+
raise HTTPException(
29+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
30+
detail="Internal server error: Database connection issue.",
31+
) from e
32+
33+
34+
async def get_current_user(
35+
request: Request,
36+
user_repo: UserRepository = Depends(get_user_repository),
37+
) -> UserResponse:
38+
try:
39+
token = request.cookies.get("access_token")
40+
if not token:
41+
raise HTTPException(
42+
status_code=status.HTTP_401_UNAUTHORIZED,
43+
detail="Not authenticated",
44+
headers={"WWW-Authenticate": "Bearer"},
45+
)
46+
47+
user_in_db = await security_service.get_current_user(token, user_repo)
48+
49+
return UserResponse(
50+
user_id=user_in_db.user_id,
51+
username=user_in_db.username,
52+
email=user_in_db.email,
53+
role=user_in_db.role,
54+
created_at=user_in_db.created_at,
55+
updated_at=user_in_db.updated_at
56+
)
57+
except HTTPException:
58+
raise
59+
except Exception:
60+
raise HTTPException(
61+
status_code=status.HTTP_401_UNAUTHORIZED,
62+
detail="Not authenticated",
63+
headers={"WWW-Authenticate": "Bearer"},
64+
)
65+
66+
67+
async def require_admin(
68+
user: UserResponse = Depends(get_current_user),
69+
) -> UserResponse:
70+
if user.role != UserRole.ADMIN:
71+
logger.warning(
72+
f"Admin access denied for user: {user.username} (role: {user.role})"
73+
)
74+
raise HTTPException(
75+
status_code=status.HTTP_403_FORBIDDEN,
76+
detail="Admin access required"
77+
)
78+
return user
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from .events import router as events_router
2+
from .settings import router as settings_router
3+
from .users import router as users_router
4+
5+
__all__ = ["events_router", "settings_router", "users_router"]

0 commit comments

Comments
 (0)