New alert service

This commit is contained in:
Urtzi Alfaro
2025-12-05 20:07:01 +01:00
parent 1fe3a73549
commit 667e6e0404
393 changed files with 26002 additions and 61033 deletions

View File

@@ -7,8 +7,8 @@ from sqlalchemy import text
from app.core.config import settings
from app.core.database import database_manager
from app.api import auth_operations, users, onboarding_progress, consent, data_export, account_deletion
from app.services.messaging import setup_messaging, cleanup_messaging
from shared.service_base import StandardFastAPIService
from shared.messaging import UnifiedEventPublisher
class AuthService(StandardFastAPIService):
@@ -114,12 +114,25 @@ class AuthService(StandardFastAPIService):
async def _setup_messaging(self):
"""Setup messaging for auth service"""
await setup_messaging()
self.logger.info("Messaging setup complete")
from shared.messaging import RabbitMQClient
try:
self.rabbitmq_client = RabbitMQClient(settings.RABBITMQ_URL, service_name="auth-service")
await self.rabbitmq_client.connect()
# Create event publisher
self.event_publisher = UnifiedEventPublisher(self.rabbitmq_client, "auth-service")
self.logger.info("Auth service messaging setup completed")
except Exception as e:
self.logger.error("Failed to setup auth messaging", error=str(e))
raise
async def _cleanup_messaging(self):
"""Cleanup messaging for auth service"""
await cleanup_messaging()
try:
if self.rabbitmq_client:
await self.rabbitmq_client.disconnect()
self.logger.info("Auth service messaging cleanup completed")
except Exception as e:
self.logger.error("Error during auth messaging cleanup", error=str(e))
async def on_shutdown(self, app: FastAPI):
"""Custom shutdown logic for auth service"""

View File

@@ -9,22 +9,12 @@ from .user_service import UserService
from .auth_service import EnhancedUserService
from .auth_service_clients import AuthServiceClientFactory
from .admin_delete import AdminUserDeleteService
from .messaging import (
publish_user_registered,
publish_user_login,
publish_user_updated,
publish_user_deactivated
)
__all__ = [
"AuthService",
"EnhancedAuthService",
"UserService",
"UserService",
"EnhancedUserService",
"AuthServiceClientFactory",
"AdminUserDeleteService",
"publish_user_registered",
"publish_user_login",
"publish_user_updated",
"publish_user_deactivated"
"AdminUserDeleteService"
]

View File

@@ -24,7 +24,6 @@ from datetime import datetime
from shared.auth.decorators import get_current_user_dep
from app.core.database import get_db
from app.services.messaging import auth_publisher
from app.services.auth_service_clients import AuthServiceClientFactory
from app.core.config import settings
@@ -460,40 +459,45 @@ class AdminUserDeleteService:
return summary
def __init__(self, database_manager, event_publisher=None):
"""Initialize service with database manager and optional event publisher"""
self.database_manager = database_manager
self.event_publisher = event_publisher
async def _publish_user_deleted_event(self, user_id: str, deletion_results: Dict[str, Any]):
"""Publish user deletion event to message queue"""
try:
await auth_publisher.publish_event(
exchange="user_events",
routing_key="user.admin.deleted",
message={
"event_type": "admin_user_deleted",
"user_id": user_id,
"timestamp": datetime.utcnow().isoformat(),
"deletion_summary": deletion_results['summary'],
"services_affected": list(deletion_results['services_processed'].keys())
}
)
logger.info("Published user deletion event", user_id=user_id)
except Exception as e:
logger.error("Failed to publish user deletion event", error=str(e))
if self.event_publisher:
try:
await self.event_publisher.publish_business_event(
event_type="auth.user.deleted",
tenant_id="system",
data={
"user_id": user_id,
"timestamp": datetime.utcnow().isoformat(),
"deletion_summary": deletion_results['summary'],
"services_affected": list(deletion_results['services_processed'].keys())
}
)
logger.info("Published user deletion event", user_id=user_id)
except Exception as e:
logger.error("Failed to publish user deletion event", error=str(e))
async def _publish_user_deletion_failed_event(self, user_id: str, error: str):
"""Publish user deletion failure event"""
try:
await auth_publisher.publish_event(
exchange="user_events",
routing_key="user.deletion.failed",
message={
"event_type": "admin_user_deletion_failed",
"user_id": user_id,
"error": error,
"timestamp": datetime.utcnow().isoformat()
}
)
logger.info("Published user deletion failure event", user_id=user_id)
except Exception as e:
logger.error("Failed to publish deletion failure event", error=str(e))
if self.event_publisher:
try:
await self.event_publisher.publish_business_event(
event_type="auth.user.deletion_failed",
tenant_id="system",
data={
"user_id": user_id,
"error": error,
"timestamp": datetime.utcnow().isoformat()
}
)
logger.info("Published user deletion failure event", user_id=user_id)
except Exception as e:
logger.error("Failed to publish deletion failure event", error=str(e))
async def _notify_admins_of_deletion(self, user_info: Dict[str, Any], deletion_results: Dict[str, Any]):
"""Send notification to other admins about the user deletion"""

View File

@@ -15,7 +15,7 @@ from app.schemas.auth import UserRegistration, UserLogin, TokenResponse, UserRes
from app.models.users import User
from app.models.tokens import RefreshToken
from app.core.security import SecurityManager
from app.services.messaging import publish_user_registered, publish_user_login
from shared.messaging import UnifiedEventPublisher, EVENT_TYPES
from shared.database.unit_of_work import UnitOfWork
from shared.database.transactions import transactional
from shared.database.exceptions import DatabaseError, ValidationError, DuplicateRecordError
@@ -30,9 +30,10 @@ AuthService = None # Will be set at the end of the file
class EnhancedAuthService:
"""Enhanced authentication service using repository pattern"""
def __init__(self, database_manager):
"""Initialize service with database manager"""
def __init__(self, database_manager, event_publisher=None):
"""Initialize service with database manager and optional event publisher"""
self.database_manager = database_manager
self.event_publisher = event_publisher
async def register_user(
self,
@@ -208,17 +209,22 @@ class EnhancedAuthService:
await uow.commit()
# Publish registration event (non-blocking)
try:
await publish_user_registered({
"user_id": str(new_user.id),
"email": new_user.email,
"full_name": new_user.full_name,
"role": new_user.role,
"registered_at": datetime.now(timezone.utc).isoformat(),
"subscription_plan": user_data.subscription_plan or "starter"
})
except Exception as e:
logger.warning("Failed to publish registration event", error=str(e))
if self.event_publisher:
try:
await self.event_publisher.publish_business_event(
event_type="auth.user.registered",
tenant_id="system", # User registration is system-wide initially
data={
"user_id": str(new_user.id),
"email": new_user.email,
"full_name": new_user.full_name,
"role": new_user.role,
"registered_at": datetime.now(timezone.utc).isoformat(),
"subscription_plan": user_data.subscription_plan or "starter"
}
)
except Exception as e:
logger.warning("Failed to publish registration event", error=str(e))
logger.info("User registered successfully using repository pattern",
user_id=new_user.id,
@@ -320,14 +326,19 @@ class EnhancedAuthService:
await uow.commit()
# Publish login event (non-blocking)
try:
await publish_user_login({
"user_id": str(user.id),
"email": user.email,
"login_at": datetime.now(timezone.utc).isoformat()
})
except Exception as e:
logger.warning("Failed to publish login event", error=str(e))
if self.event_publisher:
try:
await self.event_publisher.publish_business_event(
event_type="auth.user.login",
tenant_id="system",
data={
"user_id": str(user.id),
"email": user.email,
"login_at": datetime.now(timezone.utc).isoformat()
}
)
except Exception as e:
logger.warning("Failed to publish login event", error=str(e))
logger.info("User logged in successfully using repository pattern",
user_id=user.id,

View File

@@ -1,46 +0,0 @@
# app/services/messaging.py
"""
Messaging service for auth service
"""
from shared.messaging.rabbitmq import RabbitMQClient
from app.core.config import settings
import structlog
logger = structlog.get_logger()
# Single global instance
auth_publisher = RabbitMQClient(settings.RABBITMQ_URL, "auth-service")
async def setup_messaging():
"""Initialize messaging for auth service"""
success = await auth_publisher.connect()
if success:
logger.info("Auth service messaging initialized")
else:
logger.warning("Auth service messaging failed to initialize")
async def cleanup_messaging():
"""Cleanup messaging for auth service"""
await auth_publisher.disconnect()
logger.info("Auth service messaging cleaned up")
# Convenience functions for auth-specific events
async def publish_user_registered(user_data: dict) -> bool:
"""Publish user registered event"""
return await auth_publisher.publish_user_event("registered", user_data)
async def publish_user_login(user_data: dict) -> bool:
"""Publish user login event"""
return await auth_publisher.publish_user_event("login", user_data)
async def publish_user_logout(user_data: dict) -> bool:
"""Publish user logout event"""
return await auth_publisher.publish_user_event("logout", user_data)
async def publish_user_updated(user_data: dict) -> bool:
"""Publish user updated event"""
return await auth_publisher.publish_user_event("updated", user_data)
async def publish_user_deactivated(user_data: dict) -> bool:
"""Publish user deactivated event"""
return await auth_publisher.publish_user_event("deactivated", user_data)