mirror of
https://github.com/simple-login/app.git
synced 2024-11-16 17:08:30 +01:00
95 lines
2.9 KiB
Python
95 lines
2.9 KiB
Python
from abc import ABC, abstractmethod
|
|
|
|
import newrelic.agent
|
|
|
|
from app import config
|
|
from app.db import Session
|
|
from app.errors import ProtonPartnerNotSetUp
|
|
from app.events.generated import event_pb2
|
|
from app.log import LOG
|
|
from app.models import User, PartnerUser, SyncEvent
|
|
from app.proton.utils import get_proton_partner
|
|
from typing import Optional
|
|
|
|
NOTIFICATION_CHANNEL = "simplelogin_sync_events"
|
|
|
|
|
|
class Dispatcher(ABC):
|
|
@abstractmethod
|
|
def send(self, event: bytes):
|
|
pass
|
|
|
|
|
|
class PostgresDispatcher(Dispatcher):
|
|
def send(self, event: bytes):
|
|
instance = SyncEvent.create(content=event, flush=True)
|
|
Session.execute(f"NOTIFY {NOTIFICATION_CHANNEL}, '{instance.id}';")
|
|
|
|
@staticmethod
|
|
def get():
|
|
return PostgresDispatcher()
|
|
|
|
|
|
class GlobalDispatcher:
|
|
__dispatcher: Optional[Dispatcher] = None
|
|
|
|
@staticmethod
|
|
def get_dispatcher() -> Dispatcher:
|
|
if not GlobalDispatcher.__dispatcher:
|
|
GlobalDispatcher.__dispatcher = PostgresDispatcher.get()
|
|
return GlobalDispatcher.__dispatcher
|
|
|
|
@staticmethod
|
|
def set_dispatcher(dispatcher: Optional[Dispatcher]):
|
|
GlobalDispatcher.__dispatcher = dispatcher
|
|
|
|
|
|
class EventDispatcher:
|
|
@staticmethod
|
|
def send_event(
|
|
user: User,
|
|
content: event_pb2.EventContent,
|
|
dispatcher: Optional[Dispatcher] = None,
|
|
skip_if_webhook_missing: bool = True,
|
|
):
|
|
if dispatcher is None:
|
|
dispatcher = GlobalDispatcher.get_dispatcher()
|
|
if config.EVENT_WEBHOOK_DISABLE:
|
|
LOG.i("Not sending events because webhook is disabled")
|
|
return
|
|
|
|
if not config.EVENT_WEBHOOK and skip_if_webhook_missing:
|
|
LOG.i(
|
|
"Not sending events because webhook is not configured and allowed to be empty"
|
|
)
|
|
return
|
|
|
|
partner_user = EventDispatcher.__partner_user(user.id)
|
|
if not partner_user:
|
|
LOG.i(f"Not sending events because there's no partner user for user {user}")
|
|
return
|
|
|
|
event = event_pb2.Event(
|
|
user_id=user.id,
|
|
external_user_id=partner_user.external_user_id,
|
|
partner_id=partner_user.partner_id,
|
|
content=content,
|
|
)
|
|
|
|
serialized = event.SerializeToString()
|
|
dispatcher.send(serialized)
|
|
|
|
event_type = content.WhichOneof("content")
|
|
newrelic.agent.record_custom_event("EventStoredToDb", {"type": event_type})
|
|
LOG.i("Sent event to the dispatcher")
|
|
|
|
@staticmethod
|
|
def __partner_user(user_id: int) -> Optional[PartnerUser]:
|
|
# Check if the current user has a partner_id
|
|
try:
|
|
proton_partner_id = get_proton_partner().id
|
|
except ProtonPartnerNotSetUp:
|
|
return None
|
|
|
|
# It has. Retrieve the information for the PartnerUser
|
|
return PartnerUser.get_by(user_id=user_id, partner_id=proton_partner_id)
|