diff --git a/dashboard/src/js/login.js b/dashboard/src/js/login.js index 9074ae63d..0d653048a 100644 --- a/dashboard/src/js/login.js +++ b/dashboard/src/js/login.js @@ -84,17 +84,29 @@ app.controller('LoginController', ['$scope', '$translate', '$http', function ($s totpToken: $scope.totpToken }; - function error() { + function error(data, status) { $scope.busy = false; - $scope.error = true; + $scope.error = {}; + + if (!data || status !== 401) return $scope.error.internal = true; + + if (data.message === 'Username and password does not match') { + $scope.error.password = true; + $scope.password = ''; + setTimeout(function () { $('#inputPassword').focus(); }, 200); + } else if (data.message.indexOf('totpToken') !== -1) { + $scope.error.totpToken = true; + $scope.totpToken = ''; + setTimeout(function () { $('#inputTotpToken').focus(); }, 200); + } else { + $scope.error.generic = true; + } - $scope.password = ''; $scope.loginForm.$setPristine(); - setTimeout(function () { $('#inputPassword').focus(); }, 200); } $http.post(API_ORIGIN + '/api/v1/cloudron/login', data).success(function (data, status) { - if (status !== 200) return error(); + if (status !== 200) return error(data, status); localStorage.token = data.accessToken; diff --git a/dashboard/src/login.html b/dashboard/src/login.html index 7b2773199..fd0c6548d 100644 --- a/dashboard/src/login.html +++ b/dashboard/src/login.html @@ -67,7 +67,9 @@
-

{{ 'login.errorIncorrectCredentials' | tr }}

+

{{ 'login.errorIncorrectCredentials' | tr }}

+

{{ 'login.errorIncorrect2FAToken' | tr }}

+

{{ 'login.errorInternal' | tr }}

@@ -77,11 +79,11 @@
-
+
-
+
diff --git a/dashboard/src/translation/de.json b/dashboard/src/translation/de.json index 3631e97e4..5d12d85b6 100644 --- a/dashboard/src/translation/de.json +++ b/dashboard/src/translation/de.json @@ -39,7 +39,8 @@ "save": "Speichern", "close": "Schließen", "yes": "Ja", - "no": "Nein" + "no": "Nein", + "delete": "Löschen" }, "username": "Username", "displayName": "Name", @@ -87,7 +88,8 @@ "users": "User" }, "statusDisabled": "Deaktiviert", - "loadingPlaceholder": "Laden" + "loadingPlaceholder": "Laden", + "settings": "Einstellungen" }, "network": { "title": "Netzwerk", @@ -748,7 +750,8 @@ "jitsiHostname": "Jitsi Pfad", "cloudflareDefaultProxyStatus": "Proxying für neue DNS-Einträge aktivieren", "porkbunSecretapikey": "Geheimer API-Schlüssel", - "porkbunApikey": "API-Schlüssel" + "porkbunApikey": "API-Schlüssel", + "bunnyAccessKey": "Bunny Access Key" }, "changeDashboardDomain": { "title": "Die Dashboard-Domäne ändern", @@ -1611,7 +1614,7 @@ "appdata": { "title": "Datenverzeichnis", "dataDirPlaceholder": "Leer lassen, um Systemvorgabe zu verwenden", - "description": "Standardmäßig befinden sich die Daten dieser Anwendung unter {{ storagePath }}. Wenn dem Server der Speicherplatz ausgeht, kann durch Hinzufügen einer externen Festplatte, die Daten der Anwendung dorthin verschoben werden. Es wird nur das Ext4-Format unterstützt.", + "description": "Wenn dem Server der Speicherplatz ausgeht, kann durch Hinzufügen einer externen Festplatte, die Daten der Anwendung dorthin verschoben werden.", "moveAction": "Daten verschieben", "diskUsage": "Die App verwendet derzeit {{ size }} an Speicherplatz (ab {{ date }})." }, @@ -1781,10 +1784,11 @@ "pl": "Polnisch", "es": "Spanisch", "ru": "Russisch", - "pt": "Portugiesisch" + "pt": "Portugiesisch", + "da": "Dänisch" }, "volumes": { - "description": "Datenträger sind Verzeichnisse auf dem Server, die von Anwendungen gemeinsam genutzt werden können. Dabei kann es sich um NFS/SSHFS/CIFS-Mounts oder externe Speicherplatten handeln, die an den Server angeschlossen sind. Datenträger werden dem App-Container unter /media zur Verfügung gestellt.", + "description": "Datenträger sind Verzeichnisse auf dem Server, die von Anwendungen gemeinsam genutzt werden können.", "removeVolumeDialog": { "removeAction": "Entfernen", "description": "Dies wird den Datenträger {{ volume }} löschen. Daten innerhalb des Host-Pfades werden nicht entfernt.", @@ -1835,5 +1839,42 @@ }, "supportConfig": { "emailNotVerified": "Bitte verifizieren Sie zuerst die E-Mail Ihres cloudron.io-Kontos, um sicherzustellen, dass wir Sie kontaktieren können." + }, + "oidc": { + "newClientDialog": { + "title": "Client hinzufügen", + "description": "Neuen OpenID Connect Clienten hinzufügen.", + "createAction": "Erstellen" + }, + "client": { + "name": "Name", + "id": "Client ID", + "signingAlgorithm": "Signatur Algorithmus", + "loginRedirectUri": "Login Callback Url (bei mehreren mit Komma getrennt)", + "logoutRedirectUri": "Logout Callback Url (optional)", + "secret": "Client Geheimnis" + }, + "title": "OpenID Connect Provider", + "description": "Cloudron kann als OpenID Connect Provider für interne und externe Apps fungieren.", + "editClientDialog": { + "title": "Client {{ client }} bearbeiten" + }, + "deleteClientDialog": { + "title": "Wirklich Client {{ client }} löschen?", + "description": "Damit werden alle externen OpenID Apps, die diese Clientendetails nutzen, getrennt." + }, + "env": { + "discoveryUrl": "Discovery URL", + "logoutUrl": "Logout URL", + "profileEndpoint": "Profil Endpunkt", + "keysEndpoint": "Schlüssel Endpunkt", + "tokenEndpoint": "Token Endpunkt", + "authEndpoint": "Auth Endpunkt" + }, + "clients": { + "title": "Clienten", + "newClient": "Neuer Client", + "empty": "Noch keine Clienten erstellt" + } } } diff --git a/dashboard/src/translation/en.json b/dashboard/src/translation/en.json index 8edd99406..38e2a5668 100644 --- a/dashboard/src/translation/en.json +++ b/dashboard/src/translation/en.json @@ -1705,7 +1705,9 @@ "password": "Password", "2faToken": "2FA Token (if enabled)", "signInAction": "Sign in", - "resetPasswordAction": "Reset password" + "resetPasswordAction": "Reset password", + "errorIncorrect2FAToken": "2FA token is invalid", + "errorInternal": "Internal error, try again later" }, "passwordReset": { "title": "Password reset",