Compare commits

..

1 Commits

Author SHA1 Message Date
lebaudantoine
8b60bc57e6 wip use our internal llm + switch from json to markdown
simplify LLM's job. Do not request Json output with a single key. Instead,
make sure LLM don't output any extra information.

By simplifying LLM's job, we're making sure its output can be parsed.

I did a quick test with the Translate prompt. Adding instructions to output
only translated text seems enough after a bunch of tests.

I did a small prompt engineering, using ChatGPT and Claude to generate
a proper system prompt … it works quite okay BUT there is room for
improvement for sure.

I'ven't searched yet OS prompts we could find in a prompt library.
Perfect translation job seems to be a difficult job for a 8B model.

Please note I haven't updated yet the other prompts, let's discuss it before.
I ran my experiment with our internal LLM which is optimized for throughput,
and not latency (there is a trade-off). I'll try fine tune few of its parameters to
see if I can reduce its latency.

For 880 tokens (based on chatgpt tokens counter online). It takes roughly
17s, vs ~40s for Albert CNRS 70B.

For 180 tokens it takes roughly 3s. Without a proper UX (eg. a nicer loading
animation, streaming tokens) it feels a decade. However, asking Chatgpt the
same job take the same amount, from submitting the request to the last
token being generated.
2024-12-16 00:59:21 +01:00
57 changed files with 1121 additions and 1404 deletions

View File

@@ -156,7 +156,7 @@ jobs:
name: Run trivy scan
uses: numerique-gouv/action-trivy-cache@main
with:
docker-build-args: '-f src/frontend/servers/y-provider/Dockerfile --target y-provider'
docker-build-args: '-f src/frontend/Dockerfile --target y-provider'
docker-image-name: 'docker.io/lasuite/impress-frontend:${{ github.sha }}'
continue-on-error: true
-
@@ -164,7 +164,7 @@ jobs:
uses: docker/build-push-action@v6
with:
context: .
file: ./src/frontend/servers/y-provider/Dockerfile
file: ./src/frontend/Dockerfile
target: y-provider
build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
push: ${{ github.event_name != 'pull_request' }}

View File

@@ -95,12 +95,12 @@ jobs:
- name: Set e2e env variables
run: cat env.d/development/common.e2e.dist >> env.d/development/common.dist
- name: Install Playwright Browsers
run: cd src/frontend/apps/e2e && yarn install --frozen-lockfile && yarn install-playwright chromium
- name: Start Docker services
run: make bootstrap FLUSH_ARGS='--no-input' cache=
- name: Install Playwright Browsers
run: cd src/frontend/apps/e2e && yarn install-playwright chromium
# Tool to wait for a service to be ready
- name: Install Dockerize
run: |
@@ -151,12 +151,12 @@ jobs:
- name: Set e2e env variables
run: cat env.d/development/common.e2e.dist >> env.d/development/common.dist
- name: Install Playwright Browsers
run: cd src/frontend/apps/e2e && yarn install --frozen-lockfile && yarn install-playwright firefox webkit chromium
- name: Start Docker services
run: make bootstrap FLUSH_ARGS='--no-input' cache=
- name: Install Playwright Browsers
run: cd src/frontend/apps/e2e && yarn install-playwright firefox webkit chromium
- name: Run e2e tests
run: cd src/frontend/ && yarn e2e:test --project=firefox --project=webkit

View File

@@ -11,25 +11,8 @@ and this project adheres to
## Added
🔧(helm) add option to disable default tls setting by @dominikkaminski #519
📸(helm) production-example #529
## [1.10.0] - 2024-12-17
## Added
- ✨(backend) add server-to-server API endpoint to create documents #467
- ✨(email) white brand email #412
- ✨(y-provider) create a markdown converter endpoint #488
## Changed
- ⚡️(docker) improve y-provider image #422
## Fixed
- ⚡️(e2e) reduce flakiness on e2e tests #511
## [1.9.0] - 2024-12-11
@@ -38,6 +21,7 @@ and this project adheres to
- ✨(backend) annotate number of accesses on documents in list view #429
- ✨(backend) allow users to mark/unmark documents as favorite #429
- ✨(y-provider) create a markdown converter endpoint #488
## Changed
@@ -326,8 +310,7 @@ and this project adheres to
- 🚀 Impress, project to manage your documents easily and collaboratively.
[unreleased]: https://github.com/numerique-gouv/impress/compare/v1.10.0...main
[v1.10.0]: https://github.com/numerique-gouv/impress/releases/v1.10.0
[unreleased]: https://github.com/numerique-gouv/impress/compare/v1.9.0...main
[v1.9.0]: https://github.com/numerique-gouv/impress/releases/v1.9.0
[v1.8.2]: https://github.com/numerique-gouv/impress/releases/v1.8.2
[v1.8.1]: https://github.com/numerique-gouv/impress/releases/v1.8.1

View File

@@ -20,7 +20,7 @@ docker_build(
docker_build(
'localhost:5001/impress-y-provider:latest',
context='..',
dockerfile='../src/frontend/servers/y-provider/Dockerfile',
dockerfile='../src/frontend/Dockerfile',
only=['./src/frontend/', './docker/', './.dockerignore'],
target = 'y-provider',
live_update=[

View File

@@ -159,13 +159,17 @@ services:
user: ${DOCKER_USER:-1000}
build:
context: .
dockerfile: ./src/frontend/servers/y-provider/Dockerfile
dockerfile: ./src/frontend/Dockerfile
target: y-provider
restart: unless-stopped
env_file:
- env.d/development/common
ports:
- "4444:4444"
volumes:
- ./src/frontend/servers/y-provider:/home/frontend/servers/y-provider
- /home/frontend/servers/y-provider/node_modules/
- /home/frontend/servers/y-provider/dist/
kc_postgresql:
image: postgres:14.3

View File

@@ -1,6 +1,3 @@
# For the CI job test-e2e
SUSTAINED_THROTTLE_RATES="200/hour"
BURST_THROTTLE_RATES="200/minute"
DJANGO_SERVER_TO_SERVER_API_TOKENS=test-e2e
Y_PROVIDER_API_KEY=yprovider-api-key
Y_PROVIDER_API_BASE_URL=http://y-provider:4444/api/

View File

@@ -275,7 +275,7 @@ class ServerCreateDocumentSerializer(serializers.Serializer):
language = user.language or language
try:
document_content = YdocConverter().convert_markdown(
converter_response = YdocConverter().convert_markdown(
validated_data["content"]
)
except ConversionError as err:
@@ -283,7 +283,7 @@ class ServerCreateDocumentSerializer(serializers.Serializer):
document = models.Document.objects.create(
title=validated_data["title"],
content=document_content,
content=converter_response["content"],
creator=user,
)

View File

@@ -594,7 +594,7 @@ class Document(BaseModel):
name=sender_name
),
"message": _(
'{name} invited you with the role "{role}" on the following document:'
"{name} invited you with the role ``{role}`` on the following document:"
).format(name=sender_name_email, role=role.lower()),
}
subject = _("{name} shared a document with you: {title}").format(

View File

@@ -35,10 +35,29 @@ AI_ACTIONS = {
),
}
AI_TRANSLATE = (
"Translate the markdown text to {language:s}, preserving markdown formatting. "
'Return JSON: {{"answer": "your translated markdown text in {language:s}"}}. '
"Do not provide any other information."
"""
You are a professional translator for `{language:s}`.
### Guidelines:
1. **Preserve exactly as-is:**
- All formatting, markdown, symbols, tags
- Names, numbers, URLs, citations
- Code blocks and technical terms
2. **Translation Rules:**
- Use natural expressions in the target language
- Match the tone of the source text (default: professional)
- Maintain original meaning precisely
- Adapt idioms to suit the target culture
- Ensure grammatical correctness stylistic coherence
3. **Do Not:**
- Add, remove, or explain any content
Output only the translated text, keeping all original formatting intact.
"""
)
@@ -59,32 +78,14 @@ class AIService:
"""Helper method to call the OpenAI API and process the response."""
response = self.client.chat.completions.create(
model=settings.AI_MODEL,
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": system_content},
{"role": "user", "content": json.dumps({"markdown_input": text})},
{"role": "user", "content": text},
],
)
content = response.choices[0].message.content
try:
sanitized_content = re.sub(r'\s*"answer"\s*:\s*', '"answer": ', content)
sanitized_content = re.sub(r"\s*\}", "}", sanitized_content)
sanitized_content = re.sub(r"(?<!\\)\n", "\\\\n", sanitized_content)
sanitized_content = re.sub(r"(?<!\\)\t", "\\\\t", sanitized_content)
json_response = json.loads(sanitized_content)
except (json.JSONDecodeError, IndexError):
try:
json_response = json.loads(content)
except json.JSONDecodeError as err:
raise RuntimeError("AI response is not valid JSON", content) from err
if "answer" not in json_response:
raise RuntimeError("AI response does not contain an answer")
return json_response
return {"answer": content}
def transform(self, text, action):
"""Transform text based on specified action."""

View File

@@ -26,7 +26,6 @@ class CollaborationService:
# same pod thanks to a parameter
endpoint_url = f"{settings.COLLABORATION_API_URL}{endpoint}/?room={room}"
# Note: Collaboration microservice accepts only raw token, which is not recommended
headers = {"Authorization": settings.COLLABORATION_SERVER_SECRET}
if user_id:
headers["X-User-Id"] = user_id

View File

@@ -31,8 +31,7 @@ class YdocConverter:
@property
def auth_header(self):
"""Build microservice authentication header."""
# Note: Yprovider microservice accepts only raw token, which is not recommended
return settings.Y_PROVIDER_API_KEY
return f"Bearer {settings.CONVERSION_API_KEY}"
def convert_markdown(self, text):
"""Convert a Markdown text into our internal format using an external microservice."""
@@ -42,7 +41,7 @@ class YdocConverter:
try:
response = requests.post(
f"{settings.Y_PROVIDER_API_BASE_URL}{settings.CONVERSION_API_ENDPOINT}/",
settings.CONVERSION_API_URL,
json={
"content": text,
},
@@ -51,7 +50,6 @@ class YdocConverter:
"Content-Type": "application/json",
},
timeout=settings.CONVERSION_API_TIMEOUT,
verify=settings.CONVERSION_API_SECURE,
)
response.raise_for_status()
conversion_response = response.json()

View File

@@ -173,7 +173,7 @@ def test_api_document_accesses_create_authenticated_administrator(via, mock_user
email_content = " ".join(email.body.split())
assert f"{user.full_name} shared a document with you!" in email_content
assert (
f"{user.full_name} ({user.email}) invited you with the role &quot;{role}&quot; "
f"{user.full_name} ({user.email}) invited you with the role ``{role}`` "
f"on the following document: {document.title}"
) in email_content
assert "docs/" + str(document.id) + "/" in email_content
@@ -231,7 +231,7 @@ def test_api_document_accesses_create_authenticated_owner(via, mock_user_teams):
email_content = " ".join(email.body.split())
assert f"{user.full_name} shared a document with you!" in email_content
assert (
f"{user.full_name} ({user.email}) invited you with the role &quot;{role}&quot; "
f"{user.full_name} ({user.email}) invited you with the role ``{role}`` "
f"on the following document: {document.title}"
) in email_content
assert "docs/" + str(document.id) + "/" in email_content

View File

@@ -406,7 +406,7 @@ def test_api_document_invitations_create_privileged_members(
email_content = " ".join(email.body.split())
assert f"{user.full_name} shared a document with you!" in email_content
assert (
f"{user.full_name} ({user.email}) invited you with the role &quot;{invited}&quot; "
f"{user.full_name} ({user.email}) invited you with the role ``{invited}`` "
f"on the following document: {document.title}"
) in email_content
assert "My brand name" in email_content
@@ -536,7 +536,7 @@ def test_api_document_invitations_create_email_full_name_empty():
email_content = " ".join(email.body.split())
assert f"{user.email} shared a document with you!" in email_content
assert (
f"{user.email.capitalize()} invited you with the role &quot;reader&quot; on the "
f"{user.email.capitalize()} invited you with the role ``reader`` on the "
f"following document: {document.title}" in email_content
)

View File

@@ -25,7 +25,7 @@ def mock_convert_markdown():
with patch.object(
YdocConverter,
"convert_markdown",
return_value="Converted document content",
return_value={"content": "Converted document content"},
) as mock:
yield mock

View File

@@ -441,7 +441,7 @@ def test_models_documents__email_invitation__success():
email_content = " ".join(email.body.split())
assert (
f"Test Sender (sender@example.com) invited you with the role &quot;editor&quot; "
f"Test Sender (sender@example.com) invited you with the role ``editor`` "
f"on the following document: {document.title}" in email_content
)
assert f"docs/{document.id}/" in email_content
@@ -476,8 +476,8 @@ def test_models_documents__email_invitation__success_fr():
email_content = " ".join(email.body.split())
assert (
f"Test Sender2 (sender2@example.com) vous a invité avec le rôle &quot;propriétaire&quot; "
f"sur le document suivant: {document.title}" in email_content
f"Test Sender2 (sender2@example.com) vous a invité avec le rôle ``propriétaire`` "
f"sur le document suivant : {document.title}" in email_content
)
assert f"docs/{document.id}/" in email_content

View File

@@ -16,9 +16,9 @@ from core.services.converter_services import (
def test_auth_header(settings):
"""Test authentication header generation."""
settings.Y_PROVIDER_API_KEY = "test-key"
settings.CONVERSION_API_KEY = "test-key"
converter = YdocConverter()
assert converter.auth_header == "test-key"
assert converter.auth_header == "Bearer test-key"
def test_convert_markdown_empty_text():
@@ -97,9 +97,8 @@ def test_convert_markdown_missing_content_field(mock_post, settings):
def test_convert_markdown_full_integration(mock_post, settings):
"""Test full integration with all settings."""
settings.Y_PROVIDER_API_BASE_URL = "http://test.com/"
settings.Y_PROVIDER_API_KEY = "test-key"
settings.CONVERSION_API_ENDPOINT = "conversion-endpoint"
settings.CONVERSION_API_URL = "http://test.com"
settings.CONVERSION_API_KEY = "test-key"
settings.CONVERSION_API_TIMEOUT = 5
settings.CONVERSION_API_CONTENT_FIELD = "content"
@@ -114,14 +113,13 @@ def test_convert_markdown_full_integration(mock_post, settings):
assert result == expected_content
mock_post.assert_called_once_with(
"http://test.com/conversion-endpoint/",
"http://test.com",
json={"content": "test markdown"},
headers={
"Authorization": "test-key",
"Authorization": "Bearer test-key",
"Content-Type": "application/json",
},
timeout=5,
verify=False,
)

View File

@@ -505,20 +505,13 @@ class Base(Configuration):
"day": 200,
}
# Y provider microservice
Y_PROVIDER_API_KEY = values.Value(
environ_name="Y_PROVIDER_API_KEY",
# Conversion microservice
CONVERSION_API_KEY = values.Value(
environ_name="CONVERSION_API_KEY",
environ_prefix=None,
)
Y_PROVIDER_API_BASE_URL = values.Value(
environ_name="Y_PROVIDER_API_BASE_URL",
environ_prefix=None,
)
# Conversion endpoint
CONVERSION_API_ENDPOINT = values.Value(
default="convert-markdown",
environ_name="CONVERSION_API_ENDPOINT",
CONVERSION_API_URL = values.Value(
environ_name="CONVERSION_API_URL",
environ_prefix=None,
)
CONVERSION_API_CONTENT_FIELD = values.Value(
@@ -531,11 +524,6 @@ class Base(Configuration):
environ_name="CONVERSION_API_TIMEOUT",
environ_prefix=None,
)
CONVERSION_API_SECURE = values.Value(
default=False,
environ_name="CONVERSION_API_SECURE",
environ_prefix=None,
)
# Logging
# We want to make it easy to log to console but by default we log production

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: lasuite-people\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-17 15:50+0000\n"
"PO-Revision-Date: 2024-12-17 15:53\n"
"POT-Creation-Date: 2024-12-13 15:17+0000\n"
"PO-Revision-Date: 2024-12-13 15:22\n"
"Last-Translator: \n"
"Language-Team: German\n"
"Language: de_DE\n"
@@ -220,7 +220,7 @@ msgstr ""
#: core/models.py:597
#, python-brace-format
msgid "{name} invited you with the role \"{role}\" on the following document:"
msgid "{name} invited you with the role ``{role}`` on the following document:"
msgstr ""
#: core/models.py:600

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: lasuite-people\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-17 15:50+0000\n"
"PO-Revision-Date: 2024-12-17 15:53\n"
"POT-Creation-Date: 2024-12-13 15:17+0000\n"
"PO-Revision-Date: 2024-12-13 15:22\n"
"Last-Translator: \n"
"Language-Team: English\n"
"Language: en_US\n"
@@ -220,7 +220,7 @@ msgstr ""
#: core/models.py:597
#, python-brace-format
msgid "{name} invited you with the role \"{role}\" on the following document:"
msgid "{name} invited you with the role ``{role}`` on the following document:"
msgstr ""
#: core/models.py:600

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: lasuite-people\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-17 15:50+0000\n"
"PO-Revision-Date: 2024-12-17 15:53\n"
"POT-Creation-Date: 2024-12-13 15:17+0000\n"
"PO-Revision-Date: 2024-12-13 16:47\n"
"Last-Translator: \n"
"Language-Team: French\n"
"Language: fr_FR\n"
@@ -220,8 +220,8 @@ msgstr "{name} a partagé un document avec vous!"
#: core/models.py:597
#, python-brace-format
msgid "{name} invited you with the role \"{role}\" on the following document:"
msgstr "{name} vous a invité avec le rôle \"{role}\" sur le document suivant:"
msgid "{name} invited you with the role ``{role}`` on the following document:"
msgstr "{name} vous a invité avec le rôle ``{role}`` sur le document suivant :"
#: core/models.py:600
#, python-brace-format

View File

@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "impress"
version = "1.10.0"
version = "1.9.0"
authors = [{ "name" = "DINUM", "email" = "dev@mail.numerique.gouv.fr" }]
classifiers = [
"Development Status :: 5 - Production/Stable",
@@ -25,7 +25,7 @@ license = { file = "LICENSE" }
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"boto3==1.35.81",
"boto3==1.35.79",
"Brotli==1.1.0",
"celery[redis]==5.4.0",
"django-configurations==2.5.1",
@@ -47,7 +47,7 @@ dependencies = [
"jsonschema==4.23.0",
"markdown==3.7",
"nested-multipart-parser==1.5.0",
"openai==1.57.4",
"openai==1.57.2",
"psycopg[binary]==3.2.3",
"PyJWT==2.10.1",
"pypandoc==1.14",
@@ -74,7 +74,7 @@ dev = [
"freezegun==1.5.1",
"ipdb==0.13.13",
"ipython==8.30.0",
"pyfakefs==5.7.3",
"pyfakefs==5.7.2",
"pylint-django==2.6.1",
"pylint==3.3.2",
"pytest-cov==6.0.0",

View File

@@ -1,3 +1,33 @@
FROM node:20-alpine AS frontend-deps-y-provider
WORKDIR /home/frontend/
COPY ./src/frontend/package.json ./package.json
COPY ./src/frontend/yarn.lock ./yarn.lock
COPY ./src/frontend/servers/y-provider/package.json ./servers/y-provider/package.json
COPY ./src/frontend/packages/eslint-config-impress/package.json ./packages/eslint-config-impress/package.json
RUN yarn install
COPY ./src/frontend/ .
# Copy entrypoint
COPY ./docker/files/usr/local/bin/entrypoint /usr/local/bin/entrypoint
# ---- y-provider ----
FROM frontend-deps-y-provider AS y-provider
WORKDIR /home/frontend/servers/y-provider
RUN yarn build
# Un-privileged user running the application
ARG DOCKER_USER
USER ${DOCKER_USER}
ENTRYPOINT [ "/usr/local/bin/entrypoint" ]
CMD ["yarn", "start"]
FROM node:20-alpine AS frontend-deps
WORKDIR /home/frontend/
@@ -10,9 +40,7 @@ COPY ./src/frontend/packages/eslint-config-impress/package.json ./packages/eslin
RUN yarn install --frozen-lockfile
COPY .dockerignore ./.dockerignore
COPY ./src/frontend/.prettierrc.js ./.prettierrc.js
COPY ./src/frontend/packages/eslint-config-impress ./packages/eslint-config-impress
COPY ./src/frontend/apps/impress ./apps/impress
COPY ./src/frontend/ .
### ---- Front-end builder image ----
FROM frontend-deps AS impress

View File

@@ -1,6 +1,6 @@
import { expect, test } from '@playwright/test';
import { createDoc, goToGridDoc, keyCloakSignIn, randomName } from './common';
import { createDoc } from './common';
test.beforeEach(async ({ page }) => {
await page.goto('/');
@@ -29,47 +29,3 @@ test.describe('Doc Create', () => {
});
});
});
test.describe('Doc Create: Not loggued', () => {
test.use({ storageState: { cookies: [], origins: [] } });
test('it creates a doc server way', async ({
page,
browserName,
request,
}) => {
const markdown = `This is a normal text\n\n# And this is a large heading`;
const [title] = randomName('My server way doc create', browserName, 1);
const data = {
title,
content: markdown,
sub: `user@${browserName}.e2e`,
email: `user@${browserName}.e2e`,
};
const newDoc = await request.post(
`http://localhost:8071/api/v1.0/documents/create-for-owner/`,
{
data,
headers: {
Authorization: 'Bearer test-e2e',
format: 'json',
},
},
);
expect(newDoc.ok()).toBeTruthy();
await keyCloakSignIn(page, browserName);
await goToGridDoc(page, { title });
await expect(page.getByRole('heading', { name: title })).toBeVisible();
const editor = page.locator('.ProseMirror');
await expect(editor.getByText('This is a normal text')).toBeVisible();
await expect(
editor.locator('h1').getByText('And this is a large heading'),
).toBeVisible();
});
});

View File

@@ -233,7 +233,7 @@ test.describe('Doc Editor', () => {
test.skip(browserName === 'webkit', 'This test is very flaky with webkit');
// Check the first doc
const [doc] = await createDoc(page, 'doc-quit-1', browserName, 1);
const doc = await goToGridDoc(page);
await expect(page.locator('h2').getByText(doc)).toBeVisible();
const editor = page.locator('.ProseMirror');
@@ -272,8 +272,8 @@ test.describe('Doc Editor', () => {
).toBeVisible();
});
test('it adds an image to the doc editor', async ({ page, browserName }) => {
await createDoc(page, 'doc-image', browserName, 1);
test('it adds an image to the doc editor', async ({ page }) => {
await goToGridDoc(page);
const fileChooserPromise = page.waitForEvent('filechooser');

View File

@@ -120,14 +120,13 @@ test.describe('Doc Header', () => {
await editor.locator('h1').fill('');
// eslint-disable-next-line playwright/no-wait-for-timeout
await page.waitForTimeout(500);
await docHeader
.getByRole('heading', { name: 'Top World', level: 2 })
.fill(' ');
await page.getByText('Created at').click();
await page.getByText('Created at').click({
delay: 200,
});
await expect(
docHeader.getByRole('heading', { name: 'Untitled document', level: 2 }),

View File

@@ -1,6 +1,6 @@
{
"name": "app-e2e",
"version": "1.10.0",
"version": "1.9.0",
"private": true,
"scripts": {
"lint": "eslint . --ext .ts",
@@ -12,7 +12,7 @@
"test:ui::chromium": "yarn test:ui --project=chromium"
},
"devDependencies": {
"@playwright/test": "1.49.1",
"@playwright/test": "1.49.0",
"@types/node": "*",
"@types/pdf-parse": "1.1.4",
"eslint-config-impress": "*",

View File

@@ -19,7 +19,6 @@ export default defineConfig({
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
maxFailures: process.env.CI ? 3 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 3 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */

View File

@@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.

View File

@@ -1,6 +1,6 @@
{
"name": "app-impress",
"version": "1.10.0",
"version": "1.9.0",
"private": true,
"scripts": {
"dev": "next dev",
@@ -19,33 +19,33 @@
"@blocknote/mantine": "*",
"@blocknote/react": "*",
"@gouvfr-lasuite/integration": "1.0.2",
"@hocuspocus/provider": "2.15.0",
"@hocuspocus/provider": "2.14.0",
"@openfun/cunningham-react": "2.9.4",
"@sentry/nextjs": "8.45.1",
"@tanstack/react-query": "5.62.7",
"@sentry/nextjs": "8.42.0",
"@tanstack/react-query": "5.62.2",
"crisp-sdk-web": "1.0.25",
"i18next": "24.1.0",
"i18next-browser-languagedetector": "8.0.2",
"idb": "8.0.1",
"i18next": "24.0.5",
"i18next-browser-languagedetector": "8.0.0",
"idb": "8.0.0",
"lodash": "4.17.21",
"luxon": "3.5.0",
"next": "15.1.0",
"next": "15.0.3",
"react": "*",
"react-aria-components": "1.5.0",
"react-dom": "*",
"react-i18next": "15.2.0",
"react-select": "5.9.0",
"react-i18next": "15.1.3",
"react-select": "5.8.3",
"styled-components": "6.1.13",
"y-protocols": "1.0.6",
"yjs": "*",
"zustand": "5.0.2"
"zustand": "5.0.1"
},
"devDependencies": {
"@svgr/webpack": "8.1.0",
"@tanstack/react-query-devtools": "5.62.7",
"@tanstack/react-query-devtools": "5.62.2",
"@testing-library/dom": "10.4.0",
"@testing-library/jest-dom": "6.6.3",
"@testing-library/react": "16.1.0",
"@testing-library/react": "16.0.1",
"@testing-library/user-event": "14.5.2",
"@types/jest": "29.5.14",
"@types/lodash": "4.17.13",
@@ -60,12 +60,12 @@
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"node-fetch": "2.7.0",
"prettier": "3.4.2",
"stylelint": "16.12.0",
"prettier": "3.4.1",
"stylelint": "16.11.0",
"stylelint-config-standard": "36.0.1",
"stylelint-prettier": "5.0.2",
"typescript": "*",
"webpack": "5.97.1",
"webpack": "5.97.0",
"workbox-webpack-plugin": "7.1.0"
}
}

View File

@@ -2,29 +2,27 @@ import '@blocknote/mantine/style.css';
import {
FormattingToolbar,
FormattingToolbarController,
FormattingToolbarProps,
getFormattingToolbarItems,
} from '@blocknote/react';
import React, { useCallback } from 'react';
import React from 'react';
import { AIGroupButton } from './AIButton';
import { MarkdownButton } from './MarkdownButton';
export const BlockNoteToolbar = () => {
const formattingToolbar = useCallback(
({ blockTypeSelectItems }: FormattingToolbarProps) => (
<FormattingToolbar>
{getFormattingToolbarItems(blockTypeSelectItems)}
return (
<FormattingToolbarController
formattingToolbar={({ blockTypeSelectItems }) => (
<FormattingToolbar>
{getFormattingToolbarItems(blockTypeSelectItems)}
{/* Extra button to do some AI powered actions */}
<AIGroupButton key="AIButton" />
{/* Extra button to do some AI powered actions */}
<AIGroupButton key="AIButton" />
{/* Extra button to convert from markdown to json */}
<MarkdownButton key="customButton" />
</FormattingToolbar>
),
[],
{/* Extra button to convert from markdown to json */}
<MarkdownButton key="customButton" />
</FormattingToolbar>
)}
/>
);
return <FormattingToolbarController formattingToolbar={formattingToolbar} />;
};

View File

@@ -65,6 +65,10 @@ const DocPage = ({ id }: DocProps) => {
setDoc(docQuery);
setCurrentDoc(docQuery);
return () => {
setCurrentDoc(undefined);
};
}, [docQuery, setCurrentDoc]);
useEffect(() => {

View File

@@ -25,7 +25,7 @@ export const useSentryStore = create<SentryState>((set, get) => ({
release: packageJson.version,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
tracesSampleRate: 0.1,
tracesSampleRate: 1.0,
}),
});
},

View File

@@ -1,6 +1,6 @@
{
"name": "impress",
"version": "1.10.0",
"version": "1.9.0",
"private": true,
"workspaces": {
"packages": [
@@ -28,13 +28,13 @@
"server:test": "yarn COLLABORATION_SERVER run test"
},
"resolutions": {
"@blocknote/core": "0.21.0",
"@blocknote/mantine": "0.21.0",
"@blocknote/react": "0.21.0",
"@types/node": "22.10.2",
"@blocknote/core": "0.20.0",
"@blocknote/mantine": "0.20.0",
"@blocknote/react": "0.20.0",
"@types/node": "22.10.1",
"@types/react-dom": "18.3.1",
"@typescript-eslint/eslint-plugin": "8.18.0",
"@typescript-eslint/parser": "8.18.0",
"@typescript-eslint/eslint-plugin": "8.17.0",
"@typescript-eslint/parser": "8.17.0",
"cross-env": "7.0.3",
"eslint": "8.57.0",
"react": "18.3.1",

View File

@@ -1,17 +1,17 @@
{
"name": "eslint-config-impress",
"version": "1.10.0",
"version": "1.9.0",
"license": "MIT",
"scripts": {
"lint": "eslint --ext .js ."
},
"dependencies": {
"@next/eslint-plugin-next": "15.1.0",
"@next/eslint-plugin-next": "15.0.3",
"@tanstack/eslint-plugin-query": "5.62.1",
"@typescript-eslint/eslint-plugin": "*",
"@typescript-eslint/parser": "*",
"eslint": "*",
"eslint-config-next": "15.1.0",
"eslint-config-next": "15.0.3",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-jest": "28.9.0",
@@ -19,7 +19,7 @@
"eslint-plugin-playwright": "2.1.0",
"eslint-plugin-prettier": "5.2.1",
"eslint-plugin-react": "7.37.2",
"eslint-plugin-testing-library": "7.1.1",
"prettier": "3.4.2"
"eslint-plugin-testing-library": "7.0.0",
"prettier": "3.4.1"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "packages-i18n",
"version": "1.10.0",
"version": "1.9.0",
"private": true,
"scripts": {
"extract-translation": "yarn extract-translation:impress",

View File

@@ -1,42 +0,0 @@
FROM node:20-alpine AS y-provider-builder
WORKDIR /home/frontend/
COPY ./src/frontend/package.json ./package.json
COPY ./src/frontend/yarn.lock ./yarn.lock
COPY ./src/frontend/servers/y-provider/package.json ./servers/y-provider/package.json
COPY ./src/frontend/packages/eslint-config-impress/package.json ./packages/eslint-config-impress/package.json
RUN yarn install
COPY ./src/frontend/packages/eslint-config-impress ./packages/eslint-config-impress
COPY ./src/frontend/servers/y-provider ./servers/y-provider
WORKDIR /home/frontend/servers/y-provider
RUN yarn build
FROM node:20-alpine AS y-provider
WORKDIR /home/frontend/
COPY ./src/frontend/package.json ./package.json
COPY ./src/frontend/yarn.lock ./yarn.lock
COPY ./src/frontend/servers/y-provider/package.json ./servers/y-provider/package.json
WORKDIR /home/frontend/servers/y-provider
COPY --from=y-provider-builder \
/home/frontend/servers/y-provider/dist \
./dist
RUN NODE_ENV=production yarn install --frozen-lockfile
# Un-privileged user running the application
ARG DOCKER_USER
USER ${DOCKER_USER}
# Copy entrypoint
COPY ./docker/files/usr/local/bin/entrypoint /usr/local/bin/entrypoint
ENTRYPOINT [ "/usr/local/bin/entrypoint" ]
CMD ["yarn", "start"]

View File

@@ -14,7 +14,6 @@ jest.mock('../src/env', () => {
PORT: port,
COLLABORATION_SERVER_ORIGIN: origin,
COLLABORATION_SERVER_SECRET: 'test-secret-api-key',
Y_PROVIDER_API_KEY: 'yprovider-api-key',
};
});
@@ -102,21 +101,11 @@ describe('Server Tests', () => {
expect(response.body.error).toBe('Forbidden: Invalid API Key');
});
test('POST /api/convert-markdown with a Bearer token', async () => {
const response = await request(app as any)
.post('/api/convert-markdown')
.set('Origin', origin)
.set('Authorization', 'Bearer test-secret-api-key');
// Warning: Changing the authorization header to Bearer token format will break backend compatibility with this microservice.
expect(response.status).toBe(403);
});
test('POST /api/convert-markdown with missing body param content', async () => {
const response = await request(app as any)
.post('/api/convert-markdown')
.set('Origin', origin)
.set('Authorization', 'yprovider-api-key');
.set('Authorization', 'test-secret-api-key');
expect(response.status).toBe(400);
expect(response.body.error).toBe('Invalid request: missing content');
@@ -126,7 +115,7 @@ describe('Server Tests', () => {
const response = await request(app as any)
.post('/api/convert-markdown')
.set('Origin', origin)
.set('Authorization', 'yprovider-api-key')
.set('Authorization', 'test-secret-api-key')
.send({
content: '',
});

View File

@@ -1,6 +1,6 @@
{
"name": "server-y-provider",
"version": "1.10.0",
"version": "1.9.0",
"description": "Y.js provider for docs",
"repository": "https://github.com/numerique-gouv/impress",
"license": "MIT",
@@ -16,17 +16,17 @@
"node": ">=18"
},
"dependencies": {
"@blocknote/server-util": "0.21.0",
"@hocuspocus/server": "2.15.0",
"@sentry/node": "8.45.1",
"@sentry/profiling-node": "8.45.1",
"express": "4.21.2",
"@blocknote/server-util": "0.20.0",
"@hocuspocus/server": "2.14.0",
"@sentry/node": "8.41.0",
"@sentry/profiling-node": "8.41.0",
"express": "4.21.1",
"express-ws": "5.0.2",
"y-protocols": "1.0.6",
"yjs": "13.6.20"
},
"devDependencies": {
"@hocuspocus/provider": "2.15.0",
"@hocuspocus/provider": "2.14.0",
"@types/express": "5.0.0",
"@types/express-ws": "3.0.5",
"@types/jest": "29.5.14",
@@ -35,7 +35,7 @@
"@types/ws": "8.5.13",
"eslint-config-impress": "*",
"jest": "29.7.0",
"nodemon": "3.1.9",
"nodemon": "3.1.7",
"supertest": "7.0.0",
"ts-jest": "29.2.5",
"ts-node": "10.9.2",

View File

@@ -4,7 +4,5 @@ export const COLLABORATION_SERVER_ORIGIN =
process.env.COLLABORATION_SERVER_ORIGIN || 'http://localhost:3000';
export const COLLABORATION_SERVER_SECRET =
process.env.COLLABORATION_SERVER_SECRET || 'secret-api-key';
export const Y_PROVIDER_API_KEY =
process.env.Y_PROVIDER_API_KEY || 'yprovider-api-key';
export const PORT = Number(process.env.PORT || 4444);
export const SENTRY_DSN = process.env.SENTRY_DSN || '';

View File

@@ -4,13 +4,10 @@ import * as ws from 'ws';
import {
COLLABORATION_SERVER_ORIGIN,
COLLABORATION_SERVER_SECRET,
Y_PROVIDER_API_KEY,
} from '@/env';
import { logger } from './utils';
const VALID_API_KEYS = [COLLABORATION_SERVER_SECRET, Y_PROVIDER_API_KEY];
export const httpSecurity = (
req: Request,
res: Response,
@@ -28,9 +25,8 @@ export const httpSecurity = (
}
// Secret API Key check
// Note: Changing this header to Bearer token format will break backend compatibility with this microservice.
const apiKey = req.headers['authorization'];
if (!apiKey || !VALID_API_KEYS.includes(apiKey)) {
if (apiKey !== COLLABORATION_SERVER_SECRET) {
res.status(403).json({ error: 'Forbidden: Invalid API Key' });
return;
}

View File

@@ -6,6 +6,6 @@ import { SENTRY_DSN } from '../env';
Sentry.init({
dsn: SENTRY_DSN,
integrations: [nodeProfilingIntegration()],
tracesSampleRate: 0.1,
tracesSampleRate: 1.0,
profilesSampleRate: 1.0,
});

File diff suppressed because it is too large Load Diff

View File

@@ -11,13 +11,10 @@ backend:
DJANGO_CSRF_TRUSTED_ORIGINS: https://impress.127.0.0.1.nip.io
DJANGO_CONFIGURATION: Feature
DJANGO_ALLOWED_HOSTS: impress.127.0.0.1.nip.io
DJANGO_SERVER_TO_SERVER_API_TOKENS: secret-api-key
DJANGO_SECRET_KEY: {{ .Values.djangoSecretKey }}
DJANGO_SETTINGS_MODULE: impress.settings
DJANGO_SUPERUSER_PASSWORD: admin
DJANGO_EMAIL_BRAND_NAME: "La Suite Numérique"
DJANGO_EMAIL_HOST: "mailcatcher"
DJANGO_EMAIL_LOGO_IMG: https://impress.127.0.0.1.nip.io/assets/logo-suite-numerique.png
DJANGO_EMAIL_PORT: 1025
DJANGO_EMAIL_USE_SSL: False
LOGGING_LEVEL_HANDLERS_CONSOLE: ERROR
@@ -49,12 +46,13 @@ backend:
POSTGRES_PASSWORD: pass
REDIS_URL: redis://default:pass@redis-master:6379/1
AWS_S3_ENDPOINT_URL: http://minio.impress.svc.cluster.local:9000
AWS_S3_ACCESS_KEY_ID: root
AWS_S3_ACCESS_KEY_ID: impress
AWS_S3_SECRET_ACCESS_KEY: password
AWS_STORAGE_BUCKET_NAME: impress-media-storage
STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage
Y_PROVIDER_API_BASE_URL: http://impress-y-provider:443/api/
Y_PROVIDER_API_KEY: my-secret
AI_API_KEY: **ask antoine**
AI_BASE_URL: https://albertine.beta.numerique.gouv.fr/v1/
AI_MODEL: meta-llama/Llama-3.1-8B-Instruct
migrate:
command:
@@ -107,7 +105,6 @@ yProvider:
COLLABORATION_LOGGING: true
COLLABORATION_SERVER_ORIGIN: https://impress.127.0.0.1.nip.io
COLLABORATION_SERVER_SECRET: my-secret
Y_PROVIDER_API_KEY: my-secret
ingress:
enabled: true

View File

@@ -1,220 +0,0 @@
image:
repository: lasuite/impress-backend
pullPolicy: Always
tag: "v1.10.0"
backend:
migrateJobAnnotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
envVars:
AI_API_KEY:
secretKeyRef:
name: backend
key: AI_API_KEY
AI_BASE_URL: https://albert.api.etalab.gouv.fr/v1/
AI_MODEL: meta-llama/Meta-Llama-3.1-70B-Instruct
COLLABORATION_API_URL: https://docs.numerique.gouv.fr/collaboration/api/
COLLABORATION_SERVER_SECRET:
secretKeyRef:
name: backend
key: COLLABORATION_SERVER_SECRET
DJANGO_CSRF_TRUSTED_ORIGINS: https://docs.numerique.gouv.fr
DJANGO_CONFIGURATION: Production
DJANGO_ALLOWED_HOSTS: docs.numerique.gouv.fr
DJANGO_SECRET_KEY:
secretKeyRef:
name: backend
key: DJANGO_SECRET_KEY
DJANGO_SERVER_TO_SERVER_API_TOKENS:
secretKeyRef:
name: backend
key: DJANGO_SERVER_TO_SERVER_API_TOKENS
DJANGO_SETTINGS_MODULE: impress.settings
DJANGO_SUPERUSER_EMAIL:
secretKeyRef:
name: backend
key: DJANGO_SUPERUSER_EMAIL
DJANGO_SUPERUSER_PASSWORD:
secretKeyRef:
name: backend
key: DJANGO_SUPERUSER_PASSWORD
DJANGO_EMAIL_BRAND_NAME: "La Suite Numérique"
DJANGO_EMAIL_HOST: "smtp.tem.scw.cloud"
DJANGO_EMAIL_LOGO_IMG: https://docs.numerique.gouv.fr/assets/logo-suite-numerique.png
DJANGO_EMAIL_PORT: 587
DJANGO_EMAIL_USE_TLS: True
DJANGO_EMAIL_FROM: "noreply@docs.beta.numerique.gouv.fr"
DJANGO_EMAIL_HOST_USER:
secretKeyRef:
name: backend
key: DJANGO_EMAIL_HOST_USER
DJANGO_EMAIL_HOST_PASSWORD:
secretKeyRef:
name: backend
key: DJANGO_EMAIL_HOST_PASSWORD
DJANGO_SILENCED_SYSTEM_CHECKS: security.W008,security.W004
OIDC_OP_JWKS_ENDPOINT: https://auth.agentconnect.gouv.fr/api/v2/jwks
OIDC_OP_AUTHORIZATION_ENDPOINT: https://auth.agentconnect.gouv.fr/api/v2/authorize
OIDC_OP_TOKEN_ENDPOINT: https://auth.agentconnect.gouv.fr/api/v2/token
OIDC_OP_USER_ENDPOINT: https://auth.agentconnect.gouv.fr/api/v2/userinfo
OIDC_OP_LOGOUT_ENDPOINT: https://auth.agentconnect.gouv.fr/api/v2/session/end
OIDC_RP_CLIENT_ID:
secretKeyRef:
name: backend
key: OIDC_RP_CLIENT_ID
OIDC_RP_CLIENT_SECRET:
secretKeyRef:
name: backend
key: OIDC_RP_CLIENT_SECRET
OIDC_RP_SIGN_ALGO: RS256
OIDC_RP_SCOPES: "openid email given_name usual_name"
USER_OIDC_FIELD_TO_SHORTNAME: "given_name"
USER_OIDC_FIELDS_TO_FULLNAME: "given_name,usual_name"
OIDC_REDIRECT_ALLOWED_HOSTS: https://docs.numerique.gouv.fr
OIDC_AUTH_REQUEST_EXTRA_PARAMS: "{'acr_values': 'eidas1'}"
LOGIN_REDIRECT_URL: https://docs.numerique.gouv.fr
LOGIN_REDIRECT_URL_FAILURE: https://docs.numerique.gouv.fr
LOGOUT_REDIRECT_URL: https://docs.numerique.gouv.fr
DB_HOST:
secretKeyRef:
name: postgresql.postgres.libre.sh
key: host
DB_NAME:
secretKeyRef:
name: postgresql.postgres.libre.sh
key: database
DB_USER:
secretKeyRef:
name: postgresql.postgres.libre.sh
key: username
DB_PASSWORD:
secretKeyRef:
name: postgresql.postgres.libre.sh
key: password
DB_PORT:
secretKeyRef:
name: postgresql.postgres.libre.sh
key: port
POSTGRES_USER:
secretKeyRef:
name: postgresql.postgres.libre.sh
key: username
POSTGRES_DB:
secretKeyRef:
name: postgresql.postgres.libre.sh
key: database
POSTGRES_PASSWORD:
secretKeyRef:
name: postgresql.postgres.libre.sh
key: password
REDIS_URL:
secretKeyRef:
name: redis.redis.libre.sh
key: url
AWS_S3_ENDPOINT_URL:
secretKeyRef:
name: impress-media-storage.bucket.libre.sh
key: url
AWS_S3_ACCESS_KEY_ID:
secretKeyRef:
name: impress-media-storage.bucket.libre.sh
key: accessKey
AWS_S3_SECRET_ACCESS_KEY:
secretKeyRef:
name: impress-media-storage.bucket.libre.sh
key: secretKey
AWS_STORAGE_BUCKET_NAME:
secretKeyRef:
name: impress-media-storage.bucket.libre.sh
key: bucket
AWS_S3_REGION_NAME: local
STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage
Y_PROVIDER_API_BASE_URL: http://impress-y-provider:443/api/
Y_PROVIDER_API_KEY:
secretKeyRef:
name: backend
key: Y_PROVIDER_API_KEY
createsuperuser:
command:
- "/bin/sh"
- "-c"
- |
python manage.py createsuperuser --email $DJANGO_SUPERUSER_EMAIL --password $DJANGO_SUPERUSER_PASSWORD
restartPolicy: Never
frontend:
image:
repository: lasuite/impress-frontend
pullPolicy: Always
tag: "v1.10.0"
yProvider:
image:
repository: lasuite/impress-y-provider
pullPolicy: Always
tag: "v1.10.0"
envVars:
COLLABORATION_LOGGING: true
COLLABORATION_SERVER_ORIGIN: https://docs.numerique.gouv.fr
COLLABORATION_SERVER_SECRET:
secretKeyRef:
name: backend
key: COLLABORATION_SERVER_SECRET
Y_PROVIDER_API_KEY:
secretKeyRef:
name: backend
key: Y_PROVIDER_API_KEY
ingress:
enabled: true
host: docs.numerique.gouv.fr
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt
ingressCollaborationWS:
enabled: true
host: docs.numerique.gouv.fr
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt
nginx.ingress.kubernetes.io/auth-url: https://docs.numerique.gouv.fr/api/v1.0/documents/collaboration-auth/
ingressCollaborationApi:
enabled: true
host: docs.numerique.gouv.fr
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt
ingressAdmin:
enabled: true
host: docs.numerique.gouv.fr
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt
nginx.ingress.kubernetes.io/auth-signin: https://oauth2-proxy.beta.numerique.gouv.fr/oauth2/start
nginx.ingress.kubernetes.io/auth-url: https://oauth2-proxy.beta.numerique.gouv.fr/oauth2/auth
ingressMedia:
enabled: true
host: docs.numerique.gouv.fr
annotations:
cert-manager.io/cluster-issuer: letsencrypt
nginx.ingress.kubernetes.io/auth-response-headers: "Authorization, X-Amz-Date, X-Amz-Content-SHA256"
nginx.ingress.kubernetes.io/auth-url: https://docs.numerique.gouv.fr/api/v1.0/documents/media-auth/
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: /impress-impress-media-storage/$1
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/upstream-vhost: s3.hedy-lamarr.indiehosters.net
serviceMedia:
host: s3.hedy-lamarr.indiehosters.net
port: 443

View File

@@ -2,4 +2,4 @@ apiVersion: v2
name: extra
description: A Helm chart to add some manifests to impress
type: application
version: 1.10.0
version: 1.9.0

View File

@@ -62,6 +62,6 @@ releases:
environments:
dev:
values:
- version: 1.10.0
- version: 1.9.0
secrets:
- env.d/{{ .Environment.Name }}/secrets.enc.yaml

View File

@@ -1,4 +1,4 @@
apiVersion: v2
type: application
name: impress
version: 1.10.0
version: 1.9.0

View File

@@ -29,7 +29,7 @@ spec:
{{- if .Values.ingress.tls.enabled }}
tls:
{{- if .Values.ingress.host }}
- secretName: {{ .Values.ingress.tls.secretName | default (printf "%s-tls" $fullName) | quote }}
- secretName: {{ $fullName }}-tls
hosts:
- {{ .Values.ingress.host | quote }}
{{- end }}
@@ -115,3 +115,4 @@ spec:
{{- end }}
{{- end }}
{{- end }}

View File

@@ -29,7 +29,7 @@ spec:
{{- if .Values.ingressAdmin.tls.enabled }}
tls:
{{- if .Values.ingressAdmin.host }}
- secretName: {{ .Values.ingressAdmin.tls.secretName | default (printf "%s-tls" $fullName) | quote }}
- secretName: {{ $fullName }}-tls
hosts:
- {{ .Values.ingressAdmin.host | quote }}
{{- end }}
@@ -95,3 +95,4 @@ spec:
{{- end }}
{{- end }}
{{- end }}

View File

@@ -29,7 +29,7 @@ spec:
{{- if .Values.ingressCollaborationApi.tls.enabled }}
tls:
{{- if .Values.ingressCollaborationApi.host }}
- secretName: {{ .Values.ingressCollaborationApi.tls.secretName | default (printf "%s-tls" $fullName) | quote }}
- secretName: {{ $fullName }}-tls
hosts:
- {{ .Values.ingressCollaborationApi.host | quote }}
{{- end }}
@@ -69,3 +69,4 @@ spec:
{{- end }}
{{- end }}
{{- end }}

View File

@@ -29,7 +29,7 @@ spec:
{{- if .Values.ingressCollaborationWS.tls.enabled }}
tls:
{{- if .Values.ingressCollaborationWS.host }}
- secretName: {{ .Values.ingressCollaborationWS.tls.secretName | default (printf "%s-tls" $fullName) | quote }}
- secretName: {{ $fullName }}-tls
hosts:
- {{ .Values.ingressCollaborationWS.host | quote }}
{{- end }}
@@ -69,3 +69,4 @@ spec:
{{- end }}
{{- end }}
{{- end }}

View File

@@ -29,7 +29,7 @@ spec:
{{- if .Values.ingressMedia.tls.enabled }}
tls:
{{- if .Values.ingressMedia.host }}
- secretName: {{ .Values.ingressMedia.tls.secretName | default (printf "%s-tls" $fullName) | quote }}
- secretName: {{ $fullName }}-tls
hosts:
- {{ .Values.ingressMedia.host | quote }}
{{- end }}

View File

@@ -37,14 +37,12 @@ ingress:
## @param ingress.hosts Additional host to configure for the Ingress
hosts: []
# - chart-example.local
## @param ingress.tls.enabled Weather to enable TLS for the Ingress
## @param ingress.tls.secretName Secret name for TLS config
## @param ingress.tls.enabled Wether to enable TLS for the Ingress
## @skip ingress.tls.additional
## @extra ingress.tls.additional[].secretName Secret name for additional TLS config
## @extra ingress.tls.additional[].hosts[] Hosts for additional TLS config
tls:
enabled: true
secretName: null
additional: []
## @param ingress.customBackends Add custom backends to ingress
@@ -62,23 +60,21 @@ ingressCollaborationWS:
## @param ingress.hosts Additional host to configure for the Ingress
hosts: []
# - chart-example.local
## @param ingressCollaborationWS.tls.enabled Weather to enable TLS for the Ingress
## @param ingressCollaborationWS.tls.secretName Secret name for TLS config
## @param ingressCollaborationWS.tls.enabled Wether to enable TLS for the Ingress
## @skip ingressCollaborationWS.tls.additional
## @extra ingressCollaborationWS.tls.additional[].secretName Secret name for additional TLS config
## @extra ingressCollaborationWS.tls.additional[].hosts[] Hosts for additional TLS config
tls:
enabled: true
secretName: null
additional: []
## @param ingressCollaborationWS.customBackends Add custom backends to ingress
customBackends: []
annotations:
annotations:
nginx.ingress.kubernetes.io/auth-response-headers: "Authorization, X-Can-Edit, X-User-Id"
nginx.ingress.kubernetes.io/auth-url: https://impress.example.com/api/v1.0/documents/collaboration-auth/
nginx.ingress.kubernetes.io/enable-websocket: "true"
nginx.ingress.kubernetes.io/enable-websocket: "true"
nginx.ingress.kubernetes.io/proxy-read-timeout: "86400"
nginx.ingress.kubernetes.io/proxy-send-timeout: "86400"
nginx.ingress.kubernetes.io/upstream-hash-by: $arg_room
@@ -95,23 +91,20 @@ ingressCollaborationApi:
## @param ingress.hosts Additional host to configure for the Ingress
hosts: []
# - chart-example.local
## @param ingressCollaborationApi.tls.enabled Weather to enable TLS for the Ingress
## @param ingressCollaborationApi.tls.secretName Secret name for TLS config
## @param ingressCollaborationApi.tls.enabled Wether to enable TLS for the Ingress
## @skip ingressCollaborationApi.tls.additional
## @extra ingressCollaborationApi.tls.additional[].secretName Secret name for additional TLS config
## @extra ingressCollaborationApi.tls.additional[].hosts[] Hosts for additional TLS config
tls:
enabled: true
secretName: null
additional: []
## @param ingressCollaborationApi.customBackends Add custom backends to ingress
customBackends: []
annotations:
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: $arg_room
## @param ingressAdmin.enabled whether to enable the Ingress or not
## @param ingressAdmin.className IngressClass to use for the Ingress
## @param ingressAdmin.host Host for the Ingress
@@ -124,14 +117,12 @@ ingressAdmin:
## @param ingressAdmin.hosts Additional host to configure for the Ingress
hosts: [ ]
# - chart-example.local
## @param ingressAdmin.tls.enabled Weather to enable TLS for the Ingress
## @param ingressAdmin.tls.secretName Secret name for TLS config
## @param ingressAdmin.tls.enabled Wether to enable TLS for the Ingress
## @skip ingressAdmin.tls.additional
## @extra ingressAdmin.tls.additional[].secretName Secret name for additional TLS config
## @extra ingressAdmin.tls.additional[].hosts[] Hosts for additional TLS config
tls:
enabled: true
secretName: null
additional: []
## @param ingressMedia.enabled whether to enable the Ingress or not
@@ -146,14 +137,12 @@ ingressMedia:
## @param ingressMedia.hosts Additional host to configure for the Ingress
hosts: [ ]
# - chart-example.local
## @param ingressMedia.tls.enabled Weather to enable TLS for the Ingress
## @param ingressMedia.tls.secretName Secret name for TLS config
## @param ingressMedia.tls.enabled Wether to enable TLS for the Ingress
## @skip ingressMedia.tls.additional
## @extra ingressMedia.tls.additional[].secretName Secret name for additional TLS config
## @extra ingressMedia.tls.additional[].hosts[] Hosts for additional TLS config
tls:
enabled: true
secretName: null
additional: []
annotations:
@@ -453,4 +442,4 @@ yProvider:
extraVolumeMounts: []
## @param yProvider.extraVolumes Additional volumes to mount on the yProvider.
extraVolumes: []
extraVolumes: []

View File

@@ -1,6 +1,6 @@
{
"name": "mail_mjml",
"version": "1.10.0",
"version": "1.9.0",
"description": "An util to generate html and text django's templates from mjml templates",
"type": "module",
"dependencies": {