Commit Graph

31 Commits

Author SHA1 Message Date
lebaudantoine
ac87980a27 ♻️(backend) refactor external API authentication classes
Refactor external API authentication classes to inherit from a
common base authentication backend.

Prepare the introduction of a new authentication class responsible
for verifying tokens provided to calendar integrations.

Move token decoding responsibility to the new token service so it
can both generate and validate tokens.

Encapsulate external exceptions and expose a clear interface by
defining custom Python exceptions raised during token validation.

Taken from #897.
2026-02-24 16:07:23 +01:00
lebaudantoine
7cab46dc29 ♻️(backend) encapsulate token generation in a service
Encapsulate token generation logic for authenticating to the
external API in a well-scoped service.

This service can later be reused in other parts of the codebase,
especially for providing tokens required by calendar integrations.

Commit was cherry picked from #897
2026-02-24 16:07:23 +01:00
lebaudantoine
0fe8d9b681 🐛(backend) fix ignore recording webhook events
Fix an unexpected behavior where filtering LiveKit webhook events sometimes
failed because the room name was not reliably extracted from the webhook data,
causing notifications to be ignored.

Configure the same filtering logic locally to avoid missing this kind of issue
in the future.
2026-01-05 13:34:55 +01:00
lebaudantoine
f6cdb1125b ♻️(backend) refactor backend recording state management
Instead of relying on the egress_started event—which fires when egress is
starting, not actually started—I now rely on egress_updated for more accurate
status updates. This is especially important for the active status, which
triggers after egress has truly joined the room. Using this avoids prematurely
stopping client-side listening to room.isRecording updates. A further
refactoring may remove reliance on room updates entirely.

The goal is to minimize handling metadata in the mediator class. egress_starting
is still used for simplicity, but egress_started could be considered in the
future.

Note: if the API to start egress hasn’t responded yet, the webhook may fail to
find the recording because it currently matches by worker ID. This is unstable.
A better approach would be to pass the database ID in the egress metadata and
recover the recording from it in the webhook.
2026-01-05 00:14:00 +01:00
lebaudantoine
16badde82d 🚧(backend) update recording metadata alongside recording state changes
Previously, this was handled manually by the client, sending notifications to
other participants and keeping the recording state only in memory. There was no
shared or persisted state, so leaving and rejoining a meeting lost this
information. Delegating this responsibility solely to the client was a poor
choice.

The backend now owns this responsibility and relies on LiveKit webhooks to keep
room metadata in sync with the egress lifecycle.

This also reveals that the room.isRecording attribute does not update as fast
as the egress stop event, which is unexpected and should be investigated
further.

This will make state management working when several room’s owner will be in
the same meeting, which is expected to arrive any time soon.
2026-01-04 20:22:15 +01:00
lebaudantoine
5c74ace0d8 🐛(backend) filter LiveKit events by room name regex to exclude Tchap
Add configurable room name regex filtering to exclude Tchap events from shared
LiveKit server webhooks, preventing backend spam from unrelated application
events while maintaining UUID-based room processing for visio.

Those unrelated application events are spamming the sentry.

Acknowledges this is a pragmatic solution trading proper namespace
prefixing for immediate spam reduction with minimal refactoring impact
leaving prefix-based approach for future improvement.
2025-10-12 16:57:44 +02:00
lebaudantoine
1f71bfc5d2 🎨(backend) use pylint error names instead of codes in disable comments
Replace pylint error codes with descriptive error names in disable comments
to make suppressed warnings explicit and improve code readability.
2025-09-04 11:26:48 +02:00
lebaudantoine
888fbbcd5f 🎨(backend) use object primary key instead of id attribute
Replace id attribute references with object primary key for better code
consistency and Django model conventions.

requested by @qbey
2025-09-04 11:26:48 +02:00
lebaudantoine
5f70840398 ♻️(backend) move LiveKit participant management to server-side API
Refactor client-side LiveKit API calls to server-side endpoints
following LiveKit documentation recommendations for participant
management operations.

Replaces hacky direct client calls with proper backend-mediated
requests, improving security and following official LiveKit
2025-09-04 11:26:48 +02:00
lebaudantoine
84e62246b7 (backend) add lobby cache clearing method for room and participant
Introduce new method on lobby system to clear lobby cache for specific
room and participant combinations.

Enables targeted cleanup of lobby state when participants leave or are
removed, improving cache management and preventing stale lobby entries.
2025-09-04 11:26:48 +02:00
lebaudantoine
6c633b1ecb ♻️(backend) sync lobby and LiveKit participant UUID generation
Refactor lobby system to use consistent UUID v4 across lobby
registration and LiveKit token participant identity instead of
generating separate UUIDs.

Maintains synchronized identifiers between lobby cache and LiveKit
participants, simplifying future participant removal operations by
using the same UUID reference across both systems.
2025-09-04 11:26:48 +02:00
lebaudantoine
0f76517957 💩(backend) pass room config and user role data to LiveKit token utility
Extend LiveKit token creation utility with additional room configuration
and user role parameters to properly adapt room_admin grants and
publish sources based on permission levels.

This creates technical debt in utility function design that should be
refactored into proper service architecture for token
generation operations in future iterations.
2025-09-04 11:26:48 +02:00
lebaudantoine
f48dd5cea1 (backend) add start-subtitle endpoint
Allow any user, anonymous or authenticated, to start subtitling
in a room only if they are an active participant of it.

Subtitling a room consists of starting the multi-user transcriber agent.
This agent forwards all participants' audio to an STT server and returns
transcription segments for any active voice to the room.

User roles in the backend room system cannot be used
to determine subtitle permissions.

The transcriber agent can be triggered multiple times but will only join a
room once. Unicity is managed by the agent itself.
Any user with a valid LiveKit token can initiate subtitles. Feature flag
logic is implemented on the frontend. The frontend ensures the "start
subtitle" action is only available to users who should see it. The backend
does not enforce feature flags in this version.

Authentication in our system does not imply access to a room. The only
valid proof of access is the LiveKit API token issued by the backend.
Security consideration: A LiveKit API token is valid for 6 hours and
cannot be revoked at the end of a meeting. It is important to verify
that the token was issued for the correct room.

Calls to the agent dispatch endpoint must be server-initiated. The backend
proxies these calls, as clients cannot securely contact the agent dispatch
endpoint directly (per LiveKit documentation).

Room ID is passed as a query parameter. There is currently no validation
ensuring that the room exists prior to agent dispatch.
TODO: implement validation or error handling for non-existent rooms.

The backend does not forward LiveKit tokens to the agent. Default API
rate limiting is applied to prevent abuse.
2025-09-03 18:09:00 +02:00
lebaudantoine
8a417806e4 🐛(backend) fix lobby notification type error breaking participant alerts
Correct data type issue that was preventing lobby notifications from
being sent to other participants in the room.
2025-07-18 11:42:43 +02:00
lebaudantoine
59cd1f766a (backend) add egress limit notification handler to LiveKit service
Implement method to process egress limit reached events from LiveKit
webhooks for better recording duration management.

Livekit by default is not notifying the participant of a room when
an egress reached its limit. I needed to proxy it through the back.
2025-07-16 14:47:24 +02:00
lebaudantoine
17c486f7bf ♻️(backend) extract notify_participant to util function
Move from lobby service to utils for reuse across services. Method is
generic enough for utility status. Future: create dedicated LiveKit
service to encapsulate all LiveKit-related utilities.
2025-07-16 14:47:24 +02:00
lebaudantoine
988e5aa256 (backend) add telephony service for automatic SIP dispatch rules
Implemented a service that automatically creates a SIP dispatch rule when
the first WebRTC participant joins a room and removes it when the room
becomes empty.

Why? I don’t want a SIP participant to join an empty room.
The PIN code could be easily leaked, and there is currently no lobby
mechanism available for SIP participants.

A WebRTC participant is still required to create a room.
This behavior is inspired by a proprietary tool. The service uses LiveKit’s
webhook notification system to react to room lifecycle events. This is
a naive implementation that currently supports only a single SIP trunk and
will require refactoring to support multiple trunks. When no trunk is
specified, rules are created by default on a fallback trunk.

@rouja wrote a minimal Helm chart for LiveKit SIP with Asterisk, which
couldn’t be versioned yet due to embedded credentials. I deployed it
locally and successfully tested the integration with a remote
OVH SIP trunk.

One point to note: LiveKit lacks advanced filtering capabilities when
listing dispatch rules. Their recommendation is to fetch all rules and
filter them within your backend logic. I’ve opened a feature request asking
for at least the ability to filter dispatch rules by room, since filtering
by trunk is already supported, room-based filtering feels like a natural
addition.

Until there's an update, I prefer to keep the implementation simple.
It works well at our current scale, and can be refactored when higher load
or multi-trunk support becomes necessary.

While caching dispatch rule IDs could be a performance optimization,
I feel it would be premature and potentially error-prone due to the complexity
of invalidation. If performance becomes an issue, I’ll consider introducing
caching at that point. To handle the edge case where multiple dispatch rules
with different PIN codes are present, the service performs an extensive
cleanup during room creation to ensure SIP routing remains clean and
predictable. This edge case should not happen.

In the 'delete_dispatch_rule' if deleting one rule fails, method would exit
without deleting the other rules. It's okay IMO for a first iteration.
If multiple dispatch rules are often found for room, I would enhance this part.
2025-07-07 19:21:39 +02:00
lebaudantoine
61aa3c79c5 🩹(backend) replace requests exception with urllib3 ones
My bad, I caught the wrong exception, issue is still raising in Sentry.
It fixes commit #2a7d963f
2025-05-28 10:49:03 +02:00
lebaudantoine
b7dfafaf47 🔇(backend) downgrade marketing exceptions from error to warning level
Replace logger.exception with logger.warning to reduce Sentry noise for
unavoidable timeout errors that developers cannot act upon.
2025-05-27 15:15:46 +02:00
lebaudantoine
2a7d963f50 🥅(backend) catch request timeout and Brevo contact addition errors
Handle unhandled exceptions to prevent UX impact. Marketing email operations
are optional and should not disrupt core functionality.

My first implementation was imperfect, raising error in sentry.
2025-05-27 15:15:46 +02:00
lebaudantoine
ae17fbdaa8 ♻️(backend) extract livekit API client creation to reusable utility
Create dedicated utility function for livekit API client initialization.
Centralizes configuration logic including custom session handling for SSL
verification. Improves code reuse across backend components that interact
with LiveKit.
2025-04-24 18:05:52 +02:00
lebaudantoine
90b4449040 (backend) add email invitation endpoint for meeting participants
Implement new endpoint allowing admin/owner to invite participants via email.
Provides explicit way to search users and send meeting invitations with
direct links.

In upcoming commits, frontend will call ResourceAccess endpoint to add
invited people as members if they exist in visio, bypassing waiting room
for a smoother experience.
2025-04-17 11:22:34 +02:00
lebaudantoine
4e1a4be650 (backend) introduce a creation callback endpoint
Necessary in cross browser context situation, where we need to
pass data of a room newly created between two different windows.

This happens in Calendar integration.
2025-04-02 12:31:04 +02:00
lebaudantoine
0af30ec366 (backend) notify participants only if the room exists
Improves sendData reliability by preventing execution when the room
doesn’t exist.

This change addresses errors in staging and production where waiting
participants arrive before the room owner creates the room.

In remote environments, the LiveKit Python SDK doesn’t return a clean
Twirp error when the room is missing; instead of a proper "server unknown"
response, it raises a ContentTypeError, as if the LiveKit server weren’t
responding with a JSON payload, even though the code specifies otherwise.

While the issue cannot be reproduced locally,
this should help mitigate production errors.

Part of a broader effort to enhance data transmission reliability.

Importantly, a participant requesting entry to a room before the owner
arrives should not be considered an exception.
2025-03-25 13:33:47 +01:00
lebaudantoine
18f4a117ab 🩹(backend) invert operation order in participant handling
Invert operation sequence to first notify people in room before setting
participant in cache. Fixes infinite loop issue caused by 3s cache timeout
for waiting participants when requests take too long. Problem only occurred
when notifications were delayed, as faster notification delivery masked the
race condition.
2025-03-24 19:39:13 +01:00
lebaudantoine
fbee41f5dd ♻️(backend) avoid repeating 'service' in python modules
These modules are already stored under the 'service' folder, it was redundant.
Renamed these files based on @lunika feedbacks.
2025-03-07 18:36:30 +01:00
lebaudantoine
d2f79d4524 (backend) introduce LiveKit event-handler matching service
Create new service that matches received events with their appropriate
handlers. Provides centralized system for event routing and processing
across the application.

If an event has no handler, it would be ignored.
2025-03-07 17:05:06 +01:00
lebaudantoine
2168643fd4 (backend) add lobby cache clearing method for meeting conclusion
Implement new lobby service method to clear all participant entries from cache.

Lays foundation for upcoming feature where participant permissions reset when
meetings end. Currently introduces only the cache clearing functionality;
event handling for meeting conclusion will be implemented in future commits
2025-03-07 17:05:06 +01:00
lebaudantoine
0aa4f6389b (backend) add trusted user access level for rooms
Introduce new intermediate access level between public and restricted that
allows authenticated users to join rooms without admin approval. Not making
this the default level yet as current 12hr sessions would create painful
user experience for accessing rooms. Will reconsider default settings after
improving session management.

This access level definition may evolve to become stricter in the future,
potentially limiting access to authenticated users who share the same
organization as the room admin.
2025-03-05 11:26:14 +01:00
lebaudantoine
4d961ed162 🚧(backend) introduce a lobby system
Implement lobby service using cache as LiveKit doesn't natively support
secure lobby functionality. Their teams recommended to create our own
system in our app's backend.

The lobby system is totally independant of the DRF session IDs,
making the request_entry endpoint authentication agnostic.

This decoupling prevents future DRF changes from breaking lobby functionality
and makes participant tracking more explicit.

Security audit is needed as current LiveKit tokens have excessive privileges
for unprivileged users. I'll offer more option ASAP for the admin to control
participant privileges.

Race condition handling also requires improvements, but should not be critical
at this point.

A great enhancement, would be to add a webhook, notifying the backend when the
room is closed, to reset cache.

This commit makes redis a prerequesite to run the suite of tests. The readme
and CI will be updated in dedicated commits.
2025-03-03 21:48:22 +01:00
lebaudantoine
7309df4115 ♻️(backend) add MarketingService protocol and Brevo implementation
Introduced a MarketingService protocol for typed marketing operations,
allowing easy integration of alternative services.

Implemented a Brevo wrapper following the protocol to decouple
the codebase from the sdk. These implementations are simple and pragmatic.
Feel free to refactor them.
2024-12-31 15:09:51 +01:00