Commit Graph

308 Commits

Author SHA1 Message Date
lebaudantoine 80f3af0690 (backend) add roomkit viewset to start a room without WebRTC join
Introduce a new viewset that lets the roomkit start a room even when
no WebRTC participant has joined yet.

This is a first entry point that will be extended over time with
more actions a roomkit needs to be able to trigger.

Known limitations:

* The responsibility around SIP rules is currently split between
  the telephony feature and the roomkit one. This may need a
  refactor later on to consolidate ownership in a single place.
* The default throttle might be too low for production usage and
  will likely need to be revisited.
2026-07-30 21:18:49 +02:00
lebaudantoine 8c6752a29f 🐛(backend) allow any string as sub in the API serializer
The API serializer was too restrictive on the `sub` field, expecting
a UUID. This worked in our development and production setups because
our Keycloak is configured to emit UUID subs, but it broke for other
providers.

Per the OIDC spec and the DB model, `sub` can be any string. Align
the serializer with this and accept arbitrary string values.

Fixes #1525.
2026-07-29 00:00:35 +02:00
lebaudantoine 7f386b2e2f ♻️(frontend) derive is_administrable from participant metadata
The is_administrable flag was previously read from the room API
response through the room serializer, giving the frontend static
information about the user's rights.

Refactor the frontend so it derives this flag from the participant
role carried in the participant metadata instead.

Two benefits:

* The flag now updates live along with the participant
  attributes/metadata, so role changes are reflected immediately.
* It removes the duplication between the API response and the
  metadata, which both used to determine the user's capabilities.
2026-07-29 00:00:35 +02:00
lebaudantoine c7b23abd68 (backend) expose is_authenticated in the LiveKit token
Include the is_authenticated flag on the user in the LiveKit token
and participant metadata.

The frontend needs this information (used in the next commit) to
know whether it can offer to promote a user with access to the room
admin.
2026-07-29 00:00:35 +02:00
lebaudantoine 5a641a4366 ♻️(backend) pass the participant role in the LiveKit token
The backend previously passed an abstract is_admin_or_owner boolean
flag in the LiveKit token. That kept the frontend minimalistic and
saved it from having to handle role comparisons.

As we introduce more features that need to distinguish between the
room owner and admins, refactor the token to carry the role
directly. The frontend can then derive the relevant flags from a
richer piece of information.
2026-07-29 00:00:35 +02:00
lebaudantoine f043ad6f98 (backend) add endpoint to update a participant role during a meeting
Add an endpoint that allows updating a user's role while in a
meeting. The goal is to let users promote other connected
participants to admin or moderator, so the burden of administrating
a meeting can be shared.
2026-07-29 00:00:35 +02:00
lebaudantoine 1141c1cecd ️(backend) add permission class checking the user is in the call
Introduce a new permission class that verifies the caller making a
request is both authenticated and actually present in the call.

It will be used to gate actions that require the user to be live in
the room, for example:

* allowing someone in from the waiting room
* promoting another participant to a different role

More generally, this covers every action where, for security
reasons, we need to make sure the user is truly present in the call
and that someone is not reusing their cookie as an API key.
2026-07-29 00:00:35 +02:00
leo f4569c64e5 🐛(backend) preserve recording metadata when updating room access
Updating room access rewrote the entire metadata payload, removing information
about active recordings. This caused the frontend to lose track of ongoing
recordings and could trigger 409 errors when attempting to start a new
recording.

Consolidate the duplicated metadata update logic into
`RoomManagement.update_metadata()` and preserve merge behavior instead of
overwriting the full metadata object.
2026-07-28 10:54:03 +02:00
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
lebaudantoine 05a67320b1 🩹(backend) fix the LiveKit token to use full name as display name
Use the user's full name as the display name in the emitted LiveKit
token instead of the email.

Requested by several self-hosters.
2026-07-10 19:02:26 +02:00
lebaudantoine 10231b0333 🩹(backend) identify externally provisioned users to PostHog
In the external API, applications authenticate with a
client_id/secret and can provision users with only an email. In that
flow, users are not identified to PostHog, so the user DB id alone
is not enough to identify them in analytics afterwards.

The issue does not exist in the public API, where users are
authenticated and therefore already identified.

Inspired by @flochehab's approach in summary.
2026-07-10 10:47:04 +02:00
lebaudantoine 0c81d29ee7 (backend) allow searching the recording admin table by owner email
Add the owner's email to the searchable fields of the recording
admin table. This makes it much more convenient for the support team
to look up recordings by user.
2026-07-10 10:15:57 +02:00
Florent Chehab 224d6ce358 (backend) use feature flag in call to summary-v2
Summary enabled is now infered directly from
the feature flag analytics backend.
2026-07-07 12:09:19 +02:00
Florent Chehab 20718f2d5a (backend) implement feature flags in Posthog analytics backend
Implement feature flags related functions in
Posthog analytics backend.
We cache the results in django cache to avoid
too frequent calls to Posthog.
Especially for when we are checking multiple features in
the same user request.
2026-07-07 12:09:19 +02:00
Florent Chehab 8edcb6e973 (backend) extend analytics module to support feature flags
Extend the AnalyticsBackend class to support
user feature flags, without a breaking change to the
current implementation.

A flag value is considered to be a bool or a string.
2026-07-07 12:09:19 +02:00
lebaudantoine b00c4e5d6d ♻️(backend) refactor analytics backend from Protocol to abstract class
Switch the analytics backend interface from a typing Protocol to an
abstract base class, so the contract that backends must implement
is explicit and enforced at instantiation time.
2026-07-07 11:51:11 +02:00
Florent Chehab 3c0ba03976 ♻️(backend) refactor Bearer Auth based authentification
Created a shared class for handling Header based authentification.
This avoid duplicating logic and helps with a maintaining a signle
security related peace of code.
2026-07-06 20:53:29 +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 a98dc1484a 🩹(backend) fix case-insensitive email deduplication in merge command
The management command that merges users with duplicate emails was
comparing emails in a case-insensitive manner, which left some
duplicates in the database when their emails only differed by case.
2026-07-06 16:03:50 +02:00
lebaudantoine 657712d7cb (backend) track meeting link generation events
Track events whenever a new meeting link is generated, both through
the public API and through the external API.

The goal is twofold:

* Identify where the most links are generated from, so we can assess
  which integration or entry point works best.
* Measure how many links are generated per user, so we can consider
  a user truly active when they generate a link, rather than only
  when they participate in a meeting.
2026-07-02 17:01:46 +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
lebaudantoine 9ba97fd14f (backend) introduce a configurable analytics system
Add an analytics abstraction that allows configuring which analytics
solution the app uses. PostHog is implemented as one backend, but by
default no analytics backend is activated.

The goal is to track events in a sufficiently organized way and to
let any developer implement their own backend as long as it follows
the same protocol.
2026-07-02 17:01:46 +02:00
ilias 27dce44d40 (backend) cover encoded S3 keys with plus signs
Add a regression test for already encoded S3 notification keys that contain plus signs in the prefix.
2026-07-02 12:23:31 +02:00
ilias 78acaf395e 🐛(backend) normalize raw S3 object keys
Correction to preserve already encoded plus signs in addition to slashes.
2026-07-02 12:23:31 +02:00
ilias 4e5e648730 (backend) add parser test docstrings
Add docstrings to the S3 parser tests
2026-07-02 12:23:31 +02:00
ilias e3e33c7d0a 🐛(backend) normalize S3 notification object keys 2026-07-02 12:23:31 +02:00
lebaudantoine e42b083f20 🛂(backend) reject user access tokens on the API
The original implementation, introduced two years ago, was incorrect
and exposed the API to an undesired authentication mode: any user
access token obtained for a given user was being accepted as valid
credentials on the external API.

Restrict authentication to the intended mode so that user access
tokens are no longer accepted on this API.

Thanks @lunika spotting this.
2026-07-01 11:24:59 +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
leo be35c1d6e0 ⬆️(dependencies) update python dependencies
Update python dependencies.

Co-Authored-By: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-04 15:34:39 +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 5602d256d8 (backend) add file specific admin
Adds a file (background image) specific django admin.
Files can be previewed, and deletion is properly managed.
2026-06-04 11:41:05 +02:00
Florent Chehab 6c25d0a525 🐛(backend) update alter file state migration predecessor
Last PR was merged a bit too quicly and another migration
was added before the PR one.
2026-06-03 14:18:58 +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 85eff8afaf 🧑‍💻(backend) add email filter to target subset of users for merge cmd
Add an email substring filter to the user merge management command,
allowing selection of a subset of users concerned by the merge process.

This enables safer incremental execution of the command by testing it
on a controlled group of users before applying it globally.

The goal is to validate behavior and ensure the merge process does not
introduce unexpected side effects or inconsistencies at scale.
2026-06-02 21:55:46 +02:00
lebaudantoine 29b0a6fcb4 🧑‍💻(backend) add management command to merge duplicate users
Add a management command to merge duplicate users and reassign all
granted resources to the most recent user account in the database.

Support a dry-run mode to estimate the impact of the operation before
applying any changes. This helps validate the command and identify
potential issues in environments where realistic testing is difficult.

Add unit tests to verify the command behavior and ensure database
integrity is preserved during the merge process.
2026-06-02 21:55:46 +02:00
lebaudantoine 3554b2eb53 ♻️(backend) defend user provisioning against race condition
Move user provisioning logic out of the external token viewset into a
dedicated service to keep the viewset lightweight and easier to
maintain.

While extracting the logic, refactor user object handling to improve
robustness and make the provisioning workflow easier to reason about.

Defend against race conditions when concurrent requests attempt to
provision the same user. Rely on the existing database constraints to
guarantee uniqueness and gracefully handle integrity errors raised by
concurrent creations.
2026-06-02 20:13:16 +02:00
lebaudantoine e25aa6ce05 (backend) add test coverage for blank sub behavior
Update the test to document the actual contract without modifying the
underlying model behavior.

These tests act as non-regression coverage and explicitly assert that
users may have a null sub or email. They are intended to document the
current behavior of the initial user model rather than evolve or
constrain it.

Ghost rows have not been reported as an operational issue. For the sake
of simplicity, avoid changing the model unless required by a concrete
issue or unless the benefits clearly outweigh the added complexity.
2026-06-02 20:13:16 +02:00
lebaudantoine a8b79740e9 🐛(backend) prevent duplicate pending users on concurrent requests
Fix a race condition in the external viewset where concurrent requests
could create multiple pending users with the same email address.

No database constraint enforced email uniqueness for pending users,
allowing duplicates to be created under load.

This caused issues during user reconciliation, which expects a single
matching pending user and raises a warning when multiple records are
found.

Add a narrowly scoped migration to enforce the uniqueness constraint
and address the identified issue.
2026-06-02 20:13:16 +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 4d27f217fc ♻️(backend) prefix Swagger routes with /api
Inspired by commit eb23aef in suitenumerique/docs. The same base
route path is used everywhere, which helps when the backend sits
behind an ingress serving it with a regex like `api/*`.
2026-05-30 19:33:48 +02:00
Rahulchourasiya 5ea5460b17 🩹(backend) fix swagger and redoc documentation urls
Use canonical documentation routes and add a regression test.
2026-05-30 19:33:48 +02:00
rahul f490b095d8 (backend) support config and access level in external API room creation
Allow passing configuration and access level when creating a room
through the external API.

Also add a few guardrails:
* control whether public rooms are accepted on the external API
* set the default access level when creating a new room

Ensure the new room configuration and access level are returned by
the serializer when listing rooms.
2026-05-29 20:15:59 +02:00
ilias 04dfb9922f (backend) add core.recording.event.parsers.S3Parser
Implementation was validated against Ceph Object Store by @agasurfer.
Event payload matches the one from AWS S3 docs.
2026-05-28 19:54:23 +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