mirror of
https://github.com/suitenumerique/docs.git
synced 2026-05-06 23:22:15 +02:00
Compare commits
20 Commits
production
...
preprod
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07a6758cdc | ||
|
|
d8673a8cf7 | ||
|
|
a5af9f0776 | ||
|
|
d715e7b3b6 | ||
|
|
1da5a6a411 | ||
|
|
af5ffc22ac | ||
|
|
3434029654 | ||
|
|
6baa06bd3f | ||
|
|
8107d4f531 | ||
|
|
f8c8044605 | ||
|
|
a84f4de02c | ||
|
|
3c374e3cc7 | ||
|
|
ff364f8b3d | ||
|
|
c0cb12f002 | ||
|
|
0f0f812059 | ||
|
|
7fc59ed497 | ||
|
|
60120852f5 | ||
|
|
f2c389e2b3 | ||
|
|
305359ae15 | ||
|
|
e35671c450 |
52
.github/workflows/deploy.yml
vendored
52
.github/workflows/deploy.yml
vendored
@@ -1,52 +0,0 @@
|
||||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'preprod'
|
||||
- 'production'
|
||||
|
||||
|
||||
jobs:
|
||||
notify-argocd:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.APP_ID }}
|
||||
private-key: ${{ secrets.PRIVATE_KEY }}
|
||||
owner: ${{ github.repository_owner }}
|
||||
repositories: "impress,secrets"
|
||||
-
|
||||
name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
-
|
||||
name: Load sops secrets
|
||||
uses: rouja/actions-sops@main
|
||||
with:
|
||||
secret-file: secrets/numerique-gouv/impress/secrets.enc.env
|
||||
age-key: ${{ secrets.SOPS_PRIVATE }}
|
||||
-
|
||||
name: Call argocd github webhook
|
||||
run: |
|
||||
data='{"ref": "'$GITHUB_REF'","repository": {"html_url":"'$GITHUB_SERVER_URL'/'$GITHUB_REPOSITORY'"}}'
|
||||
sig=$(echo -n ${data} | openssl dgst -sha1 -hmac ''${ARGOCD_WEBHOOK_SECRET}'' | awk '{print "X-Hub-Signature: sha1="$2}')
|
||||
curl -X POST -H 'X-GitHub-Event:push' -H "Content-Type: application/json" -H "${sig}" --data "${data}" $ARGOCD_WEBHOOK_URL
|
||||
sig=$(echo -n ${data} | openssl dgst -sha1 -hmac ''${ARGOCD_PRODUCTION_WEBHOOK_SECRET}'' | awk '{print "X-Hub-Signature: sha1="$2}')
|
||||
curl -X POST -H 'X-GitHub-Event:push' -H "Content-Type: application/json" -H "${sig}" --data "${data}" $ARGOCD_PRODUCTION_WEBHOOK_URL
|
||||
|
||||
start-test-on-preprod:
|
||||
needs:
|
||||
- notify-argocd
|
||||
runs-on: ubuntu-latest
|
||||
if: startsWith(github.event.ref, 'refs/tags/preprod')
|
||||
steps:
|
||||
-
|
||||
name: Debug
|
||||
run: |
|
||||
echo "Start test when preprod is ready"
|
||||
3
.github/workflows/docker-hub.yml
vendored
3
.github/workflows/docker-hub.yml
vendored
@@ -8,9 +8,6 @@ on:
|
||||
- 'main'
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
env:
|
||||
DOCKER_USER: 1001:127
|
||||
|
||||
22
.github/workflows/helmfile-linter.yaml
vendored
22
.github/workflows/helmfile-linter.yaml
vendored
@@ -1,22 +0,0 @@
|
||||
name: Helmfile lint
|
||||
run-name: Helmfile lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
jobs:
|
||||
helmfile-lint:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ghcr.io/helmfile/helmfile:latest
|
||||
steps:
|
||||
-
|
||||
uses: numerique-gouv/action-helmfile-lint@main
|
||||
with:
|
||||
app-id: ${{ secrets.APP_ID }}
|
||||
age-key: ${{ secrets.SOPS_PRIVATE }}
|
||||
private-key: ${{ secrets.PRIVATE_KEY }}
|
||||
helmfile-src: "src/helm"
|
||||
repositories: "impress,secrets"
|
||||
31
CHANGELOG.md
31
CHANGELOG.md
@@ -9,6 +9,30 @@ and this project adheres to
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.7.0] - 2024-10-24
|
||||
|
||||
## Added
|
||||
|
||||
- 📝Contributing.md #352
|
||||
- 🌐(frontend) add localization to editor #368
|
||||
- ✨Public and restricted doc editable #357
|
||||
- ✨(frontend) Add full name if available #380
|
||||
|
||||
## Changed
|
||||
|
||||
- ♻️(frontend) avoid documents indexing in search engine #372
|
||||
|
||||
## Fixed
|
||||
|
||||
- 🐛(backend) require right to manage document accesses to see invitations #369
|
||||
- 🐛(i18n) same frontend and backend language using shared cookies #365
|
||||
- 🐛(frontend) add default toolbar buttons #355
|
||||
- 🐛(frontend) throttle error correctly display #378
|
||||
|
||||
## Removed
|
||||
|
||||
- 🔥(helm) remove infra related codes #366
|
||||
|
||||
|
||||
## [1.6.0] - 2024-10-17
|
||||
|
||||
@@ -16,11 +40,11 @@ and this project adheres to
|
||||
|
||||
- ✨AI to doc editor #250
|
||||
- ✨(backend) allow uploading more types of attachments #309
|
||||
- ✨(frontend) add buttons to copy document to clipboard as HTML/Markdown #300
|
||||
- ✨(frontend) add buttons to copy document to clipboard as HTML/Markdown #318
|
||||
|
||||
## Changed
|
||||
|
||||
- ♻️(frontend) More multi theme friendly #325
|
||||
- ♻️(frontend) more multi theme friendly #325
|
||||
- ♻️ Bootstrap frontend #257
|
||||
- ♻️ Add username in email #314
|
||||
|
||||
@@ -211,7 +235,8 @@ and this project adheres to
|
||||
- 🚀 Impress, project to manage your documents easily and collaboratively.
|
||||
|
||||
|
||||
[unreleased]: https://github.com/numerique-gouv/impress/compare/v1.6.0...main
|
||||
[unreleased]: https://github.com/numerique-gouv/impress/compare/v1.7.0...main
|
||||
[v1.7.0]: https://github.com/numerique-gouv/impress/releases/v1.7.0
|
||||
[v1.6.0]: https://github.com/numerique-gouv/impress/releases/v1.6.0
|
||||
[1.5.1]: https://github.com/numerique-gouv/impress/releases/v1.5.1
|
||||
[1.5.0]: https://github.com/numerique-gouv/impress/releases/v1.5.0
|
||||
|
||||
79
CONTRIBUTING.md
Normal file
79
CONTRIBUTING.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Contributing to the Project
|
||||
|
||||
Thank you for taking the time to contribute! Please follow these guidelines to ensure a smooth and productive workflow. 🚀🚀🚀
|
||||
|
||||
To get started with the project, please refer to the [README.md](https://github.com/numerique-gouv/impress/blob/main/README.md) for detailed instructions.
|
||||
|
||||
## Creating an Issue
|
||||
|
||||
When creating an issue, please provide the following details:
|
||||
|
||||
1. **Title**: A concise and descriptive title for the issue.
|
||||
2. **Description**: A detailed explanation of the issue, including relevant context or screenshots if applicable.
|
||||
3. **Steps to Reproduce**: If the issue is a bug, include the steps needed to reproduce the problem.
|
||||
4. **Expected vs. Actual Behavior**: Describe what you expected to happen and what actually happened.
|
||||
5. **Labels**: Add appropriate labels to categorize the issue (e.g., bug, feature request, documentation).
|
||||
|
||||
## Selecting an issue
|
||||
|
||||
We use a [GitHub Project](https://github.com/orgs/numerique-gouv/projects/13) in order to prioritize our workload.
|
||||
|
||||
Please check in priority the issues that are in the **todo** column and have a higher priority (P0 -> P2).
|
||||
|
||||
## Commit Message Format
|
||||
|
||||
All commit messages must adhere to the following format:
|
||||
|
||||
`<gitmoji>(type) title description`
|
||||
|
||||
* <**gitmoji**>: Use a gitmoji to represent the purpose of the commit. For example, ✨ for adding a new feature or 🔥 for removing something, see the list here: <https://gitmoji.dev/>.
|
||||
* **(type)**: Describe the type of change. Common types include `backend`, `frontend`, `CI`, `docker` etc...
|
||||
* **title**: A short, descriptive title for the change, starting with a lowercase character.
|
||||
* **description**: Include additional details about what was changed and why.
|
||||
|
||||
### Example Commit Message
|
||||
|
||||
```
|
||||
✨(frontend) add user authentication logic
|
||||
|
||||
Implemented login and signup features, and integrated OAuth2 for social login.
|
||||
```
|
||||
|
||||
## Changelog Update
|
||||
|
||||
Please add a line to the changelog describing your development. The changelog entry should include a brief summary of the changes, this helps in tracking changes effectively and keeping everyone informed. We usually include the title of the pull request, followed by the pull request ID to finish the log entry. The changelog line should be less than 80 characters in total.
|
||||
|
||||
### Example Changelog Message
|
||||
```
|
||||
## [Unreleased]
|
||||
|
||||
## Added
|
||||
|
||||
- ✨(frontend) add AI to the project #321
|
||||
```
|
||||
|
||||
## Pull Requests
|
||||
|
||||
It is nice to add information about the purpose of the pull request to help reviewers understand the context and intent of the changes. If you can, add some pictures or a small video to show the changes.
|
||||
|
||||
### Don't forget to:
|
||||
- check your commits
|
||||
- check the linting: `make lint && make frontend-lint`
|
||||
- check the tests: `make test`
|
||||
- add a changelog entry
|
||||
|
||||
Once all the required tests have passed, you can request a review from the project maintainers.
|
||||
|
||||
## Code Style
|
||||
|
||||
Please maintain consistency in code style. Run any linting tools available to make sure the code is clean and follows the project's conventions.
|
||||
|
||||
## Tests
|
||||
|
||||
Make sure that all new features or fixes have corresponding tests. Run the test suite before pushing your changes to ensure that nothing is broken.
|
||||
|
||||
## Asking for Help
|
||||
|
||||
If you need any help while contributing, feel free to open a discussion or ask for guidance in the issue tracker. We are more than happy to assist!
|
||||
|
||||
Thank you for your contributions! 👍
|
||||
4
Makefile
4
Makefile
@@ -314,6 +314,10 @@ frontend-install: ## install the frontend locally
|
||||
cd $(PATH_FRONT_IMPRESS) && yarn
|
||||
.PHONY: frontend-install
|
||||
|
||||
frontend-lint: ## run the frontend linter
|
||||
cd $(PATH_FRONT) && yarn lint
|
||||
.PHONY: frontend-lint
|
||||
|
||||
run-frontend-development: ## Run the frontend in development mode
|
||||
@$(COMPOSE) stop frontend-dev
|
||||
cd $(PATH_FRONT_IMPRESS) && yarn dev
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
"""Permission handlers for the impress core app."""
|
||||
|
||||
from django.core import exceptions
|
||||
from django.db.models import Q
|
||||
|
||||
from rest_framework import permissions
|
||||
|
||||
from core.models import DocumentAccess, RoleChoices
|
||||
|
||||
ACTION_FOR_METHOD_TO_PERMISSION = {
|
||||
"versions_detail": {"DELETE": "versions_destroy", "GET": "versions_retrieve"}
|
||||
}
|
||||
@@ -59,6 +62,38 @@ class IsOwnedOrPublic(IsAuthenticated):
|
||||
return False
|
||||
|
||||
|
||||
class CanCreateInvitationPermission(permissions.BasePermission):
|
||||
"""
|
||||
Custom permission class to handle permission checks for managing invitations.
|
||||
"""
|
||||
|
||||
def has_permission(self, request, view):
|
||||
user = request.user
|
||||
|
||||
# Ensure the user is authenticated
|
||||
if not (bool(request.auth) or request.user.is_authenticated):
|
||||
return False
|
||||
|
||||
# Apply permission checks only for creation (POST requests)
|
||||
if view.action != "create":
|
||||
return True
|
||||
|
||||
# Check if resource_id is passed in the context
|
||||
try:
|
||||
document_id = view.kwargs["resource_id"]
|
||||
except KeyError as exc:
|
||||
raise exceptions.ValidationError(
|
||||
"You must set a document ID in kwargs to manage document invitations."
|
||||
) from exc
|
||||
|
||||
# Check if the user has access to manage invitations (Owner/Admin roles)
|
||||
return DocumentAccess.objects.filter(
|
||||
Q(user=user) | Q(team__in=user.teams),
|
||||
document=document_id,
|
||||
role__in=[RoleChoices.OWNER, RoleChoices.ADMIN],
|
||||
).exists()
|
||||
|
||||
|
||||
class AccessPermission(permissions.BasePermission):
|
||||
"""Permission class for access objects."""
|
||||
|
||||
|
||||
@@ -328,48 +328,36 @@ class InvitationSerializer(serializers.ModelSerializer):
|
||||
return {}
|
||||
|
||||
def validate(self, attrs):
|
||||
"""Validate and restrict invitation to new user based on email."""
|
||||
|
||||
"""Validate invitation data."""
|
||||
request = self.context.get("request")
|
||||
user = getattr(request, "user", None)
|
||||
role = attrs.get("role")
|
||||
|
||||
try:
|
||||
document_id = self.context["resource_id"]
|
||||
except KeyError as exc:
|
||||
raise exceptions.ValidationError(
|
||||
"You must set a document ID in kwargs to create a new document invitation."
|
||||
) from exc
|
||||
attrs["document_id"] = self.context["resource_id"]
|
||||
|
||||
if not user and user.is_authenticated:
|
||||
raise exceptions.PermissionDenied(
|
||||
"Anonymous users are not allowed to create invitations."
|
||||
)
|
||||
# Only set the issuer if the instance is being created
|
||||
if self.instance is None:
|
||||
attrs["issuer"] = user
|
||||
|
||||
if not models.DocumentAccess.objects.filter(
|
||||
Q(user=user) | Q(team__in=user.teams),
|
||||
document=document_id,
|
||||
role__in=[models.RoleChoices.OWNER, models.RoleChoices.ADMIN],
|
||||
).exists():
|
||||
raise exceptions.PermissionDenied(
|
||||
"You are not allowed to manage invitations for this document."
|
||||
)
|
||||
return attrs
|
||||
|
||||
if (
|
||||
role == models.RoleChoices.OWNER
|
||||
and not models.DocumentAccess.objects.filter(
|
||||
def validate_role(self, role):
|
||||
"""Custom validation for the role field."""
|
||||
request = self.context.get("request")
|
||||
user = getattr(request, "user", None)
|
||||
document_id = self.context["resource_id"]
|
||||
|
||||
# If the role is OWNER, check if the user has OWNER access
|
||||
if role == models.RoleChoices.OWNER:
|
||||
if not models.DocumentAccess.objects.filter(
|
||||
Q(user=user) | Q(team__in=user.teams),
|
||||
document=document_id,
|
||||
role=models.RoleChoices.OWNER,
|
||||
).exists()
|
||||
):
|
||||
raise exceptions.PermissionDenied(
|
||||
"Only owners of a document can invite other users as owners."
|
||||
)
|
||||
).exists():
|
||||
raise serializers.ValidationError(
|
||||
"Only owners of a document can invite other users as owners."
|
||||
)
|
||||
|
||||
attrs["document_id"] = document_id
|
||||
attrs["issuer"] = user
|
||||
return attrs
|
||||
return role
|
||||
|
||||
|
||||
class VersionFilterSerializer(serializers.Serializer):
|
||||
|
||||
@@ -807,7 +807,10 @@ class InvitationViewset(
|
||||
|
||||
lookup_field = "id"
|
||||
pagination_class = Pagination
|
||||
permission_classes = [permissions.IsAuthenticated, permissions.AccessPermission]
|
||||
permission_classes = [
|
||||
permissions.CanCreateInvitationPermission,
|
||||
permissions.AccessPermission,
|
||||
]
|
||||
queryset = (
|
||||
models.Invitation.objects.all()
|
||||
.select_related("document")
|
||||
@@ -842,10 +845,16 @@ class InvitationViewset(
|
||||
)
|
||||
|
||||
queryset = (
|
||||
# The logged-in user should be part of a document to see its accesses
|
||||
# The logged-in user should be administrator or owner to see its accesses
|
||||
queryset.filter(
|
||||
Q(document__accesses__user=user)
|
||||
| Q(document__accesses__team__in=teams),
|
||||
Q(
|
||||
document__accesses__user=user,
|
||||
document__accesses__role__in=models.PRIVILEGED_ROLES,
|
||||
)
|
||||
| Q(
|
||||
document__accesses__team__in=teams,
|
||||
document__accesses__role__in=models.PRIVILEGED_ROLES,
|
||||
),
|
||||
)
|
||||
# Abilities are computed based on logged-in user's role and
|
||||
# the user role on each document access
|
||||
|
||||
@@ -72,6 +72,9 @@ class RoleChoices(models.TextChoices):
|
||||
OWNER = "owner", _("Owner")
|
||||
|
||||
|
||||
PRIVILEGED_ROLES = [RoleChoices.ADMIN, RoleChoices.OWNER]
|
||||
|
||||
|
||||
class LinkReachChoices(models.TextChoices):
|
||||
"""Defines types of access for links"""
|
||||
|
||||
@@ -514,6 +517,7 @@ class Document(BaseModel):
|
||||
"destroy": RoleChoices.OWNER in roles,
|
||||
"link_configuration": is_owner_or_admin,
|
||||
"manage_accesses": is_owner_or_admin,
|
||||
"invite_owner": RoleChoices.OWNER in roles,
|
||||
"partial_update": is_owner_or_admin or is_editor,
|
||||
"retrieve": can_get,
|
||||
"update": is_owner_or_admin or is_editor,
|
||||
@@ -880,8 +884,6 @@ class Invitation(BaseModel):
|
||||
|
||||
def get_abilities(self, user):
|
||||
"""Compute and return abilities for a given user."""
|
||||
can_delete = False
|
||||
can_update = False
|
||||
roles = []
|
||||
|
||||
if user.is_authenticated:
|
||||
@@ -896,17 +898,13 @@ class Invitation(BaseModel):
|
||||
except (self._meta.model.DoesNotExist, IndexError):
|
||||
roles = []
|
||||
|
||||
can_delete = bool(
|
||||
set(roles).intersection({RoleChoices.OWNER, RoleChoices.ADMIN})
|
||||
)
|
||||
|
||||
can_update = bool(
|
||||
set(roles).intersection({RoleChoices.OWNER, RoleChoices.ADMIN})
|
||||
)
|
||||
is_admin_or_owner = bool(
|
||||
set(roles).intersection({RoleChoices.OWNER, RoleChoices.ADMIN})
|
||||
)
|
||||
|
||||
return {
|
||||
"destroy": can_delete,
|
||||
"update": can_update,
|
||||
"partial_update": can_update,
|
||||
"retrieve": bool(roles),
|
||||
"destroy": is_admin_or_owner,
|
||||
"update": is_admin_or_owner,
|
||||
"partial_update": is_admin_or_owner,
|
||||
"retrieve": is_admin_or_owner,
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@ def test_api_documents_retrieve_anonymous_public():
|
||||
"ai_translate": document.link_role == "editor",
|
||||
"attachment_upload": document.link_role == "editor",
|
||||
"destroy": False,
|
||||
"invite_owner": False,
|
||||
"link_configuration": False,
|
||||
"manage_accesses": False,
|
||||
"partial_update": document.link_role == "editor",
|
||||
@@ -82,6 +83,7 @@ def test_api_documents_retrieve_authenticated_unrelated_public_or_authenticated(
|
||||
"attachment_upload": document.link_role == "editor",
|
||||
"link_configuration": False,
|
||||
"destroy": False,
|
||||
"invite_owner": False,
|
||||
"manage_accesses": False,
|
||||
"partial_update": document.link_role == "editor",
|
||||
"retrieve": True,
|
||||
|
||||
@@ -88,6 +88,7 @@ def test_models_documents_get_abilities_forbidden(is_authenticated, reach, role)
|
||||
"attachment_upload": False,
|
||||
"link_configuration": False,
|
||||
"destroy": False,
|
||||
"invite_owner": False,
|
||||
"manage_accesses": False,
|
||||
"partial_update": False,
|
||||
"retrieve": False,
|
||||
@@ -120,6 +121,7 @@ def test_models_documents_get_abilities_reader(is_authenticated, reach):
|
||||
"attachment_upload": False,
|
||||
"destroy": False,
|
||||
"link_configuration": False,
|
||||
"invite_owner": False,
|
||||
"manage_accesses": False,
|
||||
"partial_update": False,
|
||||
"retrieve": True,
|
||||
@@ -152,6 +154,7 @@ def test_models_documents_get_abilities_editor(is_authenticated, reach):
|
||||
"attachment_upload": True,
|
||||
"destroy": False,
|
||||
"link_configuration": False,
|
||||
"invite_owner": False,
|
||||
"manage_accesses": False,
|
||||
"partial_update": True,
|
||||
"retrieve": True,
|
||||
@@ -173,6 +176,7 @@ def test_models_documents_get_abilities_owner():
|
||||
"attachment_upload": True,
|
||||
"destroy": True,
|
||||
"link_configuration": True,
|
||||
"invite_owner": True,
|
||||
"manage_accesses": True,
|
||||
"partial_update": True,
|
||||
"retrieve": True,
|
||||
@@ -193,6 +197,7 @@ def test_models_documents_get_abilities_administrator():
|
||||
"attachment_upload": True,
|
||||
"destroy": False,
|
||||
"link_configuration": True,
|
||||
"invite_owner": False,
|
||||
"manage_accesses": True,
|
||||
"partial_update": True,
|
||||
"retrieve": True,
|
||||
@@ -216,6 +221,7 @@ def test_models_documents_get_abilities_editor_user(django_assert_num_queries):
|
||||
"attachment_upload": True,
|
||||
"destroy": False,
|
||||
"link_configuration": False,
|
||||
"invite_owner": False,
|
||||
"manage_accesses": False,
|
||||
"partial_update": True,
|
||||
"retrieve": True,
|
||||
@@ -241,6 +247,7 @@ def test_models_documents_get_abilities_reader_user(django_assert_num_queries):
|
||||
"attachment_upload": False,
|
||||
"destroy": False,
|
||||
"link_configuration": False,
|
||||
"invite_owner": False,
|
||||
"manage_accesses": False,
|
||||
"partial_update": False,
|
||||
"retrieve": True,
|
||||
@@ -267,6 +274,7 @@ def test_models_documents_get_abilities_preset_role(django_assert_num_queries):
|
||||
"attachment_upload": False,
|
||||
"destroy": False,
|
||||
"link_configuration": False,
|
||||
"invite_owner": False,
|
||||
"manage_accesses": False,
|
||||
"partial_update": False,
|
||||
"retrieve": True,
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
Unit tests for the Invitation model
|
||||
"""
|
||||
|
||||
import time
|
||||
from datetime import timedelta
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.core import exceptions
|
||||
from django.utils import timezone
|
||||
|
||||
import pytest
|
||||
from faker import Faker
|
||||
@@ -60,7 +62,7 @@ def test_models_invitations_role_among_choices():
|
||||
factories.InvitationFactory(role="boss")
|
||||
|
||||
|
||||
def test_models_invitations__is_expired(settings):
|
||||
def test_models_invitations_is_expired():
|
||||
"""
|
||||
The 'is_expired' property should return False until validity duration
|
||||
is exceeded and True afterwards.
|
||||
@@ -68,13 +70,16 @@ def test_models_invitations__is_expired(settings):
|
||||
expired_invitation = factories.InvitationFactory()
|
||||
assert expired_invitation.is_expired is False
|
||||
|
||||
settings.INVITATION_VALIDITY_DURATION = 1
|
||||
time.sleep(1)
|
||||
not_late = timezone.now() + timedelta(seconds=604799)
|
||||
with mock.patch("django.utils.timezone.now", return_value=not_late):
|
||||
assert expired_invitation.is_expired is False
|
||||
|
||||
assert expired_invitation.is_expired is True
|
||||
too_late = timezone.now() + timedelta(seconds=604800) # 7 days
|
||||
with mock.patch("django.utils.timezone.now", return_value=too_late):
|
||||
assert expired_invitation.is_expired is True
|
||||
|
||||
|
||||
def test_models_invitation__new_user__convert_invitations_to_accesses():
|
||||
def test_models_invitationd_new_userd_convert_invitations_to_accesses():
|
||||
"""
|
||||
Upon creating a new user, invitations linked to the email
|
||||
should be converted to accesses and then deleted.
|
||||
@@ -109,7 +114,7 @@ def test_models_invitation__new_user__convert_invitations_to_accesses():
|
||||
).exists() # the other invitation remains
|
||||
|
||||
|
||||
def test_models_invitation__new_user__filter_expired_invitations():
|
||||
def test_models_invitationd_new_user_filter_expired_invitations():
|
||||
"""
|
||||
Upon creating a new identity, valid invitations should be converted into accesses
|
||||
and expired invitations should remain unchanged.
|
||||
@@ -140,7 +145,7 @@ def test_models_invitation__new_user__filter_expired_invitations():
|
||||
|
||||
|
||||
@pytest.mark.parametrize("num_invitations, num_queries", [(0, 3), (1, 6), (20, 6)])
|
||||
def test_models_invitation__new_user__user_creation_constant_num_queries(
|
||||
def test_models_invitationd_new_userd_user_creation_constant_num_queries(
|
||||
django_assert_num_queries, num_invitations, num_queries
|
||||
):
|
||||
"""
|
||||
@@ -235,7 +240,7 @@ def test_models_document_invitations_get_abilities_reader(via, mock_user_teams):
|
||||
|
||||
assert abilities == {
|
||||
"destroy": False,
|
||||
"retrieve": True,
|
||||
"retrieve": False,
|
||||
"partial_update": False,
|
||||
"update": False,
|
||||
}
|
||||
@@ -260,7 +265,7 @@ def test_models_document_invitations_get_abilities_editor(via, mock_user_teams):
|
||||
|
||||
assert abilities == {
|
||||
"destroy": False,
|
||||
"retrieve": True,
|
||||
"retrieve": False,
|
||||
"partial_update": False,
|
||||
"update": False,
|
||||
}
|
||||
|
||||
@@ -223,6 +223,7 @@ class Base(Configuration):
|
||||
|
||||
# Languages
|
||||
LANGUAGE_CODE = values.Value("en-us")
|
||||
LANGUAGE_COOKIE_NAME = "docs_language" # cookie & language is set from frontend
|
||||
|
||||
DRF_NESTED_MULTIPART_PARSER = {
|
||||
# output of parser is converted to querydict
|
||||
|
||||
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "impress"
|
||||
version = "1.6.0"
|
||||
version = "1.7.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.10"
|
||||
dependencies = [
|
||||
"boto3==1.35.41",
|
||||
"boto3==1.35.44",
|
||||
"Brotli==1.1.0",
|
||||
"celery[redis]==5.4.0",
|
||||
"django-configurations==2.5.1",
|
||||
@@ -46,14 +46,14 @@ dependencies = [
|
||||
"jsonschema==4.23.0",
|
||||
"markdown==3.7",
|
||||
"nested-multipart-parser==1.5.0",
|
||||
"openai==1.44.1",
|
||||
"openai==1.52.0",
|
||||
"psycopg[binary]==3.2.3",
|
||||
"PyJWT==2.9.0",
|
||||
"pypandoc==1.14",
|
||||
"python-frontmatter==1.1.0",
|
||||
"python-magic==0.4.27",
|
||||
"requests==2.32.3",
|
||||
"sentry-sdk==2.16.0",
|
||||
"sentry-sdk==2.17.0",
|
||||
"url-normalize==1.4.3",
|
||||
"WeasyPrint>=60.2",
|
||||
"whitenoise==6.7.0",
|
||||
@@ -82,7 +82,7 @@ dev = [
|
||||
"pytest-icdiff==0.9",
|
||||
"pytest-xdist==3.6.1",
|
||||
"responses==0.25.3",
|
||||
"ruff==0.6.9",
|
||||
"ruff==0.7.0",
|
||||
"types-requests==2.32.0.20241016",
|
||||
]
|
||||
|
||||
|
||||
@@ -4,17 +4,17 @@ export const keyCloakSignIn = async (page: Page, browserName: string) => {
|
||||
const login = `user-e2e-${browserName}`;
|
||||
const password = `password-e2e-${browserName}`;
|
||||
|
||||
await expect(
|
||||
page.locator('.login-pf-page-header').getByText('impress'),
|
||||
).toBeVisible();
|
||||
|
||||
if (await page.getByLabel('Restart login').isVisible()) {
|
||||
await page.getByRole('textbox', { name: 'password' }).fill(password);
|
||||
|
||||
await page.click('input[type="submit"]', { force: true });
|
||||
} else {
|
||||
await page.getByRole('textbox', { name: 'username' }).fill(login);
|
||||
|
||||
await page.getByRole('textbox', { name: 'password' }).fill(password);
|
||||
|
||||
await page.click('input[type="submit"]', { force: true });
|
||||
await page.getByLabel('Restart login').click();
|
||||
}
|
||||
|
||||
await page.getByRole('textbox', { name: 'username' }).fill(login);
|
||||
await page.getByRole('textbox', { name: 'password' }).fill(password);
|
||||
await page.click('input[type="submit"]', { force: true });
|
||||
};
|
||||
|
||||
export const randomName = (name: string, browserName: string, length: number) =>
|
||||
@@ -27,7 +27,6 @@ export const createDoc = async (
|
||||
docName: string,
|
||||
browserName: string,
|
||||
length: number,
|
||||
isPublic: boolean = false,
|
||||
) => {
|
||||
const randomDocs = randomName(docName, browserName, length);
|
||||
|
||||
@@ -44,22 +43,6 @@ export const createDoc = async (
|
||||
await page.getByRole('heading', { name: 'Untitled document' }).click();
|
||||
await page.keyboard.type(randomDocs[i]);
|
||||
await page.getByText('Created at ').click();
|
||||
|
||||
if (isPublic) {
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
await page.getByText('Doc private').click();
|
||||
|
||||
await page.locator('.c__modal__backdrop').click({
|
||||
position: { x: 0, y: 0 },
|
||||
force: true,
|
||||
});
|
||||
|
||||
await expect(
|
||||
page
|
||||
.getByLabel('It is the card information about the document.')
|
||||
.getByText('Public'),
|
||||
).toBeVisible();
|
||||
}
|
||||
}
|
||||
|
||||
return randomDocs;
|
||||
|
||||
@@ -9,6 +9,78 @@ test.beforeEach(async ({ page }) => {
|
||||
});
|
||||
|
||||
test.describe('Doc Editor', () => {
|
||||
test('it check translations of the slash menu when changing language', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await createDoc(page, 'doc-toolbar', browserName, 1);
|
||||
|
||||
const header = page.locator('header').first();
|
||||
const editor = page.locator('.ProseMirror');
|
||||
// Trigger slash menu to show english menu
|
||||
await editor.click();
|
||||
await editor.fill('/');
|
||||
await expect(page.getByText('Headings', { exact: true })).toBeVisible();
|
||||
await header.click();
|
||||
await expect(page.getByText('Headings', { exact: true })).toBeHidden();
|
||||
|
||||
// Reset menu
|
||||
await editor.click();
|
||||
await editor.fill('');
|
||||
|
||||
// Change language to French
|
||||
await header.click();
|
||||
await header.getByRole('combobox').getByText('English').click();
|
||||
await header.getByRole('option', { name: 'Français' }).click();
|
||||
await expect(
|
||||
header.getByRole('combobox').getByText('Français'),
|
||||
).toBeVisible();
|
||||
|
||||
// Trigger slash menu to show french menu
|
||||
await editor.click();
|
||||
await editor.fill('/');
|
||||
await expect(page.getByText('Titres', { exact: true })).toBeVisible();
|
||||
await header.click();
|
||||
await expect(page.getByText('Titres', { exact: true })).toBeHidden();
|
||||
});
|
||||
|
||||
test('it checks default toolbar buttons are displayed', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await createDoc(page, 'doc-toolbar', browserName, 1);
|
||||
|
||||
const editor = page.locator('.ProseMirror');
|
||||
await editor.click();
|
||||
await editor.fill('test content');
|
||||
|
||||
await editor.getByText('test content').dblclick();
|
||||
|
||||
const toolbar = page.locator('.bn-formatting-toolbar');
|
||||
await expect(toolbar.locator('button[data-test="bold"]')).toBeVisible();
|
||||
await expect(toolbar.locator('button[data-test="italic"]')).toBeVisible();
|
||||
await expect(
|
||||
toolbar.locator('button[data-test="underline"]'),
|
||||
).toBeVisible();
|
||||
await expect(toolbar.locator('button[data-test="strike"]')).toBeVisible();
|
||||
await expect(
|
||||
toolbar.locator('button[data-test="alignTextLeft"]'),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
toolbar.locator('button[data-test="alignTextCenter"]'),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
toolbar.locator('button[data-test="alignTextRight"]'),
|
||||
).toBeVisible();
|
||||
await expect(toolbar.locator('button[data-test="colors"]')).toBeVisible();
|
||||
await expect(
|
||||
toolbar.locator('button[data-test="unnestBlock"]'),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
toolbar.locator('button[data-test="createLink"]'),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('checks the Doc is connected to the provider server', async ({
|
||||
page,
|
||||
browserName,
|
||||
@@ -59,9 +131,10 @@ test.describe('Doc Editor', () => {
|
||||
|
||||
test('it renders correctly when we switch from one doc to another', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
// Check the first doc
|
||||
const firstDoc = await goToGridDoc(page);
|
||||
const [firstDoc] = await createDoc(page, 'doc-switch-1', browserName, 1);
|
||||
await expect(page.locator('h2').getByText(firstDoc)).toBeVisible();
|
||||
|
||||
const editor = page.locator('.ProseMirror');
|
||||
@@ -70,9 +143,7 @@ test.describe('Doc Editor', () => {
|
||||
await expect(editor.getByText('Hello World Doc 1')).toBeVisible();
|
||||
|
||||
// Check the second doc
|
||||
const secondDoc = await goToGridDoc(page, {
|
||||
nthRow: 2,
|
||||
});
|
||||
const [secondDoc] = await createDoc(page, 'doc-switch-2', browserName, 1);
|
||||
await expect(page.locator('h2').getByText(secondDoc)).toBeVisible();
|
||||
await expect(editor.getByText('Hello World Doc 1')).toBeHidden();
|
||||
await editor.click();
|
||||
@@ -88,9 +159,12 @@ test.describe('Doc Editor', () => {
|
||||
await expect(editor.getByText('Hello World Doc 1')).toBeVisible();
|
||||
});
|
||||
|
||||
test('it saves the doc when we change pages', async ({ page }) => {
|
||||
test('it saves the doc when we change pages', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
// Check the first doc
|
||||
const doc = await goToGridDoc(page);
|
||||
const [doc] = await createDoc(page, 'doc-saves-change', browserName, 1);
|
||||
await expect(page.locator('h2').getByText(doc)).toBeVisible();
|
||||
|
||||
const editor = page.locator('.ProseMirror');
|
||||
|
||||
@@ -21,6 +21,7 @@ test.describe('Doc Header', () => {
|
||||
role: 'owner',
|
||||
user: {
|
||||
email: 'super@owner.com',
|
||||
full_name: 'Super Owner',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -65,7 +66,7 @@ test.describe('Doc Header', () => {
|
||||
card.getByText('Created at 09/01/2021, 11:00 AM'),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
card.getByText('Owners: super@owner.com / super2@owner.com'),
|
||||
card.getByText('Owners: Super Owner / super2@owner.com'),
|
||||
).toBeVisible();
|
||||
await expect(card.getByText('Your role: Owner')).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Share' })).toBeVisible();
|
||||
@@ -211,7 +212,11 @@ test.describe('Doc Header', () => {
|
||||
|
||||
const shareModal = page.getByLabel('Share modal');
|
||||
|
||||
await expect(shareModal.getByLabel('Doc private')).toBeEnabled();
|
||||
await expect(
|
||||
shareModal.getByRole('combobox', {
|
||||
name: 'Visibility',
|
||||
}),
|
||||
).not.toHaveAttribute('disabled');
|
||||
await expect(shareModal.getByText('Search by email')).toBeVisible();
|
||||
|
||||
const invitationCard = shareModal.getByLabel('List invitation card');
|
||||
@@ -284,7 +289,11 @@ test.describe('Doc Header', () => {
|
||||
|
||||
const shareModal = page.getByLabel('Share modal');
|
||||
|
||||
await expect(shareModal.getByLabel('Doc private')).toBeDisabled();
|
||||
await expect(
|
||||
shareModal.getByRole('combobox', {
|
||||
name: 'Visibility',
|
||||
}),
|
||||
).toHaveAttribute('disabled');
|
||||
await expect(shareModal.getByText('Search by email')).toBeHidden();
|
||||
|
||||
const invitationCard = shareModal.getByLabel('List invitation card');
|
||||
@@ -357,7 +366,11 @@ test.describe('Doc Header', () => {
|
||||
|
||||
const shareModal = page.getByLabel('Share modal');
|
||||
|
||||
await expect(shareModal.getByLabel('Doc private')).toBeDisabled();
|
||||
await expect(
|
||||
shareModal.getByRole('combobox', {
|
||||
name: 'Visibility',
|
||||
}),
|
||||
).toHaveAttribute('disabled');
|
||||
await expect(shareModal.getByText('Search by email')).toBeHidden();
|
||||
|
||||
const invitationCard = shareModal.getByLabel('List invitation card');
|
||||
|
||||
@@ -25,6 +25,7 @@ test.describe('Document list members', () => {
|
||||
user: {
|
||||
id: `fc092149-cafa-4ffa-a29d-e4b18af751-${pageId}-${i}`,
|
||||
email: `impress@impress.world-page-${pageId}-${i}`,
|
||||
full_name: `Impress World Page ${pageId}-${i}`,
|
||||
},
|
||||
team: '',
|
||||
role: 'editor',
|
||||
@@ -58,9 +59,11 @@ test.describe('Document list members', () => {
|
||||
await waitForElementCount(list.locator('li'), 21, 10000);
|
||||
|
||||
expect(await list.locator('li').count()).toBeGreaterThan(20);
|
||||
await expect(list.getByText(`Impress World Page 1-16`)).toBeVisible();
|
||||
await expect(
|
||||
list.getByText(`impress@impress.world-page-1-16`),
|
||||
).toBeVisible();
|
||||
await expect(list.getByText(`Impress World Page 2-15`)).toBeVisible();
|
||||
await expect(
|
||||
list.getByText(`impress@impress.world-page-2-15`),
|
||||
).toBeVisible();
|
||||
@@ -164,14 +167,22 @@ test.describe('Document list members', () => {
|
||||
const shareModal = page.getByLabel('Share modal');
|
||||
|
||||
// Admin still have the right to share
|
||||
await expect(shareModal.getByLabel('Doc private')).toBeEnabled();
|
||||
await expect(
|
||||
shareModal.getByRole('combobox', {
|
||||
name: 'Visibility',
|
||||
}),
|
||||
).not.toHaveAttribute('disabled');
|
||||
|
||||
await SelectRoleCurrentUser.click();
|
||||
await page.getByRole('option', { name: 'Reader' }).click();
|
||||
await expect(page.getByText('The role has been updated')).toBeVisible();
|
||||
|
||||
// Reader does not have the right to share
|
||||
await expect(shareModal.getByLabel('Doc private')).toBeDisabled();
|
||||
await expect(
|
||||
shareModal.getByRole('combobox', {
|
||||
name: 'Visibility',
|
||||
}),
|
||||
).toHaveAttribute('disabled');
|
||||
});
|
||||
|
||||
test('it checks the delete members', async ({ page, browserName }) => {
|
||||
|
||||
@@ -7,6 +7,22 @@ test.describe('Doc Routing', () => {
|
||||
await page.goto('/');
|
||||
});
|
||||
|
||||
test('Check the presence of the meta tag noindex', async ({ page }) => {
|
||||
const buttonCreateHomepage = page.getByRole('button', {
|
||||
name: 'Create a new document',
|
||||
});
|
||||
|
||||
await expect(buttonCreateHomepage).toBeVisible();
|
||||
await buttonCreateHomepage.click();
|
||||
await expect(
|
||||
page.getByRole('button', {
|
||||
name: 'Share',
|
||||
}),
|
||||
).toBeVisible();
|
||||
const metaDescription = page.locator('meta[name="robots"]');
|
||||
await expect(metaDescription).toHaveAttribute('content', 'noindex');
|
||||
});
|
||||
|
||||
test('checks alias docs url with homepage', async ({ page }) => {
|
||||
await expect(page).toHaveURL('/');
|
||||
|
||||
|
||||
@@ -2,39 +2,13 @@ import { expect, test } from '@playwright/test';
|
||||
|
||||
import { createDoc, keyCloakSignIn } from './common';
|
||||
|
||||
const browsersName = ['chromium', 'webkit', 'firefox'];
|
||||
|
||||
test.describe('Doc Visibility', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
});
|
||||
|
||||
test('Make a public doc', async ({ page, browserName }) => {
|
||||
const [docTitle] = await createDoc(
|
||||
page,
|
||||
'My new doc',
|
||||
browserName,
|
||||
1,
|
||||
true,
|
||||
);
|
||||
|
||||
const header = page.locator('header').first();
|
||||
await header.locator('h2').getByText('Docs').click();
|
||||
|
||||
const datagrid = page.getByLabel('Datagrid of the documents page 1');
|
||||
const datagridTable = datagrid.getByRole('table');
|
||||
|
||||
await expect(datagrid.getByLabel('Loading data')).toBeHidden({
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
await expect(datagridTable.getByText(docTitle)).toBeVisible();
|
||||
|
||||
const row = datagridTable.getByRole('row').filter({
|
||||
hasText: docTitle,
|
||||
});
|
||||
|
||||
await expect(row.getByRole('cell').nth(0)).toHaveText('Public');
|
||||
});
|
||||
|
||||
test('It checks the copy link button', async ({ page, browserName }) => {
|
||||
// eslint-disable-next-line playwright/no-skipped-test
|
||||
test.skip(
|
||||
@@ -56,12 +30,48 @@ test.describe('Doc Visibility', () => {
|
||||
|
||||
expect(clipboardContent).toMatch(page.url());
|
||||
});
|
||||
|
||||
test('It checks the link role options', async ({ page, browserName }) => {
|
||||
await createDoc(page, 'Doc role options', browserName, 1);
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
|
||||
const selectVisibility = page.getByRole('combobox', {
|
||||
name: 'Visibility',
|
||||
});
|
||||
|
||||
await expect(selectVisibility.getByText('Authenticated')).toBeVisible();
|
||||
|
||||
await expect(page.getByLabel('Read only')).toBeVisible();
|
||||
await expect(page.getByLabel('Can read and edit')).toBeVisible();
|
||||
|
||||
await selectVisibility.click();
|
||||
await page
|
||||
.getByRole('option', {
|
||||
name: 'Restricted',
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(page.getByLabel('Read only')).toBeHidden();
|
||||
await expect(page.getByLabel('Can read and edit')).toBeHidden();
|
||||
|
||||
await selectVisibility.click();
|
||||
|
||||
await page
|
||||
.getByRole('option', {
|
||||
name: 'Public',
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(page.getByLabel('Read only')).toBeVisible();
|
||||
await expect(page.getByLabel('Can read and edit')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Doc Visibility: Not loggued', () => {
|
||||
test.describe('Doc Visibility: Restricted', () => {
|
||||
test.use({ storageState: { cookies: [], origins: [] } });
|
||||
|
||||
test('A public doc is accessible even when not authentified.', async ({
|
||||
test('A doc is not accessible when not authentified.', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
@@ -70,14 +80,211 @@ test.describe('Doc Visibility: Not loggued', () => {
|
||||
|
||||
const [docTitle] = await createDoc(
|
||||
page,
|
||||
'My new doc',
|
||||
'Restricted no auth',
|
||||
browserName,
|
||||
1,
|
||||
true,
|
||||
);
|
||||
|
||||
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
await page
|
||||
.getByRole('combobox', {
|
||||
name: 'Visibility',
|
||||
})
|
||||
.click();
|
||||
await page
|
||||
.getByRole('option', {
|
||||
name: 'Restricted',
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(
|
||||
page.getByText('The document visiblitity has been updated.'),
|
||||
page.getByText('The document visibility has been updated.'),
|
||||
).toBeVisible();
|
||||
|
||||
await page.locator('.c__modal__backdrop').click({
|
||||
position: { x: 0, y: 0 },
|
||||
});
|
||||
|
||||
const urlDoc = page.url();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Logout',
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible();
|
||||
|
||||
await page.goto(urlDoc);
|
||||
|
||||
await expect(page.getByRole('textbox', { name: 'password' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('A doc is not accessible when authentified but not member.', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await page.goto('/');
|
||||
await keyCloakSignIn(page, browserName);
|
||||
|
||||
const [docTitle] = await createDoc(page, 'Restricted auth', browserName, 1);
|
||||
|
||||
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
await page
|
||||
.getByRole('combobox', {
|
||||
name: 'Visibility',
|
||||
})
|
||||
.click();
|
||||
await page
|
||||
.getByRole('option', {
|
||||
name: 'Restricted',
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(
|
||||
page.getByText('The document visibility has been updated.'),
|
||||
).toBeVisible();
|
||||
|
||||
await page.locator('.c__modal__backdrop').click({
|
||||
position: { x: 0, y: 0 },
|
||||
});
|
||||
|
||||
const urlDoc = page.url();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Logout',
|
||||
})
|
||||
.click();
|
||||
|
||||
const otherBrowser = browsersName.find((b) => b !== browserName);
|
||||
|
||||
await keyCloakSignIn(page, otherBrowser!);
|
||||
|
||||
await page.goto(urlDoc);
|
||||
|
||||
await expect(
|
||||
page.getByText('You do not have permission to perform this action.'),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('A doc is accessible when member.', async ({ page, browserName }) => {
|
||||
test.slow();
|
||||
await page.goto('/');
|
||||
await keyCloakSignIn(page, browserName);
|
||||
|
||||
const [docTitle] = await createDoc(page, 'Restricted auth', browserName, 1);
|
||||
|
||||
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
await page
|
||||
.getByRole('combobox', {
|
||||
name: 'Visibility',
|
||||
})
|
||||
.click();
|
||||
await page
|
||||
.getByRole('option', {
|
||||
name: 'Restricted',
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(
|
||||
page.getByText('The document visibility has been updated.'),
|
||||
).toBeVisible();
|
||||
|
||||
const inputSearch = page.getByLabel(/Find a member to add to the document/);
|
||||
|
||||
const otherBrowser = browsersName.find((b) => b !== browserName);
|
||||
const username = `user@${otherBrowser}.e2e`;
|
||||
await inputSearch.fill(username);
|
||||
await page.getByRole('option', { name: username }).click();
|
||||
|
||||
// Choose a role
|
||||
await page.getByRole('combobox', { name: /Choose a role/ }).click();
|
||||
await page.getByRole('option', { name: 'Administrator' }).click();
|
||||
|
||||
await page.getByRole('button', { name: 'Validate' }).click();
|
||||
|
||||
await expect(
|
||||
page.getByText(`User ${username} added to the document.`),
|
||||
).toBeVisible();
|
||||
|
||||
await page.locator('.c__modal__backdrop').click({
|
||||
position: { x: 0, y: 0 },
|
||||
});
|
||||
|
||||
const urlDoc = page.url();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Logout',
|
||||
})
|
||||
.click();
|
||||
|
||||
await keyCloakSignIn(page, otherBrowser!);
|
||||
|
||||
await page.goto(urlDoc);
|
||||
|
||||
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Share' })).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Doc Visibility: Public', () => {
|
||||
test.use({ storageState: { cookies: [], origins: [] } });
|
||||
|
||||
test('It checks a public doc in read only mode', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await page.goto('/');
|
||||
await keyCloakSignIn(page, browserName);
|
||||
|
||||
const [docTitle] = await createDoc(
|
||||
page,
|
||||
'Public read only',
|
||||
browserName,
|
||||
1,
|
||||
);
|
||||
|
||||
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
await page
|
||||
.getByRole('combobox', {
|
||||
name: 'Visibility',
|
||||
})
|
||||
.click();
|
||||
|
||||
await page
|
||||
.getByRole('option', {
|
||||
name: 'Public',
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(
|
||||
page.getByText('The document visibility has been updated.'),
|
||||
).toBeVisible();
|
||||
|
||||
await page.getByLabel('Read only').click();
|
||||
|
||||
await expect(
|
||||
page.getByText('The document visibility has been updated.').first(),
|
||||
).toBeVisible();
|
||||
|
||||
await page.locator('.c__modal__backdrop').click({
|
||||
position: { x: 0, y: 0 },
|
||||
});
|
||||
|
||||
await expect(
|
||||
page
|
||||
.getByLabel('It is the card information about the document.')
|
||||
.getByText('Public', { exact: true }),
|
||||
).toBeVisible();
|
||||
|
||||
const urlDoc = page.url();
|
||||
@@ -94,19 +301,54 @@ test.describe('Doc Visibility: Not loggued', () => {
|
||||
|
||||
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Share' })).toBeHidden();
|
||||
await expect(
|
||||
page.getByText('Read only, you cannot edit this document'),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('A private doc redirect to the OIDC when not authentified.', async ({
|
||||
test('It checks a public doc in editable mode', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
test.slow();
|
||||
await page.goto('/');
|
||||
await keyCloakSignIn(page, browserName);
|
||||
|
||||
const [docTitle] = await createDoc(page, 'My private doc', browserName, 1);
|
||||
const [docTitle] = await createDoc(page, 'Public editable', browserName, 1);
|
||||
|
||||
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
await page
|
||||
.getByRole('combobox', {
|
||||
name: 'Visibility',
|
||||
})
|
||||
.click();
|
||||
|
||||
await page
|
||||
.getByRole('option', {
|
||||
name: 'Public',
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(
|
||||
page.getByText('The document visibility has been updated.'),
|
||||
).toBeVisible();
|
||||
|
||||
await page.getByLabel('Can read and edit').click();
|
||||
|
||||
await expect(
|
||||
page.getByText('The document visibility has been updated.').first(),
|
||||
).toBeVisible();
|
||||
|
||||
await page.locator('.c__modal__backdrop').click({
|
||||
position: { x: 0, y: 0 },
|
||||
});
|
||||
|
||||
await expect(
|
||||
page
|
||||
.getByLabel('It is the card information about the document.')
|
||||
.getByText('Public', { exact: true }),
|
||||
).toBeVisible();
|
||||
|
||||
const urlDoc = page.url();
|
||||
|
||||
@@ -116,10 +358,134 @@ test.describe('Doc Visibility: Not loggued', () => {
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(page.getByRole('textbox', { name: 'password' })).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible();
|
||||
|
||||
await page.goto(urlDoc);
|
||||
|
||||
await expect(page.getByRole('textbox', { name: 'password' })).toBeVisible();
|
||||
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Share' })).toBeHidden();
|
||||
await expect(
|
||||
page.getByText('Read only, you cannot edit this document'),
|
||||
).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Doc Visibility: Authenticated', () => {
|
||||
test.use({ storageState: { cookies: [], origins: [] } });
|
||||
|
||||
test('A doc is not accessible when unauthentified.', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await page.goto('/');
|
||||
await keyCloakSignIn(page, browserName);
|
||||
|
||||
const [docTitle] = await createDoc(
|
||||
page,
|
||||
'Authenticated unauthentified',
|
||||
browserName,
|
||||
1,
|
||||
);
|
||||
|
||||
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||
|
||||
const urlDoc = page.url();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Logout',
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible();
|
||||
|
||||
await page.goto(urlDoc);
|
||||
|
||||
await expect(page.locator('h2').getByText(docTitle)).toBeHidden();
|
||||
await expect(page.getByRole('textbox', { name: 'password' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('It checks a authenticated doc in read only mode', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await page.goto('/');
|
||||
await keyCloakSignIn(page, browserName);
|
||||
|
||||
const [docTitle] = await createDoc(
|
||||
page,
|
||||
'Authenticated read only',
|
||||
browserName,
|
||||
1,
|
||||
);
|
||||
|
||||
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||
|
||||
const urlDoc = page.url();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Logout',
|
||||
})
|
||||
.click();
|
||||
|
||||
const otherBrowser = browsersName.find((b) => b !== browserName);
|
||||
await keyCloakSignIn(page, otherBrowser!);
|
||||
|
||||
await page.goto(urlDoc);
|
||||
|
||||
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Share' })).toBeVisible();
|
||||
await expect(
|
||||
page.getByText('Read only, you cannot edit this document'),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('It checks a authenticated doc in editable mode', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await page.goto('/');
|
||||
await keyCloakSignIn(page, browserName);
|
||||
|
||||
const [docTitle] = await createDoc(
|
||||
page,
|
||||
'Authenticated editable',
|
||||
browserName,
|
||||
1,
|
||||
);
|
||||
|
||||
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||
|
||||
const urlDoc = page.url();
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
|
||||
await page.getByLabel('Can read and edit').click();
|
||||
|
||||
await expect(
|
||||
page.getByText('The document visibility has been updated.').first(),
|
||||
).toBeVisible();
|
||||
|
||||
await page.locator('.c__modal__backdrop').click({
|
||||
position: { x: 0, y: 0 },
|
||||
});
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Logout',
|
||||
})
|
||||
.click();
|
||||
|
||||
const otherBrowser = browsersName.find((b) => b !== browserName);
|
||||
await keyCloakSignIn(page, otherBrowser!);
|
||||
|
||||
await page.goto(urlDoc);
|
||||
|
||||
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Share' })).toBeVisible();
|
||||
await expect(
|
||||
page.getByText('Read only, you cannot edit this document'),
|
||||
).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,4 +25,38 @@ test.describe('Language', () => {
|
||||
}),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('checks that backend uses the same language as the frontend', async ({
|
||||
page,
|
||||
}) => {
|
||||
// Helper function to intercept and assert 404 response
|
||||
const check404Response = async (expectedDetail: string) => {
|
||||
const expectedBackendResponse = page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/api') &&
|
||||
response.url().includes('non-existent-doc-uuid') &&
|
||||
response.status() === 404,
|
||||
);
|
||||
|
||||
// Trigger the specific 404 XHR response by navigating to a non-existent document
|
||||
await page.goto('/docs/non-existent-doc-uuid');
|
||||
|
||||
// Assert that the intercepted error message is in the expected language
|
||||
const interceptedBackendResponse = await expectedBackendResponse;
|
||||
expect(await interceptedBackendResponse.json()).toStrictEqual({
|
||||
detail: expectedDetail,
|
||||
});
|
||||
};
|
||||
|
||||
// Check for English 404 response
|
||||
await check404Response('Not found.');
|
||||
|
||||
// Switch language to French
|
||||
const header = page.locator('header').first();
|
||||
await header.getByRole('combobox').getByText('English').click();
|
||||
await header.getByRole('option', { name: 'Français' }).click();
|
||||
|
||||
// Check for French 404 response
|
||||
await check404Response('Pas trouvé.');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "app-e2e",
|
||||
"version": "1.6.0",
|
||||
"version": "1.7.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"lint": "eslint . --ext .ts",
|
||||
|
||||
@@ -358,6 +358,8 @@ const config = {
|
||||
},
|
||||
'forms-field': {
|
||||
color: 'var(--c--theme--colors--primary-text)',
|
||||
'footer-font-size': 'var(--c--theme--font--sizes--t)',
|
||||
'footer-color': 'var(--c--theme--colors--greyscale-text)',
|
||||
},
|
||||
'forms-input': {
|
||||
'border-radius': '4px',
|
||||
@@ -372,6 +374,9 @@ const config = {
|
||||
big: 'var(--c--theme--colors--primary-text)',
|
||||
},
|
||||
},
|
||||
'forms-radio': {
|
||||
'accent-color': 'var(--c--theme--colors--primary-600)',
|
||||
},
|
||||
'forms-select': {
|
||||
'item-font-size': '14px',
|
||||
'border-radius': '4px',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "app-impress",
|
||||
"version": "1.6.0",
|
||||
"version": "1.7.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
@@ -22,7 +22,8 @@
|
||||
"@hocuspocus/provider": "2.13.7",
|
||||
"@openfun/cunningham-react": "2.9.4",
|
||||
"@tanstack/react-query": "5.59.15",
|
||||
"i18next": "23.16.0",
|
||||
"i18next": "23.16.2",
|
||||
"i18next-browser-languagedetector": "8.0.0",
|
||||
"idb": "8.0.0",
|
||||
"lodash": "4.17.21",
|
||||
"luxon": "3.5.0",
|
||||
@@ -41,11 +42,11 @@
|
||||
"@svgr/webpack": "8.1.0",
|
||||
"@tanstack/react-query-devtools": "5.59.15",
|
||||
"@testing-library/dom": "10.4.0",
|
||||
"@testing-library/jest-dom": "6.6.1",
|
||||
"@testing-library/jest-dom": "6.6.2",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@testing-library/user-event": "14.5.2",
|
||||
"@types/jest": "29.5.13",
|
||||
"@types/lodash": "4.17.10",
|
||||
"@types/lodash": "4.17.12",
|
||||
"@types/luxon": "3.4.2",
|
||||
"@types/node": "*",
|
||||
"@types/react": "18.3.11",
|
||||
|
||||
@@ -19,7 +19,7 @@ export interface BoxProps {
|
||||
$direction?: CSSProperties['flexDirection'];
|
||||
$display?: CSSProperties['display'];
|
||||
$effect?: 'show' | 'hide';
|
||||
$flex?: boolean;
|
||||
$flex?: CSSProperties['flex'];
|
||||
$gap?: CSSProperties['gap'];
|
||||
$hasTransition?: boolean | 'slow';
|
||||
$height?: CSSProperties['height'];
|
||||
@@ -50,7 +50,7 @@ export const Box = styled('div')<BoxProps>`
|
||||
${({ $color }) => $color && `color: ${$color};`}
|
||||
${({ $direction }) => $direction && `flex-direction: ${$direction};`}
|
||||
${({ $display }) => $display && `display: ${$display};`}
|
||||
${({ $flex }) => $flex === false && `display: block;`}
|
||||
${({ $flex }) => $flex && `flex: ${$flex};`}
|
||||
${({ $gap }) => $gap && `gap: ${$gap};`}
|
||||
${({ $height }) => $height && `height: ${$height};`}
|
||||
${({ $hasTransition }) =>
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { CSSProperties, ComponentPropsWithRef, ReactHTML } from 'react';
|
||||
import {
|
||||
CSSProperties,
|
||||
ComponentPropsWithRef,
|
||||
ReactHTML,
|
||||
forwardRef,
|
||||
} from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { tokens } from '@/cunningham';
|
||||
@@ -55,18 +60,21 @@ export const TextStyled = styled(Box)<TextProps>`
|
||||
`white-space: nowrap; overflow: hidden; text-overflow: ellipsis;`}
|
||||
`;
|
||||
|
||||
export const Text = ({
|
||||
className,
|
||||
$isMaterialIcon,
|
||||
...props
|
||||
}: ComponentPropsWithRef<typeof TextStyled>) => {
|
||||
return (
|
||||
<TextStyled
|
||||
as="span"
|
||||
$theme="greyscale"
|
||||
$variation="text"
|
||||
className={`${className || ''}${$isMaterialIcon ? ' material-icons' : ''}`}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const Text = forwardRef<HTMLElement, ComponentPropsWithRef<typeof TextStyled>>(
|
||||
({ className, $isMaterialIcon, ...props }, ref) => {
|
||||
return (
|
||||
<TextStyled
|
||||
ref={ref}
|
||||
as="span"
|
||||
$theme="greyscale"
|
||||
$variation="text"
|
||||
className={`${className || ''}${$isMaterialIcon ? ' material-icons' : ''}`}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Text.displayName = 'Text';
|
||||
|
||||
export { Text };
|
||||
|
||||
@@ -8,4 +8,6 @@
|
||||
export interface User {
|
||||
id: string;
|
||||
email: string;
|
||||
full_name: string;
|
||||
short_name: string;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
line-height: initial;
|
||||
}
|
||||
|
||||
.c__field .c__field__footer {
|
||||
padding: 2px 0 0;
|
||||
font-size: var(--c--components--forms-field--footer-font-size);
|
||||
color: var(--c--components--forms-field--footer-color);
|
||||
}
|
||||
|
||||
.labelled-box label {
|
||||
color: var(--c--theme--colors--primary-text);
|
||||
}
|
||||
@@ -328,6 +334,10 @@ input:-webkit-autofill:focus {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.c__checkbox.c__checkbox--disabled .c__checkbox__label {
|
||||
color: var(--c--theme--colors--greyscale-400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Button
|
||||
*/
|
||||
@@ -532,3 +542,10 @@ input:-webkit-autofill:focus {
|
||||
.c__toast__container {
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tooltip
|
||||
*/
|
||||
.c__tooltip {
|
||||
padding: 4px 6px;
|
||||
}
|
||||
|
||||
@@ -477,6 +477,12 @@
|
||||
--c--components--forms-datepicker--border-radius: 0;
|
||||
--c--components--forms-fileuploader--border-radius: 0;
|
||||
--c--components--forms-field--color: var(--c--theme--colors--primary-text);
|
||||
--c--components--forms-field--footer-font-size: var(
|
||||
--c--theme--font--sizes--t
|
||||
);
|
||||
--c--components--forms-field--footer-color: var(
|
||||
--c--theme--colors--greyscale-text
|
||||
);
|
||||
--c--components--forms-input--border-radius: 4px;
|
||||
--c--components--forms-input--background-color: #fff;
|
||||
--c--components--forms-input--border-color: var(
|
||||
@@ -492,6 +498,9 @@
|
||||
--c--components--forms-labelledbox--label-color--big: var(
|
||||
--c--theme--colors--primary-text
|
||||
);
|
||||
--c--components--forms-radio--accent-color: var(
|
||||
--c--theme--colors--primary-600
|
||||
);
|
||||
--c--components--forms-select--item-font-size: 14px;
|
||||
--c--components--forms-select--border-radius: 4px;
|
||||
--c--components--forms-select--border-radius-hover: 4px;
|
||||
|
||||
@@ -479,7 +479,11 @@ export const tokens = {
|
||||
},
|
||||
'forms-datepicker': { 'border-radius': '0' },
|
||||
'forms-fileuploader': { 'border-radius': '0' },
|
||||
'forms-field': { color: 'var(--c--theme--colors--primary-text)' },
|
||||
'forms-field': {
|
||||
color: 'var(--c--theme--colors--primary-text)',
|
||||
'footer-font-size': 'var(--c--theme--font--sizes--t)',
|
||||
'footer-color': 'var(--c--theme--colors--greyscale-text)',
|
||||
},
|
||||
'forms-input': {
|
||||
'border-radius': '4px',
|
||||
'background-color': '#ffffff',
|
||||
@@ -491,6 +495,9 @@ export const tokens = {
|
||||
'forms-labelledbox': {
|
||||
'label-color': { big: 'var(--c--theme--colors--primary-text)' },
|
||||
},
|
||||
'forms-radio': {
|
||||
'accent-color': 'var(--c--theme--colors--primary-600)',
|
||||
},
|
||||
'forms-select': {
|
||||
'item-font-size': '14px',
|
||||
'border-radius': '4px',
|
||||
|
||||
@@ -9,14 +9,7 @@ import {
|
||||
VariantType,
|
||||
useToastProvider,
|
||||
} from '@openfun/cunningham-react';
|
||||
import {
|
||||
PropsWithChildren,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { PropsWithChildren, ReactNode, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { isAPIError } from '@/api';
|
||||
@@ -70,9 +63,8 @@ export function AIGroupButton() {
|
||||
const { t } = useTranslation();
|
||||
const { currentDoc } = useDocStore();
|
||||
const { data: docOptions } = useDocOptions();
|
||||
const [languages, setLanguages] = useState<LanguageTranslate[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const languages = useMemo(() => {
|
||||
const languages = docOptions?.actions.POST.language.choices;
|
||||
|
||||
if (!languages) {
|
||||
@@ -90,7 +82,7 @@ export function AIGroupButton() {
|
||||
'pl',
|
||||
]);
|
||||
|
||||
setLanguages(languages);
|
||||
return languages;
|
||||
}, [docOptions?.actions.POST.language.choices]);
|
||||
|
||||
const show = useMemo(() => {
|
||||
@@ -220,45 +212,19 @@ const AIMenuItemTransform = ({
|
||||
children,
|
||||
icon,
|
||||
}: PropsWithChildren<AIMenuItemTransform>) => {
|
||||
const editor = useBlockNoteEditor();
|
||||
const { mutateAsync: requestAI, isPending } = useDocAITransform();
|
||||
const handleAIError = useHandleAIError();
|
||||
|
||||
const handleAIAction = useCallback(async () => {
|
||||
const selectedBlocks = editor.getSelection()?.blocks;
|
||||
|
||||
if (!selectedBlocks || selectedBlocks.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const markdown = await editor.blocksToMarkdownLossy(selectedBlocks);
|
||||
|
||||
try {
|
||||
const responseAI = await requestAI({
|
||||
text: markdown,
|
||||
action,
|
||||
docId,
|
||||
});
|
||||
|
||||
if (!responseAI.answer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const blockMarkdown = await editor.tryParseMarkdownToBlocks(
|
||||
responseAI.answer,
|
||||
);
|
||||
editor.replaceBlocks(selectedBlocks, blockMarkdown);
|
||||
} catch (error) {
|
||||
handleAIError(error);
|
||||
}
|
||||
}, [editor, requestAI, action, docId, handleAIError]);
|
||||
const requestAIAction = async (markdown: string) => {
|
||||
const responseAI = await requestAI({
|
||||
text: markdown,
|
||||
action,
|
||||
docId,
|
||||
});
|
||||
return responseAI.answer;
|
||||
};
|
||||
|
||||
return (
|
||||
<AIMenuItem
|
||||
icon={icon}
|
||||
handleAIAction={handleAIAction}
|
||||
isPending={isPending}
|
||||
>
|
||||
<AIMenuItem icon={icon} requestAI={requestAIAction} isPending={isPending}>
|
||||
{children}
|
||||
</AIMenuItem>
|
||||
);
|
||||
@@ -276,11 +242,46 @@ const AIMenuItemTranslate = ({
|
||||
icon,
|
||||
language,
|
||||
}: PropsWithChildren<AIMenuItemTranslate>) => {
|
||||
const editor = useBlockNoteEditor();
|
||||
const { mutateAsync: requestAI, isPending } = useDocAITranslate();
|
||||
|
||||
const requestAITranslate = async (markdown: string) => {
|
||||
const responseAI = await requestAI({
|
||||
text: markdown,
|
||||
language,
|
||||
docId,
|
||||
});
|
||||
return responseAI.answer;
|
||||
};
|
||||
|
||||
return (
|
||||
<AIMenuItem
|
||||
icon={icon}
|
||||
requestAI={requestAITranslate}
|
||||
isPending={isPending}
|
||||
>
|
||||
{children}
|
||||
</AIMenuItem>
|
||||
);
|
||||
};
|
||||
|
||||
interface AIMenuItemProps {
|
||||
requestAI: (markdown: string) => Promise<string>;
|
||||
isPending: boolean;
|
||||
icon?: ReactNode;
|
||||
}
|
||||
|
||||
const AIMenuItem = ({
|
||||
requestAI,
|
||||
isPending,
|
||||
children,
|
||||
icon,
|
||||
}: PropsWithChildren<AIMenuItemProps>) => {
|
||||
const Components = useComponentsContext();
|
||||
|
||||
const editor = useBlockNoteEditor();
|
||||
const handleAIError = useHandleAIError();
|
||||
|
||||
const handleAIAction = useCallback(async () => {
|
||||
const handleAIAction = async () => {
|
||||
const selectedBlocks = editor.getSelection()?.blocks;
|
||||
|
||||
if (!selectedBlocks || selectedBlocks.length === 0) {
|
||||
@@ -290,49 +291,18 @@ const AIMenuItemTranslate = ({
|
||||
const markdown = await editor.blocksToMarkdownLossy(selectedBlocks);
|
||||
|
||||
try {
|
||||
const responseAI = await requestAI({
|
||||
text: markdown,
|
||||
language,
|
||||
docId,
|
||||
});
|
||||
const responseAI = await requestAI(markdown);
|
||||
|
||||
if (!responseAI.answer) {
|
||||
if (!responseAI) {
|
||||
return;
|
||||
}
|
||||
|
||||
const blockMarkdown = await editor.tryParseMarkdownToBlocks(
|
||||
responseAI.answer,
|
||||
);
|
||||
const blockMarkdown = await editor.tryParseMarkdownToBlocks(responseAI);
|
||||
editor.replaceBlocks(selectedBlocks, blockMarkdown);
|
||||
} catch (error) {
|
||||
handleAIError(error);
|
||||
}
|
||||
}, [editor, requestAI, language, docId, handleAIError]);
|
||||
|
||||
return (
|
||||
<AIMenuItem
|
||||
icon={icon}
|
||||
handleAIAction={handleAIAction}
|
||||
isPending={isPending}
|
||||
>
|
||||
{children}
|
||||
</AIMenuItem>
|
||||
);
|
||||
};
|
||||
|
||||
interface AIMenuItemProps {
|
||||
handleAIAction: () => Promise<void>;
|
||||
isPending: boolean;
|
||||
icon?: ReactNode;
|
||||
}
|
||||
|
||||
const AIMenuItem = ({
|
||||
handleAIAction,
|
||||
isPending,
|
||||
children,
|
||||
icon,
|
||||
}: PropsWithChildren<AIMenuItemProps>) => {
|
||||
const Components = useComponentsContext();
|
||||
};
|
||||
|
||||
if (!Components) {
|
||||
return null;
|
||||
@@ -359,26 +329,12 @@ const useHandleAIError = () => {
|
||||
const { toast } = useToastProvider();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleAIError = useCallback(
|
||||
(error: unknown) => {
|
||||
if (isAPIError(error)) {
|
||||
error.cause?.forEach((cause) => {
|
||||
if (
|
||||
cause === 'Request was throttled. Expected available in 60 seconds.'
|
||||
) {
|
||||
toast(
|
||||
t('Too many requests. Please wait 60 seconds.'),
|
||||
VariantType.ERROR,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
return (error: unknown) => {
|
||||
if (isAPIError(error) && error.status === 429) {
|
||||
toast(t('Too many requests. Please wait 60 seconds.'), VariantType.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
toast(t('AI seems busy! Please try again.'), VariantType.ERROR);
|
||||
console.error(error);
|
||||
},
|
||||
[toast, t],
|
||||
);
|
||||
|
||||
return handleAIError;
|
||||
toast(t('AI seems busy! Please try again.'), VariantType.ERROR);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { BlockNoteEditor as BlockNoteEditorCore } from '@blocknote/core';
|
||||
import { locales } from '@blocknote/core';
|
||||
import '@blocknote/core/fonts/inter.css';
|
||||
import { BlockNoteView } from '@blocknote/mantine';
|
||||
import '@blocknote/mantine/style.css';
|
||||
import { useCreateBlockNote } from '@blocknote/react';
|
||||
import { HocuspocusProvider } from '@hocuspocus/provider';
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Box, TextErrors } from '@/components';
|
||||
import { mediaUrl } from '@/core';
|
||||
@@ -113,6 +115,8 @@ export const BlockNoteContent = ({
|
||||
error: errorAttachment,
|
||||
} = useCreateDocAttachment();
|
||||
const { setHeadings, resetHeadings } = useHeadingStore();
|
||||
const { i18n } = useTranslation();
|
||||
const lang = i18n.language;
|
||||
|
||||
const uploadFile = useCallback(
|
||||
async (file: File) => {
|
||||
@@ -129,12 +133,8 @@ export const BlockNoteContent = ({
|
||||
[createDocAttachment, doc.id],
|
||||
);
|
||||
|
||||
const editor = useMemo(() => {
|
||||
if (storedEditor) {
|
||||
return storedEditor;
|
||||
}
|
||||
|
||||
return BlockNoteEditorCore.create({
|
||||
const editor = useCreateBlockNote(
|
||||
{
|
||||
collaboration: {
|
||||
provider,
|
||||
fragment: provider.document.getXmlFragment('document-store'),
|
||||
@@ -143,9 +143,11 @@ export const BlockNoteContent = ({
|
||||
color: randomColor(),
|
||||
},
|
||||
},
|
||||
dictionary: locales[lang as keyof typeof locales],
|
||||
uploadFile,
|
||||
});
|
||||
}, [provider, storedEditor, uploadFile, userData?.email]);
|
||||
},
|
||||
[provider, uploadFile, userData?.email, lang],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setStore(storeId, { editor });
|
||||
@@ -176,7 +178,7 @@ export const BlockNoteContent = ({
|
||||
)}
|
||||
|
||||
<BlockNoteView
|
||||
editor={editor}
|
||||
editor={storedEditor ?? editor}
|
||||
formattingToolbar={false}
|
||||
editable={!readOnly}
|
||||
theme="light"
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import '@blocknote/mantine/style.css';
|
||||
import {
|
||||
BasicTextStyleButton,
|
||||
BlockTypeSelect,
|
||||
ColorStyleButton,
|
||||
CreateLinkButton,
|
||||
FormattingToolbar,
|
||||
FormattingToolbarController,
|
||||
NestBlockButton,
|
||||
TextAlignButton,
|
||||
UnnestBlockButton,
|
||||
getFormattingToolbarItems,
|
||||
} from '@blocknote/react';
|
||||
import React from 'react';
|
||||
|
||||
@@ -18,42 +12,15 @@ import { MarkdownButton } from './MarkdownButton';
|
||||
export const BlockNoteToolbar = () => {
|
||||
return (
|
||||
<FormattingToolbarController
|
||||
formattingToolbar={() => (
|
||||
formattingToolbar={({ blockTypeSelectItems }) => (
|
||||
<FormattingToolbar>
|
||||
<BlockTypeSelect key="blockTypeSelect" />
|
||||
{getFormattingToolbarItems(blockTypeSelectItems)}
|
||||
|
||||
{/* Extra button to do some AI powered actions */}
|
||||
<AIGroupButton key="AIButton" />
|
||||
|
||||
{/* Extra button to convert from markdown to json */}
|
||||
<MarkdownButton key="customButton" />
|
||||
|
||||
<BasicTextStyleButton basicTextStyle="bold" key="boldStyleButton" />
|
||||
<BasicTextStyleButton
|
||||
basicTextStyle="italic"
|
||||
key="italicStyleButton"
|
||||
/>
|
||||
<BasicTextStyleButton
|
||||
basicTextStyle="underline"
|
||||
key="underlineStyleButton"
|
||||
/>
|
||||
<BasicTextStyleButton
|
||||
basicTextStyle="strike"
|
||||
key="strikeStyleButton"
|
||||
/>
|
||||
{/* Extra button to toggle code styles */}
|
||||
<BasicTextStyleButton key="codeStyleButton" basicTextStyle="code" />
|
||||
|
||||
<TextAlignButton textAlignment="left" key="textAlignLeftButton" />
|
||||
<TextAlignButton textAlignment="center" key="textAlignCenterButton" />
|
||||
<TextAlignButton textAlignment="right" key="textAlignRightButton" />
|
||||
|
||||
<ColorStyleButton key="colorStyleButton" />
|
||||
|
||||
<NestBlockButton key="nestBlockButton" />
|
||||
<UnnestBlockButton key="unnestBlockButton" />
|
||||
|
||||
<CreateLinkButton key="createLinkButton" />
|
||||
</FormattingToolbar>
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
} from '@blocknote/react';
|
||||
import { forEach, isArray } from 'lodash';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
type Block = {
|
||||
type: string;
|
||||
@@ -42,6 +43,7 @@ export function MarkdownButton() {
|
||||
const editor = useBlockNoteEditor();
|
||||
const Components = useComponentsContext();
|
||||
const selectedBlocks = useSelectedBlocks(editor);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleConvertMarkdown = () => {
|
||||
const blocks = editor.getSelection()?.blocks;
|
||||
@@ -75,7 +77,7 @@ export function MarkdownButton() {
|
||||
|
||||
return (
|
||||
<Components.FormattingToolbar.Button
|
||||
mainTooltip="Convert Markdown"
|
||||
mainTooltip={t('Convert Markdown')}
|
||||
onClick={handleConvertMarkdown}
|
||||
>
|
||||
M
|
||||
|
||||
@@ -104,7 +104,7 @@ export const DocHeader = ({ doc, versionId }: DocHeaderProps) => {
|
||||
)
|
||||
.map((access, index, accesses) => (
|
||||
<Fragment key={`access-${index}`}>
|
||||
{access.user.email}{' '}
|
||||
{access.user.full_name || access.user.email}{' '}
|
||||
{index < accesses.length - 1 ? ' / ' : ''}
|
||||
</Fragment>
|
||||
))}
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
} from '@openfun/cunningham-react';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { createGlobalStyle } from 'styled-components';
|
||||
|
||||
import { Box, Text } from '@/components';
|
||||
import { useCunninghamTheme } from '@/cunningham';
|
||||
@@ -22,12 +21,6 @@ import {
|
||||
import { useResponsiveStore } from '@/stores';
|
||||
import { isFirefox } from '@/utils/userAgent';
|
||||
|
||||
const DocTitleStyle = createGlobalStyle`
|
||||
.c__tooltip {
|
||||
padding: 4px 6px;
|
||||
}
|
||||
`;
|
||||
|
||||
interface DocTitleProps {
|
||||
doc: Doc;
|
||||
}
|
||||
@@ -126,7 +119,6 @@ const DocTitleInput = ({ doc }: DocTitleProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<DocTitleStyle />
|
||||
<Tooltip content={t('Rename')} placement="top">
|
||||
<Box
|
||||
as="h2"
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import {
|
||||
Button,
|
||||
Switch,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
Select,
|
||||
VariantType,
|
||||
useToastProvider,
|
||||
} from '@openfun/cunningham-react';
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Box, Card, IconBG } from '@/components';
|
||||
import { useCunninghamTheme } from '@/cunningham';
|
||||
|
||||
import { KEY_DOC, KEY_LIST_DOC, useUpdateDocLink } from '../api';
|
||||
import { Doc, LinkReach } from '../types';
|
||||
import { Doc, LinkReach, LinkRole } from '../types';
|
||||
|
||||
interface DocVisibilityProps {
|
||||
doc: Doc;
|
||||
@@ -18,14 +19,12 @@ interface DocVisibilityProps {
|
||||
|
||||
export const DocVisibility = ({ doc }: DocVisibilityProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [docPublic, setDocPublic] = useState(
|
||||
doc.link_reach === LinkReach.PUBLIC,
|
||||
);
|
||||
const { toast } = useToastProvider();
|
||||
const { colorsTokens } = useCunninghamTheme();
|
||||
const api = useUpdateDocLink({
|
||||
onSuccess: () => {
|
||||
toast(
|
||||
t('The document visiblitity has been updated.'),
|
||||
t('The document visibility has been updated.'),
|
||||
VariantType.SUCCESS,
|
||||
{
|
||||
duration: 4000,
|
||||
@@ -35,6 +34,34 @@ export const DocVisibility = ({ doc }: DocVisibilityProps) => {
|
||||
listInvalideQueries: [KEY_LIST_DOC, KEY_DOC],
|
||||
});
|
||||
|
||||
const transLinkReach = {
|
||||
[LinkReach.RESTRICTED]: {
|
||||
label: t('Restricted'),
|
||||
description: t('Only for people with access'),
|
||||
},
|
||||
[LinkReach.AUTHENTICATED]: {
|
||||
label: t('Authenticated'),
|
||||
description: t('Only for authenticated users'),
|
||||
},
|
||||
[LinkReach.PUBLIC]: {
|
||||
label: t('Public'),
|
||||
description: t('Anyone on the internet with the link can view'),
|
||||
},
|
||||
};
|
||||
|
||||
const linkRoleList = [
|
||||
{
|
||||
label: t('Read only'),
|
||||
value: LinkRole.READER,
|
||||
},
|
||||
{
|
||||
label: t('Can read and edit'),
|
||||
value: LinkRole.EDITOR,
|
||||
},
|
||||
];
|
||||
|
||||
const showLinkRoleOptions = doc.link_reach !== LinkReach.RESTRICTED;
|
||||
|
||||
return (
|
||||
<Card
|
||||
$margin="tiny"
|
||||
@@ -44,55 +71,73 @@ export const DocVisibility = ({ doc }: DocVisibilityProps) => {
|
||||
$align="center"
|
||||
$justify="space-between"
|
||||
$gap="1rem"
|
||||
$wrap="wrap"
|
||||
>
|
||||
<IconBG iconName="public" $margin="none" />
|
||||
<IconBG iconName="public" />
|
||||
<Box
|
||||
$width="100%"
|
||||
$wrap="wrap"
|
||||
$gap="1rem"
|
||||
$justify="space-between"
|
||||
$direction="row"
|
||||
$align="center"
|
||||
$flex="1"
|
||||
$css={`
|
||||
& .c__field__footer .c__field__text {
|
||||
${!doc.abilities.link_configuration && `color: ${colorsTokens()['greyscale-400']};`};
|
||||
}
|
||||
`}
|
||||
>
|
||||
<Box $direction="row" $gap="1rem" $align="center">
|
||||
<Switch
|
||||
label={t(docPublic ? 'Doc public' : 'Doc private')}
|
||||
defaultChecked={docPublic}
|
||||
onChange={() => {
|
||||
<Box $shrink="0" $flex="auto" $maxWidth="20rem">
|
||||
<Select
|
||||
label={t('Visibility')}
|
||||
options={Object.values(LinkReach).map((linkReach) => ({
|
||||
label: transLinkReach[linkReach].label,
|
||||
value: linkReach,
|
||||
}))}
|
||||
onChange={(evt) =>
|
||||
api.mutate({
|
||||
link_reach: evt.target.value as LinkReach,
|
||||
id: doc.id,
|
||||
link_reach: docPublic ? LinkReach.RESTRICTED : LinkReach.PUBLIC,
|
||||
link_role: 'reader',
|
||||
});
|
||||
setDocPublic(!docPublic);
|
||||
}}
|
||||
disabled={!doc.abilities.link_configuration}
|
||||
text={
|
||||
docPublic
|
||||
? t('Anyone on the internet with the link can view')
|
||||
: t('Only for people with access')
|
||||
})
|
||||
}
|
||||
value={doc.link_reach}
|
||||
clearable={false}
|
||||
text={transLinkReach[doc.link_reach].description}
|
||||
disabled={!doc.abilities.link_configuration}
|
||||
/>
|
||||
</Box>
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigator.clipboard
|
||||
.writeText(window.location.href)
|
||||
.then(() => {
|
||||
toast(t('Link Copied !'), VariantType.SUCCESS, {
|
||||
duration: 3000,
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
toast(t('Failed to copy link'), VariantType.ERROR, {
|
||||
duration: 3000,
|
||||
});
|
||||
});
|
||||
}}
|
||||
color="primary"
|
||||
icon={<span className="material-icons">copy</span>}
|
||||
>
|
||||
{t('Copy link')}
|
||||
</Button>
|
||||
{showLinkRoleOptions && (
|
||||
<Box
|
||||
$css={`
|
||||
& .c__checkbox{
|
||||
padding: 0.15rem 0.25rem;
|
||||
}
|
||||
`}
|
||||
>
|
||||
<RadioGroup
|
||||
compact
|
||||
style={{
|
||||
display: 'flex',
|
||||
}}
|
||||
text={t('How people can interact with the document')}
|
||||
>
|
||||
{linkRoleList.map((radio) => (
|
||||
<Radio
|
||||
key={radio.value}
|
||||
label={radio.label}
|
||||
value={radio.value}
|
||||
onChange={() =>
|
||||
api.mutate({
|
||||
link_role: radio.value,
|
||||
id: doc.id,
|
||||
})
|
||||
}
|
||||
checked={doc.link_role === radio.value}
|
||||
disabled={!doc.abilities.link_configuration}
|
||||
/>
|
||||
))}
|
||||
</RadioGroup>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Card>
|
||||
);
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
import {
|
||||
Button,
|
||||
VariantType,
|
||||
useToastProvider,
|
||||
} from '@openfun/cunningham-react';
|
||||
import { t } from 'i18next';
|
||||
import { createGlobalStyle } from 'styled-components';
|
||||
|
||||
@@ -41,6 +46,7 @@ interface ModalShareProps {
|
||||
export const ModalShare = ({ onClose, doc }: ModalShareProps) => {
|
||||
const { isMobile, isSmallMobile } = useResponsiveStore();
|
||||
const width = isSmallMobile ? '100vw' : isMobile ? '90vw' : '70vw';
|
||||
const { toast } = useToastProvider();
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -68,13 +74,44 @@ export const ModalShare = ({ onClose, doc }: ModalShareProps) => {
|
||||
iconName="share"
|
||||
$margin="none"
|
||||
/>
|
||||
<Box $align="flex-start">
|
||||
<Text as="h3" $size="26px" $margin="none">
|
||||
{t('Share')}
|
||||
</Text>
|
||||
<Text $size="small" $weight="normal" $textAlign="left">
|
||||
{doc.title}
|
||||
</Text>
|
||||
<Box
|
||||
$justify="space-between"
|
||||
$direction="row"
|
||||
$align="center"
|
||||
$width="100%"
|
||||
$gap="1rem"
|
||||
$wrap="wrap"
|
||||
>
|
||||
<Box $align="flex-start">
|
||||
<Text as="h3" $size="26px" $margin="none">
|
||||
{t('Share')}
|
||||
</Text>
|
||||
<Text $size="small" $weight="normal" $textAlign="left">
|
||||
{doc.title}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box $margin={{ right: '1.5rem' }} $shrink="0">
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigator.clipboard
|
||||
.writeText(window.location.href)
|
||||
.then(() => {
|
||||
toast(t('Link Copied !'), VariantType.SUCCESS, {
|
||||
duration: 3000,
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
toast(t('Failed to copy link'), VariantType.ERROR, {
|
||||
duration: 3000,
|
||||
});
|
||||
});
|
||||
}}
|
||||
color="primary"
|
||||
icon={<span className="material-icons">copy</span>}
|
||||
>
|
||||
{t('Copy link')}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Card>
|
||||
<DocVisibility doc={doc} />
|
||||
|
||||
@@ -27,6 +27,11 @@ export enum LinkReach {
|
||||
AUTHENTICATED = 'authenticated',
|
||||
}
|
||||
|
||||
export enum LinkRole {
|
||||
READER = 'reader',
|
||||
EDITOR = 'editor',
|
||||
}
|
||||
|
||||
export type Base64 = string;
|
||||
|
||||
export interface Doc {
|
||||
@@ -34,7 +39,7 @@ export interface Doc {
|
||||
title: string;
|
||||
content: Base64;
|
||||
link_reach: LinkReach;
|
||||
link_role: 'reader' | 'editor';
|
||||
link_role: LinkRole;
|
||||
accesses: Access[];
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
|
||||
@@ -84,9 +84,10 @@ export const MemberItem = ({
|
||||
$css={`flex: ${isSmallMobile ? '100%' : '70%'};`}
|
||||
>
|
||||
<IconBG iconName="account_circle" $size="2rem" />
|
||||
<Text $justify="center" $css="flex:1;">
|
||||
{access.user.email}
|
||||
</Text>
|
||||
<Box $justify="center" $css="flex:1;">
|
||||
{access.user.full_name && <Text>{access.user.full_name}</Text>}
|
||||
<Text>{access.user.email}</Text>
|
||||
</Box>
|
||||
<Box
|
||||
$direction="row"
|
||||
$gap="1rem"
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { WorkboxPlugin } from 'workbox-core';
|
||||
|
||||
import { Doc, DocsResponse } from '@/features/docs/doc-management';
|
||||
import { LinkReach, Role } from '@/features/docs/doc-management/types';
|
||||
import {
|
||||
LinkReach,
|
||||
LinkRole,
|
||||
Role,
|
||||
} from '@/features/docs/doc-management/types';
|
||||
|
||||
import { DBRequest, DocsDB } from './DocsDB';
|
||||
import { RequestSerializer } from './RequestSerializer';
|
||||
@@ -209,6 +213,8 @@ export class ApiPlugin implements WorkboxPlugin {
|
||||
user: {
|
||||
id: 'dummy-id',
|
||||
email: 'dummy-email',
|
||||
full_name: 'dummy-full-name',
|
||||
short_name: 'dummy-short-name',
|
||||
},
|
||||
abilities: {
|
||||
destroy: false,
|
||||
@@ -220,7 +226,7 @@ export class ApiPlugin implements WorkboxPlugin {
|
||||
},
|
||||
],
|
||||
link_reach: LinkReach.RESTRICTED,
|
||||
link_role: 'reader',
|
||||
link_role: LinkRole.READER,
|
||||
};
|
||||
|
||||
await DocsDB.cacheResponse(
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
import { LANGUAGE_LOCAL_STORAGE } from '../conf';
|
||||
import { getLanguage, splitLocaleCode } from '../utils';
|
||||
|
||||
describe('i18n utils', () => {
|
||||
afterEach(() => {
|
||||
localStorage.removeItem(LANGUAGE_LOCAL_STORAGE);
|
||||
});
|
||||
|
||||
it('checks language code is correctly splitted', () => {
|
||||
expect(splitLocaleCode('fr_FR')).toEqual({ language: 'fr', region: 'FR' });
|
||||
expect(splitLocaleCode('en_US')).toEqual({ language: 'en', region: 'US' });
|
||||
expect(splitLocaleCode('en')).toEqual({
|
||||
language: 'en',
|
||||
region: undefined,
|
||||
});
|
||||
expect(splitLocaleCode('fr-FR')).toEqual({ language: 'fr', region: 'FR' });
|
||||
expect(splitLocaleCode('en-US')).toEqual({ language: 'en', region: 'US' });
|
||||
});
|
||||
|
||||
it('checks that we get expected language from local storage', () => {
|
||||
localStorage.setItem(LANGUAGE_LOCAL_STORAGE, 'fr_FR');
|
||||
expect(getLanguage()).toEqual('fr');
|
||||
localStorage.removeItem(LANGUAGE_LOCAL_STORAGE);
|
||||
|
||||
localStorage.setItem(LANGUAGE_LOCAL_STORAGE, 'en_FR');
|
||||
expect(getLanguage()).toEqual('en');
|
||||
|
||||
localStorage.setItem(LANGUAGE_LOCAL_STORAGE, 'xx_XX');
|
||||
expect(getLanguage()).toEqual('fr');
|
||||
});
|
||||
|
||||
it('checks that we get expected language from browser', () => {
|
||||
Object.defineProperty(navigator, 'language', {
|
||||
value: 'fr',
|
||||
writable: false,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
expect(getLanguage()).toEqual('fr');
|
||||
|
||||
Object.defineProperty(navigator, 'language', {
|
||||
value: 'en',
|
||||
writable: false,
|
||||
configurable: true,
|
||||
});
|
||||
expect(getLanguage()).toEqual('en');
|
||||
|
||||
Object.defineProperty(navigator, 'language', {
|
||||
value: 'xx',
|
||||
writable: false,
|
||||
configurable: true,
|
||||
});
|
||||
expect(getLanguage()).toEqual('fr');
|
||||
});
|
||||
});
|
||||
@@ -2,5 +2,5 @@ export const LANGUAGES_ALLOWED: { [key: string]: string } = {
|
||||
en: 'English',
|
||||
fr: 'Français',
|
||||
};
|
||||
export const LANGUAGE_LOCAL_STORAGE = 'impress-language';
|
||||
export const BASE_LANGUAGE = 'fr';
|
||||
export const LANGUAGE_COOKIE_NAME = 'docs_language';
|
||||
export const BASE_LANGUAGE = 'en';
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
import i18n from 'i18next';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
import { LANGUAGES_ALLOWED, LANGUAGE_LOCAL_STORAGE } from './conf';
|
||||
import { BASE_LANGUAGE, LANGUAGES_ALLOWED, LANGUAGE_COOKIE_NAME } from './conf';
|
||||
import resources from './translations.json';
|
||||
import { getLanguage } from './utils';
|
||||
|
||||
i18n
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
resources,
|
||||
lng: getLanguage(),
|
||||
fallbackLng: BASE_LANGUAGE,
|
||||
supportedLngs: Object.keys(LANGUAGES_ALLOWED),
|
||||
detection: {
|
||||
order: ['cookie', 'navigator'], // detection order
|
||||
caches: ['cookie'], // Use cookies to store the language preference
|
||||
lookupCookie: LANGUAGE_COOKIE_NAME,
|
||||
cookieMinutes: 525600, // Expires after one year
|
||||
},
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
},
|
||||
preload: Object.keys(LANGUAGES_ALLOWED),
|
||||
nsSeparator: '||',
|
||||
nsSeparator: false,
|
||||
keySeparator: false,
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error('i18n initialization failed');
|
||||
});
|
||||
|
||||
// Save language in local storage
|
||||
i18n.on('languageChanged', (lng) => {
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem(LANGUAGE_LOCAL_STORAGE, lng);
|
||||
}
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
|
||||
@@ -12,8 +12,10 @@
|
||||
"Administrator": "Administrateur",
|
||||
"Anyone on the internet with the link can view": "Les personnes disposant du lien peuvent y accéder",
|
||||
"Are you sure you want to delete the document \"{{title}}\"?": "Êtes-vous sûr de vouloir supprimer le document \"{{title}}\" ?",
|
||||
"Authenticated": "Authentifié",
|
||||
"Back to home page": "Retour à l'accueil",
|
||||
"Back to top": "Retour en haut",
|
||||
"Can read and edit": "Peut lire et éditer",
|
||||
"Can't load this page, please check your internet connection.": "Impossible de charger cette page, veuillez vérifier votre connexion Internet.",
|
||||
"Cancel": "Annuler",
|
||||
"Choose a role": "Choisissez un rôle",
|
||||
@@ -23,6 +25,7 @@
|
||||
"Confirm deletion": "Confirmer la suppression",
|
||||
"Content modal to delete document": "Contenu modal pour supprimer le document",
|
||||
"Content modal to export the document": "Contenu modal pour exporter le document",
|
||||
"Convert Markdown": "Convertir le Markdown",
|
||||
"Cookies placed": "Cookies déposés",
|
||||
"Copied to clipboard": "Copié dans le presse-papier",
|
||||
"Copy as {{format}}": "Copier en {{format}}",
|
||||
@@ -61,6 +64,7 @@
|
||||
"Find a member to add to the document": "Trouver un membre à ajouter au document",
|
||||
"French Interministerial Directorate for Digital Affairs (DINUM), 20 avenue de Ségur 75007 Paris.": "Direction interministérielle des affaires numériques (DINUM), 20 avenue de Segur 75007 Paris.",
|
||||
"Go to bottom": "Aller en bas",
|
||||
"How people can interact with the document": "Comment les gens peuvent interagir avec le document",
|
||||
"If a member is editing, his works can be lost.": "Si un membre est en train d'éditer, ses travaux peuvent être perdus.",
|
||||
"If you are unable to access a content or a service, you can contact the person responsible for https://lasuite.numerique.gouv.fr to be directed to an accessible alternative or to obtain the content in another form.": "Si vous ne pouvez pas accéder à un contenu ou à un service, vous pouvez contacter la personne responsable de https://lasuite. umerique.gouv.fr pour être dirigé vers une alternative accessible ou pour obtenir le contenu sous une autre forme.",
|
||||
"Illustration:": "Illustration :",
|
||||
@@ -85,6 +89,7 @@
|
||||
"No editor found": "Pas d'éditeur trouvé",
|
||||
"Nothing exceptional, no special privileges related to a .gouv.fr.": "Rien d'exceptionnel, pas de privilèges spéciaux liés à un .gouv.fr.",
|
||||
"Offline ?!": "Hors-ligne ?!",
|
||||
"Only for authenticated users": "Uniquement pour les utilisateurs authentifiés",
|
||||
"Only for people with access": "Seulement pour les personnes avec accès",
|
||||
"Open the document options": "Ouvrir les options du document",
|
||||
"Open the header menu": "Ouvrir le menu d'en-tête",
|
||||
@@ -98,6 +103,7 @@
|
||||
"Public": "Public",
|
||||
"Publication Director": "Directeur de la publication",
|
||||
"Publisher": "Éditeur",
|
||||
"Read only": "Lecture seule",
|
||||
"Read only, you cannot edit document versions.": "En lecture seule, vous ne pouvez pas éditer les versions du document.",
|
||||
"Read only, you cannot edit this document.": "En lecture seule, vous ne pouvez pas éditer ce document.",
|
||||
"Reader": "Lecteur",
|
||||
@@ -108,6 +114,7 @@
|
||||
"Restore the version": "Restaurer la version",
|
||||
"Restore this version": "Restaurer cette version",
|
||||
"Restore this version?": "Restaurer cette version?",
|
||||
"Restricted": "Restreint",
|
||||
"Role": "Rôle",
|
||||
"Search by email": "Recherche par email",
|
||||
"Send a letter by post (free of charge, no stamp needed):": "Envoyer un courrier par la poste (gratuit, ne pas mettre de timbre):",
|
||||
@@ -120,7 +127,7 @@
|
||||
"Table of contents": "Table des matières",
|
||||
"Template": "Template",
|
||||
"The document has been deleted.": "Le document a bien été supprimé.",
|
||||
"The document visiblitity has been updated.": "La visibilité du document a été mise à jour.",
|
||||
"The document visibility has been updated.": "La visibilité du document a été mise à jour.",
|
||||
"The invitation has been removed.": "L'invitation a été supprimée.",
|
||||
"The member has been removed from the document": "Le membre a été retiré du document",
|
||||
"The role has been updated": "Le rôle a été mis à jour",
|
||||
@@ -142,6 +149,7 @@
|
||||
"Version history": "Historique des versions",
|
||||
"Version restored successfully": "Version restaurée avec succès",
|
||||
"Versions": "Versions",
|
||||
"Visibility": "Visibilité",
|
||||
"We didn't find a mail matching, try to be more accurate": "Nous n'avons pas trouvé de correspondance par mail, essayez d'être plus précis",
|
||||
"We simply comply with the law, which states that certain audience measurement tools, properly configured to respect privacy, are exempt from prior authorization.": "Nous nous conformons simplement à la loi, qui stipule que certains outils de mesure d’audience, correctement configurés pour respecter la vie privée, sont exemptés de toute autorisation préalable.",
|
||||
"We try to respond within 2 working days.": "Nous essayons de répondre dans les 2 jours ouvrables.",
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import {
|
||||
BASE_LANGUAGE,
|
||||
LANGUAGES_ALLOWED,
|
||||
LANGUAGE_LOCAL_STORAGE,
|
||||
} from './conf';
|
||||
|
||||
export const splitLocaleCode = (language: string) => {
|
||||
const locale = language.split(/[-_]/);
|
||||
return {
|
||||
language: locale[0],
|
||||
region: locale.length === 2 ? locale[1] : undefined,
|
||||
};
|
||||
};
|
||||
|
||||
export const getLanguage = () => {
|
||||
if (typeof window === 'undefined') {
|
||||
return BASE_LANGUAGE;
|
||||
}
|
||||
|
||||
const languageStore =
|
||||
localStorage.getItem(LANGUAGE_LOCAL_STORAGE) || navigator?.language;
|
||||
|
||||
const language = splitLocaleCode(languageStore).language;
|
||||
|
||||
return Object.keys(LANGUAGES_ALLOWED).includes(language)
|
||||
? language
|
||||
: BASE_LANGUAGE;
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Loader } from '@openfun/cunningham-react';
|
||||
import Head from 'next/head';
|
||||
import { useRouter as useNavigate } from 'next/navigation';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useState } from 'react';
|
||||
@@ -21,9 +22,14 @@ export function DocLayout() {
|
||||
}
|
||||
|
||||
return (
|
||||
<MainLayout withoutFooter>
|
||||
<DocPage id={id} />
|
||||
</MainLayout>
|
||||
<>
|
||||
<Head>
|
||||
<meta name="robots" content="noindex" />
|
||||
</Head>
|
||||
<MainLayout withoutFooter>
|
||||
<DocPage id={id} />
|
||||
</MainLayout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "impress",
|
||||
"version": "1.6.0",
|
||||
"version": "1.7.0",
|
||||
"private": true,
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
@@ -25,13 +25,13 @@
|
||||
"i18n:test": "yarn I18N run test"
|
||||
},
|
||||
"resolutions": {
|
||||
"@blocknote/core": "0.17.0",
|
||||
"@blocknote/mantine": "0.17.0",
|
||||
"@blocknote/react": "0.17.0",
|
||||
"@types/node": "20.16.12",
|
||||
"@blocknote/core": "0.17.1",
|
||||
"@blocknote/mantine": "0.17.1",
|
||||
"@blocknote/react": "0.17.1",
|
||||
"@types/node": "20.16.13",
|
||||
"@types/react-dom": "18.3.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.9.0",
|
||||
"@typescript-eslint/parser": "8.9.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.10.0",
|
||||
"@typescript-eslint/parser": "8.10.0",
|
||||
"cross-env": "7.0.3",
|
||||
"eslint": "8.57.0",
|
||||
"react": "18.3.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eslint-config-impress",
|
||||
"version": "1.6.0",
|
||||
"version": "1.7.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"lint": "eslint --ext .js ."
|
||||
@@ -15,11 +15,11 @@
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"eslint-plugin-import": "2.31.0",
|
||||
"eslint-plugin-jest": "28.8.3",
|
||||
"eslint-plugin-jsx-a11y": "6.10.0",
|
||||
"eslint-plugin-playwright": "1.7.0",
|
||||
"eslint-plugin-jsx-a11y": "6.10.1",
|
||||
"eslint-plugin-playwright": "1.8.0",
|
||||
"eslint-plugin-prettier": "5.2.1",
|
||||
"eslint-plugin-react": "7.37.1",
|
||||
"eslint-plugin-testing-library": "6.3.0",
|
||||
"eslint-plugin-testing-library": "6.4.0",
|
||||
"prettier": "3.3.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "packages-i18n",
|
||||
"version": "1.6.0",
|
||||
"version": "1.7.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"extract-translation": "yarn extract-translation:impress",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "server-y-provider",
|
||||
"version": "1.6.0",
|
||||
"version": "1.7.0",
|
||||
"description": "Y.js provider for docs",
|
||||
"repository": "https://github.com/numerique-gouv/impress",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1007,10 +1007,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@blocknote/core@*", "@blocknote/core@0.17.0", "@blocknote/core@^0.17.0":
|
||||
version "0.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@blocknote/core/-/core-0.17.0.tgz#c87e84ee8bd5b5d4c41e646002732d414d9f67f7"
|
||||
integrity sha512-hvqOTgmYJejWczNb9wLCBEjE0lgrkmEJgqi+wka8Z2CRkLaMV4wB1XEoncjpjtoKJeJjvhmmGuCBrfoEoYgTWw==
|
||||
"@blocknote/core@*", "@blocknote/core@0.17.1", "@blocknote/core@^0.17.1":
|
||||
version "0.17.1"
|
||||
resolved "https://registry.yarnpkg.com/@blocknote/core/-/core-0.17.1.tgz#78ba9f31648f32a293e6605cea6c3569cbb28551"
|
||||
integrity sha512-wNfdmzCBjghVZMT3Wm7IbAXPm0u2YuPkYxz8YdW8qyvk+6U+Hp60WVcBv/phGiomFfhJ4R+u0tEwD6mXDCyLrg==
|
||||
dependencies:
|
||||
"@emoji-mart/data" "^1.2.1"
|
||||
"@tiptap/core" "^2.7.1"
|
||||
@@ -1054,13 +1054,13 @@
|
||||
y-protocols "^1.0.6"
|
||||
yjs "^13.6.15"
|
||||
|
||||
"@blocknote/mantine@*", "@blocknote/mantine@0.17.0":
|
||||
version "0.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@blocknote/mantine/-/mantine-0.17.0.tgz#a7fd1c89a7dd2a28b8e7e547a8dbcde96d358f79"
|
||||
integrity sha512-GPS7QH5UI543tQQMkyUd69Tf3nZ/r2VFbAJmllcgBni3bVgaIM3Cj7LJXbo4tOz60thUdzYt6qso5nmjhdn4aw==
|
||||
"@blocknote/mantine@*", "@blocknote/mantine@0.17.1":
|
||||
version "0.17.1"
|
||||
resolved "https://registry.yarnpkg.com/@blocknote/mantine/-/mantine-0.17.1.tgz#f701d4efdba81ab7c1f8cf89d0df013448130c06"
|
||||
integrity sha512-K3Y+6uyhO70rBCAZDrW1/D+ZQm2/g6+QeN15XRq2d210IXsSVM051xgNyDEk2vpMYVNf+WJyRXHR3FoN2vc77A==
|
||||
dependencies:
|
||||
"@blocknote/core" "^0.17.0"
|
||||
"@blocknote/react" "^0.17.0"
|
||||
"@blocknote/core" "^0.17.1"
|
||||
"@blocknote/react" "^0.17.1"
|
||||
"@mantine/core" "^7.10.1"
|
||||
"@mantine/hooks" "^7.10.1"
|
||||
"@mantine/utils" "^6.0.21"
|
||||
@@ -1068,12 +1068,12 @@
|
||||
react-dom "^18"
|
||||
react-icons "^5.2.1"
|
||||
|
||||
"@blocknote/react@*", "@blocknote/react@0.17.0", "@blocknote/react@^0.17.0":
|
||||
version "0.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@blocknote/react/-/react-0.17.0.tgz#fe1ce962b2fe402798b4c6e764f06ea6a97a058c"
|
||||
integrity sha512-a/ViJKyuC029nrGgVPey/+nIkspWkceW/WwhSWUymem8GfZAI02PJoUWq2riwhgaDsEDJyw7ufiVg6ZA8FvdPw==
|
||||
"@blocknote/react@*", "@blocknote/react@0.17.1", "@blocknote/react@^0.17.1":
|
||||
version "0.17.1"
|
||||
resolved "https://registry.yarnpkg.com/@blocknote/react/-/react-0.17.1.tgz#2e10b3e6f610274995efd8ee6faa779b9bf0b178"
|
||||
integrity sha512-9irtckfgxGcTmf+8JZF61l3slu6ET4famWUtPCOXcI7a1M8uSS86bagq19qYmPVutTnUXP6K8T6svOfUn14W7Q==
|
||||
dependencies:
|
||||
"@blocknote/core" "^0.17.0"
|
||||
"@blocknote/core" "^0.17.1"
|
||||
"@floating-ui/react" "^0.26.4"
|
||||
"@tiptap/core" "^2.7.1"
|
||||
"@tiptap/react" "^2.7.1"
|
||||
@@ -3583,10 +3583,10 @@
|
||||
lz-string "^1.5.0"
|
||||
pretty-format "^27.0.2"
|
||||
|
||||
"@testing-library/jest-dom@6.6.1":
|
||||
version "6.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.6.1.tgz#835612c9d8c529c835b15bbc1d1a924310c6c73c"
|
||||
integrity sha512-mNYIiAuP4yJwV2zBRQCV7PHoQwbb6/8TfMpPcwSUzcSVDJHWOXt6hjNtIN1v5knDmimYnjJxKhsoVd4LVGIO+w==
|
||||
"@testing-library/jest-dom@6.6.2":
|
||||
version "6.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.6.2.tgz#8186aa9a07263adef9cc5a59a4772db8c31f4a5b"
|
||||
integrity sha512-P6GJD4yqc9jZLbe98j/EkyQDTPgqftohZF5FBkHY5BUERZmcf4HeO2k0XaefEg329ux2p21i1A1DmyQ1kKw2Jw==
|
||||
dependencies:
|
||||
"@adobe/css-tools" "^4.4.0"
|
||||
aria-query "^5.0.0"
|
||||
@@ -3916,10 +3916,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-5.0.0.tgz#21413001973106cda1c3a9b91eedd4ccd5469d76"
|
||||
integrity sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==
|
||||
|
||||
"@types/lodash@4.17.10":
|
||||
version "4.17.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.10.tgz#64f3edf656af2fe59e7278b73d3e62404144a6e6"
|
||||
integrity sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==
|
||||
"@types/lodash@4.17.12":
|
||||
version "4.17.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.12.tgz#25d71312bf66512105d71e55d42e22c36bcfc689"
|
||||
integrity sha512-sviUmCE8AYdaF/KIHLDJBQgeYzPBI0vf/17NaYehBJfYD1j6/L95Slh07NlyK2iNyBNaEkb3En2jRt+a8y3xZQ==
|
||||
|
||||
"@types/luxon@3.4.2":
|
||||
version "3.4.2"
|
||||
@@ -3956,10 +3956,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433"
|
||||
integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==
|
||||
|
||||
"@types/node@*", "@types/node@20.16.12":
|
||||
version "20.16.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.16.12.tgz#61cc9be049584b472fa31e465aa0ab3c090dac56"
|
||||
integrity sha512-LfPFB0zOeCeCNQV3i+67rcoVvoN5n0NVuR2vLG0O5ySQMgchuZlC4lgz546ZOJyDtj5KIgOxy+lacOimfqZAIA==
|
||||
"@types/node@*", "@types/node@20.16.13":
|
||||
version "20.16.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.16.13.tgz#148c152d757dc73f8d65f0f6f078f39050b85b0c"
|
||||
integrity sha512-GjQ7im10B0labo8ZGXDGROUl9k0BNyDgzfGpb4g/cl+4yYDWVKcozANF4FGr4/p0O/rAkQClM6Wiwkije++1Tg==
|
||||
dependencies:
|
||||
undici-types "~6.19.2"
|
||||
|
||||
@@ -4074,30 +4074,30 @@
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@*", "@typescript-eslint/eslint-plugin@8.9.0", "@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0":
|
||||
version "8.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.9.0.tgz#bf0b25305b0bf014b4b194a6919103d7ac2a7907"
|
||||
integrity sha512-Y1n621OCy4m7/vTXNlCbMVp87zSd7NH0L9cXD8aIpOaNlzeWxIK4+Q19A68gSmTNRZn92UjocVUWDthGxtqHFg==
|
||||
"@typescript-eslint/eslint-plugin@*", "@typescript-eslint/eslint-plugin@8.10.0", "@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0":
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.10.0.tgz#9c8218ed62f9a322df10ded7c34990f014df44f2"
|
||||
integrity sha512-phuB3hoP7FFKbRXxjl+DRlQDuJqhpOnm5MmtROXyWi3uS/Xg2ZXqiQfcG2BJHiN4QKyzdOJi3NEn/qTnjUlkmQ==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.10.0"
|
||||
"@typescript-eslint/scope-manager" "8.9.0"
|
||||
"@typescript-eslint/type-utils" "8.9.0"
|
||||
"@typescript-eslint/utils" "8.9.0"
|
||||
"@typescript-eslint/visitor-keys" "8.9.0"
|
||||
"@typescript-eslint/scope-manager" "8.10.0"
|
||||
"@typescript-eslint/type-utils" "8.10.0"
|
||||
"@typescript-eslint/utils" "8.10.0"
|
||||
"@typescript-eslint/visitor-keys" "8.10.0"
|
||||
graphemer "^1.4.0"
|
||||
ignore "^5.3.1"
|
||||
natural-compare "^1.4.0"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
"@typescript-eslint/parser@*", "@typescript-eslint/parser@8.9.0", "@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0":
|
||||
version "8.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.9.0.tgz#0cecda6def8aef95d7c7098359c0fda5a362d6ad"
|
||||
integrity sha512-U+BLn2rqTTHnc4FL3FJjxaXptTxmf9sNftJK62XLz4+GxG3hLHm/SUNaaXP5Y4uTiuYoL5YLy4JBCJe3+t8awQ==
|
||||
"@typescript-eslint/parser@*", "@typescript-eslint/parser@8.10.0", "@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0":
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.10.0.tgz#3cbe7206f5e42835878a74a76da533549f977662"
|
||||
integrity sha512-E24l90SxuJhytWJ0pTQydFT46Nk0Z+bsLKo/L8rtQSL93rQ6byd1V/QbDpHUTdLPOMsBCcYXZweADNCfOCmOAg==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "8.9.0"
|
||||
"@typescript-eslint/types" "8.9.0"
|
||||
"@typescript-eslint/typescript-estree" "8.9.0"
|
||||
"@typescript-eslint/visitor-keys" "8.9.0"
|
||||
"@typescript-eslint/scope-manager" "8.10.0"
|
||||
"@typescript-eslint/types" "8.10.0"
|
||||
"@typescript-eslint/typescript-estree" "8.10.0"
|
||||
"@typescript-eslint/visitor-keys" "8.10.0"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.62.0":
|
||||
@@ -4108,6 +4108,14 @@
|
||||
"@typescript-eslint/types" "5.62.0"
|
||||
"@typescript-eslint/visitor-keys" "5.62.0"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.10.0":
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.10.0.tgz#606ffe18314d7b5c2f118f2f02aaa2958107a19c"
|
||||
integrity sha512-AgCaEjhfql9MDKjMUxWvH7HjLeBqMCBfIaBbzzIcBbQPZE7CPh1m6FF+L75NUMJFMLYhCywJXIDEMa3//1A0dw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.10.0"
|
||||
"@typescript-eslint/visitor-keys" "8.10.0"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.9.0":
|
||||
version "8.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.9.0.tgz#c98fef0c4a82a484e6a1eb610a55b154d14d46f3"
|
||||
@@ -4116,13 +4124,13 @@
|
||||
"@typescript-eslint/types" "8.9.0"
|
||||
"@typescript-eslint/visitor-keys" "8.9.0"
|
||||
|
||||
"@typescript-eslint/type-utils@8.9.0":
|
||||
version "8.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.9.0.tgz#aa86da3e4555fe7c8b42ab75e13561c4b5a8dfeb"
|
||||
integrity sha512-JD+/pCqlKqAk5961vxCluK+clkppHY07IbV3vett97KOV+8C6l+CPEPwpUuiMwgbOz/qrN3Ke4zzjqbT+ls+1Q==
|
||||
"@typescript-eslint/type-utils@8.10.0":
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.10.0.tgz#99f1d2e21f8c74703e7d9c4a67a87271eaf57597"
|
||||
integrity sha512-PCpUOpyQSpxBn230yIcK+LeCQaXuxrgCm2Zk1S+PTIRJsEfU6nJ0TtwyH8pIwPK/vJoA+7TZtzyAJSGBz+s/dg==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "8.9.0"
|
||||
"@typescript-eslint/utils" "8.9.0"
|
||||
"@typescript-eslint/typescript-estree" "8.10.0"
|
||||
"@typescript-eslint/utils" "8.10.0"
|
||||
debug "^4.3.4"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
@@ -4131,6 +4139,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f"
|
||||
integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==
|
||||
|
||||
"@typescript-eslint/types@8.10.0":
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.10.0.tgz#eb29c4bc2ed23489348c297469c76d28c38fb618"
|
||||
integrity sha512-k/E48uzsfJCRRbGLapdZgrX52csmWJ2rcowwPvOZ8lwPUv3xW6CcFeJAXgx4uJm+Ge4+a4tFOkdYvSpxhRhg1w==
|
||||
|
||||
"@typescript-eslint/types@8.9.0":
|
||||
version "8.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.9.0.tgz#b733af07fb340b32e962c6c63b1062aec2dc0fe6"
|
||||
@@ -4149,6 +4162,20 @@
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.10.0":
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.10.0.tgz#36cc66e06c5f44d6781f95cb03b132e985273a33"
|
||||
integrity sha512-3OE0nlcOHaMvQ8Xu5gAfME3/tWVDpb/HxtpUZ1WeOAksZ/h/gwrBzCklaGzwZT97/lBbbxJ16dMA98JMEngW4w==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.10.0"
|
||||
"@typescript-eslint/visitor-keys" "8.10.0"
|
||||
debug "^4.3.4"
|
||||
fast-glob "^3.3.2"
|
||||
is-glob "^4.0.3"
|
||||
minimatch "^9.0.4"
|
||||
semver "^7.6.0"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.9.0":
|
||||
version "8.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.9.0.tgz#1714f167e9063062dc0df49c1d25afcbc7a96199"
|
||||
@@ -4163,17 +4190,17 @@
|
||||
semver "^7.6.0"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
"@typescript-eslint/utils@8.9.0", "@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/utils@^8.3.0":
|
||||
version "8.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.9.0.tgz#748bbe3ea5bee526d9786d9405cf1b0df081c299"
|
||||
integrity sha512-PKgMmaSo/Yg/F7kIZvrgrWa1+Vwn036CdNUvYFEkYbPwOH4i8xvkaRlu148W3vtheWK9ckKRIz7PBP5oUlkrvQ==
|
||||
"@typescript-eslint/utils@8.10.0":
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.10.0.tgz#d78d1ce3ea3d2a88a2593ebfb1c98490131d00bf"
|
||||
integrity sha512-Oq4uZ7JFr9d1ZunE/QKy5egcDRXT/FrS2z/nlxzPua2VHFtmMvFNDvpq1m/hq0ra+T52aUezfcjGRIB7vNJF9w==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.4.0"
|
||||
"@typescript-eslint/scope-manager" "8.9.0"
|
||||
"@typescript-eslint/types" "8.9.0"
|
||||
"@typescript-eslint/typescript-estree" "8.9.0"
|
||||
"@typescript-eslint/scope-manager" "8.10.0"
|
||||
"@typescript-eslint/types" "8.10.0"
|
||||
"@typescript-eslint/typescript-estree" "8.10.0"
|
||||
|
||||
"@typescript-eslint/utils@^5.58.0":
|
||||
"@typescript-eslint/utils@^5.62.0":
|
||||
version "5.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86"
|
||||
integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==
|
||||
@@ -4187,6 +4214,16 @@
|
||||
eslint-scope "^5.1.1"
|
||||
semver "^7.3.7"
|
||||
|
||||
"@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/utils@^8.3.0":
|
||||
version "8.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.9.0.tgz#748bbe3ea5bee526d9786d9405cf1b0df081c299"
|
||||
integrity sha512-PKgMmaSo/Yg/F7kIZvrgrWa1+Vwn036CdNUvYFEkYbPwOH4i8xvkaRlu148W3vtheWK9ckKRIz7PBP5oUlkrvQ==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.4.0"
|
||||
"@typescript-eslint/scope-manager" "8.9.0"
|
||||
"@typescript-eslint/types" "8.9.0"
|
||||
"@typescript-eslint/typescript-estree" "8.9.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.62.0":
|
||||
version "5.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e"
|
||||
@@ -4195,6 +4232,14 @@
|
||||
"@typescript-eslint/types" "5.62.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.10.0":
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.10.0.tgz#7ce4c0c3b82140415c9cd9babe09e0000b4e9979"
|
||||
integrity sha512-k8nekgqwr7FadWk548Lfph6V3r9OVqjzAIVskE7orMZR23cGJjAOVazsZSJW+ElyjfTM4wx/1g88Mi70DDtG9A==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.10.0"
|
||||
eslint-visitor-keys "^3.4.3"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.9.0":
|
||||
version "8.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.9.0.tgz#5f11f4d9db913f37da42776893ffe0dd1ae78f78"
|
||||
@@ -4486,7 +4531,7 @@ aria-query@5.3.0:
|
||||
dependencies:
|
||||
dequal "^2.0.3"
|
||||
|
||||
aria-query@^5.0.0:
|
||||
aria-query@^5.0.0, aria-query@^5.3.2:
|
||||
version "5.3.2"
|
||||
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59"
|
||||
integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==
|
||||
@@ -5809,7 +5854,7 @@ es-get-iterator@^1.1.3:
|
||||
isarray "^2.0.5"
|
||||
stop-iteration-iterator "^1.0.0"
|
||||
|
||||
es-iterator-helpers@^1.0.19:
|
||||
es-iterator-helpers@^1.0.19, es-iterator-helpers@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz#f6d745d342aea214fe09497e7152170dc333a7a6"
|
||||
integrity sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==
|
||||
@@ -6015,7 +6060,29 @@ eslint-plugin-jest@28.8.3:
|
||||
dependencies:
|
||||
"@typescript-eslint/utils" "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
|
||||
eslint-plugin-jsx-a11y@6.10.0, eslint-plugin-jsx-a11y@^6.7.1:
|
||||
eslint-plugin-jsx-a11y@6.10.1:
|
||||
version "6.10.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.1.tgz#87003835bad8875e023aa5db26f41a0c9e6a8fa9"
|
||||
integrity sha512-zHByM9WTUMnfsDTafGXRiqxp6lFtNoSOWBY6FonVRn3A+BUwN1L/tdBXT40BcBJi0cZjOGTXZ0eD/rTG9fEJ0g==
|
||||
dependencies:
|
||||
aria-query "^5.3.2"
|
||||
array-includes "^3.1.8"
|
||||
array.prototype.flatmap "^1.3.2"
|
||||
ast-types-flow "^0.0.8"
|
||||
axe-core "^4.10.0"
|
||||
axobject-query "^4.1.0"
|
||||
damerau-levenshtein "^1.0.8"
|
||||
emoji-regex "^9.2.2"
|
||||
es-iterator-helpers "^1.1.0"
|
||||
hasown "^2.0.2"
|
||||
jsx-ast-utils "^3.3.5"
|
||||
language-tags "^1.0.9"
|
||||
minimatch "^3.1.2"
|
||||
object.fromentries "^2.0.8"
|
||||
safe-regex-test "^1.0.3"
|
||||
string.prototype.includes "^2.0.1"
|
||||
|
||||
eslint-plugin-jsx-a11y@^6.7.1:
|
||||
version "6.10.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.0.tgz#36fb9dead91cafd085ddbe3829602fb10ef28339"
|
||||
integrity sha512-ySOHvXX8eSN6zz8Bywacm7CvGNhUtdjvqfQDVe6020TUK34Cywkw7m0KsCCk1Qtm9G1FayfTN1/7mMYnYO2Bhg==
|
||||
@@ -6037,10 +6104,10 @@ eslint-plugin-jsx-a11y@6.10.0, eslint-plugin-jsx-a11y@^6.7.1:
|
||||
safe-regex-test "^1.0.3"
|
||||
string.prototype.includes "^2.0.0"
|
||||
|
||||
eslint-plugin-playwright@1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-playwright/-/eslint-plugin-playwright-1.7.0.tgz#53b5d4e9338558289332cca0b33fe3e8378b7f80"
|
||||
integrity sha512-pDp2jFeWbBmlwDfZ39Ypdlz1+IafmRKvFTnnonX0TbS7hAByy4oh7Y6ioZRKvLGE+djd/e2VbqOo9sxgZSY2ow==
|
||||
eslint-plugin-playwright@1.8.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-playwright/-/eslint-plugin-playwright-1.8.0.tgz#b54359804f458964afb460cb2d689f41deb70081"
|
||||
integrity sha512-+vHG8VdtgMKwsEJrj973FqoTSn7GAtUsgudSeolLrigBPKwuXeHjcWKYPYPpMUVAISl3IMR7reQmK2v13sjaRw==
|
||||
dependencies:
|
||||
globals "^13.23.0"
|
||||
|
||||
@@ -6081,12 +6148,12 @@ eslint-plugin-react@7.37.1, eslint-plugin-react@^7.33.2:
|
||||
string.prototype.matchall "^4.0.11"
|
||||
string.prototype.repeat "^1.0.0"
|
||||
|
||||
eslint-plugin-testing-library@6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.3.0.tgz#9c31a9941a860efdff3c06180151ab9c8142f685"
|
||||
integrity sha512-GYcEErTt6EGwE0bPDY+4aehfEBpB2gDBFKohir8jlATSUvzStEyzCx8QWB/14xeKc/AwyXkzScSzMHnFojkWrA==
|
||||
eslint-plugin-testing-library@6.4.0:
|
||||
version "6.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.4.0.tgz#1ba8a7422e3e31cc315a73ff17c34908f56f9838"
|
||||
integrity sha512-yeWF+YgCgvNyPNI9UKnG0FjeE2sk93N/3lsKqcmR8dSfeXJwFT5irnWo7NjLf152HkRzfoFjh3LsBUrhvFz4eA==
|
||||
dependencies:
|
||||
"@typescript-eslint/utils" "^5.58.0"
|
||||
"@typescript-eslint/utils" "^5.62.0"
|
||||
|
||||
eslint-scope@5.1.1, eslint-scope@^5.1.1:
|
||||
version "5.1.1"
|
||||
@@ -7100,6 +7167,13 @@ human-signals@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
|
||||
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
|
||||
|
||||
i18next-browser-languagedetector@8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.0.tgz#b6fdd9b43af67c47f2c26c9ba27710a1eaf31e2f"
|
||||
integrity sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.23.2"
|
||||
|
||||
i18next-parser@9.0.2:
|
||||
version "9.0.2"
|
||||
resolved "https://registry.yarnpkg.com/i18next-parser/-/i18next-parser-9.0.2.tgz#f9d627422d33c352967556c8724975d58f1f5a95"
|
||||
@@ -7123,7 +7197,14 @@ i18next-parser@9.0.2:
|
||||
vinyl "~3.0.0"
|
||||
vinyl-fs "^4.0.0"
|
||||
|
||||
i18next@23.16.0, i18next@^23.5.1:
|
||||
i18next@23.16.2:
|
||||
version "23.16.2"
|
||||
resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.16.2.tgz#ef6868ef6ac7bcaee4f5fe35132021d44e8d1063"
|
||||
integrity sha512-dFyxwLXxEQK32f6tITBMaRht25mZPJhQ0WbC0p3bO2mWBal9lABTMqSka5k+GLSRWLzeJBKDpH7BeIA9TZI7Jg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.23.2"
|
||||
|
||||
i18next@^23.5.1:
|
||||
version "23.16.0"
|
||||
resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.16.0.tgz#6127b49a30c19ba5caf0de8aeb3e15df60f7f01e"
|
||||
integrity sha512-Ni3CG6c14teOogY19YNRl+kYaE/Rb59khy0VyHVn4uOZ97E2E/Yziyi6r3C3s9+wacjdLZiq/LLYyx+Cgd+FCw==
|
||||
@@ -10598,7 +10679,16 @@ string-length@^4.0.1:
|
||||
char-regex "^1.0.2"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
"string-width-cjs@npm:string-width@^4.2.0":
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
dependencies:
|
||||
emoji-regex "^8.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
@@ -10616,7 +10706,7 @@ string-width@^5.0.1, string-width@^5.1.2:
|
||||
emoji-regex "^9.2.2"
|
||||
strip-ansi "^7.0.1"
|
||||
|
||||
string.prototype.includes@^2.0.0:
|
||||
string.prototype.includes@^2.0.0, string.prototype.includes@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz#eceef21283640761a81dbe16d6c7171a4edf7d92"
|
||||
integrity sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==
|
||||
@@ -10710,7 +10800,14 @@ stringify-object@^3.3.0:
|
||||
is-obj "^1.0.1"
|
||||
is-regexp "^1.0.0"
|
||||
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
@@ -12047,7 +12144,16 @@ workbox-window@7.1.0:
|
||||
"@types/trusted-types" "^2.0.2"
|
||||
workbox-core "7.1.0"
|
||||
|
||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
|
||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
djangoSuperUserEmail: ENC[AES256_GCM,data:7b1xfYmr1g0RlBmsHBRA39ZPV/6+1DrtHQ==,iv:/GW7oLxPTZYmRWVPvyAQMoZl1owHM4Fo0XAOtyEh2rA=,tag:DaqoW+dglyAOXMm5+mrDfA==,type:str]
|
||||
djangoSuperUserPass: ENC[AES256_GCM,data:RQgX,iv:q3CdfmwGfHSTjLXTimDk/1MyoFLviRuwmZa2E7GUzhY=,tag:HCtdtqgSxdJIHFhI8xpegQ==,type:str]
|
||||
djangoSecretKey: ENC[AES256_GCM,data:mtJCf6mKfj/fJkg4wmfIvvU1vkUEF77BI8TUFikp/M3nPveDXhKmy3Cw3cXFpOYiFZ0=,iv:qwPRKsPS1Jhylj5asbmknXm1xOX3nfp9iccuorUrcj0=,tag:ENVfAt4i3PttoqD8+Kc4wQ==,type:str]
|
||||
oidc:
|
||||
clientId: ENC[AES256_GCM,data:wndPCbysbWDybdHglcG+wkMWk1rrD40hKqFxct9T3TLEGOk/,iv:RH1OdBX1GYIT90sSq0AGz49fFi6dL0m49Pegs6Ko9tQ=,tag:/tKytQwoZkBX1Tf96gAjIA==,type:str]
|
||||
clientSecret: ENC[AES256_GCM,data:MUJ0wsg+LC2QZ1jZ0Twd3FS3dQevmJq9/97qVI3ARHuJIVlQz0Qah4vE7/iR+sn7ME2o1s1AzV4c1Yx/F3nHBg==,iv:LvinICSzF/8EvrHZD4Jp6lt7g3yxSOEgVHPrc3SShjo=,tag:yvkyyBXmhEkmGL7jZevUCA==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age15fyxdwmg5mvldtqqus87xspuws2u0cpvwheehrtvkexj4tnsqqysw6re2x
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMMjFCeWhkUmRWTnlIM1JM
|
||||
dVFock1DWmtXQnpQZWZMWW1YdndhSS93MlVFCmxKVDUwOUt0NjJIZiswSm5aRi9U
|
||||
VEllelBZVmFKdVFzcVJPUm50VHo5RTgKLS0tIDlkU3htTEdSREFOSUxlTGVtUm1n
|
||||
RzJZbzhFcDNZKzdxMWFHTWx6Uy9GVFkKTw8LbhzAACp0NUHDfNcXpZyr2pJyNxxw
|
||||
C7j/UB0cAejlSJHaUUiZ6TEcslXRpqnNagwUw4z/uzo7m4temay22A==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age16hnlml8yv4ynwy0seer57g8qww075crd0g7nsundz3pj4wk7m3vqftszg7
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQQjBNMnVlNURQVWdjSyty
|
||||
RGozcmN5eTUwRHJIWnhhc1E3U1NXQ3AwTWxBCnFjbmJNZnFiRVJ6VHhmQmt1Vk5n
|
||||
OTVXWVh3RzhoMWNrbUl6OHphTjFLQVUKLS0tIGJjUlNhK0dHQ2R3SCtrbTRnaFJT
|
||||
Q1pyRXhSVm8xQWk2NG1MK0srVU1pL2sKkoxGCM00UM2leTNCn5H8499uwJw1NIXs
|
||||
PoRNgplehrHFptrAwGEpSYMXbxu88N7EWa/rtOp+sHWK5zpxscMkjA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1plkp8td6zzfcavjusmsfrlk54t9vn8jjxm8zaz7cmnr7kzl2nfnsd54hwg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzYnpkYnJnYnJjVFRHRzRa
|
||||
N09JOXVnQkVrcVcwdk9kR1k1azNib2lkMVZFCmhvOHlpVnJ0RlRpYWZ1TkVoaklV
|
||||
NmNzY3BEeWN1MUtKWmZFT2RaMUxBRW8KLS0tIG92ZmhsZ29LSkRSREhiaG9kWXhH
|
||||
akREb0ttYVpNWTJHb1pjaWRFbWpxUjgKgZp3cN2rZw4ktbpb5cUnDEtsT/KWszGi
|
||||
pmpJHgsMADigyUc+Pjw+1pwpn0FtXVEXGedbf8bBuJavvbS2PuJBsg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age12g6f5fse25tgrwweleh4jls3qs52hey2edh759smulwmk5lnzadslu2cp3
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxaHZJeStiVnBzTGNTNzdo
|
||||
UDFVTU51ZWp0WWorUnBlSzVBSU9IU2JnbUNNCkpMZGdNV3FUYkZOcWNLK0JWci81
|
||||
WGNwYi9Jb0QrV0lkUzNJWTcrUjIzUmMKLS0tIHlTKzNsVzNsSGFuYjJ0RFp0Y1Nr
|
||||
a1VOcDBPTTYvNjkxN092N1UrYk1CM2cKNifC3ZLOrFTFKA9iKg8nPpZb+3DxnTwq
|
||||
grsrxQa40b/Vv/aPoiPBMeSENDcH48X/EhMFNKX7dvl+7HEaY+QPlA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1hnhuzj96ktkhpyygvmz0x9h8mfvssz7ss6emmukags644mdhf4msajk93r
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoZ2ZlcllJeGlKUDNxUk1w
|
||||
ekZ3TSttaXREV1FBRWwzNW54cjlYbHpLdWpRCnhSL2hEVVBEWEJKQWF0YTk1YzhJ
|
||||
RTBGN25sT0hBM3V4QndiTVkveDBwQ2cKLS0tIEdoZGRLRXdCME1wcUJHQXhtSHBQ
|
||||
UVEyNUVIanF6Z3ZSUjU1aTk0NFRBR0EKGuH5vzOV9lP/qRew0maECapKtLILaf/4
|
||||
XoSgPnjh8pIbJG7i9VKnFORlzkNJ6OPhZlX3ax15hd1qQv0PSCMBDA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2024-07-02T10:03:17Z"
|
||||
mac: ENC[AES256_GCM,data:qx236E1cFtBmbYyUf6B95/Fwu2hoi9ZAhUcYiY/tsG9h1+kwXntfkvbH3ekyI7A5ZrpJXMeQZ7gLc+ohci4m5Ju+/G39MjMt+ww0Y6gBMqe59YlHfeFD2mYsnn9j1pqtbrIJ6+8fLDmhaXtGtXP3qRmFTc9LwL6Rm+5gn8cjcnA=,iv:TC7zBnQ0hRz0JSytrYVnyJiI1eMWRTBqctLajZYUhvU=,tag:wCBeo2xD5UpdRqGjkZxbXA==,type:str]
|
||||
pgp: []
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.8.1
|
||||
@@ -1,120 +0,0 @@
|
||||
image:
|
||||
repository: localhost:5001/impress-backend
|
||||
pullPolicy: Always
|
||||
tag: "latest"
|
||||
|
||||
backend:
|
||||
replicas: 1
|
||||
envVars:
|
||||
DJANGO_CSRF_TRUSTED_ORIGINS: https://impress.127.0.0.1.nip.io,http://impress.127.0.0.1.nip.io
|
||||
DJANGO_CONFIGURATION: Production
|
||||
DJANGO_ALLOWED_HOSTS: "*"
|
||||
DJANGO_SECRET_KEY: {{ .Values.djangoSecretKey }}
|
||||
DJANGO_SETTINGS_MODULE: impress.settings
|
||||
DJANGO_SUPERUSER_PASSWORD: admin
|
||||
DJANGO_EMAIL_HOST: "mailcatcher"
|
||||
DJANGO_EMAIL_PORT: 1025
|
||||
DJANGO_EMAIL_USE_SSL: False
|
||||
OIDC_OP_JWKS_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/jwks
|
||||
OIDC_OP_AUTHORIZATION_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/authorize
|
||||
OIDC_OP_TOKEN_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/token
|
||||
OIDC_OP_USER_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/userinfo
|
||||
OIDC_OP_LOGOUT_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/session/end
|
||||
OIDC_RP_CLIENT_ID: {{ .Values.oidc.clientId }}
|
||||
OIDC_RP_CLIENT_SECRET: {{ .Values.oidc.clientSecret }}
|
||||
OIDC_RP_SIGN_ALGO: RS256
|
||||
OIDC_RP_SCOPES: "openid email"
|
||||
OIDC_REDIRECT_ALLOWED_HOSTS: https://impress.127.0.0.1.nip.io
|
||||
OIDC_AUTH_REQUEST_EXTRA_PARAMS: "{'acr_values': 'eidas1'}"
|
||||
LOGIN_REDIRECT_URL: https://impress.127.0.0.1.nip.io
|
||||
LOGIN_REDIRECT_URL_FAILURE: https://impress.127.0.0.1.nip.io
|
||||
LOGOUT_REDIRECT_URL: https://impress.127.0.0.1.nip.io
|
||||
DB_HOST: postgres-postgresql
|
||||
DB_NAME: impress
|
||||
DB_USER: dinum
|
||||
DB_PASSWORD: pass
|
||||
DB_PORT: 5432
|
||||
POSTGRES_DB: impress
|
||||
POSTGRES_USER: dinum
|
||||
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: impress
|
||||
AWS_S3_SECRET_ACCESS_KEY: password
|
||||
AWS_STORAGE_BUCKET_NAME: impress-media-storage
|
||||
STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage
|
||||
|
||||
migrate:
|
||||
command:
|
||||
- "/bin/sh"
|
||||
- "-c"
|
||||
- |
|
||||
python manage.py migrate --no-input &&
|
||||
python manage.py create_demo --force
|
||||
restartPolicy: Never
|
||||
|
||||
command:
|
||||
- "gunicorn"
|
||||
- "-c"
|
||||
- "/usr/local/etc/gunicorn/impress.py"
|
||||
- "impress.wsgi:application"
|
||||
- "--reload"
|
||||
|
||||
createsuperuser:
|
||||
command:
|
||||
- "/bin/sh"
|
||||
- "-c"
|
||||
- |
|
||||
python manage.py createsuperuser --email admin@example.com --password admin
|
||||
restartPolicy: Never
|
||||
|
||||
frontend:
|
||||
envVars:
|
||||
PORT: 8080
|
||||
NEXT_PUBLIC_API_ORIGIN: https://impress.127.0.0.1.nip.io
|
||||
NEXT_PUBLIC_Y_PROVIDER_URL: wss://impress.127.0.0.1.nip.io/ws
|
||||
NEXT_PUBLIC_MEDIA_URL: https://impress.127.0.0.1.nip.io
|
||||
|
||||
replicas: 1
|
||||
command:
|
||||
- yarn
|
||||
- dev
|
||||
|
||||
image:
|
||||
repository: localhost:5001/impress-frontend
|
||||
pullPolicy: Always
|
||||
tag: "latest"
|
||||
|
||||
yProvider:
|
||||
replicas: 1
|
||||
|
||||
image:
|
||||
repository: localhost:5001/impress-y-provider
|
||||
pullPolicy: Always
|
||||
tag: "latest"
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
host: impress.127.0.0.1.nip.io
|
||||
|
||||
ingressWS:
|
||||
enabled: true
|
||||
host: impress.127.0.0.1.nip.io
|
||||
|
||||
ingressAdmin:
|
||||
enabled: true
|
||||
host: impress.127.0.0.1.nip.io
|
||||
|
||||
ingressMedia:
|
||||
enabled: true
|
||||
host: impress.127.0.0.1.nip.io
|
||||
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/auth-url: https://impress.127.0.0.1.nip.io/api/v1.0/documents/retrieve-auth/
|
||||
nginx.ingress.kubernetes.io/auth-response-headers: "Authorization, X-Amz-Date, X-Amz-Content-SHA256"
|
||||
nginx.ingress.kubernetes.io/upstream-vhost: minio.impress.svc.cluster.local:9000
|
||||
nginx.ingress.kubernetes.io/rewrite-target: /impress-media-storage/$1
|
||||
|
||||
serviceMedia:
|
||||
host: minio.impress.svc.cluster.local
|
||||
port: 9000
|
||||
@@ -1 +0,0 @@
|
||||
../../../../secrets/numerique-gouv/impress/env/preprod/secrets.enc.yaml
|
||||
@@ -1,183 +0,0 @@
|
||||
image:
|
||||
repository: lasuite/impress-backend
|
||||
pullPolicy: Always
|
||||
tag: "v1.6.0-preprod"
|
||||
|
||||
backend:
|
||||
migrateJobAnnotations:
|
||||
argocd.argoproj.io/hook: PreSync
|
||||
argocd.argoproj.io/hook-delete-policy: HookSucceeded
|
||||
envVars:
|
||||
AI_API_KEY:
|
||||
secretKeyRef:
|
||||
name: backend
|
||||
key: AI_API_KEY
|
||||
AI_BASE_URL:
|
||||
secretKeyRef:
|
||||
name: backend
|
||||
key: AI_BASE_URL
|
||||
AI_MODEL: meta-llama/Meta-Llama-3.1-70B-Instruct
|
||||
DJANGO_CSRF_TRUSTED_ORIGINS: http://impress-preprod.beta.numerique.gouv.fr,https://impress-preprod.beta.numerique.gouv.fr
|
||||
DJANGO_CONFIGURATION: Production
|
||||
DJANGO_ALLOWED_HOSTS: "*"
|
||||
DJANGO_SUPERUSER_EMAIL:
|
||||
secretKeyRef:
|
||||
name: backend
|
||||
key: DJANGO_SUPERUSER_EMAIL
|
||||
DJANGO_SECRET_KEY:
|
||||
secretKeyRef:
|
||||
name: backend
|
||||
key: DJANGO_SECRET_KEY
|
||||
DJANGO_SETTINGS_MODULE: impress.settings
|
||||
DJANGO_SUPERUSER_PASSWORD:
|
||||
secretKeyRef:
|
||||
name: backend
|
||||
key: DJANGO_SUPERUSER_PASSWORD
|
||||
DJANGO_EMAIL_HOST: "smtp.tem.scw.cloud"
|
||||
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://fca.integ01.dev-agentconnect.fr/api/v2/jwks
|
||||
OIDC_OP_AUTHORIZATION_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/authorize
|
||||
OIDC_OP_TOKEN_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/token
|
||||
OIDC_OP_USER_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/userinfo
|
||||
OIDC_OP_LOGOUT_ENDPOINT: https://fca.integ01.dev-agentconnect.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"
|
||||
OIDC_REDIRECT_ALLOWED_HOSTS: https://impress-preprod.beta.numerique.gouv.fr
|
||||
OIDC_AUTH_REQUEST_EXTRA_PARAMS: "{'acr_values': 'eidas1'}"
|
||||
LOGIN_REDIRECT_URL: https://impress-preprod.beta.numerique.gouv.fr
|
||||
LOGIN_REDIRECT_URL_FAILURE: https://impress-preprod.beta.numerique.gouv.fr
|
||||
LOGOUT_REDIRECT_URL: https://impress-preprod.beta.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
|
||||
|
||||
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.6.0-preprod"
|
||||
|
||||
yProvider:
|
||||
image:
|
||||
repository: lasuite/impress-y-provider
|
||||
pullPolicy: Always
|
||||
tag: "v1.6.0-preprod"
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
host: impress-preprod.beta.numerique.gouv.fr
|
||||
className: nginx
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
|
||||
ingressWS:
|
||||
enabled: true
|
||||
host: impress-preprod.beta.numerique.gouv.fr
|
||||
className: nginx
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
|
||||
ingressAdmin:
|
||||
enabled: true
|
||||
host: impress-preprod.beta.numerique.gouv.fr
|
||||
className: nginx
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/auth-signin: https://oauth2-proxy-preprod.beta.numerique.gouv.fr/oauth2/start
|
||||
nginx.ingress.kubernetes.io/auth-url: https://oauth2-proxy-preprod.beta.numerique.gouv.fr/oauth2/auth
|
||||
|
||||
ingressMedia:
|
||||
enabled: true
|
||||
host: impress-preprod.beta.numerique.gouv.fr
|
||||
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/auth-response-headers: "Authorization, X-Amz-Date, X-Amz-Content-SHA256"
|
||||
nginx.ingress.kubernetes.io/auth-url: https://impress-preprod.beta.numerique.gouv.fr/api/v1.0/documents/retrieve-auth/
|
||||
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
|
||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/rewrite-target: /impress-preprod-impress-media-storage/$1
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/upstream-vhost: s3.margaret-hamilton.indiehosters.net
|
||||
|
||||
serviceMedia:
|
||||
host: s3.margaret-hamilton.indiehosters.net
|
||||
port: 443
|
||||
@@ -1 +0,0 @@
|
||||
../../../../secrets/numerique-gouv/impress/env/production/secrets.enc.yaml
|
||||
@@ -1,183 +0,0 @@
|
||||
image:
|
||||
repository: lasuite/impress-backend
|
||||
pullPolicy: Always
|
||||
tag: "v1.6.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:
|
||||
secretKeyRef:
|
||||
name: backend
|
||||
key: AI_BASE_URL
|
||||
AI_MODEL: meta-llama/Meta-Llama-3.1-70B-Instruct
|
||||
DJANGO_CSRF_TRUSTED_ORIGINS: https://docs.numerique.gouv.fr
|
||||
DJANGO_CONFIGURATION: Production
|
||||
DJANGO_ALLOWED_HOSTS: "*"
|
||||
DJANGO_SECRET_KEY:
|
||||
secretKeyRef:
|
||||
name: backend
|
||||
key: DJANGO_SECRET_KEY
|
||||
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_HOST: "smtp.tem.scw.cloud"
|
||||
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"
|
||||
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
|
||||
|
||||
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.6.0"
|
||||
|
||||
yProvider:
|
||||
image:
|
||||
repository: lasuite/impress-y-provider
|
||||
pullPolicy: Always
|
||||
tag: "v1.6.0"
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
host: docs.numerique.gouv.fr
|
||||
className: nginx
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt
|
||||
|
||||
ingressWS:
|
||||
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-prod
|
||||
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/retrieve-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
|
||||
@@ -1 +0,0 @@
|
||||
../../../../secrets/numerique-gouv/impress/env/staging/secrets.enc.yaml
|
||||
@@ -1,183 +0,0 @@
|
||||
image:
|
||||
repository: lasuite/impress-backend
|
||||
pullPolicy: Always
|
||||
tag: "main"
|
||||
|
||||
backend:
|
||||
migrateJobAnnotations:
|
||||
argocd.argoproj.io/hook: PreSync
|
||||
argocd.argoproj.io/hook-delete-policy: HookSucceeded
|
||||
envVars:
|
||||
AI_API_KEY:
|
||||
secretKeyRef:
|
||||
name: backend
|
||||
key: AI_API_KEY
|
||||
AI_BASE_URL:
|
||||
secretKeyRef:
|
||||
name: backend
|
||||
key: AI_BASE_URL
|
||||
AI_MODEL: meta-llama/Meta-Llama-3.1-70B-Instruct
|
||||
DJANGO_CSRF_TRUSTED_ORIGINS: http://impress-staging.beta.numerique.gouv.fr,https://impress-staging.beta.numerique.gouv.fr
|
||||
DJANGO_CONFIGURATION: Production
|
||||
DJANGO_ALLOWED_HOSTS: "*"
|
||||
DJANGO_SECRET_KEY:
|
||||
secretKeyRef:
|
||||
name: backend
|
||||
key: DJANGO_SECRET_KEY
|
||||
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_HOST: "smtp.tem.scw.cloud"
|
||||
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://fca.integ01.dev-agentconnect.fr/api/v2/jwks
|
||||
OIDC_OP_AUTHORIZATION_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/authorize
|
||||
OIDC_OP_TOKEN_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/token
|
||||
OIDC_OP_USER_ENDPOINT: https://fca.integ01.dev-agentconnect.fr/api/v2/userinfo
|
||||
OIDC_OP_LOGOUT_ENDPOINT: https://fca.integ01.dev-agentconnect.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"
|
||||
OIDC_REDIRECT_ALLOWED_HOSTS: https://impress-staging.beta.numerique.gouv.fr
|
||||
OIDC_AUTH_REQUEST_EXTRA_PARAMS: "{'acr_values': 'eidas1'}"
|
||||
LOGIN_REDIRECT_URL: https://impress-staging.beta.numerique.gouv.fr
|
||||
LOGIN_REDIRECT_URL_FAILURE: https://impress-staging.beta.numerique.gouv.fr
|
||||
LOGOUT_REDIRECT_URL: https://impress-staging.beta.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
|
||||
|
||||
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: "main"
|
||||
|
||||
yProvider:
|
||||
image:
|
||||
repository: lasuite/impress-y-provider
|
||||
pullPolicy: Always
|
||||
tag: "main"
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
host: impress-staging.beta.numerique.gouv.fr
|
||||
className: nginx
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
|
||||
ingressWS:
|
||||
enabled: true
|
||||
host: impress-staging.beta.numerique.gouv.fr
|
||||
className: nginx
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
|
||||
ingressAdmin:
|
||||
enabled: true
|
||||
host: impress-staging.beta.numerique.gouv.fr
|
||||
className: nginx
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/auth-signin: https://oauth2-proxy-preprod.beta.numerique.gouv.fr/oauth2/start
|
||||
nginx.ingress.kubernetes.io/auth-url: https://oauth2-proxy-preprod.beta.numerique.gouv.fr/oauth2/auth
|
||||
|
||||
ingressMedia:
|
||||
enabled: true
|
||||
host: impress-staging.beta.numerique.gouv.fr
|
||||
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/auth-response-headers: "Authorization, X-Amz-Date, X-Amz-Content-SHA256"
|
||||
nginx.ingress.kubernetes.io/auth-url: https://impress-staging.beta.numerique.gouv.fr/api/v1.0/documents/retrieve-auth/
|
||||
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
|
||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/rewrite-target: /impress-staging-impress-media-storage/$1
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/upstream-vhost: s3.margaret-hamilton.indiehosters.net
|
||||
|
||||
serviceMedia:
|
||||
host: s3.margaret-hamilton.indiehosters.net
|
||||
port: 443
|
||||
@@ -1,5 +0,0 @@
|
||||
apiVersion: v2
|
||||
name: extra
|
||||
description: A Helm chart to add some manifests to impress
|
||||
type: application
|
||||
version: 0.1.0
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: core.libre.sh/v1alpha1
|
||||
kind: Redis
|
||||
metadata:
|
||||
name: redis
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
spec:
|
||||
disableAuth: false
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: core.libre.sh/v1alpha1
|
||||
kind: Postgres
|
||||
metadata:
|
||||
name: postgresql
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
spec:
|
||||
database: impress
|
||||
@@ -1,8 +0,0 @@
|
||||
apiVersion: core.libre.sh/v1alpha1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: impress-media-storage
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
spec:
|
||||
provider: data
|
||||
versioned: true
|
||||
@@ -1,82 +0,0 @@
|
||||
repositories:
|
||||
- name: bitnami
|
||||
url: registry-1.docker.io/bitnamicharts
|
||||
oci: true
|
||||
|
||||
releases:
|
||||
- name: postgres
|
||||
installed: {{ eq .Environment.Name "dev" | toYaml }}
|
||||
namespace: {{ .Namespace }}
|
||||
chart: bitnami/postgresql
|
||||
version: 13.1.5
|
||||
values:
|
||||
- auth:
|
||||
username: dinum
|
||||
password: pass
|
||||
database: impress
|
||||
- tls:
|
||||
enabled: true
|
||||
autoGenerated: true
|
||||
|
||||
- name: minio
|
||||
installed: {{ eq .Environment.Name "dev" | toYaml }}
|
||||
namespace: {{ .Namespace }}
|
||||
chart: bitnami/minio
|
||||
version: 12.10.10
|
||||
values:
|
||||
- auth:
|
||||
rootUser: impress
|
||||
rootPassword: password
|
||||
- provisioning:
|
||||
enabled: true
|
||||
buckets:
|
||||
- name: impress-media-storage
|
||||
versioning: true
|
||||
|
||||
- name: redis
|
||||
installed: {{ eq .Environment.Name "dev" | toYaml }}
|
||||
namespace: {{ .Namespace }}
|
||||
chart: bitnami/redis
|
||||
version: 18.19.2
|
||||
values:
|
||||
- auth:
|
||||
password: pass
|
||||
architecture: standalone
|
||||
|
||||
- name: extra
|
||||
installed: {{ ne .Environment.Name "dev" | toYaml }}
|
||||
namespace: {{ .Namespace }}
|
||||
chart: ./extra
|
||||
secrets:
|
||||
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
|
||||
|
||||
- name: impress
|
||||
version: {{ .Values.version }}
|
||||
namespace: {{ .Namespace }}
|
||||
chart: ./impress
|
||||
values:
|
||||
- env.d/{{ .Environment.Name }}/values.impress.yaml.gotmpl
|
||||
secrets:
|
||||
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
|
||||
|
||||
environments:
|
||||
dev:
|
||||
values:
|
||||
- version: 0.0.1
|
||||
secrets:
|
||||
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
|
||||
staging:
|
||||
values:
|
||||
- version: 0.0.1
|
||||
secrets:
|
||||
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
|
||||
preprod:
|
||||
values:
|
||||
- version: 0.0.1
|
||||
secrets:
|
||||
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
|
||||
production:
|
||||
values:
|
||||
- version: 0.0.1
|
||||
secrets:
|
||||
- env.d/{{ .Environment.Name }}/secrets.enc.yaml
|
||||
@@ -1,4 +0,0 @@
|
||||
apiVersion: v2
|
||||
type: application
|
||||
name: impress
|
||||
version: 0.0.1
|
||||
@@ -1,128 +0,0 @@
|
||||
# Impress helm chart
|
||||
|
||||
## Parameters
|
||||
|
||||
### General configuration
|
||||
|
||||
| Name | Description | Value |
|
||||
| ------------------------------------------ | ---------------------------------------------------- | ------------------------ |
|
||||
| `image.repository` | Repository to use to pull impress's container image | `lasuite/impress-backend` |
|
||||
| `image.tag` | impress's container tag | `latest` |
|
||||
| `image.pullPolicy` | Container image pull policy | `IfNotPresent` |
|
||||
| `image.credentials.username` | Username for container registry authentication | |
|
||||
| `image.credentials.password` | Password for container registry authentication | |
|
||||
| `image.credentials.registry` | Registry url for which the credentials are specified | |
|
||||
| `image.credentials.name` | Name of the generated secret for imagePullSecrets | |
|
||||
| `nameOverride` | Override the chart name | `""` |
|
||||
| `fullnameOverride` | Override the full application name | `""` |
|
||||
| `ingress.enabled` | whether to enable the Ingress or not | `false` |
|
||||
| `ingress.className` | IngressClass to use for the Ingress | `nil` |
|
||||
| `ingress.host` | Host for the Ingress | `impress.example.com` |
|
||||
| `ingress.path` | Path to use for the Ingress | `/` |
|
||||
| `ingress.hosts` | Additional host to configure for the Ingress | `[]` |
|
||||
| `ingress.tls.enabled` | Weather to enable TLS for the Ingress | `true` |
|
||||
| `ingress.tls.additional[].secretName` | Secret name for additional TLS config | |
|
||||
| `ingress.tls.additional[].hosts[]` | Hosts for additional TLS config | |
|
||||
| `ingress.customBackends` | Add custom backends to ingress | `[]` |
|
||||
| `ingressAdmin.enabled` | whether to enable the Ingress or not | `false` |
|
||||
| `ingressAdmin.className` | IngressClass to use for the Ingress | `nil` |
|
||||
| `ingressAdmin.host` | Host for the Ingress | `impress.example.com` |
|
||||
| `ingressAdmin.path` | Path to use for the Ingress | `/admin` |
|
||||
| `ingressAdmin.hosts` | Additional host to configure for the Ingress | `[]` |
|
||||
| `ingressAdmin.tls.enabled` | Weather to enable TLS for the Ingress | `true` |
|
||||
| `ingressAdmin.tls.additional[].secretName` | Secret name for additional TLS config | |
|
||||
| `ingressAdmin.tls.additional[].hosts[]` | Hosts for additional TLS config | |
|
||||
|
||||
### backend
|
||||
|
||||
| Name | Description | Value |
|
||||
| ----------------------------------------------------- | ---------------------------------------------------------------------------------- | ----------------------------------------------- |
|
||||
| `backend.command` | Override the backend container command | `[]` |
|
||||
| `backend.args` | Override the backend container args | `[]` |
|
||||
| `backend.replicas` | Amount of backend replicas | `3` |
|
||||
| `backend.shareProcessNamespace` | Enable share process namespace between containers | `false` |
|
||||
| `backend.sidecars` | Add sidecars containers to backend deployment | `[]` |
|
||||
| `backend.securityContext` | Configure backend Pod security context | `nil` |
|
||||
| `backend.envVars` | Configure backend container environment variables | `undefined` |
|
||||
| `backend.envVars.BY_VALUE` | Example environment variable by setting value directly | |
|
||||
| `backend.envVars.FROM_CONFIGMAP.configMapKeyRef.name` | Name of a ConfigMap when configuring env vars from a ConfigMap | |
|
||||
| `backend.envVars.FROM_CONFIGMAP.configMapKeyRef.key` | Key within a ConfigMap when configuring env vars from a ConfigMap | |
|
||||
| `backend.envVars.FROM_SECRET.secretKeyRef.name` | Name of a Secret when configuring env vars from a Secret | |
|
||||
| `backend.envVars.FROM_SECRET.secretKeyRef.key` | Key within a Secret when configuring env vars from a Secret | |
|
||||
| `backend.podAnnotations` | Annotations to add to the backend Pod | `{}` |
|
||||
| `backend.service.type` | backend Service type | `ClusterIP` |
|
||||
| `backend.service.port` | backend Service listening port | `80` |
|
||||
| `backend.service.targetPort` | backend container listening port | `8000` |
|
||||
| `backend.service.annotations` | Annotations to add to the backend Service | `{}` |
|
||||
| `backend.migrate.command` | backend migrate command | `["python","manage.py","migrate","--no-input"]` |
|
||||
| `backend.migrate.restartPolicy` | backend migrate job restart policy | `Never` |
|
||||
| `backend.probes.liveness.path` | Configure path for backend HTTP liveness probe | `/__heartbeat__` |
|
||||
| `backend.probes.liveness.targetPort` | Configure port for backend HTTP liveness probe | `undefined` |
|
||||
| `backend.probes.liveness.initialDelaySeconds` | Configure initial delay for backend liveness probe | `10` |
|
||||
| `backend.probes.liveness.initialDelaySeconds` | Configure timeout for backend liveness probe | `10` |
|
||||
| `backend.probes.startup.path` | Configure path for backend HTTP startup probe | `undefined` |
|
||||
| `backend.probes.startup.targetPort` | Configure port for backend HTTP startup probe | `undefined` |
|
||||
| `backend.probes.startup.initialDelaySeconds` | Configure initial delay for backend startup probe | `undefined` |
|
||||
| `backend.probes.startup.initialDelaySeconds` | Configure timeout for backend startup probe | `undefined` |
|
||||
| `backend.probes.readiness.path` | Configure path for backend HTTP readiness probe | `/__lbheartbeat__` |
|
||||
| `backend.probes.readiness.targetPort` | Configure port for backend HTTP readiness probe | `undefined` |
|
||||
| `backend.probes.readiness.initialDelaySeconds` | Configure initial delay for backend readiness probe | `10` |
|
||||
| `backend.probes.readiness.initialDelaySeconds` | Configure timeout for backend readiness probe | `10` |
|
||||
| `backend.resources` | Resource requirements for the backend container | `{}` |
|
||||
| `backend.nodeSelector` | Node selector for the backend Pod | `{}` |
|
||||
| `backend.tolerations` | Tolerations for the backend Pod | `[]` |
|
||||
| `backend.affinity` | Affinity for the backend Pod | `{}` |
|
||||
| `backend.persistence` | Additional volumes to create and mount on the backend. Used for debugging purposes | `{}` |
|
||||
| `backend.persistence.volume-name.size` | Size of the additional volume | |
|
||||
| `backend.persistence.volume-name.type` | Type of the additional volume, persistentVolumeClaim or emptyDir | |
|
||||
| `backend.persistence.volume-name.mountPath` | Path where the volume should be mounted to | |
|
||||
| `backend.extraVolumeMounts` | Additional volumes to mount on the backend. | `[]` |
|
||||
| `backend.extraVolumes` | Additional volumes to mount on the backend. | `[]` |
|
||||
|
||||
### frontend
|
||||
|
||||
| Name | Description | Value |
|
||||
| ------------------------------------------------------ | ----------------------------------------------------------------------------------- | ------------------------- |
|
||||
| `frontend.image.repository` | Repository to use to pull impress's frontend container image | `lasuite/impress-frontend` |
|
||||
| `frontend.image.tag` | impress's frontend container tag | `latest` |
|
||||
| `frontend.image.pullPolicy` | frontend container image pull policy | `IfNotPresent` |
|
||||
| `frontend.command` | Override the frontend container command | `[]` |
|
||||
| `frontend.args` | Override the frontend container args | `[]` |
|
||||
| `frontend.replicas` | Amount of frontend replicas | `3` |
|
||||
| `frontend.shareProcessNamespace` | Enable share process namefrontend between containers | `false` |
|
||||
| `frontend.sidecars` | Add sidecars containers to frontend deployment | `[]` |
|
||||
| `frontend.securityContext` | Configure frontend Pod security context | `nil` |
|
||||
| `frontend.envVars` | Configure frontend container environment variables | `undefined` |
|
||||
| `frontend.envVars.BY_VALUE` | Example environment variable by setting value directly | |
|
||||
| `frontend.envVars.FROM_CONFIGMAP.configMapKeyRef.name` | Name of a ConfigMap when configuring env vars from a ConfigMap | |
|
||||
| `frontend.envVars.FROM_CONFIGMAP.configMapKeyRef.key` | Key within a ConfigMap when configuring env vars from a ConfigMap | |
|
||||
| `frontend.envVars.FROM_SECRET.secretKeyRef.name` | Name of a Secret when configuring env vars from a Secret | |
|
||||
| `frontend.envVars.FROM_SECRET.secretKeyRef.key` | Key within a Secret when configuring env vars from a Secret | |
|
||||
| `frontend.podAnnotations` | Annotations to add to the frontend Pod | `{}` |
|
||||
| `frontend.service.type` | frontend Service type | `ClusterIP` |
|
||||
| `frontend.service.port` | frontend Service listening port | `80` |
|
||||
| `frontend.service.targetPort` | frontend container listening port | `8080` |
|
||||
| `frontend.service.annotations` | Annotations to add to the frontend Service | `{}` |
|
||||
| `frontend.probes` | Configure probe for frontend | `{}` |
|
||||
| `frontend.probes.liveness.path` | Configure path for frontend HTTP liveness probe | |
|
||||
| `frontend.probes.liveness.targetPort` | Configure port for frontend HTTP liveness probe | |
|
||||
| `frontend.probes.liveness.initialDelaySeconds` | Configure initial delay for frontend liveness probe | |
|
||||
| `frontend.probes.liveness.initialDelaySeconds` | Configure timeout for frontend liveness probe | |
|
||||
| `frontend.probes.startup.path` | Configure path for frontend HTTP startup probe | |
|
||||
| `frontend.probes.startup.targetPort` | Configure port for frontend HTTP startup probe | |
|
||||
| `frontend.probes.startup.initialDelaySeconds` | Configure initial delay for frontend startup probe | |
|
||||
| `frontend.probes.startup.initialDelaySeconds` | Configure timeout for frontend startup probe | |
|
||||
| `frontend.probes.readiness.path` | Configure path for frontend HTTP readiness probe | |
|
||||
| `frontend.probes.readiness.targetPort` | Configure port for frontend HTTP readiness probe | |
|
||||
| `frontend.probes.readiness.initialDelaySeconds` | Configure initial delay for frontend readiness probe | |
|
||||
| `frontend.probes.readiness.initialDelaySeconds` | Configure timeout for frontend readiness probe | |
|
||||
| `frontend.resources` | Resource requirements for the frontend container | `{}` |
|
||||
| `frontend.nodeSelector` | Node selector for the frontend Pod | `{}` |
|
||||
| `frontend.tolerations` | Tolerations for the frontend Pod | `[]` |
|
||||
| `frontend.affinity` | Affinity for the frontend Pod | `{}` |
|
||||
| `frontend.persistence` | Additional volumes to create and mount on the frontend. Used for debugging purposes | `{}` |
|
||||
| `frontend.persistence.volume-name.size` | Size of the additional volume | |
|
||||
| `frontend.persistence.volume-name.type` | Type of the additional volume, persistentVolumeClaim or emptyDir | |
|
||||
| `frontend.persistence.volume-name.mountPath` | Path where the volume should be mounted to | |
|
||||
| `frontend.extraVolumeMounts` | Additional volumes to mount on the frontend. | `[]` |
|
||||
| `frontend.extraVolumes` | Additional volumes to mount on the frontend. | `[]` |
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker image ls | grep readme-generator-for-helm
|
||||
if [ "$?" -ne "0" ]; then
|
||||
git clone https://github.com/bitnami/readme-generator-for-helm.git /tmp/readme-generator-for-helm
|
||||
cd /tmp/readme-generator-for-helm
|
||||
docker build -t readme-generator-for-helm:latest .
|
||||
cd $(dirname -- "${BASH_SOURCE[0]}")
|
||||
fi
|
||||
docker run --rm -it -v ./values.yaml:/app/values.yaml -v ./README.md:/app/README.md readme-generator-for-helm:latest readme-generator -v values.yaml -r README.md
|
||||
@@ -1,184 +0,0 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "impress.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "impress.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "impress.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
impress.labels
|
||||
*/}}
|
||||
{{- define "impress.labels" -}}
|
||||
helm.sh/chart: {{ include "impress.chart" . }}
|
||||
{{ include "impress.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "impress.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "impress.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
transform dictionnary of environment variables
|
||||
Usage : {{ include "impress.env.transformDict" .Values.envVars }}
|
||||
|
||||
Example:
|
||||
envVars:
|
||||
# Using simple strings as env vars
|
||||
ENV_VAR_NAME: "envVar value"
|
||||
# Using a value from a configMap
|
||||
ENV_VAR_FROM_CM:
|
||||
configMapKeyRef:
|
||||
name: cm-name
|
||||
key: "key_in_cm"
|
||||
# Using a value from a secret
|
||||
ENV_VAR_FROM_SECRET:
|
||||
secretKeyRef:
|
||||
name: secret-name
|
||||
key: "key_in_secret"
|
||||
*/}}
|
||||
{{- define "impress.env.transformDict" -}}
|
||||
{{- range $key, $value := . }}
|
||||
- name: {{ $key | quote }}
|
||||
{{- if $value | kindIs "map" }}
|
||||
valueFrom: {{ $value | toYaml | nindent 4 }}
|
||||
{{- else }}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
impress env vars
|
||||
*/}}
|
||||
{{- define "impress.common.env" -}}
|
||||
{{- $topLevelScope := index . 0 -}}
|
||||
{{- $workerScope := index . 1 -}}
|
||||
{{- include "impress.env.transformDict" $workerScope.envVars -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
|
||||
Requires array with top level scope and component name
|
||||
*/}}
|
||||
{{- define "impress.common.labels" -}}
|
||||
{{- $topLevelScope := index . 0 -}}
|
||||
{{- $component := index . 1 -}}
|
||||
{{- include "impress.labels" $topLevelScope }}
|
||||
app.kubernetes.io/component: {{ $component }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common selector labels
|
||||
|
||||
Requires array with top level scope and component name
|
||||
*/}}
|
||||
{{- define "impress.common.selectorLabels" -}}
|
||||
{{- $topLevelScope := index . 0 -}}
|
||||
{{- $component := index . 1 -}}
|
||||
{{- include "impress.selectorLabels" $topLevelScope }}
|
||||
app.kubernetes.io/component: {{ $component }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "impress.probes.abstract" -}}
|
||||
{{- if .exec -}}
|
||||
exec:
|
||||
{{- toYaml .exec | nindent 2 }}
|
||||
{{- else if .tcpSocket -}}
|
||||
tcpSocket:
|
||||
{{- toYaml .tcpSocket | nindent 2 }}
|
||||
{{- else -}}
|
||||
httpGet:
|
||||
path: {{ .path }}
|
||||
port: {{ .targetPort }}
|
||||
{{- end }}
|
||||
initialDelaySeconds: {{ .initialDelaySeconds | eq nil | ternary 0 .initialDelaySeconds }}
|
||||
timeoutSeconds: {{ .timeoutSeconds | eq nil | ternary 1 .timeoutSeconds }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Full name for the backend
|
||||
|
||||
Requires top level scope
|
||||
*/}}
|
||||
{{- define "impress.backend.fullname" -}}
|
||||
{{ include "impress.fullname" . }}-backend
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Full name for the frontend
|
||||
|
||||
Requires top level scope
|
||||
*/}}
|
||||
{{- define "impress.frontend.fullname" -}}
|
||||
{{ include "impress.fullname" . }}-frontend
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Full name for the yProvider
|
||||
|
||||
Requires top level scope
|
||||
*/}}
|
||||
{{- define "impress.yProvider.fullname" -}}
|
||||
{{ include "impress.fullname" . }}-y-provider
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Usage : {{ include "impress.secret.dockerconfigjson.name" (dict "fullname" (include "impress.fullname" .) "imageCredentials" .Values.path.to.the.image1) }}
|
||||
*/}}
|
||||
{{- define "impress.secret.dockerconfigjson.name" }}
|
||||
{{- if (default (dict) .imageCredentials).name }}{{ .imageCredentials.name }}{{ else }}{{ .fullname | trunc 63 | trimSuffix "-" }}-dockerconfig{{ end -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Usage : {{ include "impress.secret.dockerconfigjson" (dict "fullname" (include "impress.fullname" .) "imageCredentials" .Values.path.to.the.image1) }}
|
||||
*/}}
|
||||
{{- define "impress.secret.dockerconfigjson" }}
|
||||
{{- if .imageCredentials -}}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ template "impress.secret.dockerconfigjson.name" (dict "fullname" .fullname "imageCredentials" .imageCredentials) }}
|
||||
annotations:
|
||||
"helm.sh/hook": pre-install,pre-upgrade
|
||||
"helm.sh/hook-weight": "-5"
|
||||
"helm.sh/hook-delete-policy": before-hook-creation
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
data:
|
||||
.dockerconfigjson: {{ template "impress.secret.dockerconfigjson.data" .imageCredentials }}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
@@ -1,136 +0,0 @@
|
||||
{{- $envVars := include "impress.common.env" (list . .Values.backend) -}}
|
||||
{{- $fullName := include "impress.backend.fullname" . -}}
|
||||
{{- $component := "backend" -}}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.backend.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- with .Values.backend.podAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 8 }}
|
||||
spec:
|
||||
{{- if $.Values.image.credentials }}
|
||||
imagePullSecrets:
|
||||
- name: {{ include "impress.secret.dockerconfigjson.name" (dict "fullname" (include "impress.fullname" .) "imageCredentials" $.Values.image.credentials) }}
|
||||
{{- end}}
|
||||
shareProcessNamespace: {{ .Values.backend.shareProcessNamespace }}
|
||||
containers:
|
||||
{{- with .Values.backend.sidecars }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ (.Values.backend.image | default dict).repository | default .Values.image.repository }}:{{ (.Values.backend.image | default dict).tag | default .Values.image.tag }}"
|
||||
imagePullPolicy: {{ (.Values.backend.image | default dict).pullPolicy | default .Values.image.pullPolicy }}
|
||||
{{- with .Values.backend.command }}
|
||||
command:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.args }}
|
||||
args:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
env:
|
||||
{{- if $envVars}}
|
||||
{{- $envVars | indent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.backend.service.targetPort }}
|
||||
protocol: TCP
|
||||
{{- if .Values.backend.probes.liveness }}
|
||||
livenessProbe:
|
||||
{{- include "impress.probes.abstract" (merge .Values.backend.probes.liveness (dict "targetPort" .Values.backend.service.targetPort )) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.backend.probes.readiness }}
|
||||
readinessProbe:
|
||||
{{- include "impress.probes.abstract" (merge .Values.backend.probes.readiness (dict "targetPort" .Values.backend.service.targetPort )) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.backend.probes.startup }}
|
||||
startupProbe:
|
||||
{{- include "impress.probes.abstract" (merge .Values.backend.probes.startup (dict "targetPort" .Values.backend.service.targetPort )) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{- range $index, $value := .Values.mountFiles }}
|
||||
- name: "files-{{ $index }}"
|
||||
mountPath: {{ $value.path }}
|
||||
subPath: content
|
||||
{{- end }}
|
||||
{{- range $name, $volume := .Values.backend.persistence }}
|
||||
- name: "{{ $name }}"
|
||||
mountPath: "{{ $volume.mountPath }}"
|
||||
{{- end }}
|
||||
{{- range .Values.backend.extraVolumeMounts }}
|
||||
- name: {{ .name }}
|
||||
mountPath: {{ .mountPath }}
|
||||
subPath: {{ .subPath | default "" }}
|
||||
readOnly: {{ .readOnly }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
{{- range $index, $value := .Values.mountFiles }}
|
||||
- name: "files-{{ $index }}"
|
||||
configMap:
|
||||
name: "{{ include "impress.fullname" $ }}-files-{{ $index }}"
|
||||
{{- end }}
|
||||
{{- range $name, $volume := .Values.backend.persistence }}
|
||||
- name: "{{ $name }}"
|
||||
{{- if eq $volume.type "emptyDir" }}
|
||||
emptyDir: {}
|
||||
{{- else }}
|
||||
persistentVolumeClaim:
|
||||
claimName: "{{ $fullName }}-{{ $name }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range .Values.backend.extraVolumes }}
|
||||
- name: {{ .name }}
|
||||
{{- if .existingClaim }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .existingClaim }}
|
||||
{{- else if .hostPath }}
|
||||
hostPath:
|
||||
{{ toYaml .hostPath | nindent 12 }}
|
||||
{{- else if .csi }}
|
||||
csi:
|
||||
{{- toYaml .csi | nindent 12 }}
|
||||
{{- else if .configMap }}
|
||||
configMap:
|
||||
{{- toYaml .configMap | nindent 12 }}
|
||||
{{- else if .emptyDir }}
|
||||
emptyDir:
|
||||
{{- toYaml .emptyDir | nindent 12 }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -1,122 +0,0 @@
|
||||
{{- $envVars := include "impress.common.env" (list . .Values.backend) -}}
|
||||
{{- $fullName := include "impress.backend.fullname" . -}}
|
||||
{{- $component := "backend" -}}
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: {{ $fullName }}-migrate
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-options: Replace=true,Force=true
|
||||
{{- with .Values.backend.migrateJobAnnotations }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- with .Values.backend.podAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 8 }}
|
||||
spec:
|
||||
{{- if $.Values.image.credentials }}
|
||||
imagePullSecrets:
|
||||
- name: {{ include "impress.secret.dockerconfigjson.name" (dict "fullname" (include "impress.fullname" .) "imageCredentials" $.Values.image.credentials) }}
|
||||
{{- end}}
|
||||
shareProcessNamespace: {{ .Values.backend.shareProcessNamespace }}
|
||||
containers:
|
||||
{{- with .Values.backend.sidecars }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ (.Values.backend.image | default dict).repository | default .Values.image.repository }}:{{ (.Values.backend.image | default dict).tag | default .Values.image.tag }}"
|
||||
imagePullPolicy: {{ (.Values.backend.image | default dict).pullPolicy | default .Values.image.pullPolicy }}
|
||||
{{- with .Values.backend.migrate.command }}
|
||||
command:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.args }}
|
||||
args:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
env:
|
||||
{{- if $envVars}}
|
||||
{{- $envVars | indent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{- range $index, $value := .Values.mountFiles }}
|
||||
- name: "files-{{ $index }}"
|
||||
mountPath: {{ $value.path }}
|
||||
subPath: content
|
||||
{{- end }}
|
||||
{{- range $name, $volume := .Values.backend.persistence }}
|
||||
- name: "{{ $name }}"
|
||||
mountPath: "{{ $volume.mountPath }}"
|
||||
{{- end }}
|
||||
{{- range .Values.backend.extraVolumeMounts }}
|
||||
- name: {{ .name }}
|
||||
mountPath: {{ .mountPath }}
|
||||
subPath: {{ .subPath | default "" }}
|
||||
readOnly: {{ .readOnly }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
restartPolicy: {{ .Values.backend.migrate.restartPolicy }}
|
||||
volumes:
|
||||
{{- range $index, $value := .Values.mountFiles }}
|
||||
- name: "files-{{ $index }}"
|
||||
configMap:
|
||||
name: "{{ include "impress.fullname" $ }}-files-{{ $index }}"
|
||||
{{- end }}
|
||||
{{- range $name, $volume := .Values.backend.persistence }}
|
||||
- name: "{{ $name }}"
|
||||
{{- if eq $volume.type "emptyDir" }}
|
||||
emptyDir: {}
|
||||
{{- else }}
|
||||
persistentVolumeClaim:
|
||||
claimName: "{{ $fullName }}-{{ $name }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range .Values.backend.extraVolumes }}
|
||||
- name: {{ .name }}
|
||||
{{- if .existingClaim }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .existingClaim }}
|
||||
{{- else if .hostPath }}
|
||||
hostPath:
|
||||
{{ toYaml .hostPath | nindent 12 }}
|
||||
{{- else if .csi }}
|
||||
csi:
|
||||
{{- toYaml .csi | nindent 12 }}
|
||||
{{- else if .configMap }}
|
||||
configMap:
|
||||
{{- toYaml .configMap | nindent 12 }}
|
||||
{{- else if .emptyDir }}
|
||||
emptyDir:
|
||||
{{- toYaml .emptyDir | nindent 12 }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -1,122 +0,0 @@
|
||||
{{- $envVars := include "impress.common.env" (list . .Values.backend) -}}
|
||||
{{- $fullName := include "impress.backend.fullname" . -}}
|
||||
{{- $component := "backend" -}}
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: {{ $fullName }}-createsuperuser
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-options: Replace=true,Force=true
|
||||
{{- with .Values.backend.migrateJobAnnotations }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- with .Values.backend.podAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 8 }}
|
||||
spec:
|
||||
{{- if $.Values.image.credentials }}
|
||||
imagePullSecrets:
|
||||
- name: {{ include "impress.secret.dockerconfigjson.name" (dict "fullname" (include "impress.fullname" .) "imageCredentials" $.Values.image.credentials) }}
|
||||
{{- end}}
|
||||
shareProcessNamespace: {{ .Values.backend.shareProcessNamespace }}
|
||||
containers:
|
||||
{{- with .Values.backend.sidecars }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ (.Values.backend.image | default dict).repository | default .Values.image.repository }}:{{ (.Values.backend.image | default dict).tag | default .Values.image.tag }}"
|
||||
imagePullPolicy: {{ (.Values.backend.image | default dict).pullPolicy | default .Values.image.pullPolicy }}
|
||||
{{- with .Values.backend.createsuperuser.command }}
|
||||
command:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.args }}
|
||||
args:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
env:
|
||||
{{- if $envVars}}
|
||||
{{- $envVars | indent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{- range $index, $value := .Values.mountFiles }}
|
||||
- name: "files-{{ $index }}"
|
||||
mountPath: {{ $value.path }}
|
||||
subPath: content
|
||||
{{- end }}
|
||||
{{- range $name, $volume := .Values.backend.persistence }}
|
||||
- name: "{{ $name }}"
|
||||
mountPath: "{{ $volume.mountPath }}"
|
||||
{{- end }}
|
||||
{{- range .Values.backend.extraVolumeMounts }}
|
||||
- name: {{ .name }}
|
||||
mountPath: {{ .mountPath }}
|
||||
subPath: {{ .subPath | default "" }}
|
||||
readOnly: {{ .readOnly }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.backend.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
restartPolicy: {{ .Values.backend.createsuperuser.restartPolicy }}
|
||||
volumes:
|
||||
{{- range $index, $value := .Values.mountFiles }}
|
||||
- name: "files-{{ $index }}"
|
||||
configMap:
|
||||
name: "{{ include "impress.fullname" $ }}-files-{{ $index }}"
|
||||
{{- end }}
|
||||
{{- range $name, $volume := .Values.backend.persistence }}
|
||||
- name: "{{ $name }}"
|
||||
{{- if eq $volume.type "emptyDir" }}
|
||||
emptyDir: {}
|
||||
{{- else }}
|
||||
persistentVolumeClaim:
|
||||
claimName: "{{ $fullName }}-{{ $name }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range .Values.backend.extraVolumes }}
|
||||
- name: {{ .name }}
|
||||
{{- if .existingClaim }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .existingClaim }}
|
||||
{{- else if .hostPath }}
|
||||
hostPath:
|
||||
{{ toYaml .hostPath | nindent 12 }}
|
||||
{{- else if .csi }}
|
||||
csi:
|
||||
{{- toYaml .csi | nindent 12 }}
|
||||
{{- else if .configMap }}
|
||||
configMap:
|
||||
{{- toYaml .configMap | nindent 12 }}
|
||||
{{- else if .emptyDir }}
|
||||
emptyDir:
|
||||
{{- toYaml .emptyDir | nindent 12 }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -1,21 +0,0 @@
|
||||
{{- $envVars := include "impress.common.env" (list . .Values.backend) -}}
|
||||
{{- $fullName := include "impress.backend.fullname" . -}}
|
||||
{{- $component := "backend" -}}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||
annotations:
|
||||
{{- toYaml $.Values.backend.service.annotations | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.backend.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.backend.service.port }}
|
||||
targetPort: {{ .Values.backend.service.targetPort }}
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 4 }}
|
||||
@@ -1,136 +0,0 @@
|
||||
{{- $envVars := include "impress.common.env" (list . .Values.frontend) -}}
|
||||
{{- $fullName := include "impress.frontend.fullname" . -}}
|
||||
{{- $component := "frontend" -}}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.frontend.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- with .Values.frontend.podAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 8 }}
|
||||
spec:
|
||||
{{- if $.Values.image.credentials }}
|
||||
imagePullSecrets:
|
||||
- name: {{ include "impress.secret.dockerconfigjson.name" (dict "fullname" (include "impress.fullname" .) "imageCredentials" $.Values.image.credentials) }}
|
||||
{{- end}}
|
||||
shareProcessNamespace: {{ .Values.frontend.shareProcessNamespace }}
|
||||
containers:
|
||||
{{- with .Values.frontend.sidecars }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ (.Values.frontend.image | default dict).repository | default .Values.image.repository }}:{{ (.Values.frontend.image | default dict).tag | default .Values.image.tag }}"
|
||||
imagePullPolicy: {{ (.Values.frontend.image | default dict).pullPolicy | default .Values.image.pullPolicy }}
|
||||
{{- with .Values.frontend.command }}
|
||||
command:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.frontend.args }}
|
||||
args:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
env:
|
||||
{{- if $envVars}}
|
||||
{{- $envVars | indent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.frontend.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.frontend.service.targetPort }}
|
||||
protocol: TCP
|
||||
{{- if .Values.frontend.probes.liveness }}
|
||||
livenessProbe:
|
||||
{{- include "impress.probes.abstract" (merge .Values.frontend.probes.liveness (dict "targetPort" .Values.frontend.service.targetPort )) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.frontend.probes.readiness }}
|
||||
readinessProbe:
|
||||
{{- include "impress.probes.abstract" (merge .Values.frontend.probes.readiness (dict "targetPort" .Values.frontend.service.targetPort )) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.frontend.probes.startup }}
|
||||
startupProbe:
|
||||
{{- include "impress.probes.abstract" (merge .Values.frontend.probes.startup (dict "targetPort" .Values.frontend.service.targetPort )) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.frontend.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{- range $index, $value := .Values.mountFiles }}
|
||||
- name: "files-{{ $index }}"
|
||||
mountPath: {{ $value.path }}
|
||||
subPath: content
|
||||
{{- end }}
|
||||
{{- range $name, $volume := .Values.frontend.persistence }}
|
||||
- name: "{{ $name }}"
|
||||
mountPath: "{{ $volume.mountPath }}"
|
||||
{{- end }}
|
||||
{{- range .Values.frontend.extraVolumeMounts }}
|
||||
- name: {{ .name }}
|
||||
mountPath: {{ .mountPath }}
|
||||
subPath: {{ .subPath | default "" }}
|
||||
readOnly: {{ .readOnly }}
|
||||
{{- end }}
|
||||
{{- with .Values.frontend.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.frontend.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.frontend.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
{{- range $index, $value := .Values.mountFiles }}
|
||||
- name: "files-{{ $index }}"
|
||||
configMap:
|
||||
name: "{{ include "impress.fullname" $ }}-files-{{ $index }}"
|
||||
{{- end }}
|
||||
{{- range $name, $volume := .Values.frontend.persistence }}
|
||||
- name: "{{ $name }}"
|
||||
{{- if eq $volume.type "emptyDir" }}
|
||||
emptyDir: {}
|
||||
{{- else }}
|
||||
persistentVolumeClaim:
|
||||
claimName: "{{ $fullName }}-{{ $name }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range .Values.frontend.extraVolumes }}
|
||||
- name: {{ .name }}
|
||||
{{- if .existingClaim }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .existingClaim }}
|
||||
{{- else if .hostPath }}
|
||||
hostPath:
|
||||
{{ toYaml .hostPath | nindent 12 }}
|
||||
{{- else if .csi }}
|
||||
csi:
|
||||
{{- toYaml .csi | nindent 12 }}
|
||||
{{- else if .configMap }}
|
||||
configMap:
|
||||
{{- toYaml .configMap | nindent 12 }}
|
||||
{{- else if .emptyDir }}
|
||||
emptyDir:
|
||||
{{- toYaml .emptyDir | nindent 12 }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -1,21 +0,0 @@
|
||||
{{- $envVars := include "impress.common.env" (list . .Values.frontend) -}}
|
||||
{{- $fullName := include "impress.frontend.fullname" . -}}
|
||||
{{- $component := "frontend" -}}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||
annotations:
|
||||
{{- toYaml $.Values.frontend.service.annotations | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.frontend.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.frontend.service.port }}
|
||||
targetPort: {{ .Values.frontend.service.targetPort }}
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 4 }}
|
||||
@@ -1,118 +0,0 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include "impress.fullname" . -}}
|
||||
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
|
||||
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
{{- else -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
{{- end }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{- include "impress.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls.enabled }}
|
||||
tls:
|
||||
{{- if .Values.ingress.host }}
|
||||
- secretName: {{ $fullName }}-tls
|
||||
hosts:
|
||||
- {{ .Values.ingress.host | quote }}
|
||||
{{- end }}
|
||||
{{- range .Values.ingress.tls.additional }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- if .Values.ingress.host }}
|
||||
- host: {{ .Values.ingress.host | quote }}
|
||||
http:
|
||||
paths:
|
||||
- path: {{ .Values.ingress.path | quote }}
|
||||
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
pathType: Prefix
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ include "impress.frontend.fullname" . }}
|
||||
port:
|
||||
number: {{ .Values.frontend.service.port }}
|
||||
{{- else }}
|
||||
serviceName: {{ include "impress.frontend.fullname" . }}
|
||||
servicePort: {{ .Values.frontend.service.port }}
|
||||
{{- end }}
|
||||
- path: /api
|
||||
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
pathType: Prefix
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ include "impress.backend.fullname" . }}
|
||||
port:
|
||||
number: {{ .Values.backend.service.port }}
|
||||
{{- else }}
|
||||
serviceName: {{ include "impress.backend.fullname" . }}
|
||||
servicePort: {{ .Values.backend.service.port }}
|
||||
{{- end }}
|
||||
{{- with .Values.ingress.customBackends }}
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ . | quote }}
|
||||
http:
|
||||
paths:
|
||||
- path: {{ $.Values.ingress.path | quote }}
|
||||
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
pathType: Prefix
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ include "impress.frontend.fullname" $ }}
|
||||
port:
|
||||
number: {{ $.Values.frontend.service.port }}
|
||||
{{- else }}
|
||||
serviceName: {{ include "impress.frontend.fullname" $ }}
|
||||
servicePort: {{ $.Values.frontend.service.port }}
|
||||
{{- end }}
|
||||
- path: /api
|
||||
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
pathType: Prefix
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ include "impress.backend.fullname" $ }}
|
||||
port:
|
||||
number: {{ $.Values.backend.service.port }}
|
||||
{{- else }}
|
||||
serviceName: {{ include "impress.backend.fullname" $ }}
|
||||
servicePort: {{ $.Values.backend.service.port }}
|
||||
{{- end }}
|
||||
{{- with $.Values.ingress.customBackends }}
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
{{- if .Values.ingressAdmin.enabled -}}
|
||||
{{- $fullName := include "impress.fullname" . -}}
|
||||
{{- if and .Values.ingressAdmin.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||
{{- if not (hasKey .Values.ingressAdmin.annotations "kubernetes.io/ingress.class") }}
|
||||
{{- $_ := set .Values.ingressAdmin.annotations "kubernetes.io/ingress.class" .Values.ingressAdmin.className}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
{{- else -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
{{- end }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}-admin
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{- include "impress.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingressAdmin.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if and .Values.ingressAdmin.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||
ingressClassName: {{ .Values.ingressAdmin.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingressAdmin.tls.enabled }}
|
||||
tls:
|
||||
{{- if .Values.ingressAdmin.host }}
|
||||
- secretName: {{ $fullName }}-tls
|
||||
hosts:
|
||||
- {{ .Values.ingressAdmin.host | quote }}
|
||||
{{- end }}
|
||||
{{- range .Values.ingressAdmin.tls.additional }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- if .Values.ingressAdmin.host }}
|
||||
- host: {{ .Values.ingressAdmin.host | quote }}
|
||||
http:
|
||||
paths:
|
||||
- path: {{ .Values.ingressAdmin.path | quote }}
|
||||
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
pathType: Prefix
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ include "impress.backend.fullname" . }}
|
||||
port:
|
||||
number: {{ .Values.backend.service.port }}
|
||||
{{- else }}
|
||||
serviceName: {{ include "impress.backend.fullname" . }}
|
||||
servicePort: {{ .Values.backend.service.port }}
|
||||
{{- end }}
|
||||
- path: /static
|
||||
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
pathType: Prefix
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ include "impress.backend.fullname" . }}
|
||||
port:
|
||||
number: {{ .Values.backend.service.port }}
|
||||
{{- else }}
|
||||
serviceName: {{ include "impress.backend.fullname" . }}
|
||||
servicePort: {{ .Values.backend.service.port }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range .Values.ingressAdmin.hosts }}
|
||||
- host: {{ . | quote }}
|
||||
http:
|
||||
paths:
|
||||
- path: {{ $.Values.ingressAdmin.path | quote }}
|
||||
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
pathType: Prefix
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ include "impress.backend.fullname" $ }}
|
||||
port:
|
||||
number: {{ $.Values.backend.service.port }}
|
||||
{{- else }}
|
||||
serviceName: {{ include "impress.backend.fullname" $ }}
|
||||
servicePort: {{ $.Values.backend.service.port }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
{{- if .Values.ingressMedia.enabled -}}
|
||||
{{- $fullName := include "impress.fullname" . -}}
|
||||
{{- if and .Values.ingressMedia.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||
{{- if not (hasKey .Values.ingressMedia.annotations "kubernetes.io/ingress.class") }}
|
||||
{{- $_ := set .Values.ingressMedia.annotations "kubernetes.io/ingress.class" .Values.ingressMedia.className}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
{{- else -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
{{- end }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}-media
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{- include "impress.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingressMedia.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if and .Values.ingressMedia.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||
ingressClassName: {{ .Values.ingressMedia.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingressMedia.tls.enabled }}
|
||||
tls:
|
||||
{{- if .Values.ingressMedia.host }}
|
||||
- secretName: {{ $fullName }}-tls
|
||||
hosts:
|
||||
- {{ .Values.ingressMedia.host | quote }}
|
||||
{{- end }}
|
||||
{{- range .Values.ingressMedia.tls.additional }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- if .Values.ingressMedia.host }}
|
||||
- host: {{ .Values.ingressMedia.host | quote }}
|
||||
http:
|
||||
paths:
|
||||
- path: {{ .Values.ingressMedia.path | quote }}
|
||||
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
pathType: Prefix
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ $fullName }}-media
|
||||
port:
|
||||
number: {{ .Values.serviceMedia.port }}
|
||||
{{- else }}
|
||||
serviceName: {{ $fullName }}-media
|
||||
servicePort: {{ .Values.serviceMedia.port }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range .Values.ingressMedia.hosts }}
|
||||
- host: {{ . | quote }}
|
||||
http:
|
||||
paths:
|
||||
- path: {{ $.Values.ingressMedia.path | quote }}
|
||||
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
pathType: Prefix
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ $fullName }}-media
|
||||
port:
|
||||
number: {{ .Values.serviceMedia.port }}
|
||||
{{- else }}
|
||||
serviceName: {{ $fullName }}-media
|
||||
servicePort: {{ .Values.serviceMedia.port }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -1,72 +0,0 @@
|
||||
{{- if .Values.ingressWS.enabled -}}
|
||||
{{- $fullName := include "impress.fullname" . -}}
|
||||
{{- if and .Values.ingressWS.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||
{{- if not (hasKey .Values.ingressWS.annotations "kubernetes.io/ingress.class") }}
|
||||
{{- $_ := set .Values.ingressWS.annotations "kubernetes.io/ingress.class" .Values.ingressWS.className}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
{{- else -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
{{- end }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}-ws
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{- include "impress.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingressWS.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if and .Values.ingressWS.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||
ingressClassName: {{ .Values.ingressWS.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingressWS.tls.enabled }}
|
||||
tls:
|
||||
{{- if .Values.ingressWS.host }}
|
||||
- secretName: {{ $fullName }}-tls
|
||||
hosts:
|
||||
- {{ .Values.ingressWS.host | quote }}
|
||||
{{- end }}
|
||||
{{- range .Values.ingressWS.tls.additional }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- if .Values.ingressWS.host }}
|
||||
- host: {{ .Values.ingressWS.host | quote }}
|
||||
http:
|
||||
paths:
|
||||
- path: {{ .Values.ingressWS.path | quote }}
|
||||
{{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
pathType: ImplementationSpecific
|
||||
{{- end }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ include "impress.yProvider.fullname" . }}
|
||||
port:
|
||||
number: {{ .Values.yProvider.service.port }}
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ include "impress.yProvider.fullname" . }}
|
||||
port:
|
||||
number: {{ .Values.yProvider.service.port }}
|
||||
{{- else }}
|
||||
serviceName: {{ include "impress.yProvider.fullname" . }}
|
||||
servicePort: {{ .Values.yProvider.service.port }}
|
||||
{{- end }}
|
||||
{{- with .Values.ingressWS.customBackends }}
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
{{- $fullName := include "impress.fullname" . -}}
|
||||
{{- $component := "media" -}}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ $fullName }}-media
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||
annotations:
|
||||
{{- toYaml $.Values.serviceMedia.annotations | nindent 4 }}
|
||||
spec:
|
||||
type: ExternalName
|
||||
externalName: {{ $.Values.serviceMedia.host }}
|
||||
@@ -1,23 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: backend
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
annotations:
|
||||
"helm.sh/hook": pre-install,pre-upgrade
|
||||
"helm.sh/hook-weight": "-5"
|
||||
"helm.sh/hook-delete-policy": before-hook-creation
|
||||
stringData:
|
||||
DJANGO_SUPERUSER_EMAIL: {{ .Values.djangoSuperUserEmail }}
|
||||
DJANGO_SUPERUSER_PASSWORD: {{ .Values.djangoSuperUserPass }}
|
||||
DJANGO_SECRET_KEY: {{ .Values.djangoSecretKey }}
|
||||
{{- if .Values.djangoEmailHostUser }}
|
||||
DJANGO_EMAIL_HOST_USER: {{ .Values.djangoEmailHostUser }}
|
||||
{{- end }}
|
||||
{{- if .Values.djangoEmailHostPassword }}
|
||||
DJANGO_EMAIL_HOST_PASSWORD: {{ .Values.djangoEmailHostPassword }}
|
||||
{{- end }}
|
||||
OIDC_RP_CLIENT_ID: {{ .Values.oidc.clientId }}
|
||||
OIDC_RP_CLIENT_SECRET: {{ .Values.oidc.clientSecret }}
|
||||
AI_API_KEY: {{ .Values.aiApiKey }}
|
||||
AI_BASE_URL: {{ .Values.aiBaseUrl }}
|
||||
@@ -1,136 +0,0 @@
|
||||
{{- $envVars := include "impress.common.env" (list . .Values.yProvider) -}}
|
||||
{{- $fullName := include "impress.yProvider.fullname" . -}}
|
||||
{{- $component := "yProvider" -}}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.yProvider.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- with .Values.yProvider.podAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 8 }}
|
||||
spec:
|
||||
{{- if $.Values.image.credentials }}
|
||||
imagePullSecrets:
|
||||
- name: {{ include "impress.secret.dockerconfigjson.name" (dict "fullname" (include "impress.fullname" .) "imageCredentials" $.Values.image.credentials) }}
|
||||
{{- end}}
|
||||
shareProcessNamespace: {{ .Values.yProvider.shareProcessNamespace }}
|
||||
containers:
|
||||
{{- with .Values.yProvider.sidecars }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ (.Values.yProvider.image | default dict).repository | default .Values.image.repository }}:{{ (.Values.yProvider.image | default dict).tag | default .Values.image.tag }}"
|
||||
imagePullPolicy: {{ (.Values.yProvider.image | default dict).pullPolicy | default .Values.image.pullPolicy }}
|
||||
{{- with .Values.yProvider.command }}
|
||||
command:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.yProvider.args }}
|
||||
args:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
env:
|
||||
{{- if $envVars}}
|
||||
{{- $envVars | indent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.yProvider.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.yProvider.service.targetPort }}
|
||||
protocol: TCP
|
||||
{{- if .Values.yProvider.probes.liveness }}
|
||||
livenessProbe:
|
||||
{{- include "impress.probes.abstract" (merge .Values.yProvider.probes.liveness (dict "targetPort" .Values.yProvider.service.targetPort )) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.yProvider.probes.readiness }}
|
||||
readinessProbe:
|
||||
{{- include "impress.probes.abstract" (merge .Values.yProvider.probes.readiness (dict "targetPort" .Values.yProvider.service.targetPort )) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.yProvider.probes.startup }}
|
||||
startupProbe:
|
||||
{{- include "impress.probes.abstract" (merge .Values.yProvider.probes.startup (dict "targetPort" .Values.yProvider.service.targetPort )) | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.yProvider.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{- range $index, $value := .Values.mountFiles }}
|
||||
- name: "files-{{ $index }}"
|
||||
mountPath: {{ $value.path }}
|
||||
subPath: content
|
||||
{{- end }}
|
||||
{{- range $name, $volume := .Values.yProvider.persistence }}
|
||||
- name: "{{ $name }}"
|
||||
mountPath: "{{ $volume.mountPath }}"
|
||||
{{- end }}
|
||||
{{- range .Values.yProvider.extraVolumeMounts }}
|
||||
- name: {{ .name }}
|
||||
mountPath: {{ .mountPath }}
|
||||
subPath: {{ .subPath | default "" }}
|
||||
readOnly: {{ .readOnly }}
|
||||
{{- end }}
|
||||
{{- with .Values.yProvider.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.yProvider.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.yProvider.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
{{- range $index, $value := .Values.mountFiles }}
|
||||
- name: "files-{{ $index }}"
|
||||
configMap:
|
||||
name: "{{ include "impress.fullname" $ }}-files-{{ $index }}"
|
||||
{{- end }}
|
||||
{{- range $name, $volume := .Values.yProvider.persistence }}
|
||||
- name: "{{ $name }}"
|
||||
{{- if eq $volume.type "emptyDir" }}
|
||||
emptyDir: {}
|
||||
{{- else }}
|
||||
persistentVolumeClaim:
|
||||
claimName: "{{ $fullName }}-{{ $name }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range .Values.yProvider.extraVolumes }}
|
||||
- name: {{ .name }}
|
||||
{{- if .existingClaim }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .existingClaim }}
|
||||
{{- else if .hostPath }}
|
||||
hostPath:
|
||||
{{ toYaml .hostPath | nindent 12 }}
|
||||
{{- else if .csi }}
|
||||
csi:
|
||||
{{- toYaml .csi | nindent 12 }}
|
||||
{{- else if .configMap }}
|
||||
configMap:
|
||||
{{- toYaml .configMap | nindent 12 }}
|
||||
{{- else if .emptyDir }}
|
||||
emptyDir:
|
||||
{{- toYaml .emptyDir | nindent 12 }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -1,21 +0,0 @@
|
||||
{{- $envVars := include "impress.common.env" (list . .Values.yProvider) -}}
|
||||
{{- $fullName := include "impress.yProvider.fullname" . -}}
|
||||
{{- $component := "yProvider" -}}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
labels:
|
||||
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
|
||||
annotations:
|
||||
{{- toYaml $.Values.yProvider.service.annotations | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.yProvider.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.yProvider.service.port }}
|
||||
targetPort: {{ .Values.yProvider.service.targetPort }}
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
{{- include "impress.common.selectorLabels" (list . $component) | nindent 4 }}
|
||||
@@ -1,415 +0,0 @@
|
||||
# Default values for impress.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
## @section General configuration
|
||||
|
||||
## @param image.repository Repository to use to pull impress's container image
|
||||
## @param image.tag impress's container tag
|
||||
## @param image.pullPolicy Container image pull policy
|
||||
## @extra image.credentials.username Username for container registry authentication
|
||||
## @extra image.credentials.password Password for container registry authentication
|
||||
## @extra image.credentials.registry Registry url for which the credentials are specified
|
||||
## @extra image.credentials.name Name of the generated secret for imagePullSecrets
|
||||
image:
|
||||
repository: lasuite/impress-backend
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "latest"
|
||||
|
||||
## @param nameOverride Override the chart name
|
||||
## @param fullnameOverride Override the full application name
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
## @skip commonEnvVars
|
||||
commonEnvVars: &commonEnvVars
|
||||
<<: []
|
||||
|
||||
## @param ingress.enabled whether to enable the Ingress or not
|
||||
## @param ingress.className IngressClass to use for the Ingress
|
||||
## @param ingress.host Host for the Ingress
|
||||
## @param ingress.path Path to use for the Ingress
|
||||
ingress:
|
||||
enabled: false
|
||||
className: null
|
||||
host: impress.example.com
|
||||
path: /
|
||||
## @param ingress.hosts Additional host to configure for the Ingress
|
||||
hosts: []
|
||||
# - chart-example.local
|
||||
## @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
|
||||
additional: []
|
||||
|
||||
## @param ingress.customBackends Add custom backends to ingress
|
||||
customBackends: []
|
||||
|
||||
## @param ingressWS.enabled whether to enable the Ingress or not
|
||||
## @param ingressWS.className IngressClass to use for the Ingress
|
||||
## @param ingressWS.host Host for the Ingress
|
||||
## @param ingressWS.path Path to use for the Ingress
|
||||
ingressWS:
|
||||
enabled: false
|
||||
className: null
|
||||
host: impress.example.com
|
||||
path: /ws
|
||||
## @param ingress.hosts Additional host to configure for the Ingress
|
||||
hosts: []
|
||||
# - chart-example.local
|
||||
## @param ingressWS.tls.enabled Wether to enable TLS for the Ingress
|
||||
## @skip ingressWS.tls.additional
|
||||
## @extra ingressWS.tls.additional[].secretName Secret name for additional TLS config
|
||||
## @extra ingressWS.tls.additional[].hosts[] Hosts for additional TLS config
|
||||
tls:
|
||||
enabled: true
|
||||
additional: []
|
||||
|
||||
## @param ingressWS.customBackends Add custom backends to ingress
|
||||
customBackends: []
|
||||
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/enable-websocket: "true"
|
||||
nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"
|
||||
|
||||
## @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
|
||||
## @param ingressAdmin.path Path to use for the Ingress
|
||||
ingressAdmin:
|
||||
enabled: false
|
||||
className: null
|
||||
host: impress.example.com
|
||||
path: /admin
|
||||
## @param ingressAdmin.hosts Additional host to configure for the Ingress
|
||||
hosts: [ ]
|
||||
# - chart-example.local
|
||||
## @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
|
||||
additional: []
|
||||
|
||||
## @param ingressMedia.enabled whether to enable the Ingress or not
|
||||
## @param ingressMedia.className IngressClass to use for the Ingress
|
||||
## @param ingressMedia.host Host for the Ingress
|
||||
## @param ingressMedia.path Path to use for the Ingress
|
||||
ingressMedia:
|
||||
enabled: false
|
||||
className: null
|
||||
host: impress.example.com
|
||||
path: /media/(.*)
|
||||
## @param ingressMedia.hosts Additional host to configure for the Ingress
|
||||
hosts: [ ]
|
||||
# - chart-example.local
|
||||
## @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
|
||||
additional: []
|
||||
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/auth-url: https://impress.example.com/api/v1.0/documents/retrieve-auth/
|
||||
nginx.ingress.kubernetes.io/auth-response-headers: "Authorization, X-Amz-Date, X-Amz-Content-SHA256"
|
||||
nginx.ingress.kubernetes.io/upstream-vhost: minio.impress.svc.cluster.local:9000
|
||||
|
||||
serviceMedia:
|
||||
host: minio.impress.svc.cluster.local
|
||||
port: 9000
|
||||
annotations: {}
|
||||
|
||||
|
||||
## @section backend
|
||||
|
||||
backend:
|
||||
|
||||
## @param backend.command Override the backend container command
|
||||
command: []
|
||||
|
||||
## @param backend.args Override the backend container args
|
||||
args: []
|
||||
|
||||
## @param backend.replicas Amount of backend replicas
|
||||
replicas: 3
|
||||
|
||||
## @param backend.shareProcessNamespace Enable share process namespace between containers
|
||||
shareProcessNamespace: false
|
||||
|
||||
## @param backend.sidecars Add sidecars containers to backend deployment
|
||||
sidecars: []
|
||||
|
||||
## @param backend.migrateJobAnnotations Annotations for the migrate job
|
||||
migrateJobAnnotations: {}
|
||||
|
||||
## @param backend.securityContext Configure backend Pod security context
|
||||
securityContext: null
|
||||
|
||||
## @param backend.envVars Configure backend container environment variables
|
||||
## @extra backend.envVars.BY_VALUE Example environment variable by setting value directly
|
||||
## @extra backend.envVars.FROM_CONFIGMAP.configMapKeyRef.name Name of a ConfigMap when configuring env vars from a ConfigMap
|
||||
## @extra backend.envVars.FROM_CONFIGMAP.configMapKeyRef.key Key within a ConfigMap when configuring env vars from a ConfigMap
|
||||
## @extra backend.envVars.FROM_SECRET.secretKeyRef.name Name of a Secret when configuring env vars from a Secret
|
||||
## @extra backend.envVars.FROM_SECRET.secretKeyRef.key Key within a Secret when configuring env vars from a Secret
|
||||
## @skip backend.envVars
|
||||
envVars:
|
||||
<<: *commonEnvVars
|
||||
|
||||
## @param backend.podAnnotations Annotations to add to the backend Pod
|
||||
podAnnotations: {}
|
||||
|
||||
## @param backend.service.type backend Service type
|
||||
## @param backend.service.port backend Service listening port
|
||||
## @param backend.service.targetPort backend container listening port
|
||||
## @param backend.service.annotations Annotations to add to the backend Service
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
targetPort: 8000
|
||||
annotations: {}
|
||||
|
||||
## @param backend.migrate.command backend migrate command
|
||||
## @param backend.migrate.restartPolicy backend migrate job restart policy
|
||||
migrate:
|
||||
command:
|
||||
- "python"
|
||||
- "manage.py"
|
||||
- "migrate"
|
||||
- "--no-input"
|
||||
restartPolicy: Never
|
||||
|
||||
## @param backend.probes.liveness.path [nullable] Configure path for backend HTTP liveness probe
|
||||
## @param backend.probes.liveness.targetPort [nullable] Configure port for backend HTTP liveness probe
|
||||
## @param backend.probes.liveness.initialDelaySeconds [nullable] Configure initial delay for backend liveness probe
|
||||
## @param backend.probes.liveness.initialDelaySeconds [nullable] Configure timeout for backend liveness probe
|
||||
## @param backend.probes.startup.path [nullable] Configure path for backend HTTP startup probe
|
||||
## @param backend.probes.startup.targetPort [nullable] Configure port for backend HTTP startup probe
|
||||
## @param backend.probes.startup.initialDelaySeconds [nullable] Configure initial delay for backend startup probe
|
||||
## @param backend.probes.startup.initialDelaySeconds [nullable] Configure timeout for backend startup probe
|
||||
## @param backend.probes.readiness.path [nullable] Configure path for backend HTTP readiness probe
|
||||
## @param backend.probes.readiness.targetPort [nullable] Configure port for backend HTTP readiness probe
|
||||
## @param backend.probes.readiness.initialDelaySeconds [nullable] Configure initial delay for backend readiness probe
|
||||
## @param backend.probes.readiness.initialDelaySeconds [nullable] Configure timeout for backend readiness probe
|
||||
probes:
|
||||
liveness:
|
||||
path: /__heartbeat__
|
||||
initialDelaySeconds: 10
|
||||
readiness:
|
||||
path: /__lbheartbeat__
|
||||
initialDelaySeconds: 10
|
||||
|
||||
## @param backend.resources Resource requirements for the backend container
|
||||
resources: {}
|
||||
|
||||
## @param backend.nodeSelector Node selector for the backend Pod
|
||||
nodeSelector: {}
|
||||
|
||||
## @param backend.tolerations Tolerations for the backend Pod
|
||||
tolerations: []
|
||||
|
||||
## @param backend.affinity Affinity for the backend Pod
|
||||
affinity: {}
|
||||
|
||||
## @param backend.persistence Additional volumes to create and mount on the backend. Used for debugging purposes
|
||||
## @extra backend.persistence.volume-name.size Size of the additional volume
|
||||
## @extra backend.persistence.volume-name.type Type of the additional volume, persistentVolumeClaim or emptyDir
|
||||
## @extra backend.persistence.volume-name.mountPath Path where the volume should be mounted to
|
||||
persistence: {}
|
||||
|
||||
## @param backend.extraVolumeMounts Additional volumes to mount on the backend.
|
||||
extraVolumeMounts: []
|
||||
|
||||
## @param backend.extraVolumes Additional volumes to mount on the backend.
|
||||
extraVolumes: []
|
||||
|
||||
|
||||
## @section frontend
|
||||
|
||||
frontend:
|
||||
## @param frontend.image.repository Repository to use to pull impress's frontend container image
|
||||
## @param frontend.image.tag impress's frontend container tag
|
||||
## @param frontend.image.pullPolicy frontend container image pull policy
|
||||
image:
|
||||
repository: lasuite/impress-frontend
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "latest"
|
||||
|
||||
## @param frontend.command Override the frontend container command
|
||||
command: []
|
||||
|
||||
## @param frontend.args Override the frontend container args
|
||||
args: []
|
||||
|
||||
## @param frontend.replicas Amount of frontend replicas
|
||||
replicas: 3
|
||||
|
||||
## @param frontend.shareProcessNamespace Enable share process namefrontend between containers
|
||||
shareProcessNamespace: false
|
||||
|
||||
## @param frontend.sidecars Add sidecars containers to frontend deployment
|
||||
sidecars: []
|
||||
|
||||
## @param frontend.securityContext Configure frontend Pod security context
|
||||
securityContext: null
|
||||
|
||||
## @param frontend.envVars Configure frontend container environment variables
|
||||
## @extra frontend.envVars.BY_VALUE Example environment variable by setting value directly
|
||||
## @extra frontend.envVars.FROM_CONFIGMAP.configMapKeyRef.name Name of a ConfigMap when configuring env vars from a ConfigMap
|
||||
## @extra frontend.envVars.FROM_CONFIGMAP.configMapKeyRef.key Key within a ConfigMap when configuring env vars from a ConfigMap
|
||||
## @extra frontend.envVars.FROM_SECRET.secretKeyRef.name Name of a Secret when configuring env vars from a Secret
|
||||
## @extra frontend.envVars.FROM_SECRET.secretKeyRef.key Key within a Secret when configuring env vars from a Secret
|
||||
## @skip frontend.envVars
|
||||
envVars:
|
||||
<<: *commonEnvVars
|
||||
|
||||
## @param frontend.podAnnotations Annotations to add to the frontend Pod
|
||||
podAnnotations: {}
|
||||
|
||||
## @param frontend.service.type frontend Service type
|
||||
## @param frontend.service.port frontend Service listening port
|
||||
## @param frontend.service.targetPort frontend container listening port
|
||||
## @param frontend.service.annotations Annotations to add to the frontend Service
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
annotations: {}
|
||||
|
||||
## @param frontend.probes Configure probe for frontend
|
||||
## @extra frontend.probes.liveness.path Configure path for frontend HTTP liveness probe
|
||||
## @extra frontend.probes.liveness.targetPort Configure port for frontend HTTP liveness probe
|
||||
## @extra frontend.probes.liveness.initialDelaySeconds Configure initial delay for frontend liveness probe
|
||||
## @extra frontend.probes.liveness.initialDelaySeconds Configure timeout for frontend liveness probe
|
||||
## @extra frontend.probes.startup.path Configure path for frontend HTTP startup probe
|
||||
## @extra frontend.probes.startup.targetPort Configure port for frontend HTTP startup probe
|
||||
## @extra frontend.probes.startup.initialDelaySeconds Configure initial delay for frontend startup probe
|
||||
## @extra frontend.probes.startup.initialDelaySeconds Configure timeout for frontend startup probe
|
||||
## @extra frontend.probes.readiness.path Configure path for frontend HTTP readiness probe
|
||||
## @extra frontend.probes.readiness.targetPort Configure port for frontend HTTP readiness probe
|
||||
## @extra frontend.probes.readiness.initialDelaySeconds Configure initial delay for frontend readiness probe
|
||||
## @extra frontend.probes.readiness.initialDelaySeconds Configure timeout for frontend readiness probe
|
||||
probes: {}
|
||||
|
||||
## @param frontend.resources Resource requirements for the frontend container
|
||||
resources: {}
|
||||
|
||||
## @param frontend.nodeSelector Node selector for the frontend Pod
|
||||
nodeSelector: {}
|
||||
|
||||
## @param frontend.tolerations Tolerations for the frontend Pod
|
||||
tolerations: []
|
||||
|
||||
## @param frontend.affinity Affinity for the frontend Pod
|
||||
affinity: {}
|
||||
|
||||
## @param frontend.persistence Additional volumes to create and mount on the frontend. Used for debugging purposes
|
||||
## @extra frontend.persistence.volume-name.size Size of the additional volume
|
||||
## @extra frontend.persistence.volume-name.type Type of the additional volume, persistentVolumeClaim or emptyDir
|
||||
## @extra frontend.persistence.volume-name.mountPath Path where the volume should be mounted to
|
||||
persistence: {}
|
||||
|
||||
## @param frontend.extraVolumeMounts Additional volumes to mount on the frontend.
|
||||
extraVolumeMounts: []
|
||||
|
||||
## @param frontend.extraVolumes Additional volumes to mount on the frontend.
|
||||
extraVolumes: []
|
||||
|
||||
## @section yProvider
|
||||
|
||||
yProvider:
|
||||
## @param yProvider.image.repository Repository to use to pull impress's yProvider container image
|
||||
## @param yProvider.image.tag impress's yProvider container tag
|
||||
## @param yProvider.image.pullPolicy yProvider container image pull policy
|
||||
image:
|
||||
repository: lasuite/impress-y-provider
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "latest"
|
||||
|
||||
## @param yProvider.command Override the yProvider container command
|
||||
command: []
|
||||
|
||||
## @param yProvider.args Override the yProvider container args
|
||||
args: []
|
||||
|
||||
## @param yProvider.replicas Amount of yProvider replicas
|
||||
replicas: 3
|
||||
|
||||
## @param yProvider.shareProcessNamespace Enable share process nameyProvider between containers
|
||||
shareProcessNamespace: false
|
||||
|
||||
## @param yProvider.sidecars Add sidecars containers to yProvider deployment
|
||||
sidecars: []
|
||||
|
||||
## @param yProvider.securityContext Configure yProvider Pod security context
|
||||
securityContext: null
|
||||
|
||||
## @param yProvider.envVars Configure yProvider container environment variables
|
||||
## @extra yProvider.envVars.BY_VALUE Example environment variable by setting value directly
|
||||
## @extra yProvider.envVars.FROM_CONFIGMAP.configMapKeyRef.name Name of a ConfigMap when configuring env vars from a ConfigMap
|
||||
## @extra yProvider.envVars.FROM_CONFIGMAP.configMapKeyRef.key Key within a ConfigMap when configuring env vars from a ConfigMap
|
||||
## @extra yProvider.envVars.FROM_SECRET.secretKeyRef.name Name of a Secret when configuring env vars from a Secret
|
||||
## @extra yProvider.envVars.FROM_SECRET.secretKeyRef.key Key within a Secret when configuring env vars from a Secret
|
||||
## @skip yProvider.envVars
|
||||
envVars:
|
||||
<<: *commonEnvVars
|
||||
|
||||
## @param yProvider.podAnnotations Annotations to add to the yProvider Pod
|
||||
podAnnotations: {}
|
||||
|
||||
## @param yProvider.service.type yProvider Service type
|
||||
## @param yProvider.service.port yProvider Service listening port
|
||||
## @param yProvider.service.targetPort yProvider container listening port
|
||||
## @param yProvider.service.annotations Annotations to add to the yProvider Service
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 443
|
||||
targetPort: 4444
|
||||
annotations: {}
|
||||
|
||||
## @param yProvider.probes Configure probe for yProvider
|
||||
## @extra yProvider.probes.liveness.path Configure path for yProvider HTTP liveness probe
|
||||
## @extra yProvider.probes.liveness.targetPort Configure port for yProvider HTTP liveness probe
|
||||
## @extra yProvider.probes.liveness.initialDelaySeconds Configure initial delay for yProvider liveness probe
|
||||
## @extra yProvider.probes.liveness.initialDelaySeconds Configure timeout for yProvider liveness probe
|
||||
## @extra yProvider.probes.startup.path Configure path for yProvider HTTP startup probe
|
||||
## @extra yProvider.probes.startup.targetPort Configure port for yProvider HTTP startup probe
|
||||
## @extra yProvider.probes.startup.initialDelaySeconds Configure initial delay for yProvider startup probe
|
||||
## @extra yProvider.probes.startup.initialDelaySeconds Configure timeout for yProvider startup probe
|
||||
## @extra yProvider.probes.readiness.path Configure path for yProvider HTTP readiness probe
|
||||
## @extra yProvider.probes.readiness.targetPort Configure port for yProvider HTTP readiness probe
|
||||
## @extra yProvider.probes.readiness.initialDelaySeconds Configure initial delay for yProvider readiness probe
|
||||
## @extra yProvider.probes.readiness.initialDelaySeconds Configure timeout for yProvider readiness probe
|
||||
probes:
|
||||
liveness:
|
||||
path: /ping
|
||||
initialDelaySeconds: 10
|
||||
|
||||
## @param yProvider.resources Resource requirements for the yProvider container
|
||||
resources: {}
|
||||
|
||||
## @param yProvider.nodeSelector Node selector for the yProvider Pod
|
||||
nodeSelector: {}
|
||||
|
||||
## @param yProvider.tolerations Tolerations for the yProvider Pod
|
||||
tolerations: []
|
||||
|
||||
## @param yProvider.affinity Affinity for the yProvider Pod
|
||||
affinity: {}
|
||||
|
||||
## @param yProvider.persistence Additional volumes to create and mount on the yProvider. Used for debugging purposes
|
||||
## @extra yProvider.persistence.volume-name.size Size of the additional volume
|
||||
## @extra yProvider.persistence.volume-name.type Type of the additional volume, persistentVolumeClaim or emptyDir
|
||||
## @extra yProvider.persistence.volume-name.mountPath Path where the volume should be mounted to
|
||||
persistence: {}
|
||||
|
||||
## @param yProvider.extraVolumeMounts Additional volumes to mount on the yProvider.
|
||||
extraVolumeMounts: []
|
||||
|
||||
## @param yProvider.extraVolumes Additional volumes to mount on the yProvider.
|
||||
extraVolumes: []
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mail_mjml",
|
||||
"version": "1.6.0",
|
||||
"version": "1.7.0",
|
||||
"description": "An util to generate html and text django's templates from mjml templates",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
|
||||
Reference in New Issue
Block a user