Skip to content
Open
10 changes: 10 additions & 0 deletions backend/iam/sso/saml/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@
views.FinishACSView.as_view(),
name="saml_finish_acs",
),
path(
"generate-keys/",
views.GenerateSAMLKeyView.as_view(),
name="generate_saml_keys",
),
path(
"download-cert/",
views.DownloadSAMLPublicCertView.as_view(),
name="download_saml_cert",
),
]
),
)
Expand Down
116 changes: 108 additions & 8 deletions backend/iam/sso/saml/views.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
from allauth.account.models import EmailAddress
# === Python standard library ===
import json
from datetime import datetime, timedelta
from django.http import HttpRequest, HttpResponseRedirect, HttpResponse
from django.http.response import Http404
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.views import View

# === Third-party packages ===
import structlog
from rest_framework.views import APIView
from django.views.decorators.csrf import csrf_exempt
from rest_framework.response import Response
from rest_framework import status

from cryptography import x509
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import NameOID

from allauth.account.models import EmailAddress
from allauth.core.exceptions import SignupClosedException
from allauth.socialaccount.adapter import get_account_adapter
from allauth.socialaccount.internal.flows.login import (
pre_social_login,
record_authentication,
)
from allauth.socialaccount.models import PermissionDenied, SocialLogin
from allauth.socialaccount.providers.saml.provider import SAMLProvider
from allauth.socialaccount.providers.saml.views import (
AuthProcess,
LoginSession,
Expand All @@ -18,19 +39,15 @@
httpkit,
render_authentication_error,
)
from allauth.socialaccount.providers.saml.provider import SAMLProvider
from allauth.utils import ValidationError
from django.http import HttpRequest, HttpResponseRedirect
from django.http.response import Http404
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.views import View
from rest_framework.views import csrf_exempt

# === Application-specific imports ===
from core.permissions import IsAdministrator # ou une permission plus adaptée
from iam.models import User
from iam.sso.errors import AuthError
from iam.sso.models import SSOSettings
from iam.utils import generate_token
from global_settings.models import GlobalSettings

DEFAULT_SAML_ATTRIBUTE_MAPPING_EMAIL = SAMLProvider.default_attribute_mapping["email"]

Expand Down Expand Up @@ -192,3 +209,86 @@ def dispatch(self, request, organization_slug):
email_object.save()
logger.info("Email verified", user=user)
return HttpResponseRedirect(next_url)


class GenerateSAMLKeyView(SAMLViewMixin, APIView):
"""
Endpoint to generate a key pair (private key + self-signed X.509 certificate).
Accessible only to admins (to be adapted as needed).
"""

permission_classes = [IsAdministrator]

def post(self, request, organization_slug):
try:
data = json.loads(request.body)
except json.JSONDecodeError:
data = {}
cn = data.get("common_name", "saml-sp.example.com")
days = int(data.get("days", 365))

# RSA key generation
key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)

# Self-signed certificate generation
subject = issuer = x509.Name(
[
x509.NameAttribute(NameOID.COMMON_NAME, cn),
]
)
cert = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(issuer)
.public_key(key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.utcnow())
.not_valid_after(datetime.utcnow() + timedelta(days=days))
.sign(private_key=key, algorithm=hashes.SHA256())
)

private_key_pem = key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption(),
)

cert_pem = cert.public_bytes(serialization.Encoding.PEM)

provider = self.get_provider(organization_slug)
# Retrieves the 'advanced' dictionary, or creates it if it doesn't exist
advanced_settings = provider.app.settings.get("advanced", {})
advanced_settings["private_key"] = private_key_pem.decode("utf-8")
advanced_settings["x509cert"] = cert_pem.decode("utf-8")

# Re-injects the dict into the application configuration
settings = GlobalSettings.objects.get(name=GlobalSettings.Names.SSO)
settings.value["settings"]["advanced"] = advanced_settings
settings.save()

return Response(
{
"message": f"Key and certificate saved in advanced settings of SP {organization_slug}",
"cert": cert_pem.decode("utf-8"),
},
status=status.HTTP_201_CREATED,
)


class DownloadSAMLPublicCertView(SAMLViewMixin, APIView):
permission_classes = [IsAdministrator]

def get(self, request, organization_slug):
provider = self.get_provider(organization_slug)
cert_pem = provider.app.settings.get("advanced", {}).get("x509cert")
if not cert_pem:
return HttpResponse(status=404)

response = HttpResponse(cert_pem, content_type="application/x-pem-file")
response["Content-Disposition"] = (
'attachment; filename="ciso-saml-public-cert.pem"'
)
return response
37 changes: 36 additions & 1 deletion backend/iam/sso/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,20 @@ class SSOSettingsWriteSerializer(BaseModelSerializer):
required=False,
source="settings.advanced.want_name_id_encrypted",
)
sp_x509cert = serializers.CharField(
required=False,
allow_blank=True,
allow_null=True,
source="settings.advanced.x509cert",
)
sp_private_key = serializers.CharField(
required=False,
allow_blank=True,
allow_null=True,
trim_whitespace=False,
source="settings.advanced.private_key",
write_only=True,
)
oidc_has_secret = serializers.SerializerMethodField()

def get_oidc_has_secret(self, obj) -> bool:
Expand All @@ -224,13 +238,34 @@ class Meta:
model = SSOSettings
exclude = ["value"]

def to_representation(self, instance):
data = super().to_representation(instance)

# remove nested private_key if present
advanced = data.get("settings", {}).get("advanced", {})
if "private_key" in advanced:
advanced.pop("private_key")

return data

def update(self, instance, validated_data):
settings_object = GlobalSettings.objects.get(name=GlobalSettings.Names.SSO)

# Use stored secret if no secret is transmitted
# Use stored secret and sp_private_key if no transmitted
validated_data["secret"] = validated_data.get(
"secret", settings_object.value.get("secret", "")
)
validated_data["settings"]["advanced"]["private_key"] = (
validated_data.get("settings", {})
.get("advanced", {})
.get(
"private_key",
settings_object.value.get("settings", {})
.get("advanced", {})
.get("private_key", ""),
)
)

validated_data["provider_id"] = validated_data.get("provider", "n/a")
if "settings" not in validated_data:
validated_data["settings"] = {}
Expand Down
4 changes: 2 additions & 2 deletions backend/iam/sso/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ def post(self, request, *args, **kwargs):
next_url=next_url,
headless=True,
)
except:
logger.error("Cannot perform redirection, Check your IdP URLs")
except Exception as e:
logger.error("SSO redirection failed", provider=provider.id, error=str(e))
return render_authentication_error(request, provider, error="failedSSO")


Expand Down
9 changes: 8 additions & 1 deletion frontend/messages/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -938,5 +938,12 @@
"securityObjectiveScale": "مقياس خصائص الأمان",
"securityObjectiveScaleHelpText": "اختر مقياسك لخصائص الأمان (1 إلى 4 بشكل افتراضي)",
"actor": "فاعل",
"action": "إجراء"
"action": "إجراء",
"privateKey": "المفتاح الخاص",
"generateDots": "إنشاء...",
"samlKeysGenerated": "تم إنشاء مفاتيح SAML بنجاح",
"samlPrivateKeyHelpText": "كتابة فقط: استخدم هذا الحقل فقط إذا كنت بحاجة إلى تقديم مفتاح/شهادة خاص بك. خلاف ذلك، سيقوم التطبيق بإنشائه.",
"samlCertificateHelpText": "يمكنك تحديد شهادتك الخاصة أو السماح للتطبيق بإنشائها.",
"samlAuthnRequestSignedHelpText": "عند التمكين، يتم توقيع طلب المصادقة SAML بالمفتاح الخاص أدناه. يتم إرسال الشهادة العامة المقابلة إلى موفر الهوية حتى يتمكن من التحقق من التوقيع.",
Comment on lines +945 to +947
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix incorrect translation of “write-protected”.

كتابة فقط means “write-only”, which inverts the intent of the English string (“Read-only / write-protected”). This will mislead admins configuring SAML. Please update it to convey “للقراءة فقط” (or equivalent) before shipping.

-"samlPrivateKeyHelpText": "كتابة فقط: استخدم هذا الحقل فقط إذا كنت بحاجة إلى تقديم مفتاح/شهادة خاص بك. خلاف ذلك، سيقوم التطبيق بإنشائه.",
+"samlPrivateKeyHelpText": "للقراءة فقط: استخدم هذا الحقل فقط إذا كنت بحاجة إلى تقديم مفتاح/شهادة خاص بك. خلاف ذلك، سيقوم التطبيق بإنشائه.",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"samlPrivateKeyHelpText": "كتابة فقط: استخدم هذا الحقل فقط إذا كنت بحاجة إلى تقديم مفتاح/شهادة خاص بك. خلاف ذلك، سيقوم التطبيق بإنشائه.",
"samlCertificateHelpText": "يمكنك تحديد شهادتك الخاصة أو السماح للتطبيق بإنشائها.",
"samlAuthnRequestSignedHelpText": "عند التمكين، يتم توقيع طلب المصادقة SAML بالمفتاح الخاص أدناه. يتم إرسال الشهادة العامة المقابلة إلى موفر الهوية حتى يتمكن من التحقق من التوقيع.",
"samlPrivateKeyHelpText": "للقراءة فقط: استخدم هذا الحقل فقط إذا كنت بحاجة إلى تقديم مفتاح/شهادة خاص بك. خلاف ذلك، سيقوم التطبيق بإنشائه.",
"samlCertificateHelpText": "يمكنك تحديد شهادتك الخاصة أو السماح للتطبيق بإنشائها.",
"samlAuthnRequestSignedHelpText": "عند التمكين، يتم توقيع طلب المصادقة SAML بالمفتاح الخاص أدناه. يتم إرسال الشهادة العامة المقابلة إلى موفر الهوية حتى يتمكن من التحقق من التوقيع.",
🤖 Prompt for AI Agents
In frontend/messages/ar.json around lines 945 to 947, the Arabic string "كتابة
فقط" is incorrect (means "write-only") while the English intends "read-only /
write-protected"; update that value to "للقراءة فقط" (or an equivalent phrase
like "للقراءة فقط — محمي من الكتابة") so the message correctly conveys
read-only/write-protected intent, preserving the rest of the sentence and
punctuation.

"downloadCertificate": "تنزيل الشهادة"
}
9 changes: 8 additions & 1 deletion frontend/messages/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -958,5 +958,12 @@
"securityObjectiveScale": "Měřítko bezpečnostních vlastností",
"securityObjectiveScaleHelpText": "Vyberte měřítko pro bezpečnostní vlastnosti (1 až 4 výchozí)",
"actor": "Aktér",
"action": "Akce"
"action": "Akce",
"privateKey": "Soukromý klíč",
"generateDots": "Generování...",
"samlKeysGenerated": "SAML klíče úspěšně vygenerovány",
"samlPrivateKeyHelpText": "Pouze pro zápis: použijte toto pole pouze v případě, že potřebujete zadat vlastní soukromý klíč/certifikát. Jinak aplikace vygeneruje klíč.",
"samlCertificateHelpText": "Můžete zadat vlastní certifikát nebo nechat aplikaci vygenerovat klíč.",
"samlAuthnRequestSignedHelpText": "Pokud je povoleno, požadavek na ověření SAML je podepsán soukromým klíčem níže. Odpovídající veřejný certifikát je odeslán poskytovateli identity, aby mohl ověřit podpis.",
"downloadCertificate": "Stáhnout certifikát"
}
9 changes: 8 additions & 1 deletion frontend/messages/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -1250,5 +1250,12 @@
"securityObjectiveScale": "Skala for sikkerhedsegenskaber",
"securityObjectiveScaleHelpText": "Vælg skala for sikkerhedsegenskaber (1 til 4 som standard)",
"actor": "Aktør",
"action": "Handling"
"action": "Handling",
"privateKey": "Privat nøgle",
"generateDots": "Genererer...",
"samlKeysGenerated": "SAML-nøgler genereret med succes",
"samlPrivateKeyHelpText": "Skrivebeskyttet: brug kun dette felt, hvis du skal angive din egen private nøgle/certifikat. Ellers vil applikationen generere det.",
"samlCertificateHelpText": "Du kan angive dit eget certifikat eller lade applikationen generere det.",
"samlAuthnRequestSignedHelpText": "Når aktiveret, bliver SAML-autentificeringsanmodningen underskrevet med den private nøgle nedenfor. Det tilsvarende offentlige certifikat sendes til Identity Provider, så det kan verificere underskriften.",
"downloadCertificate": "Download certifikat"
}
9 changes: 8 additions & 1 deletion frontend/messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -975,5 +975,12 @@
"securityObjectiveScale": "Skala für Sicherheitsmerkmale",
"securityObjectiveScaleHelpText": "Wählen Sie Ihre Skala für Sicherheitsmerkmale (Standardmäßig 1 bis 4)",
"actor": "Akteur",
"action": "Aktion"
"action": "Aktion",
"privateKey": "Privater Schlüssel",
"generateDots": "Generiere...",
"samlKeysGenerated": "SAML-Schlüssel erfolgreich generiert",
"samlPrivateKeyHelpText": "Schreibgeschützt: Verwenden Sie dieses Feld nur, wenn Sie Ihren eigenen privaten Schlüssel/Zertifikat angeben müssen. Andernfalls generiert die Anwendung ihn.",
"samlCertificateHelpText": "Sie können Ihr eigenes Zertifikat angeben oder die Anwendung generieren lassen.",
"samlAuthnRequestSignedHelpText": "Wenn aktiviert, wird die SAML-Authentifizierungsanfrage mit dem privaten Schlüssel unten signiert. Das zugehörige öffentliche Zertifikat wird an den Identitätsanbieter gesendet, damit er die Signatur überprüfen kann.",
"downloadCertificate": "Zertifikat herunterladen"
}
9 changes: 8 additions & 1 deletion frontend/messages/el.json
Original file line number Diff line number Diff line change
Expand Up @@ -1667,5 +1667,12 @@
"image": "Εικόνα",
"securityObjectives": "Ασφαλή ιδιότητες",
"securityObjectiveScale": "Κλίμακα ασφαλών ιδιοτήτων",
"securityObjectiveScaleHelpText": "Επιλέξτε την κλίμακα σας για τις ασφαλείς ιδιότητες (1 έως 4 από προεπιλογή)"
"securityObjectiveScaleHelpText": "Επιλέξτε την κλίμακα σας για τις ασφαλείς ιδιότητες (1 έως 4 από προεπιλογή)",
"privateKey": "Κλειδί ιδιωτικό",
"generateDots": "Δημιουργία...",
"samlKeysGenerated": "Τα κλειδιά SAML δημιουργήθηκαν επιτυχώς",
"samlPrivateKeyHelpText": "Write-only: χρησιμοποιήστε αυτό το πεδίο μόνο αν χρειάζεται να παρέχετε δικό σας κλειδί ιδιωτικό/πιστοποιητικό. Διαφορετικά, η εφαρμογή θα το δημιουργήσει αυτόματα.",
"samlCertificateHelpText": "Μπορείτε να καθορίσετε δικό σας πιστοποιητικό ή να αφήσετε την εφαρμογή να το δημιουργήσει αυτόματα.",
Comment on lines +1671 to +1675
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix Greek phrasing for private key strings

Η τρέχουσα μετάφραση αντιστρέφει το ουσιαστικό/επίθετο και αφήνει το “Write-only” στα αγγλικά, κάτι που φαίνεται πρόχειρο στο UI. Παρακαλώ προσαρμόστε την ορολογία ώστε να είναι φυσική στα ελληνικά.

-	"privateKey": "Κλειδί ιδιωτικό",
+	"privateKey": "Ιδιωτικό κλειδί",
@@
-	"samlPrivateKeyHelpText": "Write-only: χρησιμοποιήστε αυτό το πεδίο μόνο αν χρειάζεται να παρέχετε δικό σας κλειδί ιδιωτικό/πιστοποιητικό. Διαφορετικά, η εφαρμογή θα το δημιουργήσει αυτόματα.",
+	"samlPrivateKeyHelpText": "Μόνο για εγγραφή (write-only): χρησιμοποιήστε αυτό το πεδίο μόνο αν χρειάζεται να παρέχετε δικό σας ιδιωτικό κλειδί/πιστοποιητικό. Διαφορετικά, η εφαρμογή θα το δημιουργήσει αυτόματα.",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"privateKey": "Κλειδί ιδιωτικό",
"generateDots": "Δημιουργία...",
"samlKeysGenerated": "Τα κλειδιά SAML δημιουργήθηκαν επιτυχώς",
"samlPrivateKeyHelpText": "Write-only: χρησιμοποιήστε αυτό το πεδίο μόνο αν χρειάζεται να παρέχετε δικό σας κλειδί ιδιωτικό/πιστοποιητικό. Διαφορετικά, η εφαρμογή θα το δημιουργήσει αυτόματα.",
"samlCertificateHelpText": "Μπορείτε να καθορίσετε δικό σας πιστοποιητικό ή να αφήσετε την εφαρμογή να το δημιουργήσει αυτόματα.",
"privateKey": "Ιδιωτικό κλειδί",
"generateDots": "Δημιουργία...",
"samlKeysGenerated": "Τα κλειδιά SAML δημιουργήθηκαν επιτυχώς",
"samlPrivateKeyHelpText": "Μόνο για εγγραφή (write-only): χρησιμοποιήστε αυτό το πεδίο μόνο αν χρειάζεται να παρέχετε δικό σας ιδιωτικό κλειδί/πιστοποιητικό. Διαφορετικά, η εφαρμογή θα το δημιουργήσει αυτόματα.",
"samlCertificateHelpText": "Μπορείτε να καθορίσετε δικό σας πιστοποιητικό ή να αφήσετε την εφαρμογή να το δημιουργήσει αυτόματα.",
🤖 Prompt for AI Agents
In frontend/messages/el.json around lines 1671 to 1675, the Greek phrasing flips
noun/adjective order and leaves "Write-only" in English; update the strings to
natural Greek by placing adjectives after nouns and translating "Write-only"
(e.g., "Μόνο εγγραφή" or better "Μόνο για εγγραφή/εγγραφή μόνο") and rephrase
the help texts to sound fluent — for example change "Κλειδί ιδιωτικό" to
"Ιδιωτικό κλειδί" and rewrite "Write-only: χρησιμοποιήστε..." to a fully Greek
sentence that conveys "Μόνο για εγγραφή: χρησιμοποιήστε αυτό το πεδίο μόνο αν
χρειάζεται..." while keeping the samlCertificateHelpText similarly natural
(e.g., "Μπορείτε να παρέχετε δικό σας πιστοποιητικό ή να αφήσετε την εφαρμογή να
το δημιουργήσει αυτόματα.").

"samlAuthnRequestSignedHelpText": "Όταν είναι ενεργοποιημένο, το αίτημα αυθεντικοποίησης SAML υπογράφεται με το ιδιωτικό κλειδί παρακάτω. Το αντίστοιχο δημόσιο πιστοποιητικό αποστέλλεται στον πάροχο ταυτότητας ώστε να μπορέσει να επαληθεύσει την υπογραφή.",
"downloadCertificate": "Λήψη πιστοποιητικού"
}
9 changes: 8 additions & 1 deletion frontend/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2206,5 +2206,12 @@
"libraryOverview": "{objectType}: {count}",
"evidenceRevisions": "Revisions",
"addEvidenceRevision": "Add Revision",
"associatedEvidenceRevisions": "Associated versions"
"associatedEvidenceRevisions": "Associated versions",
"privateKey": "Private Key",
"generateDots": "Generate...",
"samlKeysGenerated": "Saml keys successfully generated",
"samlPrivateKeyHelpText": "Write-only: use this field only if you need to supply your own private key/certificate. Otherwise, the application will generate it.",
"samlCertificateHelpText": "You can specify your own certificate or let the application generate it.",
"samlAuthnRequestSignedHelpText": "When enabled, the SAML authentication request is signed with the private key below. The corresponding public certificate is sent to the Identity Provider so it can verify the signature.",
"downloadCertificate": "Download certificate"
}
9 changes: 8 additions & 1 deletion frontend/messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -975,5 +975,12 @@
"securityObjectiveScale": "Escala de propiedades de seguridad",
"securityObjectiveScaleHelpText": "Elija su escala para las propiedades de seguridad (1 a 4 por defecto)",
"actor": "Actor",
"action": "Acción"
"action": "Acción",
"privateKey": "Clave privada",
"generateDots": "Generando...",
"samlKeysGenerated": "Claves SAML generadas con éxito",
"samlPrivateKeyHelpText": "Sólo escritura: utilice este campo solo si necesita proporcionar su propia clave/certificado privado. De lo contrario, la aplicación lo generará.",
"samlCertificateHelpText": "Puede especificar su propio certificado o dejar que la aplicación lo genere.",
Comment on lines +982 to +983
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Correct the “read-only” wording in Spanish.

The phrase “Sólo escritura” communicates the opposite of “write-protected/read-only” from the source text. To avoid confusing users, switch it to “Sólo lectura” (or similar) in this sentence.

-"samlPrivateKeyHelpText": "Sólo escritura: utilice este campo solo si necesita proporcionar su propia clave/certificado privado. De lo contrario, la aplicación lo generará.",
+"samlPrivateKeyHelpText": "Sólo lectura: utilice este campo solo si necesita proporcionar su propia clave/certificado privado. De lo contrario, la aplicación lo generará.",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"samlPrivateKeyHelpText": "Sólo escritura: utilice este campo solo si necesita proporcionar su propia clave/certificado privado. De lo contrario, la aplicación lo generará.",
"samlCertificateHelpText": "Puede especificar su propio certificado o dejar que la aplicación lo genere.",
"samlPrivateKeyHelpText": "Sólo lectura: utilice este campo solo si necesita proporcionar su propia clave/certificado privado. De lo contrario, la aplicación lo generará.",
"samlCertificateHelpText": "Puede especificar su propio certificado o dejar que la aplicación lo genere.",
🤖 Prompt for AI Agents
In frontend/messages/es.json around lines 982 to 983, the Spanish string for
samlPrivateKeyHelpText uses "Sólo escritura" which incorrectly conveys
"write-only"; replace it with "Sólo lectura" (or equivalent like "Solo lectura"
if following project accent rules) so the sentence reads that the field is
read-only/for display only and matches the original meaning; update the JSON
value accordingly and ensure punctuation/spacing remains consistent with
neighboring entries.

"samlAuthnRequestSignedHelpText": "Cuando está habilitado, la solicitud de autenticación SAML se firma con la clave privada a continuación. El certificado público correspondiente se envía al Proveedor de Identidad para que pueda verificar la firma.",
"downloadCertificate": "Descargar certificado"
}
9 changes: 8 additions & 1 deletion frontend/messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -2139,5 +2139,12 @@
"hasMfaEnabled": "MFA activée",
"evidenceRevisions": "Révisions",
"addEvidenceRevision": "Nouvelle révision",
"associatedEvidenceRevisions": "Versions associées"
"associatedEvidenceRevisions": "Révisions associées",
"privateKey": "Clé privée",
"generateDots": "Générer...",
"samlKeysGenerated": "Clés SAML générées avec succès",
"samlPrivateKeyHelpText": "Écriture seule : utilisez ce champ uniquement si vous devez fournir votre propre clé/certificat privée. Sinon, l'application générera celle-ci.",
"samlCertificateHelpText": "Vous pouvez spécifier votre propre certificat ou laisser l'application le générer.",
"samlAuthnRequestSignedHelpText": "Lorsque cette option est activée, la requête d'authentification SAML est signée avec la clé privée ci-dessous. Le certificat public correspondant est envoyé au fournisseur d'identité afin qu'il puisse vérifier la signature.",
"downloadCertificate": "Télécharger le certificat"
}
9 changes: 8 additions & 1 deletion frontend/messages/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -939,5 +939,12 @@
"securityObjectiveScale": "सुरक्षा गुण स्केल",
"securityObjectiveScaleHelpText": "सुरक्षा गुणों के लिए अपना स्केल चुनें (डिफ़ॉल्ट रूप से 1 से 4)",
"actor": "अभिनेता",
"action": "क्रिया"
"action": "कार्रवाई",
"privateKey": "निजी कुंजी",
"generateDots": "उत्पन्न...",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Complete the imperative phrase for “Generate…”

“उत्पन्न...” truncates the imperative and reads awkwardly in Hindi. Adding “करें” keeps it consistent with other buttons (e.g., “डाउनलोड करें”).

-	"generateDots": "उत्पन्न...",
+	"generateDots": "उत्पन्न करें...",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"generateDots": "उत्पन्न...",
"generateDots": "उत्पन्न करें...",
🤖 Prompt for AI Agents
In frontend/messages/hi.json around line 944, the translation string
"generateDots": "उत्पन्न..." uses an incomplete imperative; replace it with a
complete imperative phrase like "उत्पन्न करें" to match other button labels
(e.g., "डाउनलोड करें") and maintain consistent tone across the UI.

"samlKeysGenerated": "सामल कुंजियाँ सफलतापूर्वक उत्पन्न की गईं",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Keep the “SAML” acronym unchanged

Line 945 spells “SAML” as “सामल”, which diverges from the established acronym usage elsewhere in this file (e.g., “SAML IdP कॉन्फ़िगरेशन”). Please retain the uppercase Latin acronym for consistency and to avoid confusing readers.

-	"samlKeysGenerated": "सामल कुंजियाँ सफलतापूर्वक उत्पन्न की गईं",
+	"samlKeysGenerated": "SAML कुंजियाँ सफलतापूर्वक उत्पन्न की गईं",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"samlKeysGenerated": "सामल कुंजियाँ सफलतापूर्वक उत्पन्न की गईं",
"samlKeysGenerated": "SAML कुंजियाँ सफलतापूर्वक उत्पन्न की गईं",
🤖 Prompt for AI Agents
In frontend/messages/hi.json around line 945, the string uses the Devanagari
transliteration "सामल" for the SAML acronym; replace that token with the
uppercase Latin acronym "SAML" so the value becomes "SAML कुंजियाँ सफलतापूर्वक
उत्पन्न की गईं" to match other entries (e.g., "SAML IdP कॉन्फ़िगरेशन") and keep
acronym usage consistent.

"samlPrivateKeyHelpText": "लेखन-केवल: इस क्षेत्र का उपयोग केवल तभी करें यदि आपको अपना निजी कुंजी/सर्टिफिकेट प्रदान करने की आवश्यकता है। अन्यथा, एप्लिकेशन इसे उत्पन्न करेगा।",
"samlCertificateHelpText": "आप अपना स्वयं का सर्टिफिकेट निर्दिष्ट कर सकते हैं या एप्लिकेशन को इसे उत्पन्न करने दें।",
"samlAuthnRequestSignedHelpText": "जब सक्षम किया जाता है, तो SAML प्रमाणीकरण अनुरोध नीचे दिए गए निजी कुंजी के साथ हस्ताक्षरित किया जाता है। संबंधित सार्वजनिक सर्टिफिकेट को पहचान प्रदाता को भेजा जाता है ताकि यह हस्ताक्षर की पुष्टि कर सके।",
"downloadCertificate": "सर्टिफिकेट डाउनलोड करें"
}
9 changes: 8 additions & 1 deletion frontend/messages/hr.json
Original file line number Diff line number Diff line change
Expand Up @@ -2200,5 +2200,12 @@
"isSelectedHelpText": "Odlučite treba li biti pušteno u procjenu",
"quantRiskPriorityHelpText": "Korisno analitičaru za forsiranje poretka u izvještaju za Upravu",
"lossThreshold": "Prag gubitka",
"lossThresholdHelpText": "Maksimalni prihvatljivi gubitak koji će služiti kao osnova za toleranciju"
"lossThresholdHelpText": "Maksimalni prihvatljivi gubitak koji će služiti kao osnova za toleranciju",
"privateKey": "Privatni ključ",
"generateDots": "Generiraj...",
"samlKeysGenerated": "SAML ključevi uspješno generirani",
"samlPrivateKeyHelpText": "Samo za pisanje: koristite ovo polje samo ako trebate unijeti vlastiti privatni ključ/certifikat. U suprotnom, aplikacija će ga generirati.",
"samlCertificateHelpText": "Možete navesti vlastiti certifikat ili pustiti aplikaciju da ga generira.",
"samlAuthnRequestSignedHelpText": "Kada je omogućeno, zahtjev za SAML autentifikaciju potpisuje se privatnim ključem ispod. Odgovarajući javni certifikat šalje se Identity Provideru kako bi mogao provjeriti potpis.",
"downloadCertificate": "Preuzmi certifikat"
}
Loading