mirror of
https://github.com/suitenumerique/meet.git
synced 2026-09-30 22:48:35 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 22adccb353 | |||
| 3ab651d6c7 | |||
| 919af928aa | |||
| 3ed38f1c48 | |||
| f172c5795e | |||
| 262b168414 | |||
| 6c371c8cb3 | |||
| 1a8906c0a1 | |||
| 99ba8e330e | |||
| 059e5f1ec4 | |||
| 39ab9359e4 | |||
| d0a0d60ece | |||
| 27bd136741 | |||
| ad2ca6b4ef |
@@ -0,0 +1,9 @@
|
||||
[codespell]
|
||||
# Files that are not English, or generated
|
||||
skip = ./.git,*.pdf,*.po,*.pot,*.json,*.lock,package-lock.json,
|
||||
./LICENSES,
|
||||
./src/summary/summary/core/locales,
|
||||
./src/summary/summary/core/prompt.py
|
||||
# Valid words in French (connexion) or in the code (statics)
|
||||
ignore-words-list = connexion,statics
|
||||
check-filenames = true
|
||||
@@ -0,0 +1,20 @@
|
||||
# Debian 13 base image (python:3.14-slim): no fixed version available yet.
|
||||
# Review regularly and remove entries once Debian ships a fix.
|
||||
|
||||
# util-linux
|
||||
CVE-2026-76642
|
||||
CVE-2026-78408
|
||||
CVE-2026-78409
|
||||
CVE-2026-78410
|
||||
|
||||
# acl
|
||||
CVE-2026-54369
|
||||
|
||||
# ncurses
|
||||
CVE-2025-69720
|
||||
|
||||
# systemd
|
||||
CVE-2026-16742
|
||||
|
||||
# perl-base (fix deferred by Debian)
|
||||
CVE-2026-9538
|
||||
@@ -0,0 +1,19 @@
|
||||
name: Changelog Workflow
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled, unlabeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
changelog:
|
||||
uses: suitenumerique/ci/.github/workflows/_changelog.yml@ca6401ac83e981e5b0a94f06f68baaa6e6d0a436 # v0.0.1
|
||||
+22
-176
@@ -11,180 +11,30 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint-git:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request' # Makes sense only for pull requests
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: show
|
||||
run: git log
|
||||
- name: Enforce absence of print statements in code
|
||||
if: always()
|
||||
run: |
|
||||
! git diff origin/${{ github.event.pull_request.base.ref }}..HEAD -- . ':(exclude).github/workflows/**' | grep "print("
|
||||
- name: Check absence of fixup commits
|
||||
if: always()
|
||||
run: |
|
||||
! git log | grep 'fixup!'
|
||||
- name: Install uv
|
||||
if: always()
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
|
||||
- name: Lint commit messages added to main
|
||||
if: always()
|
||||
run: uvx --no-build --from gitlint-core==0.19.1 gitlint --commits origin/${{ github.event.pull_request.base.ref }}..HEAD
|
||||
|
||||
check-changelog:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
contains(github.event.pull_request.labels.*.name, 'noChangeLog') == false &&
|
||||
github.event_name == 'pull_request'
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
with:
|
||||
fetch-depth: 50
|
||||
- name: Check that the CHANGELOG has been modified in the current branch
|
||||
run: git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.after }} | grep 'CHANGELOG.md'
|
||||
|
||||
lint-changelog:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
- name: Check CHANGELOG max line length
|
||||
run: |
|
||||
max_line_length=$(cat CHANGELOG.md | grep -Ev "^\[.*\]: https://github.com" | wc -L)
|
||||
if [ $max_line_length -ge 80 ]; then
|
||||
echo "ERROR: CHANGELOG has lines longer than 80 characters."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
build-mails:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
working-directory: src/mail
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0
|
||||
with:
|
||||
node-version: "22"
|
||||
|
||||
- name: Restore the mail templates
|
||||
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0
|
||||
id: mail-templates
|
||||
with:
|
||||
path: "src/backend/core/templates/mail"
|
||||
key: mail-templates-${{ hashFiles('src/mail/mjml') }}
|
||||
|
||||
- name: Install yarn
|
||||
if: steps.mail-templates.outputs.cache-hit != 'true'
|
||||
run: npm install -g --ignore-scripts yarn@1.22.22
|
||||
|
||||
- name: Install node dependencies
|
||||
if: steps.mail-templates.outputs.cache-hit != 'true'
|
||||
run: yarn install --frozen-lockfile --ignore-scripts
|
||||
|
||||
- name: Build mails
|
||||
if: steps.mail-templates.outputs.cache-hit != 'true'
|
||||
run: yarn build
|
||||
|
||||
- name: Cache mail templates
|
||||
if: steps.mail-templates.outputs.cache-hit != 'true'
|
||||
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0
|
||||
with:
|
||||
path: "src/backend/core/templates/mail"
|
||||
key: mail-templates-${{ hashFiles('src/mail/mjml') }}
|
||||
|
||||
lint-back:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
working-directory: src/backend
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.13"
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
|
||||
- name: Install the project
|
||||
run: uv sync --locked --all-extras
|
||||
|
||||
- name: Check code formatting with ruff
|
||||
run: uv run --no-sync --no-build ruff format . --diff
|
||||
- name: Lint code with ruff
|
||||
run: uv run --no-sync --no-build ruff check .
|
||||
- name: Lint code with pylint
|
||||
run: uv run --no-sync --no-build pylint meet demo core
|
||||
|
||||
lint-agents:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
working-directory: src/agents
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.13"
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
|
||||
- name: Install the project
|
||||
run: uv sync --locked --all-extras --no-build
|
||||
- name: Check code formatting with ruff
|
||||
run: uv run --no-sync --no-build ruff format . --diff
|
||||
- name: Lint code with ruff
|
||||
run: uv run --no-sync --no-build ruff check .
|
||||
|
||||
lint-summary:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
working-directory: src/summary
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.13"
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
|
||||
- name: Install the project
|
||||
run: uv sync --locked --all-extras
|
||||
- name: Check code formatting with ruff
|
||||
run: uv run --no-sync --no-build ruff format . --diff
|
||||
- name: Lint code with ruff
|
||||
run: uv run --no-sync --no-build ruff check .
|
||||
lint-python:
|
||||
name: lint ${{ matrix.service }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- service: backend
|
||||
working_directory: src/backend
|
||||
pylint_targets: meet demo core
|
||||
- service: agents
|
||||
working_directory: src/agents
|
||||
pylint_targets: ""
|
||||
- service: summary
|
||||
working_directory: src/summary
|
||||
pylint_targets: ""
|
||||
uses: suitenumerique/ci/.github/workflows/_python-lint.yml@ca6401ac83e981e5b0a94f06f68baaa6e6d0a436 # v0.0.1
|
||||
with:
|
||||
working_directory: ${{ matrix.working_directory }}
|
||||
python_version: "3.13"
|
||||
pylint_targets: ${{ matrix.pylint_targets }}
|
||||
|
||||
test-back:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-mails
|
||||
permissions:
|
||||
contents: read
|
||||
defaults:
|
||||
@@ -244,12 +94,8 @@ jobs:
|
||||
sudo mkdir -p /data/media && \
|
||||
sudo mkdir -p /data/static
|
||||
|
||||
- name: Restore the mail templates
|
||||
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0
|
||||
id: mail-templates
|
||||
with:
|
||||
path: "src/backend/core/templates/mail"
|
||||
key: mail-templates-${{ hashFiles('src/mail/mjml') }}
|
||||
- name: Build or restore the mail templates
|
||||
uses: suitenumerique/ci/actions/mail-templates@ca6401ac83e981e5b0a94f06f68baaa6e6d0a436 # v0.0.1
|
||||
|
||||
# Creates the access key and the bucket on startup
|
||||
- name: Start Garage
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
name: Project quality Workflow
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
quality:
|
||||
uses: suitenumerique/ci/.github/workflows/_project-quality.yml@ca6401ac83e981e5b0a94f06f68baaa6e6d0a436 # v0.0.1
|
||||
with:
|
||||
print_check_paths: src/backend src/summary src/agents
|
||||
codespell_ignore_words: "unsecure"
|
||||
@@ -1,33 +0,0 @@
|
||||
name: Download Crowdin translations
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
types: [file-fully-translated]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
crowdin:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
|
||||
- name: Download Crowdin files
|
||||
uses: crowdin/github-action@c7af9bc98b01694653031fef2a0dc6c7888ce9bc # v2.17.0
|
||||
with:
|
||||
upload_sources: false
|
||||
upload_translations: false
|
||||
download_translations: true
|
||||
localization_branch_name: l10n_crowdin_translations
|
||||
create_pull_request: true
|
||||
pull_request_title: "New Crowdin translations"
|
||||
pull_request_body: "New Crowdin pull request with translations"
|
||||
pull_request_base_branch_name: "main"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
CROWDIN_BASE_PATH: ${{ github.workspace }}
|
||||
@@ -1,5 +1,5 @@
|
||||
name: Docker Hub Workflow
|
||||
run-name: Docker Hub Workflow
|
||||
name: Docker images
|
||||
run-name: Docker images
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -15,265 +15,62 @@ on:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
DOCKER_USER: 1001:127
|
||||
DOCKER_CONTAINER_REGISTRY_HOSTNAME: docker.io
|
||||
DOCKER_CONTAINER_REGISTRY_NAMESPACE: lasuite
|
||||
IS_MULTI_PLATFORM_BUILD: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
BUILD_PLATFORMS: ${{ startsWith(github.ref, 'refs/tags/v') && 'linux/amd64,linux/arm64' || 'linux/amd64' }}
|
||||
|
||||
jobs:
|
||||
build-and-push-backend:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
-
|
||||
name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
-
|
||||
name: Set up QEMU
|
||||
if: env.IS_MULTI_PLATFORM_BUILD == 'true'
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||
-
|
||||
name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
|
||||
with:
|
||||
images: '${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-backend'
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request' || startsWith(github.head_ref, 'integration/')
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USER }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
-
|
||||
name: Run trivy scan
|
||||
uses: numerique-gouv/action-trivy-cache@d6e94cfb488f03a0b3e8b8739aad94e74d24d8da # main
|
||||
with:
|
||||
docker-build-args: '--target backend-production -f Dockerfile'
|
||||
docker-image-name: '${{ env.DOCKER_CONTAINER_REGISTRY_HOSTNAME }}/${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-backend:${{ github.sha }}'
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||
with:
|
||||
context: .
|
||||
target: backend-production
|
||||
platforms: ${{ env.BUILD_PLATFORMS }}
|
||||
build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
|
||||
push: ${{ github.event_name != 'pull_request' || startsWith(github.head_ref, 'integration/') }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
build-and-push-frontend-generic:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
-
|
||||
name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
-
|
||||
name: Set up QEMU
|
||||
if: env.IS_MULTI_PLATFORM_BUILD == 'true'
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||
-
|
||||
name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
|
||||
with:
|
||||
images: '${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-frontend'
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request' || startsWith(github.head_ref, 'integration/')
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USER }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
-
|
||||
name: Run trivy scan
|
||||
uses: numerique-gouv/action-trivy-cache@d6e94cfb488f03a0b3e8b8739aad94e74d24d8da # main
|
||||
with:
|
||||
docker-build-args: '-f src/frontend/Dockerfile --target frontend-production'
|
||||
docker-image-name: '${{ env.DOCKER_CONTAINER_REGISTRY_HOSTNAME }}/${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-frontend:${{ github.sha }}'
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||
with:
|
||||
context: .
|
||||
file: ./src/frontend/Dockerfile
|
||||
target: frontend-production
|
||||
platforms: ${{ env.BUILD_PLATFORMS }}
|
||||
build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
|
||||
push: ${{ github.event_name != 'pull_request' || startsWith(github.head_ref, 'integration/') }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
build-and-push-frontend-dinum:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
-
|
||||
name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
-
|
||||
name: Set up QEMU
|
||||
if: env.IS_MULTI_PLATFORM_BUILD == 'true'
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||
-
|
||||
name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
|
||||
with:
|
||||
images: '${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-frontend-dinum'
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request' || startsWith(github.head_ref, 'integration/')
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USER }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
-
|
||||
name: Run trivy scan
|
||||
uses: numerique-gouv/action-trivy-cache@d6e94cfb488f03a0b3e8b8739aad94e74d24d8da # main
|
||||
with:
|
||||
docker-build-args: '-f docker/dinum-frontend/Dockerfile --target frontend-production'
|
||||
docker-image-name: '${{ env.DOCKER_CONTAINER_REGISTRY_HOSTNAME }}/${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-frontend-dinum:${{ github.sha }}'
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||
with:
|
||||
context: .
|
||||
file: ./docker/dinum-frontend/Dockerfile
|
||||
target: frontend-production
|
||||
platforms: ${{ env.BUILD_PLATFORMS }}
|
||||
build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
|
||||
push: ${{ github.event_name != 'pull_request' || startsWith(github.head_ref, 'integration/') }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
build-and-push-summary:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
-
|
||||
name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
-
|
||||
name: Set up QEMU
|
||||
if: env.IS_MULTI_PLATFORM_BUILD == 'true'
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||
-
|
||||
name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
|
||||
with:
|
||||
images: '${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-summary'
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request' || startsWith(github.head_ref, 'integration/')
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USER }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
-
|
||||
name: Run trivy scan
|
||||
uses: numerique-gouv/action-trivy-cache@d6e94cfb488f03a0b3e8b8739aad94e74d24d8da # main
|
||||
continue-on-error: true
|
||||
with:
|
||||
docker-build-args: '-f src/summary/Dockerfile --target production'
|
||||
docker-image-name: '${{ env.DOCKER_CONTAINER_REGISTRY_HOSTNAME }}/${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-summary:${{ github.sha }}'
|
||||
docker-context: './src/summary'
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||
with:
|
||||
context: ./src/summary
|
||||
file: ./src/summary/Dockerfile
|
||||
target: production
|
||||
platforms: ${{ env.BUILD_PLATFORMS }}
|
||||
build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
|
||||
push: ${{ github.event_name != 'pull_request' || startsWith(github.head_ref, 'integration/') }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
build-and-push-agents:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
-
|
||||
name: Checkout repository
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
-
|
||||
name: Set up QEMU
|
||||
if: env.IS_MULTI_PLATFORM_BUILD == 'true'
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||
-
|
||||
name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
|
||||
with:
|
||||
images: lasuite/meet-agents
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request' || startsWith(github.head_ref, 'integration/')
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USER }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
-
|
||||
name: Run trivy scan
|
||||
uses: numerique-gouv/action-trivy-cache@d6e94cfb488f03a0b3e8b8739aad94e74d24d8da # main
|
||||
continue-on-error: true
|
||||
with:
|
||||
docker-build-args: '-f src/agents/Dockerfile --target production'
|
||||
docker-image-name: '${{ env.DOCKER_CONTAINER_REGISTRY_HOSTNAME }}/${{ env.DOCKER_CONTAINER_REGISTRY_NAMESPACE }}/meet-agents:${{ github.sha }}'
|
||||
docker-context: './src/agents'
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||
with:
|
||||
context: ./src/agents
|
||||
file: ./src/agents/Dockerfile
|
||||
target: production
|
||||
platforms: ${{ env.BUILD_PLATFORMS }}
|
||||
build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
|
||||
push: ${{ github.event_name != 'pull_request' || startsWith(github.head_ref, 'integration/') }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-and-push:
|
||||
name: ${{ matrix.service }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- service: backend
|
||||
image_name: lasuite/meet-backend
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
target: backend-production
|
||||
- service: frontend
|
||||
image_name: lasuite/meet-frontend
|
||||
context: .
|
||||
file: ./src/frontend/Dockerfile
|
||||
target: frontend-production
|
||||
- service: frontend-dinum
|
||||
image_name: lasuite/meet-frontend-dinum
|
||||
context: .
|
||||
file: ./docker/dinum-frontend/Dockerfile
|
||||
target: frontend-production
|
||||
- service: summary
|
||||
image_name: lasuite/meet-summary
|
||||
context: ./src/summary
|
||||
file: ./src/summary/Dockerfile
|
||||
target: production
|
||||
- service: agents
|
||||
image_name: lasuite/meet-agents
|
||||
context: ./src/agents
|
||||
file: ./src/agents/Dockerfile
|
||||
target: production
|
||||
uses: suitenumerique/ci/.github/workflows/_docker-publish.yml@ca6401ac83e981e5b0a94f06f68baaa6e6d0a436 # v0.0.1
|
||||
with:
|
||||
image_name: ${{ matrix.image_name }}
|
||||
context: ${{ matrix.context }}
|
||||
file: ${{ matrix.file }}
|
||||
target: ${{ matrix.target }}
|
||||
docker_user: "1001:127"
|
||||
is_multi_platform: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
should_push: ${{ github.event_name != 'pull_request' || startsWith(github.head_ref, 'integration/') }}
|
||||
trivy_scan: true
|
||||
trivy_ignore_files: ./.github/.trivyignore
|
||||
secrets:
|
||||
DOCKER_HUB_USER: ${{ secrets.DOCKER_HUB_USER }}
|
||||
DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
|
||||
notify-argocd:
|
||||
permissions:
|
||||
contents: read
|
||||
needs:
|
||||
- build-and-push-frontend-generic
|
||||
- build-and-push-frontend-dinum
|
||||
- build-and-push-backend
|
||||
- build-and-push-summary
|
||||
- build-and-push-agents
|
||||
- build-and-push
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'pull_request'
|
||||
steps:
|
||||
- uses: numerique-gouv/action-argocd-webhook-notification@cac2ee67896eb13e84e804f60c4271370424eaa8 # main
|
||||
- uses: suitenumerique/ci/actions/argocd-webhook-notification@ca6401ac83e981e5b0a94f06f68baaa6e6d0a436 # v0.0.1
|
||||
id: notify
|
||||
with:
|
||||
deployment_repo_path: "${{ secrets.DEPLOYMENT_REPO_URL }}"
|
||||
|
||||
@@ -1,33 +1,17 @@
|
||||
name: Release Chart
|
||||
run-name: Release Chart
|
||||
name: Release Helm chart
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- src/helm/meet/**
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
release:
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cleanup
|
||||
run: rm -rf ./src/helm/extra
|
||||
|
||||
- name: Install Helm
|
||||
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
- name: Publish Helm charts
|
||||
uses: numerique-gouv/helm-gh-pages@2cf477ae49d7c70037ceb1685803f4f7bad9b981 # add-overwrite-option
|
||||
with:
|
||||
charts_dir: ./src/helm
|
||||
linting: on
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
uses: suitenumerique/ci/.github/workflows/_release-helm-chart.yml@ca6401ac83e981e5b0a94f06f68baaa6e6d0a436 # v0.0.1
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
name: Security analysis
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- "**"
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
zizmor:
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
security-events: write
|
||||
uses: suitenumerique/ci/.github/workflows/_zizmor.yml@ca6401ac83e981e5b0a94f06f68baaa6e6d0a436 # v0.0.1
|
||||
with:
|
||||
config: .github/zizmor.yml
|
||||
@@ -0,0 +1,5 @@
|
||||
rules:
|
||||
unpinned-uses:
|
||||
config:
|
||||
policies:
|
||||
"suitenumerique/*": ref-pin
|
||||
+22
-6
@@ -8,14 +8,35 @@ and this project adheres to
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- 🔒(backend) throttle meeting link generation
|
||||
- 🔒️(backend) add a daily cap on room creation
|
||||
|
||||
### Fixed
|
||||
|
||||
- 🐛(frontend) enforce recording-mode permissions on the checkboxes
|
||||
- 🔒️(agents) fix util-linux CVEs reported by Cyberwatch
|
||||
|
||||
## [1.33.0] - 2026-09-30
|
||||
|
||||
### Added
|
||||
|
||||
- ✨(backend) purge rooms inactive for a configurable period
|
||||
- 🔨(makefile) add targets to list and download files stored in Garage
|
||||
|
||||
### Changed
|
||||
|
||||
- ⬆️(backend) update python dependencies
|
||||
- ⬆️(summary) update python dependencies
|
||||
- ⬆️(agents) update python dependencies
|
||||
- ♻️(agents) replace the minio client by boto3
|
||||
- 🔧(compose) replace MinIO by Garage for local development
|
||||
- 🔧(helm) point media services to Garage by default
|
||||
|
||||
### Fixed
|
||||
|
||||
- 🔒️(backend) fix critical and high CVEs in PyJWT
|
||||
- ⚡️(frontend) disable posthog-js periodic feature flag reloads
|
||||
|
||||
## [1.32.1] - 2026-09-25
|
||||
@@ -30,10 +51,8 @@ and this project adheres to
|
||||
### Added
|
||||
|
||||
- ✨(backend) make the LiveKit default video codec configurable
|
||||
- ✨(backend) purge rooms inactive for a configurable period
|
||||
- 🔧(dev) add support for Bureautix workstations
|
||||
- ✨(frontend) add screen share zoom controls #1498
|
||||
- 🔨(makefile) add targets to list and download files stored in Garage
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -52,9 +71,6 @@ and this project adheres to
|
||||
- ⬆️(addons) upgrade i18next from 26.4.0 to 26.4.2
|
||||
- 🔖(helm) release chart 0.0.28
|
||||
- ♻️(backend) decouple recording event handling from LiveKit egress statuses
|
||||
- ♻️(agents) replace the minio client by boto3
|
||||
- 🔧(compose) replace MinIO by Garage for local development
|
||||
- 🔧(helm) point media services to Garage by default
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -389,7 +405,7 @@ and this project adheres to
|
||||
|
||||
### Fixed
|
||||
|
||||
- ♿️(frontend) improve accessibilty of the Effects panel #1401
|
||||
- ♿️(frontend) improve accessibility of the Effects panel #1401
|
||||
|
||||
## [1.20.0] - 2026-06-12
|
||||
|
||||
|
||||
+8
-8
@@ -55,12 +55,12 @@ function _docker_compose() {
|
||||
function _dc_run() {
|
||||
_set_user
|
||||
|
||||
user_args="--user=$USER_ID"
|
||||
if [ -z $USER_ID ]; then
|
||||
user_args=""
|
||||
user_args=()
|
||||
if [ -n "$USER_ID" ]; then
|
||||
user_args=("--user=$USER_ID")
|
||||
fi
|
||||
|
||||
_docker_compose run --rm $user_args "$@"
|
||||
_docker_compose run --rm "${user_args[@]}" "$@"
|
||||
}
|
||||
|
||||
# _dc_exec: wrap docker compose exec command
|
||||
@@ -74,12 +74,12 @@ function _dc_exec() {
|
||||
|
||||
echo "🐳(compose) exec command: '\$@'"
|
||||
|
||||
user_args="--user=$USER_ID"
|
||||
if [ -z $USER_ID ]; then
|
||||
user_args=""
|
||||
user_args=()
|
||||
if [ -n "$USER_ID" ]; then
|
||||
user_args=("--user=$USER_ID")
|
||||
fi
|
||||
|
||||
_docker_compose exec $user_args "$@"
|
||||
_docker_compose exec "${user_args[@]}" "$@"
|
||||
}
|
||||
|
||||
# _django_manage: wrap django's manage.py command with docker compose
|
||||
|
||||
@@ -40,7 +40,7 @@ if [ -n "$CUSTOM_LOGO_URL" ]; then
|
||||
[[ "$IS_SVG" == false ]] && echo "[custom-logo] ERROR: not a valid SVG file" >&2 && exit 1
|
||||
|
||||
mv -f "$TMP_FILE" "$LOGO_FILE"
|
||||
echo "[custom-logo] INFO: Custom logo downloaded successfuly"
|
||||
echo "[custom-logo] INFO: Custom logo downloaded successfully"
|
||||
fi
|
||||
|
||||
mv src/backend/* ./
|
||||
|
||||
@@ -7,7 +7,7 @@ gunicorn -b 0.0.0.0:8000 meet.wsgi:application --log-file - &
|
||||
bin/run &
|
||||
|
||||
# if the current shell is killed, also terminate all its children
|
||||
trap "pkill SIGTERM -P $$" SIGTERM
|
||||
trap 'pkill -TERM -P $$' SIGTERM
|
||||
|
||||
# wait for a single child to finish,
|
||||
wait -n
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
set -o errexit
|
||||
|
||||
CURRENT_DIR=$(pwd)
|
||||
NAMESPACE=${1:-meet}
|
||||
SECRET_NAME=${2:-bitwarden-cli-meet}
|
||||
TEMP_SECRET_FILE=$(mktemp)
|
||||
@@ -30,10 +29,10 @@ check_secret_exists() {
|
||||
# Collect user input securely
|
||||
get_user_input() {
|
||||
echo "Please provide the following information:"
|
||||
read -p "Enter your Vaultwarden email login: " LOGIN
|
||||
read -s -p "Enter your Vaultwarden password: " PASSWORD
|
||||
read -r -p "Enter your Vaultwarden email login: " LOGIN
|
||||
read -r -s -p "Enter your Vaultwarden password: " PASSWORD
|
||||
echo
|
||||
read -p "Enter your Vaultwarden server url: " URL
|
||||
read -r -p "Enter your Vaultwarden server url: " URL
|
||||
}
|
||||
|
||||
# Create and apply the secret
|
||||
@@ -77,7 +76,7 @@ main() {
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -e ${TEMP_SECRET_FILE}
|
||||
echo -e "${TEMP_SECRET_FILE}"
|
||||
|
||||
get_user_input
|
||||
echo -e "\nCreating Vaultwarden secret…"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
mkdir -p "$(dirname -- "${BASH_SOURCE[0]}")/../.git/hooks/"
|
||||
PRE_COMMIT_FILE="$(dirname -- "${BASH_SOURCE[0]}")/../.git/hooks/pre-commit"
|
||||
|
||||
cat <<'EOF' >$PRE_COMMIT_FILE
|
||||
cat <<'EOF' >"$PRE_COMMIT_FILE"
|
||||
#!/bin/bash
|
||||
|
||||
# directories containing potential secrets
|
||||
@@ -27,4 +27,4 @@ for d in $DIRS; do
|
||||
done
|
||||
EOF
|
||||
|
||||
chmod +x $PRE_COMMIT_FILE
|
||||
chmod +x "$PRE_COMMIT_FILE"
|
||||
|
||||
@@ -68,7 +68,7 @@ fi
|
||||
|
||||
# Ask user for release version number
|
||||
echo ""
|
||||
read -p "Enter release version number (e.g., 1.2.3): " VERSION
|
||||
read -r -p "Enter release version number (e.g., 1.2.3): " VERSION
|
||||
|
||||
# Validate version format (basic semver check)
|
||||
if ! [[ $VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
git submodule update --init --recursive
|
||||
# shellcheck disable=SC2016
|
||||
git submodule foreach 'git fetch origin; git checkout $(git rev-parse --abbrev-ref HEAD); git reset --hard origin/$(git rev-parse --abbrev-ref HEAD); git submodule update --recursive; git clean -dfx'
|
||||
|
||||
@@ -8,6 +8,6 @@ environments=$(awk '/environments:/ {flag=1; next} flag && NF {print} !NF {flag=
|
||||
|
||||
for env in $environments; do
|
||||
echo "################### $env lint ###################"
|
||||
helmfile -e $env -f src/helm/helmfile.yaml lint || exit 1
|
||||
helmfile -e "$env" -f src/helm/helmfile.yaml lint || exit 1
|
||||
echo -e "\n"
|
||||
done
|
||||
|
||||
@@ -153,7 +153,6 @@ services:
|
||||
target: frontend-production
|
||||
args:
|
||||
VITE_API_BASE_URL: "http://localhost:8071"
|
||||
VITE_MEDIA_BASE_URL: "http://localhost:8083"
|
||||
VITE_APP_TITLE: "LaSuite Meet"
|
||||
image: meet:frontend-development
|
||||
ports:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Bureautix proxy overrides
|
||||
#
|
||||
# Builds submitted through the Docker API of the Podman service get none of
|
||||
# the proxy variables in their RUN steps. We need to pass the http_proxy explicitely
|
||||
# the proxy variables in their RUN steps. We need to pass the http_proxy explicitly
|
||||
# otherwise all connections fail during the build.
|
||||
|
||||
x-proxy-vars: &proxy-vars
|
||||
|
||||
@@ -4,36 +4,6 @@ server {
|
||||
server_name localhost;
|
||||
charset utf-8;
|
||||
|
||||
# Proxy auth for recordings (authorized by the recordings viewset)
|
||||
location /media/recordings/ {
|
||||
auth_request /media-auth-recordings;
|
||||
auth_request_set $authHeader $upstream_http_authorization;
|
||||
auth_request_set $authDate $upstream_http_x_amz_date;
|
||||
auth_request_set $authContentSha256 $upstream_http_x_amz_content_sha256;
|
||||
|
||||
proxy_set_header Authorization $authHeader;
|
||||
proxy_set_header X-Amz-Date $authDate;
|
||||
proxy_set_header X-Amz-Content-SHA256 $authContentSha256;
|
||||
|
||||
proxy_pass http://garage:9000/meet-media-storage/recordings/;
|
||||
proxy_set_header Host garage:9000;
|
||||
proxy_hide_header Content-Disposition;
|
||||
add_header Content-Disposition "attachment";
|
||||
}
|
||||
|
||||
location = /media-auth-recordings {
|
||||
internal;
|
||||
proxy_pass http://app-dev:8000/api/v1.0/recordings/media-auth/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Original-URL $request_uri;
|
||||
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
proxy_set_header X-Original-Method $request_method;
|
||||
}
|
||||
|
||||
# Proxy auth for media
|
||||
location /media/ {
|
||||
# Auth request configuration
|
||||
|
||||
+119
-117
@@ -14,7 +14,7 @@ This document is a step-by-step guide that describes how to install LaSuite Meet
|
||||
|
||||
If you do not have a kubernetes test cluster, you can install everything on a local kind cluster. In this case, the simplest way is to use our script located in this repo under **bin/start-kind.sh**.
|
||||
|
||||
IMPORTANT: The kind method will only deploy meet as a local instance(127.0.0.1) that can only be accessed from the device where it has been deployed.
|
||||
IMPORTANT: The kind method will only deploy meet as a local instance(127.0.0.1) that can only be accessed from the device where it has been deployed.
|
||||
|
||||
To be able to use the script, you will need to install the following components:
|
||||
|
||||
@@ -311,120 +311,122 @@ frontend:
|
||||
|
||||
These are the environmental options available on meet backend.
|
||||
|
||||
| Option | Description | default |
|
||||
|-------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| DATA_DIR | Data directory location | /data |
|
||||
| DJANGO_ALLOWED_HOSTS | Hosts that are allowed | [] |
|
||||
| DJANGO_SECRET_KEY | Secret key used for Django security | |
|
||||
| DJANGO_SILENCED_SYSTEM_CHECKS | Silence Django system checks | [] |
|
||||
| DJANGO_ALLOW_UNSECURE_USER_LISTING | Allow unsecure user listing | false |
|
||||
| DB_ENGINE | Database engine used | django.db.backends.postgresql_psycopg2 |
|
||||
| DB_NAME | Name of the database | meet |
|
||||
| DB_USER | User used to connect to database | dinum |
|
||||
| DB_PASSWORD | Password used to connect to the database | pass |
|
||||
| DB_HOST | Hostname of the database | localhost |
|
||||
| DB_PORT | Port to connect to database | 5432 |
|
||||
| STORAGES_STATICFILES_BACKEND | Static file serving engine | whitenoise.storage.CompressedManifestStaticFilesStorage |
|
||||
| AWS_S3_ENDPOINT_URL | S3 host endpoint | |
|
||||
| AWS_S3_ACCESS_KEY_ID | S3 access key | |
|
||||
| AWS_S3_SECRET_ACCESS_KEY | S3 secret key | |
|
||||
| AWS_S3_REGION_NAME | S3 region | |
|
||||
| AWS_STORAGE_BUCKET_NAME | S3 bucket name | meet-media-storage |
|
||||
| DJANGO_LANGUAGE_CODE | Default language | en-us |
|
||||
| REDIS_URL | Redis endpoint | redis://redis:6379/1 |
|
||||
| SESSION_COOKIE_AGE | Session cookie expiration in seconds | 43200 (12 hours) |
|
||||
| REQUEST_ENTRY_THROTTLE_RATES | Entry request throttle rates | 150/minute |
|
||||
| CREATION_CALLBACK_THROTTLE_RATES | Creation callback throttle rates | 600/minute |
|
||||
| SPECTACULAR_SETTINGS_ENABLE_DJANGO_DEPLOY_CHECK | Enable Django deploy check | false |
|
||||
| CSRF_TRUSTED_ORIGINS | CSRF trusted origins list | [] |
|
||||
| FRONTEND_CUSTOM_CSS_URL | URL of an additional CSS file to load in the frontend app. If set, a `<link>` tag with this URL as href is added to the `<head>` of the frontend app | |
|
||||
| FRONTEND_ANALYTICS | Analytics information | {} |
|
||||
| FRONTEND_SUPPORT | Crisp frontend support configuration, also you can pass help articles, with `help_article_transcript`, `help_article_recording`, `help_article_more_tools` | {} |
|
||||
| FRONTEND_MANIFEST_LINK | Link to the "Learn more" button on the homepage | {} |
|
||||
| FRONTEND_SILENCE_LIVEKIT_DEBUG | Silence LiveKit debug logs | false |
|
||||
| FRONTEND_IS_SILENT_LOGIN_ENABLED | Enable silent login feature | true |
|
||||
| FRONTEND_FEEDBACK | Frontend feedback configuration | {} |
|
||||
| FRONTEND_DOCUMENTATION_URL | URL of the documentation opened from the room options menu. If unset, the documentation menu item is hidden | |
|
||||
| FRONTEND_USE_FRENCH_GOV_FOOTER | Show the French government footer in the homepage | false |
|
||||
| FRONTEND_USE_PROCONNECT_BUTTON | Show a "Login with ProConnect" button in the homepage instead of a "Login" button | false |
|
||||
| DJANGO_EMAIL_BACKEND | Email backend library | django.core.mail.backends.smtp.EmailBackend |
|
||||
| DJANGO_EMAIL_HOST | Host of the email server | |
|
||||
| DJANGO_EMAIL_HOST_USER | User to connect to the email server | |
|
||||
| DJANGO_EMAIL_HOST_PASSWORD | Password to connect to the email server | |
|
||||
| DJANGO_EMAIL_PORT | Port to connect to the email server | |
|
||||
| DJANGO_EMAIL_USE_TLS | Enable TLS on email connection | false |
|
||||
| DJANGO_EMAIL_USE_SSL | Enable SSL on email connection | false |
|
||||
| DJANGO_EMAIL_FROM | Email from account | from@example.com |
|
||||
| EMAIL_BRAND_NAME | Email branding name | |
|
||||
| EMAIL_SUPPORT_EMAIL | Support email address | |
|
||||
| EMAIL_LOGO_IMG | Email logo image | |
|
||||
| EMAIL_DOMAIN | Email domain | |
|
||||
| EMAIL_APP_BASE_URL | Email app base URL | |
|
||||
| DJANGO_CORS_ALLOW_ALL_ORIGINS | Allow all CORS origins | false |
|
||||
| DJANGO_CORS_ALLOWED_ORIGINS | Origins to allow (string list) | [] |
|
||||
| DJANGO_CORS_ALLOWED_ORIGIN_REGEXES | Origins to allow (regex patterns) | [] |
|
||||
| SENTRY_DSN | Sentry server DSN | |
|
||||
| DJANGO_CELERY_BROKER_URL | Celery broker host | redis://redis:6379/0 |
|
||||
| DJANGO_CELERY_BROKER_TRANSPORT_OPTIONS | Celery broker options | {} |
|
||||
| OIDC_CREATE_USER | Create OIDC user if not exists | true |
|
||||
| OIDC_VERIFY_SSL | Verify SSL for OIDC | true |
|
||||
| OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION | Fallback to email for identification | false |
|
||||
| OIDC_RP_SIGN_ALGO | Token verification algorithm used by OIDC | RS256 |
|
||||
| OIDC_RP_CLIENT_ID | OIDC client ID | meet |
|
||||
| OIDC_RP_CLIENT_SECRET | OIDC client secret | |
|
||||
| OIDC_OP_JWKS_ENDPOINT | OIDC endpoint for JWKS | |
|
||||
| OIDC_OP_AUTHORIZATION_ENDPOINT | OIDC endpoint for authorization | |
|
||||
| OIDC_OP_TOKEN_ENDPOINT | OIDC endpoint for token | |
|
||||
| OIDC_OP_USER_ENDPOINT | OIDC endpoint for user | |
|
||||
| OIDC_OP_USER_ENDPOINT_FORMAT | OIDC endpoint format (AUTO, JWT, JSON) | AUTO |
|
||||
| OIDC_OP_LOGOUT_ENDPOINT | OIDC endpoint for logout | |
|
||||
| OIDC_AUTH_REQUEST_EXTRA_PARAMS | Extra parameters for OIDC request | {} |
|
||||
| OIDC_RP_SCOPES | OIDC scopes | openid email |
|
||||
| OIDC_USE_NONCE | Use nonce for OIDC | true |
|
||||
| OIDC_REDIRECT_REQUIRE_HTTPS | Require HTTPS for OIDC | false |
|
||||
| OIDC_REDIRECT_ALLOWED_HOSTS | Allowed redirect hosts for OIDC | [] |
|
||||
| OIDC_STORE_ID_TOKEN | Store OIDC ID token | true |
|
||||
| OIDC_REDIRECT_FIELD_NAME | Redirect field for OIDC | returnTo |
|
||||
| OIDC_USERINFO_FULLNAME_FIELDS | Full name claim from OIDC token | ["given_name", "usual_name"] |
|
||||
| OIDC_USERINFO_SHORTNAME_FIELD | Short name claim from OIDC token | given_name |
|
||||
| OIDC_USERINFO_ESSENTIAL_CLAIMS | Required claims from OIDC token | [] |
|
||||
| OIDC_USE_PKCE | Enable the use of PKCE (Proof Key for Code Exchange) during the OAuth 2.0 authorization code flow. Recommended for enhanced security. | False |
|
||||
| OIDC_PKCE_CODE_CHALLENGE_METHOD | Method used to generate the PKCE code challenge. Common values include S256 and plain. Refer to the mozilla-django-oidc documentation for supported options. | S256 |
|
||||
| OIDC_PKCE_CODE_VERIFIER_SIZE | Length of the random string used as the PKCE code verifier. Must be an integer between 43 and 128, inclusive. | 64 |
|
||||
| LOGIN_REDIRECT_URL | Login redirect URL | |
|
||||
| LOGIN_REDIRECT_URL_FAILURE | Login redirect URL for failure | |
|
||||
| LOGOUT_REDIRECT_URL | URL to redirect to on logout | |
|
||||
| ALLOW_LOGOUT_GET_METHOD | Allow logout through GET method | true |
|
||||
| LIVEKIT_API_KEY | LiveKit API key | |
|
||||
| LIVEKIT_API_SECRET | LiveKit API secret | |
|
||||
| LIVEKIT_API_URL | LiveKit API URL | |
|
||||
| LIVEKIT_VERIFY_SSL | Verify SSL for LiveKit connections | true |
|
||||
| LIVEKIT_FORCE_WSS_PROTOCOL | Enables WSS protocol conversion for legacy browser compatibility (Firefox <124, Chrome <125, Edge <125) where HTTPS URLs fail in WebSocket() constructor. | false |
|
||||
| LIVEKIT_ENABLE_FIREFOX_PROXY_WORKAROUND | Firefox-only connection warmup: pre-calls WebSocket endpoint (expecting 401) to initialize cache, resolving proxy/network connectivity issues. | false |
|
||||
| RESOURCE_DEFAULT_ACCESS_LEVEL | Default resource access level for rooms | public |
|
||||
| ALLOW_UNREGISTERED_ROOMS | Allow usage of unregistered rooms | true |
|
||||
| ROOM_INACTIVITY_DELETION_DAYS | Days without being started after which a room is purged. Unset to never purge | |
|
||||
| RECORDING_ENABLE | Record meeting option | false |
|
||||
| RECORDING_OUTPUT_FOLDER | Folder to store meetings | recordings |
|
||||
| Option | Description | default |
|
||||
|-------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| DATA_DIR | Data directory location | /data |
|
||||
| DJANGO_ALLOWED_HOSTS | Hosts that are allowed | [] |
|
||||
| DJANGO_SECRET_KEY | Secret key used for Django security | |
|
||||
| DJANGO_SILENCED_SYSTEM_CHECKS | Silence Django system checks | [] |
|
||||
| DJANGO_ALLOW_UNSECURE_USER_LISTING | Allow unsecure user listing | false |
|
||||
| DB_ENGINE | Database engine used | django.db.backends.postgresql_psycopg2 |
|
||||
| DB_NAME | Name of the database | meet |
|
||||
| DB_USER | User used to connect to database | dinum |
|
||||
| DB_PASSWORD | Password used to connect to the database | pass |
|
||||
| DB_HOST | Hostname of the database | localhost |
|
||||
| DB_PORT | Port to connect to database | 5432 |
|
||||
| STORAGES_STATICFILES_BACKEND | Static file serving engine | whitenoise.storage.CompressedManifestStaticFilesStorage |
|
||||
| AWS_S3_ENDPOINT_URL | S3 host endpoint | |
|
||||
| AWS_S3_ACCESS_KEY_ID | S3 access key | |
|
||||
| AWS_S3_SECRET_ACCESS_KEY | S3 secret key | |
|
||||
| AWS_S3_REGION_NAME | S3 region | |
|
||||
| AWS_STORAGE_BUCKET_NAME | S3 bucket name | meet-media-storage |
|
||||
| DJANGO_LANGUAGE_CODE | Default language | en-us |
|
||||
| REDIS_URL | Redis endpoint | redis://redis:6379/1 |
|
||||
| SESSION_COOKIE_AGE | Session cookie expiration in seconds | 43200 (12 hours) |
|
||||
| ROOM_CREATION_THROTTLE_RATES | Room creation throttle rate per authenticated user | 50/minute | 50/minute |
|
||||
| ROOM_CREATION_DAILY_THROTTLE_RATES | Daily room creation cap per authenticated user | 1000/day |
|
||||
| REQUEST_ENTRY_THROTTLE_RATES | Entry request throttle rates | 150/minute |
|
||||
| CREATION_CALLBACK_THROTTLE_RATES | Creation callback throttle rates | 600/minute |
|
||||
| SPECTACULAR_SETTINGS_ENABLE_DJANGO_DEPLOY_CHECK | Enable Django deploy check | false |
|
||||
| CSRF_TRUSTED_ORIGINS | CSRF trusted origins list | [] |
|
||||
| FRONTEND_CUSTOM_CSS_URL | URL of an additional CSS file to load in the frontend app. If set, a `<link>` tag with this URL as href is added to the `<head>` of the frontend app | |
|
||||
| FRONTEND_ANALYTICS | Analytics information | {} |
|
||||
| FRONTEND_SUPPORT | Crisp frontend support configuration, also you can pass help articles, with `help_article_transcript`, `help_article_recording`, `help_article_more_tools` | {} |
|
||||
| FRONTEND_MANIFEST_LINK | Link to the "Learn more" button on the homepage | {} |
|
||||
| FRONTEND_SILENCE_LIVEKIT_DEBUG | Silence LiveKit debug logs | false |
|
||||
| FRONTEND_IS_SILENT_LOGIN_ENABLED | Enable silent login feature | true |
|
||||
| FRONTEND_FEEDBACK | Frontend feedback configuration | {} |
|
||||
| FRONTEND_DOCUMENTATION_URL | URL of the documentation opened from the room options menu. If unset, the documentation menu item is hidden | |
|
||||
| FRONTEND_USE_FRENCH_GOV_FOOTER | Show the French government footer in the homepage | false |
|
||||
| FRONTEND_USE_PROCONNECT_BUTTON | Show a "Login with ProConnect" button in the homepage instead of a "Login" button | false |
|
||||
| DJANGO_EMAIL_BACKEND | Email backend library | django.core.mail.backends.smtp.EmailBackend |
|
||||
| DJANGO_EMAIL_HOST | Host of the email server | |
|
||||
| DJANGO_EMAIL_HOST_USER | User to connect to the email server | |
|
||||
| DJANGO_EMAIL_HOST_PASSWORD | Password to connect to the email server | |
|
||||
| DJANGO_EMAIL_PORT | Port to connect to the email server | |
|
||||
| DJANGO_EMAIL_USE_TLS | Enable TLS on email connection | false |
|
||||
| DJANGO_EMAIL_USE_SSL | Enable SSL on email connection | false |
|
||||
| DJANGO_EMAIL_FROM | Email from account | from@example.com |
|
||||
| EMAIL_BRAND_NAME | Email branding name | |
|
||||
| EMAIL_SUPPORT_EMAIL | Support email address | |
|
||||
| EMAIL_LOGO_IMG | Email logo image | |
|
||||
| EMAIL_DOMAIN | Email domain | |
|
||||
| EMAIL_APP_BASE_URL | Email app base URL | |
|
||||
| DJANGO_CORS_ALLOW_ALL_ORIGINS | Allow all CORS origins | false |
|
||||
| DJANGO_CORS_ALLOWED_ORIGINS | Origins to allow (string list) | [] |
|
||||
| DJANGO_CORS_ALLOWED_ORIGIN_REGEXES | Origins to allow (regex patterns) | [] |
|
||||
| SENTRY_DSN | Sentry server DSN | |
|
||||
| DJANGO_CELERY_BROKER_URL | Celery broker host | redis://redis:6379/0 |
|
||||
| DJANGO_CELERY_BROKER_TRANSPORT_OPTIONS | Celery broker options | {} |
|
||||
| OIDC_CREATE_USER | Create OIDC user if not exists | true |
|
||||
| OIDC_VERIFY_SSL | Verify SSL for OIDC | true |
|
||||
| OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION | Fallback to email for identification | false |
|
||||
| OIDC_RP_SIGN_ALGO | Token verification algorithm used by OIDC | RS256 |
|
||||
| OIDC_RP_CLIENT_ID | OIDC client ID | meet |
|
||||
| OIDC_RP_CLIENT_SECRET | OIDC client secret | |
|
||||
| OIDC_OP_JWKS_ENDPOINT | OIDC endpoint for JWKS | |
|
||||
| OIDC_OP_AUTHORIZATION_ENDPOINT | OIDC endpoint for authorization | |
|
||||
| OIDC_OP_TOKEN_ENDPOINT | OIDC endpoint for token | |
|
||||
| OIDC_OP_USER_ENDPOINT | OIDC endpoint for user | |
|
||||
| OIDC_OP_USER_ENDPOINT_FORMAT | OIDC endpoint format (AUTO, JWT, JSON) | AUTO |
|
||||
| OIDC_OP_LOGOUT_ENDPOINT | OIDC endpoint for logout | |
|
||||
| OIDC_AUTH_REQUEST_EXTRA_PARAMS | Extra parameters for OIDC request | {} |
|
||||
| OIDC_RP_SCOPES | OIDC scopes | openid email |
|
||||
| OIDC_USE_NONCE | Use nonce for OIDC | true |
|
||||
| OIDC_REDIRECT_REQUIRE_HTTPS | Require HTTPS for OIDC | false |
|
||||
| OIDC_REDIRECT_ALLOWED_HOSTS | Allowed redirect hosts for OIDC | [] |
|
||||
| OIDC_STORE_ID_TOKEN | Store OIDC ID token | true |
|
||||
| OIDC_REDIRECT_FIELD_NAME | Redirect field for OIDC | returnTo |
|
||||
| OIDC_USERINFO_FULLNAME_FIELDS | Full name claim from OIDC token | ["given_name", "usual_name"] |
|
||||
| OIDC_USERINFO_SHORTNAME_FIELD | Short name claim from OIDC token | given_name |
|
||||
| OIDC_USERINFO_ESSENTIAL_CLAIMS | Required claims from OIDC token | [] |
|
||||
| OIDC_USE_PKCE | Enable the use of PKCE (Proof Key for Code Exchange) during the OAuth 2.0 authorization code flow. Recommended for enhanced security. | False |
|
||||
| OIDC_PKCE_CODE_CHALLENGE_METHOD | Method used to generate the PKCE code challenge. Common values include S256 and plain. Refer to the mozilla-django-oidc documentation for supported options. | S256 |
|
||||
| OIDC_PKCE_CODE_VERIFIER_SIZE | Length of the random string used as the PKCE code verifier. Must be an integer between 43 and 128, inclusive. | 64 |
|
||||
| LOGIN_REDIRECT_URL | Login redirect URL | |
|
||||
| LOGIN_REDIRECT_URL_FAILURE | Login redirect URL for failure | |
|
||||
| LOGOUT_REDIRECT_URL | URL to redirect to on logout | |
|
||||
| ALLOW_LOGOUT_GET_METHOD | Allow logout through GET method | true |
|
||||
| LIVEKIT_API_KEY | LiveKit API key | |
|
||||
| LIVEKIT_API_SECRET | LiveKit API secret | |
|
||||
| LIVEKIT_API_URL | LiveKit API URL | |
|
||||
| LIVEKIT_VERIFY_SSL | Verify SSL for LiveKit connections | true |
|
||||
| LIVEKIT_FORCE_WSS_PROTOCOL | Enables WSS protocol conversion for legacy browser compatibility (Firefox <124, Chrome <125, Edge <125) where HTTPS URLs fail in WebSocket() constructor. | false |
|
||||
| LIVEKIT_ENABLE_FIREFOX_PROXY_WORKAROUND | Firefox-only connection warmup: pre-calls WebSocket endpoint (expecting 401) to initialize cache, resolving proxy/network connectivity issues. | false |
|
||||
| RESOURCE_DEFAULT_ACCESS_LEVEL | Default resource access level for rooms | public |
|
||||
| ALLOW_UNREGISTERED_ROOMS | Allow usage of unregistered rooms | true |
|
||||
| ROOM_INACTIVITY_DELETION_DAYS | Days without being started after which a room is purged. Unset to never purge | |
|
||||
| RECORDING_ENABLE | Record meeting option | false |
|
||||
| RECORDING_OUTPUT_FOLDER | Folder to store meetings | recordings |
|
||||
| RECORDING_WORKER_CLASSES | Worker classes for recording | {"screen_recording": "core.recording.worker.services.VideoCompositeEgressService","transcript": "core.recording.worker.services.AudioCompositeEgressService"} |
|
||||
| RECORDING_EXPIRATION_DAYS | Recording expiration in days | |
|
||||
| RECORDING_MAX_DURATION | Maximum recording duration in milliseconds. Must match LiveKit Egress configuration exactly. | |
|
||||
| SCREEN_RECORDING_BASE_URL | Screen recording base URL | |
|
||||
| SUMMARY_SERVICE_ENDPOINT | Summary service endpoint | |
|
||||
| SUMMARY_SERVICE_API_TOKEN | API token for summary service | |
|
||||
| SIGNUP_NEW_USER_TO_MARKETING_EMAIL | Signup users to marketing emails | false |
|
||||
| MARKETING_SERVICE_CLASS | Marketing service class | core.services.marketing.BrevoMarketingService |
|
||||
| BREVO_API_KEY | Brevo API key for marketing emails | |
|
||||
| BREVO_API_CONTACT_LIST_IDS | Brevo API contact list IDs | [] |
|
||||
| DJANGO_BREVO_API_CONTACT_ATTRIBUTES | Brevo contact attributes | {"VISIO_USER": true} |
|
||||
| BREVO_API_TIMEOUT | Brevo timeout in seconds | 1 |
|
||||
| LOBBY_KEY_PREFIX | Lobby key prefix | room_lobby |
|
||||
| LOBBY_WAITING_TIMEOUT | Lobby waiting timeout in seconds | 3 |
|
||||
| LOBBY_DENIED_TIMEOUT | Lobby deny timeout in seconds | 5 |
|
||||
| LOBBY_ACCEPTED_TIMEOUT | Lobby accept timeout in seconds | 21600 (6 hours) |
|
||||
| LOBBY_NOTIFICATION_TYPE | Lobby notification types | participantWaiting |
|
||||
| LOBBY_COOKIE_NAME | Lobby cookie name | lobbyParticipantId |
|
||||
| ROOM_CREATION_CALLBACK_CACHE_TIMEOUT | Room creation callback cache timeout | 600 (10 minutes) |
|
||||
| ROOM_TELEPHONY_ENABLED | Enable SIP telephony feature | false |
|
||||
| ROOM_TELEPHONY_PIN_LENGTH | Telephony PIN length | 10 |
|
||||
| ROOM_TELEPHONY_PIN_MAX_RETRIES | Telephony PIN maximum retries | 5 |
|
||||
| RECORDING_EXPIRATION_DAYS | Recording expiration in days | |
|
||||
| RECORDING_MAX_DURATION | Maximum recording duration in milliseconds. Must match LiveKit Egress configuration exactly. | |
|
||||
| SCREEN_RECORDING_BASE_URL | Screen recording base URL | |
|
||||
| SUMMARY_SERVICE_ENDPOINT | Summary service endpoint | |
|
||||
| SUMMARY_SERVICE_API_TOKEN | API token for summary service | |
|
||||
| SIGNUP_NEW_USER_TO_MARKETING_EMAIL | Signup users to marketing emails | false |
|
||||
| MARKETING_SERVICE_CLASS | Marketing service class | core.services.marketing.BrevoMarketingService |
|
||||
| BREVO_API_KEY | Brevo API key for marketing emails | |
|
||||
| BREVO_API_CONTACT_LIST_IDS | Brevo API contact list IDs | [] |
|
||||
| DJANGO_BREVO_API_CONTACT_ATTRIBUTES | Brevo contact attributes | {"VISIO_USER": true} |
|
||||
| BREVO_API_TIMEOUT | Brevo timeout in seconds | 1 |
|
||||
| LOBBY_KEY_PREFIX | Lobby key prefix | room_lobby |
|
||||
| LOBBY_WAITING_TIMEOUT | Lobby waiting timeout in seconds | 3 |
|
||||
| LOBBY_DENIED_TIMEOUT | Lobby deny timeout in seconds | 5 |
|
||||
| LOBBY_ACCEPTED_TIMEOUT | Lobby accept timeout in seconds | 21600 (6 hours) |
|
||||
| LOBBY_NOTIFICATION_TYPE | Lobby notification types | participantWaiting |
|
||||
| LOBBY_COOKIE_NAME | Lobby cookie name | lobbyParticipantId |
|
||||
| ROOM_CREATION_CALLBACK_CACHE_TIMEOUT | Room creation callback cache timeout | 600 (10 minutes) |
|
||||
| ROOM_TELEPHONY_ENABLED | Enable SIP telephony feature | false |
|
||||
| ROOM_TELEPHONY_PIN_LENGTH | Telephony PIN length | 10 |
|
||||
| ROOM_TELEPHONY_PIN_MAX_RETRIES | Telephony PIN maximum retries | 5 |
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": ["github>numerique-gouv/renovate-configuration"],
|
||||
"extends": ["github>suitenumerique/ci//renovate/default"],
|
||||
"dependencyDashboard": true,
|
||||
"labels": ["dependencies", "noChangeLog"],
|
||||
"packageRules": [
|
||||
|
||||
@@ -21,7 +21,7 @@ const { initI18n, translateUI } = require("../common/i18n");
|
||||
document.querySelector("#close-msg").style.display = "block";
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(`Error occured: ${e}`);
|
||||
console.error(`Error occurred: ${e}`);
|
||||
})
|
||||
.finally(() => {
|
||||
// NOTE: doesn't work with the desktop client — the browser considers
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:3.14.6-slim AS base
|
||||
FROM python:3.14.7-slim AS base
|
||||
|
||||
# Install system dependencies required by LiveKit, fetching packages over HTTPS only for Bureautix proxy
|
||||
RUN sed -i "s|^URIs: http://|URIs: https://|" /etc/apt/sources.list.d/debian.sources \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
[project]
|
||||
name = "agents"
|
||||
version = "1.32.1"
|
||||
version = "1.33.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"livekit-agents==1.7.0",
|
||||
|
||||
Generated
+1
-1
@@ -9,7 +9,7 @@ resolution-markers = [
|
||||
|
||||
[[package]]
|
||||
name = "agents"
|
||||
version = "1.32.1"
|
||||
version = "1.33.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "boto3" },
|
||||
|
||||
@@ -20,6 +20,33 @@ class MonitoredUserRateThrottle(MonitoredThrottleMixin, UserRateThrottle):
|
||||
"""Throttle for the monitored scoped rate throttle."""
|
||||
|
||||
|
||||
class RoomCreationUserRateThrottle(MonitoredUserRateThrottle):
|
||||
"""Throttle room creation per authenticated user.
|
||||
|
||||
Can be declared at the viewset level: every action other than "create"
|
||||
is left unthrottled, so the same class can be reused on any viewset
|
||||
exposing a room creation endpoint.
|
||||
"""
|
||||
|
||||
scope = "room_creation"
|
||||
|
||||
def get_cache_key(self, request, view):
|
||||
"""Throttle only room creations."""
|
||||
if getattr(view, "action", None) != "create":
|
||||
return None
|
||||
return super().get_cache_key(request, view)
|
||||
|
||||
|
||||
class RoomCreationDailyUserRateThrottle(RoomCreationUserRateThrottle):
|
||||
"""Cap room creation per authenticated user over a day.
|
||||
|
||||
Complements the short-term RoomCreationUserRateThrottle, which absorbs
|
||||
bursts but lets a user steadily create rooms over hours or days.
|
||||
"""
|
||||
|
||||
scope = "room_creation_daily"
|
||||
|
||||
|
||||
class RequestEntryAuthenticatedUserRateThrottle(MonitoredUserRateThrottle):
|
||||
"""Throttle authenticated user requesting room entry"""
|
||||
|
||||
|
||||
@@ -180,6 +180,10 @@ class RoomViewSet(
|
||||
permission_classes = [permissions.RoomPermissions]
|
||||
queryset = models.Room.objects.all()
|
||||
serializer_class = serializers.RoomSerializer
|
||||
throttle_classes = [
|
||||
throttling.RoomCreationUserRateThrottle,
|
||||
throttling.RoomCreationDailyUserRateThrottle,
|
||||
]
|
||||
|
||||
def get_object(self):
|
||||
"""Allow getting a room by its slug."""
|
||||
|
||||
@@ -24,7 +24,7 @@ class BaseEgressService:
|
||||
|
||||
def _get_filepath(self, filename: str, extension: str) -> str:
|
||||
"""Construct the file path for a given filename and extension.
|
||||
Unsecure method, doesn't handle paths robustly and securely.
|
||||
Insecure method, doesn't handle paths robustly and securely.
|
||||
"""
|
||||
return f"{self._config.output_folder}/{filename}.{extension}"
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ def test_api_files_list_anonymous_not_allowed():
|
||||
|
||||
def test_api_files_list_authentificated_user_allowed():
|
||||
"""
|
||||
Authentificated users should be allowed to list files
|
||||
Authenticated users should be allowed to list files
|
||||
"""
|
||||
user = factories.UserFactory()
|
||||
client = APIClient()
|
||||
|
||||
@@ -9,6 +9,10 @@ from django.core.cache import cache
|
||||
import pytest
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
from ...api.throttling import (
|
||||
RoomCreationDailyUserRateThrottle,
|
||||
RoomCreationUserRateThrottle,
|
||||
)
|
||||
from ...factories import RoomFactory, UserFactory
|
||||
from ...models import Room, RoomAccessLevel
|
||||
|
||||
@@ -312,3 +316,145 @@ def test_api_rooms_create_authenticated_blank_user_default_access_level():
|
||||
assert response.status_code == 201
|
||||
room = Room.objects.get()
|
||||
assert room.access_level == settings.RESOURCE_DEFAULT_ACCESS_LEVEL
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def room_creation_throttle(monkeypatch):
|
||||
"""Lower the room creation rate for the duration of a test."""
|
||||
monkeypatch.setitem(
|
||||
settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"], "room_creation", "2/minute"
|
||||
)
|
||||
|
||||
|
||||
def test_api_rooms_create_throttled(room_creation_throttle):
|
||||
"""Excess requests are rejected and create no room."""
|
||||
|
||||
client = APIClient()
|
||||
client.force_login(UserFactory())
|
||||
|
||||
for index in range(2):
|
||||
response = client.post("/api/v1.0/rooms/", {"name": f"Room {index}"})
|
||||
assert response.status_code == 201
|
||||
|
||||
response = client.post("/api/v1.0/rooms/", {"name": "Blocked room"})
|
||||
assert response.status_code == 429
|
||||
assert 0 < int(response["Retry-After"]) <= 60
|
||||
assert Room.objects.count() == 2
|
||||
|
||||
|
||||
def test_api_rooms_create_throttle_per_user(room_creation_throttle):
|
||||
"""Users sharing an IP have independent creation limits."""
|
||||
|
||||
client = APIClient()
|
||||
client.force_login(UserFactory())
|
||||
for index in range(2):
|
||||
response = client.post("/api/v1.0/rooms/", {"name": f"First user room {index}"})
|
||||
assert response.status_code == 201
|
||||
|
||||
response = client.post("/api/v1.0/rooms/", {"name": "Blocked room"})
|
||||
assert response.status_code == 429
|
||||
|
||||
client.force_login(UserFactory())
|
||||
response = client.post("/api/v1.0/rooms/", {"name": "Second user room"})
|
||||
assert response.status_code == 201
|
||||
|
||||
|
||||
def test_api_rooms_create_throttle_does_not_limit_other_actions(room_creation_throttle):
|
||||
"""Exhausting creation capacity leaves listing and updating available."""
|
||||
|
||||
client = APIClient()
|
||||
client.force_login(UserFactory())
|
||||
for index in range(2):
|
||||
response = client.post("/api/v1.0/rooms/", {"name": f"Room {index}"})
|
||||
assert response.status_code == 201
|
||||
room_id = response.json()["id"]
|
||||
|
||||
assert client.post("/api/v1.0/rooms/", {"name": "Blocked room"}).status_code == 429
|
||||
assert client.get("/api/v1.0/rooms/").status_code == 200
|
||||
assert (
|
||||
client.patch(
|
||||
f"/api/v1.0/rooms/{room_id}/", {"name": "Renamed room"}
|
||||
).status_code
|
||||
== 200
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def daily_room_creation_throttle(monkeypatch):
|
||||
"""Use a tiny daily cap, a loose burst limit and a controllable clock.
|
||||
|
||||
Rates are patched with monkeypatch.setitem so they are restored after the
|
||||
test. Returns a one-item list holding the current fake timestamp.
|
||||
"""
|
||||
rates = RoomCreationDailyUserRateThrottle.THROTTLE_RATES
|
||||
monkeypatch.setitem(rates, "room_creation", "100/minute")
|
||||
monkeypatch.setitem(rates, "room_creation_daily", "3/day")
|
||||
now = [1_000_000.0]
|
||||
monkeypatch.setattr(RoomCreationUserRateThrottle, "timer", lambda self: now[0])
|
||||
return now
|
||||
|
||||
|
||||
def test_api_rooms_create_daily_throttled(daily_room_creation_throttle):
|
||||
"""The daily cap still applies once the short-term window has elapsed."""
|
||||
now = daily_room_creation_throttle
|
||||
client = APIClient()
|
||||
client.force_login(UserFactory())
|
||||
|
||||
for index in range(3):
|
||||
response = client.post("/api/v1.0/rooms/", {"name": f"Room {index}"})
|
||||
assert response.status_code == 201
|
||||
now[0] += 120 # Spread creations beyond the short-term window.
|
||||
|
||||
response = client.post("/api/v1.0/rooms/", {"name": "Blocked room"})
|
||||
assert response.status_code == 429
|
||||
assert int(response["Retry-After"]) > 60
|
||||
assert Room.objects.count() == 3
|
||||
|
||||
|
||||
def test_api_rooms_create_daily_throttle_resets(daily_room_creation_throttle):
|
||||
"""Room creation is allowed again once a day has passed."""
|
||||
now = daily_room_creation_throttle
|
||||
client = APIClient()
|
||||
client.force_login(UserFactory())
|
||||
|
||||
for index in range(3):
|
||||
response = client.post("/api/v1.0/rooms/", {"name": f"Room {index}"})
|
||||
assert response.status_code == 201
|
||||
|
||||
response = client.post("/api/v1.0/rooms/", {"name": "Blocked room"})
|
||||
assert response.status_code == 429
|
||||
|
||||
now[0] += 24 * 60 * 60 + 1
|
||||
response = client.post("/api/v1.0/rooms/", {"name": "Next day room"})
|
||||
assert response.status_code == 201
|
||||
|
||||
|
||||
def test_api_rooms_create_daily_throttle_per_user(daily_room_creation_throttle):
|
||||
"""Each user has its own daily cap."""
|
||||
client = APIClient()
|
||||
client.force_login(UserFactory())
|
||||
for index in range(3):
|
||||
response = client.post("/api/v1.0/rooms/", {"name": f"Room {index}"})
|
||||
assert response.status_code == 201
|
||||
assert client.post("/api/v1.0/rooms/", {"name": "Blocked"}).status_code == 429
|
||||
|
||||
client.force_login(UserFactory())
|
||||
response = client.post("/api/v1.0/rooms/", {"name": "Other user room"})
|
||||
assert response.status_code == 201
|
||||
|
||||
|
||||
def test_api_rooms_create_daily_throttle_does_not_limit_other_actions(
|
||||
daily_room_creation_throttle,
|
||||
):
|
||||
"""Reaching the daily cap leaves listing and updating available."""
|
||||
client = APIClient()
|
||||
client.force_login(UserFactory())
|
||||
for index in range(3):
|
||||
response = client.post("/api/v1.0/rooms/", {"name": f"Room {index}"})
|
||||
assert response.status_code == 201
|
||||
room_id = response.json()["id"]
|
||||
|
||||
assert client.post("/api/v1.0/rooms/", {"name": "Blocked"}).status_code == 429
|
||||
assert client.get("/api/v1.0/rooms/").status_code == 200
|
||||
response = client.patch(f"/api/v1.0/rooms/{room_id}/", {"name": "Renamed"})
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -458,7 +458,7 @@ def test_mute_participant_livekit_token_presence_check_twirp_error_forbidden(
|
||||
room = RoomFactory()
|
||||
|
||||
mock_livekit_client.room.get_participant.side_effect = TwirpError(
|
||||
msg="an error occured", code="not_found", status=500
|
||||
msg="an error occurred", code="not_found", status=500
|
||||
)
|
||||
|
||||
user = AnonymousUser()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Test SIP mamagement service.
|
||||
Test SIP management service.
|
||||
"""
|
||||
|
||||
# pylint: disable=W0212
|
||||
|
||||
@@ -361,6 +361,16 @@ class Base(Configuration):
|
||||
"DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.URLPathVersioning",
|
||||
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
|
||||
"DEFAULT_THROTTLE_RATES": {
|
||||
"room_creation": values.Value(
|
||||
default="50/minute",
|
||||
environ_name="ROOM_CREATION_THROTTLE_RATES",
|
||||
environ_prefix=None,
|
||||
),
|
||||
"room_creation_daily": values.Value(
|
||||
default="1000/day",
|
||||
environ_name="ROOM_CREATION_DAILY_THROTTLE_RATES",
|
||||
environ_prefix=None,
|
||||
),
|
||||
"request_entry": values.Value(
|
||||
default="150/minute",
|
||||
environ_name="REQUEST_ENTRY_THROTTLE_RATES",
|
||||
|
||||
@@ -7,7 +7,7 @@ build-backend = "uv_build"
|
||||
|
||||
[project]
|
||||
name = "meet"
|
||||
version = "1.32.1"
|
||||
version = "1.33.0"
|
||||
authors = [{ "name" = "DINUM", "email" = "dev@mail.numerique.gouv.fr" }]
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
@@ -53,7 +53,7 @@ dependencies = [
|
||||
"posthog==7.44.0",
|
||||
"psycopg[binary]==3.3.4",
|
||||
"pydantic==2.13.4",
|
||||
"PyJWT==2.13.0",
|
||||
"PyJWT==2.14.0",
|
||||
"python-frontmatter==1.3.0",
|
||||
"python-magic==0.4.27",
|
||||
"requests==2.34.2",
|
||||
|
||||
Generated
+5
-5
@@ -1297,7 +1297,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "meet"
|
||||
version = "1.32.1"
|
||||
version = "1.33.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "aiohttp" },
|
||||
@@ -1398,7 +1398,7 @@ requires-dist = [
|
||||
{ name = "posthog", specifier = "==7.44.0" },
|
||||
{ name = "psycopg", extras = ["binary"], specifier = "==3.3.4" },
|
||||
{ name = "pydantic", specifier = "==2.13.4" },
|
||||
{ name = "pyjwt", specifier = "==2.13.0" },
|
||||
{ name = "pyjwt", specifier = "==2.14.0" },
|
||||
{ name = "python-frontmatter", specifier = "==1.3.0" },
|
||||
{ name = "python-magic", specifier = "==0.4.27" },
|
||||
{ name = "redis", specifier = "==5.2.1" },
|
||||
@@ -2023,11 +2023,11 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pyjwt"
|
||||
version = "2.13.0"
|
||||
version = "2.14.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/af/c3/8a3b59c25070cc61dc517fbdfa5dc0904670c96f605cc69759dc09166b99/pyjwt-2.14.0.tar.gz", hash = "sha256:77283c83fb56ecf566a886c757a714bc83668e38156de2cce8263302f42e0b86", size = 113177, upload-time = "2026-09-11T13:11:54.638Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274, upload-time = "2026-05-21T19:54:35.362Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9c/97/672cb32ce0dfea44b740cb7b4f97038463b9cf7c0ead1aacf595572851d6/pyjwt-2.14.0-py3-none-any.whl", hash = "sha256:ad0cef71c756a56e74863c2919cf0985f72decbcfcb550ee2f422e7c62b5eedc", size = 32896, upload-time = "2026-09-11T13:11:53.409Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -39,9 +39,6 @@ ENV VITE_API_BASE_URL=${VITE_API_BASE_URL}
|
||||
ARG VITE_APP_TITLE
|
||||
ENV VITE_APP_TITLE=${VITE_APP_TITLE}
|
||||
|
||||
ARG VITE_MEDIA_BASE_URL
|
||||
ENV VITE_MEDIA_BASE_URL=${VITE_MEDIA_BASE_URL}
|
||||
|
||||
RUN npm run build
|
||||
|
||||
# ---- Front-end image ----
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "meet",
|
||||
"version": "1.32.1",
|
||||
"version": "1.33.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "meet",
|
||||
"version": "1.32.1",
|
||||
"version": "1.33.0",
|
||||
"dependencies": {
|
||||
"@fontsource-variable/atkinson-hyperlegible-next": "5.3.0",
|
||||
"@fontsource-variable/lexend": "5.3.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "meet",
|
||||
"private": true,
|
||||
"version": "1.32.1",
|
||||
"version": "1.33.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "panda codegen && vite",
|
||||
|
||||
@@ -121,7 +121,7 @@ const config: Config = {
|
||||
},
|
||||
tokens: defineTokens({
|
||||
/* we take a few things from the panda preset but for now we clear out some stuff.
|
||||
* This way we'll only add the things we need step by step and prevent using lots of differents things.
|
||||
* This way we'll only add the things we need step by step and prevent using lots of different things.
|
||||
*/
|
||||
...pandaPreset.theme.tokens,
|
||||
colors: defineTokens.colors({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export const mediaUrl = (path: string) => {
|
||||
const origin =
|
||||
import.meta.env.VITE_MEDIA_BASE_URL ||
|
||||
import.meta.env.VITE_API_BASE_URL ||
|
||||
(typeof window !== 'undefined' ? window.location.origin : '')
|
||||
|
||||
// Remove leading/trailing slashes from origin/path if it exists
|
||||
|
||||
@@ -45,6 +45,10 @@ export const ScreenRecordingSidePanel = () => {
|
||||
FeatureFlags.ScreenRecording
|
||||
)
|
||||
|
||||
const hasTranscriptAccess = useHasRecordingAccess(
|
||||
RecordingMode.Transcript,
|
||||
FeatureFlags.Transcript
|
||||
)
|
||||
const { notifyParticipants } = useNotifyParticipants()
|
||||
const { selectedLanguageKey, isLanguageSetToAuto } =
|
||||
useTranscriptionLanguage()
|
||||
@@ -88,7 +92,7 @@ export const ScreenRecordingSidePanel = () => {
|
||||
...(!isLanguageSetToAuto && {
|
||||
language: selectedLanguageKey,
|
||||
}),
|
||||
...(includeTranscript && { transcribe: true }),
|
||||
...(includeTranscript && hasTranscriptAccess && { transcribe: true }),
|
||||
}
|
||||
|
||||
await startRecording({
|
||||
@@ -182,24 +186,26 @@ export const ScreenRecordingSidePanel = () => {
|
||||
<RowWrapper iconName="mail" position="last">
|
||||
<Text variant="sm">{t('details.receiver')}</Text>
|
||||
</RowWrapper>
|
||||
|
||||
<div className={css({ height: '15px' })} />
|
||||
|
||||
<div
|
||||
className={css({
|
||||
width: '100%',
|
||||
marginLeft: '20px',
|
||||
})}
|
||||
>
|
||||
<Checkbox
|
||||
size="sm"
|
||||
isSelected={includeTranscript}
|
||||
onChange={setIncludeTranscript}
|
||||
isDisabled={statuses.isActive || isPendingToStart}
|
||||
>
|
||||
<Text variant="sm">{t('details.transcription')}</Text>
|
||||
</Checkbox>
|
||||
</div>
|
||||
{hasTranscriptAccess && (
|
||||
<>
|
||||
<div className={css({ height: '15px' })} />
|
||||
<div
|
||||
className={css({
|
||||
width: '100%',
|
||||
marginLeft: '20px',
|
||||
})}
|
||||
>
|
||||
<Checkbox
|
||||
size="sm"
|
||||
isSelected={includeTranscript}
|
||||
onChange={setIncludeTranscript}
|
||||
isDisabled={statuses.isActive || isPendingToStart}
|
||||
>
|
||||
<Text variant="sm">{t('details.transcription')}</Text>
|
||||
</Checkbox>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</VStack>
|
||||
<ControlsButton
|
||||
i18nKeyPrefix={keyPrefix}
|
||||
|
||||
@@ -53,6 +53,10 @@ export const TranscriptSidePanel = () => {
|
||||
FeatureFlags.Transcript
|
||||
)
|
||||
|
||||
const hasScreenRecordingAccess = useHasRecordingAccess(
|
||||
RecordingMode.ScreenRecording,
|
||||
FeatureFlags.ScreenRecording
|
||||
)
|
||||
const hasFeatureWithoutAdminRights = useHasFeatureWithoutAdminRights(
|
||||
RecordingMode.Transcript,
|
||||
FeatureFlags.Transcript
|
||||
@@ -97,7 +101,9 @@ export const TranscriptSidePanel = () => {
|
||||
room.localParticipant
|
||||
)
|
||||
} else {
|
||||
const recordingMode = includeScreenRecording
|
||||
const withScreenRecording =
|
||||
includeScreenRecording && hasScreenRecordingAccess
|
||||
const recordingMode = withScreenRecording
|
||||
? RecordingMode.ScreenRecording
|
||||
: RecordingMode.Transcript
|
||||
|
||||
@@ -105,7 +111,7 @@ export const TranscriptSidePanel = () => {
|
||||
...(!isLanguageSetToAuto && {
|
||||
language: selectedLanguageKey,
|
||||
}),
|
||||
...(includeScreenRecording && {
|
||||
...(withScreenRecording && {
|
||||
transcribe: true,
|
||||
original_mode: RecordingMode.Transcript,
|
||||
}),
|
||||
@@ -122,7 +128,7 @@ export const TranscriptSidePanel = () => {
|
||||
type: NotificationType.TranscriptionStarted,
|
||||
})
|
||||
captureEvent('transcript-started', {
|
||||
includeScreenRecording: includeScreenRecording,
|
||||
includeScreenRecording: withScreenRecording,
|
||||
language: selectedLanguageKey,
|
||||
})
|
||||
}
|
||||
@@ -234,22 +240,26 @@ export const TranscriptSidePanel = () => {
|
||||
</Button>
|
||||
</Text>
|
||||
</RowWrapper>
|
||||
<div className={css({ height: '15px' })} />
|
||||
<div
|
||||
className={css({
|
||||
width: '100%',
|
||||
marginLeft: '20px',
|
||||
})}
|
||||
>
|
||||
<Checkbox
|
||||
size="sm"
|
||||
isSelected={includeScreenRecording}
|
||||
onChange={setIncludeScreenRecording}
|
||||
isDisabled={statuses.isActive || isPendingToStart}
|
||||
>
|
||||
<Text variant="sm">{t('details.recording')}</Text>
|
||||
</Checkbox>
|
||||
</div>
|
||||
{hasScreenRecordingAccess && (
|
||||
<>
|
||||
<div className={css({ height: '15px' })} />
|
||||
<div
|
||||
className={css({
|
||||
width: '100%',
|
||||
marginLeft: '20px',
|
||||
})}
|
||||
>
|
||||
<Checkbox
|
||||
size="sm"
|
||||
isSelected={includeScreenRecording}
|
||||
onChange={setIncludeScreenRecording}
|
||||
isDisabled={statuses.isActive || isPendingToStart}
|
||||
>
|
||||
<Text variant="sm">{t('details.recording')}</Text>
|
||||
</Checkbox>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</VStack>
|
||||
<ControlsButton
|
||||
i18nKeyPrefix={keyPrefix}
|
||||
|
||||
@@ -148,7 +148,7 @@ const RecordingDownload = () => {
|
||||
</Text>
|
||||
<LinkButton
|
||||
href={mediaUrl(data.key)}
|
||||
download={`${data.room.name}-${formatDate(data.created_at)}.${data.key.split('.').pop()}`}
|
||||
download={`${data.room.name}-${formatDate(data.created_at)}`}
|
||||
>
|
||||
{t('success.button')}
|
||||
</LinkButton>
|
||||
|
||||
@@ -158,7 +158,7 @@ export const Conference = ({
|
||||
*
|
||||
* Issue: On Firefox behind proxy configurations, WebSocket signaling fails to establish.
|
||||
* Symptom: Client receives HTTP 200 instead of expected 101 (Switching Protocols).
|
||||
* Root Cause: Certificate/security issue where the initial request is considered unsecure.
|
||||
* Root Cause: Certificate/security issue where the initial request is considered insecure.
|
||||
*
|
||||
* Solution: Pre-establish a WebSocket connection to the signaling server, which fails.
|
||||
* This "primes" the connection, allowing subsequent WebSocket establishments to work correctly.
|
||||
|
||||
Vendored
-1
@@ -6,7 +6,6 @@ declare const __MEDIAPIPE_VERSION__: string
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_API_BASE_URL: string
|
||||
readonly VITE_APP_TITLE: string
|
||||
readonly VITE_MEDIA_BASE_URL?: string
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
docker image ls | grep readme-generator-for-helm
|
||||
if [ "$?" -ne "0" ]; then
|
||||
if ! docker image ls | grep readme-generator-for-helm; then
|
||||
git clone https://github.com/bitnami/readme-generator-for-helm.git /tmp/readme-generator-for-helm
|
||||
cd /tmp/readme-generator-for-helm
|
||||
cd /tmp/readme-generator-for-helm || exit 1
|
||||
docker build -t readme-generator-for-helm:latest .
|
||||
cd $(dirname -- "${BASH_SOURCE[0]}")
|
||||
cd "$(dirname -- "${BASH_SOURCE[0]}")" || exit 1
|
||||
fi
|
||||
docker run --rm -it -v .:/source -w /source readme-generator-for-helm:latest readme-generator -v values.yaml -r README.md
|
||||
|
||||
@@ -51,7 +51,7 @@ app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
transform dictionnary of environment variables
|
||||
transform dictionary of environment variables
|
||||
Usage : {{ include "meet.env.transformDict" .Values.envVars }}
|
||||
|
||||
Example:
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "mail_mjml",
|
||||
"version": "1.32.1",
|
||||
"version": "1.33.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "mail_mjml",
|
||||
"version": "1.32.1",
|
||||
"version": "1.33.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@html-to/text-cli": "0.6.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mail_mjml",
|
||||
"version": "1.32.1",
|
||||
"version": "1.33.0",
|
||||
"description": "An util to generate html and text django's templates from mjml templates",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "sdk",
|
||||
"version": "1.32.1",
|
||||
"version": "1.33.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "sdk",
|
||||
"version": "1.32.1",
|
||||
"version": "1.33.0",
|
||||
"license": "ISC",
|
||||
"workspaces": [
|
||||
"./library",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sdk",
|
||||
"version": "1.32.1",
|
||||
"version": "1.33.0",
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
[project]
|
||||
name = "summary"
|
||||
version = "1.32.1"
|
||||
version = "1.33.0"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"fastapi[standard]>=0.105.0",
|
||||
|
||||
Generated
+1
-1
@@ -1484,7 +1484,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "summary"
|
||||
version = "1.32.1"
|
||||
version = "1.33.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "boto3" },
|
||||
|
||||
Reference in New Issue
Block a user