Commit Graph

106 Commits

Author SHA1 Message Date
lebaudantoine f55fa0c42b 🐛(backend) fix info panel crash for unregistered rooms
The info panel was crashing when opening a room that was not
registered in the database (with ALLOW_UNREGISTERED_ROOMS=true),
because the API response did not include the room slug.

Instead of adding frontend fallbacks, update the unregistered-room
response to include the slug, keeping the API contract consistent
with registered rooms.

Note: this still relies on the unregistered-room response staying
aligned with the registered-room schema. Any future divergence
between the two responses could introduce similar issues.
A refactoring on the backend side is needed.

It closes #1441.
2026-07-10 19:45:56 +02:00
lebaudantoine 0d5136206f (all) allow forcing SSO display name for authenticated users
Add a new setting that controls whether an authenticated user can
rename or modify their display name, or if they must use the one
returned by the SSO.

When the setting is disabled, only anonymous users can set a display
name freely; authenticated users always use their SSO display name.

Requested by many self-hosters.
2026-07-10 19:02:26 +02:00
Florent Chehab 7fa172d100 (visio) use compatible with summary v2
This commit introduces the compatibility with summary v2.
It tecnically doesn't break the compatibility with v1 as
v1 params are still sent. But we advise people using the
transcribe feature in their own deployments to adapt to the
new v2 API, as this compatibility will be removed in a
future major version.

* RecordingStatusChoices now has
EXTERNAL_PROCESS_SUCCESSFUL
& EXTERNAL_PROCESS_FAILED
Values, which are changed by a new webhook that
can be called by the transcribe service.
This webhook is protected by its own bearer token.
* Title for the document is computed in visio,
* Tests are added / updated accordingly
2026-07-06 20:53:29 +02:00
lebaudantoine d2bfbee389 🩹(backend) fix client_id retrieval from request.auth
request.auth is a dict, not an object, so the getattr call was
failing when trying to retrieve client_id. Access it as a dict key
instead.
2026-07-02 17:01:46 +02:00
leo aee1847303 (backend) add LiveKit egress_ended fallback for saving recordings
Recording lifecycle previously relied exclusively on the MinIO storage-hook
endpoint to transition from STOPPED to SAVED, which made the system dependent
on MinIO bucket notifications and lifecycle configuration. Introduce support
for LiveKit egress_ended webhook (EGRESS_COMPLETE, EGRESS_LIMIT_REACHED) as
 an alternative finalization mechanism for self-hosted deployments that do
 not use MinIO / S3 hooks.

Change behavior of existing configuation RECORDING_STORAGE_EVENT_ENABLE.
When the LiveKit mechanism is enabled (RECORDING_STORAGE_EVENT_ENABLE=False),
RecordingEventsService.handle_complete is triggered from
LiveKitEventsService._handle_egress_ended.
2026-06-24 20:51:58 +02:00
Florent Chehab 5c15140783 (backend) add command to clean pending and deleted files
Since we have added custom backgrounds, they could be
soft deleted but were never really deleted.
This commits introduces a command to actually delete
this files.
In introduces also a command to purge pending upload
.
2026-06-18 18:07:43 +02:00
Florent Chehab c79984a883 🔒️(backend) prevent accessing files if they are not ready
With the addition of the ANALYSING state
files could be accessed in the short time they
were in that state.
We now require files to be in ready.

Also adds missing frontend types (no impact).
2026-06-04 17:03:42 +02:00
Florent Chehab 8d653b30e5 🧵(backend) improve robustness of the delete file process
* Make the call the delete celery task after the transaction
this makes sure the file object is in the right
state before being deleted.
2026-06-04 11:41:06 +02:00
Florent Chehab d13e3a8a5d ️(backend) change db state instead of using long running row lock
When analysing a file, the previous commit introduced a row level lock
to make sure we would analyse and promote a single file.
This commit changes the locking mechanism so that it happens with
the upload state which avoids long running db locks and potential
perf issues.
2026-06-03 13:45:32 +02:00
Florent Chehab a82d7f885a 🔒️(backend) prevnt file change post checks
Before this commit, post a file check, the policy could be
reused to change the verified file.
Now, files are uplaoded to a temporary location, then inside
a transaction that prevents concurrent calls, the file is
copied to its final destination and the checks are run on that one.
A new file can still be updated with the policy but it will never be read, etc.

As part of this change, all files in the new tmp directory
on s3 should have an expiration policy.
2026-06-03 13:45:31 +02:00
lebaudantoine 7390673bfc ️(frontend) backport phone number formatting to the backend
Use the Python port of Google's phone number library on the backend
instead of the JS one on the client. Saves 140Kb of unnecessary JS
and avoids a complex dynamic import that would have been required to
optimize loading.

The transformation is static: the phone number lives in the Django
settings, so the backend can format it once and pass the result to
the client. This avoids every client loading the 140Kb library and
re-computing the same information.

Moreover, within a single client, the transformation was previously
re-computed several times during a webapp lifecycle.
2026-05-30 23:39:05 +02:00
lebaudantoine 71f76a81e9 ♻️(backend) refactor caller identity getter
Enhance getting the caller's identity to prevent None.
2026-05-17 23:42:54 +02:00
lebaudantoine 385da86759 🔒️(backend) verify participant presence before mute operations
Ensure the participant requesting a mute action is still present
in the room before processing the request.

This mitigates scenarios where a previously issued token could be
reused after the meeting has ended.

Current token lifetime is intentionally long-lived and will be
refactored in the future to better align with LiveKit session
constraints. In the meantime, add this extra validation step to
reduce the attack surface.
2026-05-17 23:39:53 +02:00
lebaudantoine 32fbedd358 (backend) extend live synchronization to lobby access level updates
Extend the existing live synchronization mechanism beyond room
configuration to also include lobby access level changes.

This ensures that all owners and admins sharing a room maintain a
consistent and up-to-date view of room state in the frontend,
including configuration and access control updates.
2026-05-17 23:39:53 +02:00
lebaudantoine 534cf000b2 (backend) expose room configuration to all API consumers
Update room serialization to include room configuration for all
users fetching the API response, not only room owners.
This behavior was inherited from the original upstream project.

At the moment, exposing this configuration does not appear to
introduce meaningful security concerns or provide attackers with
additional capabilities.

The decision will continue to be reviewed from a security
perspective, but sharing the configuration improves frontend
consistency and synchronization.
2026-05-17 23:39:53 +02:00
lebaudantoine 5bac1668fe ♻️(fullstack) simplify source serialization
Simplify source serialization and validation logic while improving
type safety around room configuration handling.

Introduce a dedicated TypeScript type matching the backend
Pydantic model more precisely.

Also harmonize track source casing between frontend and backend to
remove redundant conversion logic and resolve #1282.
2026-05-17 23:39:53 +02:00
lebaudantoine 5a7a0da923 (backend) add synchronization mechanism for room configuration updates
Introduce synchronization of room configuration changes across
active participants.

When a room configuration is updated through a PUT operation, the
backend now performs an additional LiveKit API call to notify room
participants through a room metadata update event.

This ensures admins and owners quickly see up-to-date settings in
their administration panel. It also prepares the frontend for
automatic updates of unprivileged participants room’s data without
refetching it from the API.

An event-driven design was chosen instead of storing the full room
configuration in LiveKit metadata. While embedding the state
directly in metadata would provide immediate synchronization, it
would also require initializing and maintaining configuration
state during room creation or webhook handling, increasing the
risk of operational failures and regressions.

Instead, the backend emits lightweight synchronization events and
active clients update their React Query cache, which remains the
single source of truth for room configuration data.
2026-05-17 23:39:53 +02:00
lebaudantoine c20daafd81 (fullstack) support everyone_can_mute room configuration
Introduce a new room setting controlling whether all participants,
including non-privileged users, can mute others.

Update API validation accordingly and add the frontend controls
allowing administrators to toggle the option and persist the
configuration through the API.
2026-05-17 23:39:53 +02:00
lebaudantoine 288562cc0e 🛂(backend) allow participants to mute others based on room configuration
Enable any participant to mute others when the room configuration
allows it. This is enabled by default for all meetings unless
explicitly disabled by an administrator.

Privileged users retain the ability to mute any participant
regardless of the room configuration.
2026-05-17 23:39:53 +02:00
leo 1612d8b2d4 (audio) assign users to diarization speaker results using VAD
Introduce a new user assignment mechanism to for more friendly output
than the current (SPEAKER_0, SPEAKER_1, ...). Use the VAD metadata to
compare speech intervals with those returned by WhisperX. User with the
highest overlap score above a defined threshold is assigned to each segment.
This method allows for multi-speaker scenarios for a single account.
2026-05-07 12:45:00 +02:00
EpsilonFO a2bccf4f4f 🐛(backend) make start-recording atomic and fault-tolerant
Wrap Recording and RecordingAccess creation in a single transaction so a
partial failure does not leave orphan rows, and return 409 instead of 500
when a recording is already in progress for the room.

When the worker fails to start, transition the Recording to
FAILED_TO_START so the unique partial constraint on (room, status) no
longer blocks future recording attempts on the same room.
2026-05-04 22:15:14 +02:00
leo 0c0ce87947 🔒️(backend) validate Room configuration with Pydantic schema
Room.configuration accepted arbitrary JSON without validation, allowing unsafe
or malformed payloads to be stored and creating a security risk. Define a
Pydantic schema to enforce structure and constraints, and add validation
at the serializer level to reject invalid inputs.
2026-05-04 18:10:44 +02:00
lebaudantoine 012857f8c6 🔧(backend) add setting to toggle application token exchange mechanism
Introduce a configuration flag to enable or disable the
application token exchange (service account) mechanism.

This allows activating alternative authentication backends
without requiring full application token configuration.

Required to support the upcoming add-ons authentication backend.
2026-04-29 20:32:25 +02:00
lebaudantoine ecb710688d (backend) introduce add-ons authentication backend
Add a new authentication backend for add-ons, with a core service
managing session state in cache and exposing three API endpoints.

Microsoft Add-ins recommend launching authentication from the
side panel via a dialog, then returning the JWT to the parent
context using postMessage. However, due to Django and SSO security
constraints (window.opener not preserved), this approach is not
viable.

Implement a three-step authentication flow:

- `/init`: create a session, return a short-lived transit token
  and CSRF token. Store session ID in a secure HttpOnly cookie.
- `/poll`: allow the add-on to poll until authentication is
  complete, then consume the session and clear the cookie.
- `/exchange`: exchange the transit token for a JWT, which is
  later retrieved via the `/poll` endpoint.

The add-on opens an authentication dialog, stores the transit
token in sessionStorage, and performs the exchange after login.

This approach works within iframe constraints and provides a
sufficiently secure v0 despite known limitations.
2026-04-24 09:27:18 +02:00
lebaudantoine 3b474ba1c0 ♻️(backend) control metadata collector agent launch via feature flag
Allow controlling when the metadata collector agent is started,
enabling users to try the feature and disable it if needed.

Introduce a user-level feature flag to toggle the agent for the
initial release.
2026-04-17 12:17:27 +02:00
leo 8507cdd2b6 (backend) add metadata collection of VAD, connection and chat events
Introduce MetadataCollector and MetadataCollectorService classes to
centralize the collection and storage of user connections, VAD events,
and chat messages. This creates a structured foundation for future speaker
assignment logic based on voice activity detection. Add tests for this new
feature.
2026-04-17 12:17:27 +02:00
lebaudantoine 07af7a85ff 🥅(backend) refine Twirp error handling for participant operations
Avoid mapping all Twirp errors to generic 500 responses.

Explicitly handle the case where a participant is no longer in
the room, as this may indicate suspicious behavior or a client
state issue.

Improve error discrimination to provide more accurate responses.
2026-04-09 00:37:42 +02:00
lebaudantoine 6180ac4e4f 🔒️(backend) rely on backend to allow participant update their metadata
Introduce toggle-hand and rename endpoints in RoomViewSet,
secured with LiveKit token authentication.

Remove direct permission for clients to update their own metadata
via LiveKit tokens to prevent spoofing (e.g. faking admin status).

Proxy participant metadata updates through the backend to enforce
proper validation and authorization.

Signed-off-by: lebaudantoine <lebaud.antoine131@gmail.com>
2026-04-09 00:37:42 +02:00
lebaudantoine d5a614d2b5 🐛(backend) fix regression in update-participant endpoint
Serialization hardening introduced a breaking change between the
frontend and backend. Adjust the Pydantic model to restore
compatibility.

Reinstate support for can_subscribe_metric, which is passed by
default from the frontend.
2026-03-25 12:20:45 +01:00
lebaudantoine dcb788b57b 🔒️(backend) avoid information exposure through exception messages
Sanitize error handling to prevent leaking internal details when
invalid or malicious requests are sent to the API.

Return generic error responses to reduce the risk of information
disclosure during probing attempts.
2026-03-13 17:33:55 +01:00
lebaudantoine f3e90c3999 ♻️(backend) clarify storage hook message for intentionally ignored req
Update the response message to explicitly state that certain
notifications are ignored on purpose, avoiding confusion
during debugging or log inspection.
2026-03-13 15:42:30 +01:00
lebaudantoine cb4ed3c9d7 🩹(backend) ignore non-recording uploads in storage webhook handler
With the introduction of background file uploads, a misconfigured
MinIO webhook could trigger the storage hook endpoint for unrelated
files.

While the dev setup now filters events via the MinIO lifecycle
configuration, add a safeguard at the application level.

Enforce a stricter filepath regex when parsing storage hook events
and ignore files outside the recording output directory.

Return a clean 200 response to acknowledge the webhook while
avoiding unnecessary processing.
2026-03-13 15:34:02 +01:00
lebaudantoine 0ba445895c ♻️(backend) merge room name regex and centralize patterns in enums
Combine the regex used in Drive with the one from the recording
feature and centralize them in the enums module.

Although the module name suggests only enums, it also hosts
shared constants used across the codebase.
2026-03-13 15:34:02 +01:00
Florent Chehab 3b719ab9ba (settings) disable file upload by default & max count
Add FILE_UPLOAD_ENABLED setting (default to False, to avoid
a breaking change). Also adds a max_count_by_user sub setting
to restrict the number of uploaded files per user.
2026-03-12 14:55:33 +01:00
lebaudantoine f57db0acc8 ♻️(backend) refactor uploaded file's key format
Remove the user-provided filename while preserving the extension,
and switch to the format `uuid.extension`.

This is more natural than the previous `uuid/.extension` format
and avoids confusion.

Update related tests accordingly.
2026-03-12 10:39:59 +01:00
lebaudantoine 566eacc8fe (backend) add authenticated user rate throttling on request-entry
Throttle the request-entry endpoint for authenticated users also
to guard against accidental hammering from buggy clients.

Authenticated users are throttled via RequestEntryUserRateThrottle.
Anonymous users are throttled using the lobby participant cookie
through RequestEntryAnonRateThrottle.
2026-03-11 18:07:39 +01:00
lebaudantoine d19023a1ba 🐛(backend) refactor lobby throttling to use participant id instead of IP
use the lobby participant cookie ID as the throttle cache key
rather than the client IP address.

This avoids penalising multiple users behind the same NAT or proxy
and aligns throttling with how LobbyService identifies participants.

This bug was spotted in production where users from ministries behind
NAT was blocked by throttling while using visio.

If no cookie is present yet, skip throttling for the request. The
cookie will be set on the first response and throttling will apply
from subsequent requests.

This throttle is intended to protect against accidental hammering
from buggy clients, not as a security control against DoS attacks.

This is not a security measure, we should use a WAF.
2026-03-11 18:07:39 +01:00
lebaudantoine c3fd1a89ef 🩹(backend) add page_size to pagination for room endpoints
Align room endpoints with the pagination behavior used across
other API endpoints and resolve issue #1055.
2026-03-11 16:27:02 +01:00
Hadrien Blanc 6b08b8da1b 📝 Fix documentation and comment typos 2026-03-10 22:56:08 +01:00
Florent Chehab dc278a6064 (backend) add file upload feature & tests
For the coming features we will need to store files on the meet side.
(for instance user backgrounds).

This commits adds a new Model to manage files, and the associated
serializers & viewsets. All are tested.

This work was heavily inspired by the work done by our friends at
https://github.com/suitenumerique/drive
It build on the same architecture design (upload directly to S3 but
download goes through our proxy), but model is much much simplier
(no folders, no file sharing, etc.).
2026-03-06 11:31:39 +01:00
lebaudantoine 42647d6d25 🦺(backend) strengthen API validation for recording options
Improve validation of parameters accepted when starting a
recording to prevent unsupported or unexpected values.

Language validation will be further tightened to only accept
languages supported by the transcribe microservice.

Add extensive API validation tests to cover these scenarios.
2026-03-03 19:05:15 +01:00
lebaudantoine 720eb6a93e ♻️(backend) extract forbidden permission fields from the serializer
These fields previously triggered a suspicious operation exception
when passed to the API.

Make the list configurable so the serializer behavior can be
adjusted without requiring a new release.
2026-03-03 13:30:10 +01:00
lebaudantoine bfbf253033 🔒️(backend) enhance API input validation to strengthen security
During the bug bounty, attempts were made to pass unexpected hidden
fields to manipulate room behavior and join as a ghost.

Treat these parameters as suspicious. They are not sent by the
frontend, so their presence likely indicates tampering.

Explicitly allow the parameters but emit warning logs to help detect
and investigate suspicious activity.
2026-03-03 13:30:10 +01:00
lebaudantoine 6742f5d19d (backend) monitor throttling rate failure through sentry
Use a mixin, introduced by @lunika in the shared
backend library to monitor throttling behavior.

The mixin tracks when throttling limits are reached, sending errors to Sentry
to trigger alerts when configured. This helps detect misconfigurations,
fine-tune throttling settings, and identify suspicious operations.

This enables safely increasing API throttling limits while ensuring stability,
providing confidence that higher limits won’t break the system.
2026-02-09 15:50:53 +01:00
lebaudantoine 23de7e52bc ♻️(backend) extract throttling classes into a module
Extract throttling classes into a dedicated Python module, following the
structure of suitenumerique/docs.

This is a preparatory refactor to ease upcoming changes to the throttling
implementation. No functional behavior change is introduced in this commit.
2026-02-09 15:50:53 +01:00
lebaudantoine 587a5bc574 (frontend) allow starting both a recording and a transcription
Major user feature request: allow starting recording and transcription
simultaneously. Inspired by Google Meet UX, add a subtle checkbox letting users
start a recording alongside transcription.

The backend support for this feature is not yet implemented and will come in
upcoming commits, I can only pass the options to the API. The update of the
notification service will be handled later.
We’re half way with a functional feature.

This is not enabled by default because screen recording is resource-intensive. I
prefer users opt in rather than making it their default choice until feature
usage and performance stabilize.
2026-01-04 20:22:15 +01:00
lebaudantoine b0e27b38e2 🔒️(backend) avoid serializing rooms's pin code when restricted
Prevent anonymous users waiting in the lobby, or attacker
to discover the room pin code, that would allow them to join a room.
2025-12-17 10:05:23 +01:00
lebaudantoine 8044e3d6d8 ♻️(backend) replace Django permissions with feature flag decorator
Refactor feature flag mechanism from Django permission classes to custom
decorator that returns 404 Not Found when features are disabled instead
of exposing API structure through permission errors.

Improves security by preventing information disclosure about disabled
features and provides more appropriate response semantics. Custom
decorator approach is better suited for feature toggling than Django's
permission system which is designed for authorization.
2025-09-08 17:17:45 +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