diff --git a/package-lock.json b/package-lock.json index 8c0ab7f..cf722fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ucentral-client", - "version": "2.2.5", + "version": "2.2.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ucentral-client", - "version": "2.2.5", + "version": "2.2.8", "dependencies": { "@coreui/coreui": "^3.4.0", "@coreui/icons": "^2.0.1", @@ -32,7 +32,7 @@ "react-tooltip": "^4.2.21", "react-widgets": "^5.1.1", "sass": "^1.35.1", - "ucentral-libs": "^0.9.58", + "ucentral-libs": "^0.9.62", "uuid": "^8.3.2" }, "devDependencies": { @@ -9279,6 +9279,11 @@ "node": ">= 0.8.0" } }, + "node_modules/libphonenumber-js": { + "version": "1.9.37", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.37.tgz", + "integrity": "sha512-RnUR4XwiVhMLnT7uFSdnmLeprspquuDtaShAgKTA+g/ms9/S4hQU3/QpFdh3iXPHtxD52QscXLm2W2+QBmvYAg==" + }, "node_modules/lilconfig": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.3.tgz", @@ -9518,14 +9523,12 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -9533,6 +9536,16 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.reduce": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", + "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" + }, + "node_modules/lodash.startswith": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.startswith/-/lodash.startswith-4.2.1.tgz", + "integrity": "sha1-xZjErc4YiiflMUVzHNxsDnF3YAw=" + }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -12189,6 +12202,23 @@ "react": "^16.0.0 || ^17.0.0" } }, + "node_modules/react-phone-input-2": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/react-phone-input-2/-/react-phone-input-2-2.14.0.tgz", + "integrity": "sha512-gOY3jUpwO7ulryXPEdqzH7L6DPqI9RQxKfBxZbgqAwXyALGsmwLWFyi2RQwXlBLWN/EPPT4Nv6I9TESVY2YBcg==", + "dependencies": { + "classnames": "^2.2.6", + "lodash.debounce": "^4.0.8", + "lodash.memoize": "^4.1.2", + "lodash.reduce": "^4.6.0", + "lodash.startswith": "^4.2.1", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "^16.12.0 || ^17.0.0", + "react-dom": "^16.12.0 || ^17.0.0" + } + }, "node_modules/react-redux": { "version": "7.2.4", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.4.tgz", @@ -14812,18 +14842,20 @@ } }, "node_modules/ucentral-libs": { - "version": "0.9.58", - "resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.9.58.tgz", - "integrity": "sha512-K0bacVDGzjK//pddaMNVh2WDOep0/22tV1EhEfMKBAzaXgYEx2Ir3fg/GQzswCkfwg9i0kDWKiAXqRQ8pWLblg==", + "version": "0.9.62", + "resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.9.62.tgz", + "integrity": "sha512-teqIoFOkALEFzqRwdEuLWoDgIOiLhUt+ZDiS2ygYmqVsbCQZWUk/iOEpfLr1ZkRcEUtOPdrjqIRF5HrMopAPHA==", "dependencies": { "@coreui/coreui": "^3.4.0", "@coreui/icons": "^2.0.1", "@coreui/icons-react": "^1.1.0", "@coreui/react": "^3.4.6", "@coreui/react-chartjs": "^1.1.0", + "libphonenumber-js": "^1.9.37", "lodash": "^4.17.21", "react-flow-renderer": "^9.6.6", "react-paginate": "^7.1.3", + "react-phone-input-2": "^2.14.0", "react-router-dom": "^5.2.0", "react-select": "^4.3.1", "react-tooltip": "^4.2.21", @@ -23416,6 +23448,11 @@ "type-check": "~0.4.0" } }, + "libphonenumber-js": { + "version": "1.9.37", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.37.tgz", + "integrity": "sha512-RnUR4XwiVhMLnT7uFSdnmLeprspquuDtaShAgKTA+g/ms9/S4hQU3/QpFdh3iXPHtxD52QscXLm2W2+QBmvYAg==" + }, "lilconfig": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.3.tgz", @@ -23598,14 +23635,12 @@ "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" }, "lodash.merge": { "version": "4.6.2", @@ -23613,6 +23648,16 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "lodash.reduce": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", + "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" + }, + "lodash.startswith": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.startswith/-/lodash.startswith-4.2.1.tgz", + "integrity": "sha1-xZjErc4YiiflMUVzHNxsDnF3YAw=" + }, "lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -25559,6 +25604,19 @@ "prop-types": "^15.6.1" } }, + "react-phone-input-2": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/react-phone-input-2/-/react-phone-input-2-2.14.0.tgz", + "integrity": "sha512-gOY3jUpwO7ulryXPEdqzH7L6DPqI9RQxKfBxZbgqAwXyALGsmwLWFyi2RQwXlBLWN/EPPT4Nv6I9TESVY2YBcg==", + "requires": { + "classnames": "^2.2.6", + "lodash.debounce": "^4.0.8", + "lodash.memoize": "^4.1.2", + "lodash.reduce": "^4.6.0", + "lodash.startswith": "^4.2.1", + "prop-types": "^15.7.2" + } + }, "react-redux": { "version": "7.2.4", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.4.tgz", @@ -27653,18 +27711,20 @@ } }, "ucentral-libs": { - "version": "0.9.58", - "resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.9.58.tgz", - "integrity": "sha512-K0bacVDGzjK//pddaMNVh2WDOep0/22tV1EhEfMKBAzaXgYEx2Ir3fg/GQzswCkfwg9i0kDWKiAXqRQ8pWLblg==", + "version": "0.9.62", + "resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.9.62.tgz", + "integrity": "sha512-teqIoFOkALEFzqRwdEuLWoDgIOiLhUt+ZDiS2ygYmqVsbCQZWUk/iOEpfLr1ZkRcEUtOPdrjqIRF5HrMopAPHA==", "requires": { "@coreui/coreui": "^3.4.0", "@coreui/icons": "^2.0.1", "@coreui/icons-react": "^1.1.0", "@coreui/react": "^3.4.6", "@coreui/react-chartjs": "^1.1.0", + "libphonenumber-js": "^1.9.37", "lodash": "^4.17.21", "react-flow-renderer": "^9.6.6", "react-paginate": "^7.1.3", + "react-phone-input-2": "^2.14.0", "react-router-dom": "^5.2.0", "react-select": "^4.3.1", "react-tooltip": "^4.2.21", diff --git a/package.json b/package.json index 9f40d0c..f01a229 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ucentral-client", - "version": "2.2.5", + "version": "2.2.8", "dependencies": { "@coreui/coreui": "^3.4.0", "@coreui/icons": "^2.0.1", @@ -26,7 +26,7 @@ "react-tooltip": "^4.2.21", "react-widgets": "^5.1.1", "sass": "^1.35.1", - "ucentral-libs": "^0.9.58", + "ucentral-libs": "^0.9.62", "uuid": "^8.3.2" }, "main": "index.js", diff --git a/public/favicon.ico b/public/favicon.ico index 8e76896..d3f1ee8 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json index 6d87336..d34a10b 100644 --- a/public/locales/de/translation.json +++ b/public/locales/de/translation.json @@ -369,6 +369,7 @@ "error_create_venue": "Fehler beim Erstellen des Veranstaltungsortes", "error_delete_tag": "Fehler beim Löschen des Inventar-Tags", "error_get_venue": "Fehler beim Abrufen von Veranstaltungsorten", + "error_pushing_config": "Fehler beim Versuch, die Konfiguration auf das Gerät zu übertragen: {{error}}", "error_retrieving": "Beim Abrufen von Inventar-Tags ist ein Fehler aufgetreten", "error_unassign": "Fehler beim Aufheben der Zuweisung", "error_update_venue": "Fehler beim Aktualisieren des Veranstaltungsorts", @@ -417,12 +418,15 @@ "venue": "Tagungsort" }, "login": { + "account_verification": "Bestätigung des Kontos", + "authentication_expired": "Authentifizierung abgelaufen, bitte starten Sie den Anmeldevorgang erneut", "change_password": "Ändere das Passwort", "change_password_error": "Fehler beim Ändern des Passworts. Stellen Sie sicher, dass das neue Passwort gültig ist, indem Sie die Seite \"Passwortrichtlinie\" besuchen", "change_password_instructions": "Geben Sie Ihr neues Passwort ein und bestätigen Sie es", "changing_password": "Passwort ändern...", "confirm_new_password": "Bestätige neues Passwort", "different_passwords": "Sie müssen das gleiche Passwort zweimal eingeben", + "email_code_validation": "Bitte überprüfen Sie Ihr E-Mail-Postfach und geben Sie den Bestätigungscode, den wir Ihnen gerade gesendet haben, in das Feld unten ein", "forgot_password_error": "Fehler beim Versuch, eine E-Mail mit vergessenem Passwort zu senden. Stellen Sie sicher, dass diese Benutzer-ID mit einem Konto verknüpft ist.", "forgot_password_explanation": "Geben Sie Ihren Benutzernamen ein, um eine E-Mail mit Anweisungen zum Zurücksetzen Ihres Passworts zu erhalten", "forgot_password_success": "Sie sollten in Kürze eine E-Mail mit Anweisungen zum Zurücksetzen Ihres Passworts erhalten. Bitte überprüfen Sie Ihren Spam, wenn Sie die E-Mail nicht finden können", @@ -431,6 +435,7 @@ "login_error": "Anmeldefehler, stellen Sie sicher, dass die von Ihnen angegebenen Informationen gültig sind", "new_password": "Neues Kennwort", "password": "Passwort", + "phone_validation_explanation": "Bitte überprüfen Sie Ihr Mobilgerät und geben Sie den Bestätigungscode, den wir Ihnen gerade gesendet haben, in das Feld unten ein", "please_enter_gateway": "Bitte geben Sie eine uCentralSec-URL ein", "please_enter_password": "Bitte geben Sie Ihr Passwort ein", "please_enter_username": "Bitte geben Sie Ihren Benutzernamen ein", @@ -439,7 +444,9 @@ "sending_ellipsis": "Senden…", "sign_in_to_account": "Melden Sie sich bei Ihrem Konto an", "url": "uCentralSec-URL", - "username": "Benutzername" + "username": "Benutzername", + "verification_code": "Geben Sie hier Ihre Bestätigung ein", + "wrong_code": "Der eingegebene Bestätigungscode ist ungültig." }, "reboot": { "directions": "Wann möchten Sie dieses Gerät neu starten?", @@ -530,6 +537,7 @@ "add_phone_number": "Telefonnummer hinzufügen", "avatar": "Dein Avatar", "avatar_file": "Dein Avatar (max. 2 MB)", + "check_phone": "Bitte überprüfen Sie Ihr Telefon auf Ihren Validierungscode", "create": "Benutzer erstellen", "create_failure": "Fehler beim Erstellen des Benutzers. Bitte stellen Sie sicher, dass diese E-Mail-Adresse nicht bereits mit einem Konto verknüpft ist.", "create_success": "Benutzer erfolgreich erstellt", @@ -543,13 +551,16 @@ "description": "Beschreibung", "edit": "Benutzer bearbeiten", "email_address": "E-Mail-Addresse", + "enter_new_phone": "Geben Sie Ihre neue Telefonnummer ein:", "error_fetching_users": "Fehler beim Abrufen der Nutzer: {{error}}", + "error_sending_code": "Fehler beim Versuch, den Validierungscode zu senden. Bitte bestätigen Sie, dass Ihre Telefonnummer gültig ist.", "force_password_change": "Passwortänderung bei der Anmeldung erzwingen", "id": "Benutzeridentifikation.", "last_login": "Letzte Anmeldung", "login_id": "Anmelde-ID.", "my_profile": "Mein Profil", "name": "Name", + "new_code_sent": "Neuer Code gesendet!", "nickname": "Spitzname", "nickname_explanation": "Spitzname (optional)", "not_validated": "Nicht validiert", @@ -559,14 +570,19 @@ "provide_email": "Bitte geben Sie eine gültige E-Mail Adresse an", "provide_password": "Bitte geben Sie ein gültiges Passwort ein", "save_avatar": "Avatar speichern", + "send_code": "Code senden", + "send_code_again": "Code nochmal senden", "show_hide_password": "Passwort anzeigen/verbergen", + "successful_validation": "Telefonnummer bestätigt! Klicken Sie auf die Schaltfläche Speichern, um es mit Ihrem Profil zu verknüpfen", "update_failure": "Fehler beim Aktualisieren: {{error}}", "update_failure_title": "Update fehlgeschlagen", "update_success": "Benutzer erfolgreich aktualisiert", "update_success_title": "Erfolg", "user_role": "Rolle", "users": "Benutzer", - "validated": "Bestätigt" + "validate_phone": "Bestätigen", + "validated": "Bestätigt", + "wrong_validation_code": "Sie haben keinen gültigen Code eingegeben. Bitte versuchen Sie es erneut und vergewissern Sie sich, dass Sie die richtige Telefonnummer eingegeben haben" }, "wifi_analysis": { "association": "Verband", diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 100e828..51b03f4 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -369,6 +369,7 @@ "error_create_venue": "Error while creating venue", "error_delete_tag": "Error while deleting inventory tag", "error_get_venue": "Error while retrieving venues", + "error_pushing_config": "Error while trying to push configuration to device: {{error}}", "error_retrieving": "Error occurred while retrieving inventory tags", "error_unassign": "Error during unassign operation", "error_update_venue": "Error while updating venue", @@ -417,12 +418,15 @@ "venue": "Venue" }, "login": { + "account_verification": "Account Verification", + "authentication_expired": "Authentication expired, please start the login process again", "change_password": "Change Password", "change_password_error": "Error while changing password. Make sure the new password is valid by visiting the 'Password Policy' page", "change_password_instructions": "Enter and confirm your new password", "changing_password": "Changing Password... ", "confirm_new_password": "Confirm New Password", "different_passwords": "You need to enter the same password twice", + "email_code_validation": "Please check your email box and enter the verification code we have just sent you in the box below", "forgot_password_error": "Error while trying to send Forgot Password email. Please make sure this userId is associated to an account.", "forgot_password_explanation": "Enter your username to receive an email containing the instructions to reset your password", "forgot_password_success": "You should soon receive an email containing the instructions to reset your password. Please make sure to check your spam if you can't find the email", @@ -431,6 +435,7 @@ "login_error": "Login error, make sure the information you are providing is valid", "new_password": "New Password", "password": "Password", + "phone_validation_explanation": "Please check your mobile device and enter the verification code we have just sent you in the box below", "please_enter_gateway": "Please enter a uCentralSec URL", "please_enter_password": "Please enter your password", "please_enter_username": "Please enter your username", @@ -439,7 +444,9 @@ "sending_ellipsis": "Sending... ", "sign_in_to_account": "Sign in to your account", "url": "uCentralSec URL", - "username": "Username" + "username": "Username", + "verification_code": "Enter your verification here", + "wrong_code": "The verification code that was entered is not valid. " }, "reboot": { "directions": "When would you like to reboot this device?", @@ -530,6 +537,7 @@ "add_phone_number": "Add Phone Number", "avatar": "Your Avatar", "avatar_file": "Your Avatar (max. of 2 MB)", + "check_phone": "Please check your phone for your validation code", "create": "Create User", "create_failure": "Error while creating user. Please make sure this email address is not already linked to an account.", "create_success": "User Created Successfully", @@ -543,13 +551,16 @@ "description": "Description", "edit": "Edit User", "email_address": "Email Address", + "enter_new_phone": "Enter your new phone number: ", "error_fetching_users": "Error fetching users: {{error}}", + "error_sending_code": "Error while trying to send validation code. Please confirm that your phone number is valid.", "force_password_change": "Force Password Change on Login", "id": "User Id.", "last_login": "Last Login", "login_id": "Login Id.", "my_profile": "My Profile", "name": "Name", + "new_code_sent": "New Code Sent!", "nickname": "Nickname", "nickname_explanation": "Nickname (optional)", "not_validated": "Not Validated", @@ -559,14 +570,19 @@ "provide_email": "Please provide a valid email address", "provide_password": "Please provide a valid password", "save_avatar": "Save Avatar", + "send_code": "Send Code", + "send_code_again": "Send Code Again", "show_hide_password": "Show/Hide Password", + "successful_validation": "Phone Number Validated! Click the save button to link it to your profile", "update_failure": "Error while trying to update: {{error}}", "update_failure_title": "Update Failed", "update_success": "User Updated Successfully", "update_success_title": "Success", "user_role": "Role", "users": "Users", - "validated": "Validated" + "validate_phone": "Validate", + "validated": "Validated", + "wrong_validation_code": "You have not entered a valid code. Please try again and make sure you have entered the right phone number" }, "wifi_analysis": { "association": "Association", diff --git a/public/locales/es/translation.json b/public/locales/es/translation.json index 0692478..f3ea93f 100644 --- a/public/locales/es/translation.json +++ b/public/locales/es/translation.json @@ -369,6 +369,7 @@ "error_create_venue": "Error al crear el lugar", "error_delete_tag": "Error al eliminar la etiqueta de inventario", "error_get_venue": "Error al recuperar lugares", + "error_pushing_config": "Error al intentar enviar la configuración al dispositivo: {{error}}", "error_retrieving": "Se produjo un error al recuperar las etiquetas de inventario", "error_unassign": "Error durante la operación de anulación de asignación", "error_update_venue": "Error al actualizar el lugar", @@ -417,12 +418,15 @@ "venue": "Lugar de encuentro" }, "login": { + "account_verification": "Verificación de la cuenta", + "authentication_expired": "Autenticación caducada, vuelva a iniciar el proceso de inicio de sesión", "change_password": "Cambia la contraseña", "change_password_error": "Error al cambiar la contraseña. Asegúrese de que la nueva contraseña sea válida visitando la página 'Política de contraseñas'", "change_password_instructions": "Ingrese y confirme su nueva contraseña", "changing_password": "Cambio de contraseña ...", "confirm_new_password": "confirmar nueva contraseña", "different_passwords": "Debes ingresar la misma contraseña dos veces", + "email_code_validation": "Por favor, marque su casilla de correo electrónico e ingrese el código de verificación que le acabamos de enviar en la casilla a continuación.", "forgot_password_error": "Error al intentar enviar el correo electrónico de Olvidé mi contraseña. Asegúrese de que este ID de usuario esté asociado a una cuenta.", "forgot_password_explanation": "Ingrese su nombre de usuario para recibir un correo electrónico con las instrucciones para restablecer su contraseña", "forgot_password_success": "Pronto debería recibir un correo electrónico con las instrucciones para restablecer su contraseña. Asegúrese de verificar su correo no deseado si no puede encontrar el correo electrónico", @@ -431,6 +435,7 @@ "login_error": "Error de inicio de sesión, asegúrese de que la información que proporciona sea válida", "new_password": "Nueva contraseña", "password": "Contraseña", + "phone_validation_explanation": "Verifique su dispositivo móvil e ingrese el código de verificación que le acabamos de enviar en el cuadro a continuación", "please_enter_gateway": "Ingrese una URL de uCentralSec", "please_enter_password": "Por favor, introduzca su contraseña", "please_enter_username": "Por favor, ingrese su nombre de usuario", @@ -439,7 +444,9 @@ "sending_ellipsis": "Enviando...", "sign_in_to_account": "Iniciar sesión en su cuenta", "url": "URL de uCentralSec", - "username": "Nombre de usuario" + "username": "Nombre de usuario", + "verification_code": "Ingrese su verificación aquí", + "wrong_code": "El código de verificación que se ingresó no es válido." }, "reboot": { "directions": "¿Cuándo le gustaría reiniciar este dispositivo?", @@ -530,6 +537,7 @@ "add_phone_number": "Agregar el número de teléfono", "avatar": "Tu avatar", "avatar_file": "Tu avatar (máx. De 2 MB)", + "check_phone": "Por favor revise su teléfono para su código de validación", "create": "Crear usuario", "create_failure": "Error al crear usuario. Asegúrese de que esta dirección de correo electrónico no esté vinculada a una cuenta.", "create_success": "Usuario creado con éxito", @@ -543,13 +551,16 @@ "description": "Descripción", "edit": "editar usuario", "email_address": "Dirección de correo electrónico", + "enter_new_phone": "Ingrese su nuevo número de teléfono:", "error_fetching_users": "Error al obtener usuarios: {{error}}", + "error_sending_code": "Error al intentar enviar el código de validación. Confirma que tu número de teléfono es válido.", "force_password_change": "Forzar cambio de contraseña al iniciar sesión", "id": "Id. De usuario", "last_login": "Último acceso", "login_id": "Ingresar identificación.", "my_profile": "Mi perfil", "name": "Nombre", + "new_code_sent": "¡Nuevo código enviado!", "nickname": "Apodo", "nickname_explanation": "Apodo (opcional)", "not_validated": "No validado", @@ -559,14 +570,19 @@ "provide_email": "Por favor ingrese su dirección de correo electrónico válida", "provide_password": "Proporcione una contraseña válida", "save_avatar": "Guardar avatar", + "send_code": "Enviar código", + "send_code_again": "Enviar Código De nuevo", "show_hide_password": "Mostrar / Ocultar contraseña", + "successful_validation": "¡Número de teléfono validado! Haga clic en el botón guardar para vincularlo a su perfil", "update_failure": "Error al intentar actualizar: {{error}}", "update_failure_title": "Actualización fallida", "update_success": "Usuario actualizado con éxito", "update_success_title": "Éxito", "user_role": "papel", "users": "Usuarios", - "validated": "Validado" + "validate_phone": "validar", + "validated": "Validado", + "wrong_validation_code": "No ha introducido un código válido. Vuelve a intentarlo y asegúrate de haber ingresado el número de teléfono correcto." }, "wifi_analysis": { "association": "Asociación", diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index 6204279..2cab7a8 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -369,6 +369,7 @@ "error_create_venue": "Erreur lors de la création du lieu", "error_delete_tag": "Erreur lors de la suppression de la balise d'inventaire", "error_get_venue": "Erreur lors de la récupération des lieux", + "error_pushing_config": "Erreur lors de la tentative d'envoi de la configuration sur l'appareil : {{error}}", "error_retrieving": "Une erreur s'est produite lors de la récupération des balises d'inventaire", "error_unassign": "Erreur lors de l'opération de désaffectation", "error_update_venue": "Erreur lors de la mise à jour du lieu", @@ -417,12 +418,15 @@ "venue": "Lieu" }, "login": { + "account_verification": "Vérification de compte", + "authentication_expired": "Authentification expirée, veuillez recommencer le processus de connexion", "change_password": "Changer le mot de passe", "change_password_error": "Erreur lors du changement de mot de passe. Assurez-vous que le nouveau mot de passe est valide en visitant la page « Politique de mot de passe »", "change_password_instructions": "Saisissez et confirmez votre nouveau mot de passe", "changing_password": "Modification du mot de passe...", "confirm_new_password": "Confirmer le nouveau mot de passe", "different_passwords": "Vous devez saisir deux fois le même mot de passe", + "email_code_validation": "Veuillez vérifier votre boîte e-mail et entrer le code de vérification que nous venons de vous envoyer dans la case ci-dessous", "forgot_password_error": "Erreur lors de la tentative d'envoi de l'e-mail Mot de passe oublié. Veuillez vous assurer que cet identifiant est associé à un compte.", "forgot_password_explanation": "Entrez votre nom d'utilisateur pour recevoir un e-mail contenant les instructions pour réinitialiser votre mot de passe", "forgot_password_success": "Vous devriez bientôt recevoir un e-mail contenant les instructions pour réinitialiser votre mot de passe. S'il vous plaît assurez-vous de vérifier vos spams si vous ne trouvez pas l'e-mail", @@ -431,6 +435,7 @@ "login_error": "Erreur de connexion, assurez-vous que les informations que vous fournissez sont valides", "new_password": "Nouveau mot de passe", "password": "Mot de passe", + "phone_validation_explanation": "Veuillez vérifier votre appareil mobile et entrer le code de vérification que nous venons de vous envoyer dans la case ci-dessous", "please_enter_gateway": "Veuillez saisir une URL uCentralSec", "please_enter_password": "s'il vous plait entrez votre mot de passe", "please_enter_username": "s'il vous plaît entrez votre nom d'utilisateur", @@ -439,7 +444,9 @@ "sending_ellipsis": "Envoi...", "sign_in_to_account": "Connectez-vous à votre compte", "url": "URL uCentralSec", - "username": "Nom d'utilisateur" + "username": "Nom d'utilisateur", + "verification_code": "Entrez votre vérification ici", + "wrong_code": "Le code de vérification saisi n'est pas valide." }, "reboot": { "directions": "Quand souhaitez-vous redémarrer cet appareil ?", @@ -530,6 +537,7 @@ "add_phone_number": "Ajouter un numéro de téléphone", "avatar": "Votre avatar", "avatar_file": "Votre Avatar (max. de 2 Mo)", + "check_phone": "Veuillez vérifier votre téléphone pour votre code de validation", "create": "Créer un utilisateur", "create_failure": "Erreur lors de la création de l'utilisateur. Veuillez vous assurer que cette adresse e-mail n'est pas déjà liée à un compte.", "create_success": "L'utilisateur a été créé avec succès", @@ -543,13 +551,16 @@ "description": "La description", "edit": "Modifier l'utilisateur", "email_address": "Adresse électronique", + "enter_new_phone": "Saisissez votre nouveau numéro de téléphone :", "error_fetching_users": "Erreur lors de la récupération des utilisateurs : {{error}}", + "error_sending_code": "Erreur lors de la tentative d'envoi du code de validation. Veuillez confirmer que votre numéro de téléphone est valide.", "force_password_change": "Forcer le changement de mot de passe lors de la connexion", "id": "Identifiant d'utilisateur.", "last_login": "Dernière connexion", "login_id": "Identifiant de connexion.", "my_profile": "Mon profil", "name": "Prénom", + "new_code_sent": "Nouveau code envoyé !", "nickname": "Surnom", "nickname_explanation": "Surnom (optionnel)", "not_validated": "Pas valide", @@ -559,14 +570,19 @@ "provide_email": "Veuillez fournir une adresse email valide", "provide_password": "Veuillez fournir un mot de passe valide", "save_avatar": "Enregistrer l'avatar", + "send_code": "Envoyer le code", + "send_code_again": "Envoyer code à nouveau", "show_hide_password": "Afficher/Masquer le mot de passe", + "successful_validation": "Numéro de téléphone validé ! Cliquez sur le bouton Enregistrer pour le lier à votre profil", "update_failure": "Erreur lors de la tentative de mise à jour : {{error}}", "update_failure_title": "mise à jour a échoué", "update_success": "L'utilisateur a bien été mis à jour", "update_success_title": "Succès", "user_role": "Rôle", "users": "Utilisateurs", - "validated": "Validé" + "validate_phone": "Valider", + "validated": "Validé", + "wrong_validation_code": "Vous n'avez pas entré de code valide. Veuillez réessayer et assurez-vous d'avoir entré le bon numéro de téléphone" }, "wifi_analysis": { "association": "Association", diff --git a/public/locales/pt/translation.json b/public/locales/pt/translation.json index 717abf8..1bc77b8 100644 --- a/public/locales/pt/translation.json +++ b/public/locales/pt/translation.json @@ -369,6 +369,7 @@ "error_create_venue": "Erro ao criar local", "error_delete_tag": "Erro ao excluir tag de inventário", "error_get_venue": "Erro ao recuperar locais", + "error_pushing_config": "Erro ao tentar enviar a configuração para o dispositivo: {{error}}", "error_retrieving": "Ocorreu um erro ao recuperar as tags de inventário", "error_unassign": "Erro durante operação de cancelamento de atribuição", "error_update_venue": "Erro ao atualizar o local", @@ -417,12 +418,15 @@ "venue": "Local" }, "login": { + "account_verification": "Verificação de conta", + "authentication_expired": "Autenticação expirada, reinicie o processo de login", "change_password": "Mudar senha", "change_password_error": "Erro ao alterar a senha. Certifique-se de que a nova senha é válida visitando a página 'Política de senha'", "change_password_instructions": "Digite e confirme sua nova senha", "changing_password": "Alterando senha ...", "confirm_new_password": "confirme a nova senha", "different_passwords": "Você precisa inserir a mesma senha duas vezes", + "email_code_validation": "Verifique sua caixa de e-mail e insira o código de verificação que acabamos de enviar na caixa abaixo", "forgot_password_error": "Erro ao tentar enviar e-mail Esqueci a senha. Certifique-se de que este userId esteja associado a uma conta.", "forgot_password_explanation": "Digite seu nome de usuário para receber um e-mail contendo as instruções para redefinir sua senha", "forgot_password_success": "Em breve, você receberá um e-mail com as instruções para redefinir sua senha. Certifique-se de verificar o seu spam se você não conseguir encontrar o e-mail", @@ -431,6 +435,7 @@ "login_error": "Erro de login, certifique-se de que as informações que você está fornecendo são válidas", "new_password": "Nova senha", "password": "Senha", + "phone_validation_explanation": "Verifique seu dispositivo móvel e insira o código de verificação que acabamos de enviar na caixa abaixo", "please_enter_gateway": "Insira um URL uCentralSec", "please_enter_password": "Por favor, insira sua senha", "please_enter_username": "Por favor insira seu nome de usuário", @@ -439,7 +444,9 @@ "sending_ellipsis": "Enviando ...", "sign_in_to_account": "Faça login em sua conta", "url": "URL uCentralSec", - "username": "Nome de usuário" + "username": "Nome de usuário", + "verification_code": "Insira sua verificação aqui", + "wrong_code": "O código de verificação inserido não é válido." }, "reboot": { "directions": "Quando você gostaria de reinicializar este dispositivo?", @@ -530,6 +537,7 @@ "add_phone_number": "ADICIONAR NÚMERO DE TELEFONE", "avatar": "Seu avatar", "avatar_file": "Seu avatar (máx. De 2 MB)", + "check_phone": "Por favor, verifique o seu telefone para o seu código de validação", "create": "Criar usuário", "create_failure": "Erro ao criar usuário. Certifique-se de que este endereço de e-mail ainda não esteja vinculado a uma conta.", "create_success": "Usuário criado com sucesso", @@ -543,13 +551,16 @@ "description": "Descrição", "edit": "Editar usuário", "email_address": "Endereço de e-mail", + "enter_new_phone": "Insira seu novo número de telefone:", "error_fetching_users": "Erro ao buscar usuários: {{error}}", + "error_sending_code": "Erro ao tentar enviar o código de validação. Por favor, confirme se o seu número de telefone é válido.", "force_password_change": "Forçar mudança de senha no login", "id": "ID do usuário.", "last_login": "Último login", "login_id": "Identificação de usuário.", "my_profile": "Meu perfil", "name": "Nome", + "new_code_sent": "Novo código enviado!", "nickname": "Apelido", "nickname_explanation": "Apelido (opcional)", "not_validated": "Não validado", @@ -559,14 +570,19 @@ "provide_email": "Por favor, forneça um endereço de e-mail válido", "provide_password": "Forneça uma senha válida", "save_avatar": "Salvar Avatar", + "send_code": "Enviar código", + "send_code_again": "Envie o Código Novamente", "show_hide_password": "Mostrar / ocultar senha", + "successful_validation": "Número de telefone validado! Clique no botão Salvar para vinculá-lo ao seu perfil", "update_failure": "Erro ao tentar atualizar: {{error}}", "update_failure_title": "Atualização falhou", "update_success": "Usuário atualizado com sucesso", "update_success_title": "Sucesso", "user_role": "Função", "users": "Comercial", - "validated": "Validado" + "validate_phone": "validar", + "validated": "Validado", + "wrong_validation_code": "Você não digitou um código válido. Por favor, tente novamente e certifique-se de ter inserido o número de telefone correto" }, "wifi_analysis": { "association": "Associação", diff --git a/src/App.js b/src/App.js index 9cb09d0..bafaa71 100644 --- a/src/App.js +++ b/src/App.js @@ -5,6 +5,7 @@ import Router from 'router'; import { AuthProvider } from 'ucentral-libs'; import { checkIfJson } from 'utils/helper'; import axiosInstance from 'utils/axiosInstance'; +import { getItem } from 'utils/localStorageHelper'; const loading = (
@@ -13,9 +14,9 @@ const loading = ( ); const App = () => { - const storageToken = sessionStorage.getItem('access_token'); - const apiEndpoints = checkIfJson(sessionStorage.getItem('gateway_endpoints')) - ? JSON.parse(sessionStorage.getItem('gateway_endpoints')) + const storageToken = getItem('access_token'); + const apiEndpoints = checkIfJson(getItem('gateway_endpoints')) + ? JSON.parse(getItem('gateway_endpoints')) : {}; return ( diff --git a/src/pages/LoginPage/index.js b/src/pages/LoginPage/index.js index 0634807..aa9f93e 100644 --- a/src/pages/LoginPage/index.js +++ b/src/pages/LoginPage/index.js @@ -1,7 +1,8 @@ import React, { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import * as axios from 'axios'; -import { LoginPage, useFormFields, useAuth } from 'ucentral-libs'; +import { LoginPage, useFormFields, useAuth, useToast } from 'ucentral-libs'; +import { setItem } from 'utils/localStorageHelper'; const initialFormState = { username: { @@ -46,6 +47,7 @@ const initialResponseState = { const Login = () => { const { t, i18n } = useTranslation(); const { setCurrentToken, setEndpoints } = useAuth(); + const { addToast } = useToast(); const [defaultConfig, setDefaultConfig] = useState({ value: '', error: false, @@ -61,8 +63,7 @@ const Login = () => { passwordPattern: '', accessPolicy: '', }); - const [isLogin, setIsLogin] = useState(true); - const [isPasswordChange, setIsChangePassword] = useState(false); + const [formType, setFormType] = useState('login'); const [fields, updateFieldWithId, updateField, setFormFields] = useFormFields(initialFormState); const axiosInstance = axios.create(); axiosInstance.defaults.timeout = 5000; @@ -76,7 +77,8 @@ const Login = () => { }); setLoginResponse(initialResponseState); setForgotResponse(initialResponseState); - setIsLogin(!isLogin); + if (formType === 'login') setFormType('forgot-password'); + else setFormType('login'); }; const cancelPasswordChange = () => { @@ -88,8 +90,7 @@ const Login = () => { }); setLoginResponse(initialResponseState); setForgotResponse(initialResponseState); - setIsLogin(true); - setIsChangePassword(false); + setFormType('login'); }; const signInValidation = () => { @@ -106,7 +107,10 @@ const Login = () => { updateField('username', { error: true }); valid = false; } - if (isPasswordChange && fields.newpassword.value !== fields.confirmpassword.value) { + if ( + formType === 'change-password' && + fields.newpassword.value !== fields.confirmpassword.value + ) { updateField('confirmpassword', { error: true }); valid = false; } @@ -172,6 +176,20 @@ const Login = () => { .catch(); }; + const getGatewayUIUrl = (token, gwUrl) => { + axiosInstance + .get(`${gwUrl}/api/v1/system?command=info`, { + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}`, + }, + }) + .then((response) => { + if (response.data.UI) setItem('owgw-ui', response.data.UI); + }) + .catch(() => {}); + }; + const SignIn = () => { setLoginResponse(initialResponseState); if (signInValidation()) { @@ -183,18 +201,23 @@ const Login = () => { password: fields.password.value, }; - if (isPasswordChange) { + if (formType === 'change-password') { parameters.newPassword = fields.newpassword.value; } axiosInstance .post(`${fields.ucentralsecurl.value}/api/v1/oauth2`, parameters) .then((response) => { - if (response.data.userMustChangePassword) { - setIsChangePassword(true); + // If there's MFA to do + if (response.data.method && response.data.created) { + setFormType(`validation-${response.data.method}-${response.data.uuid}`); return null; } - sessionStorage.setItem('access_token', response.data.access_token); + if (response.data.userMustChangePassword) { + setFormType('change-password'); + return null; + } + setItem('access_token', response.data.access_token); token = response.data.access_token; return axiosInstance.get(`${fields.ucentralsecurl.value}/api/v1/systemEndpoints`, { headers: { @@ -211,18 +234,19 @@ const Login = () => { for (const endpoint of response.data.endpoints) { endpoints[endpoint.type] = endpoint.uri; } - sessionStorage.setItem('gateway_endpoints', JSON.stringify(endpoints)); + if (endpoints.owgw) getGatewayUIUrl(token, endpoints.owgw); + setItem('gateway_endpoints', JSON.stringify(endpoints)); setEndpoints(endpoints); setCurrentToken(token); } }) .catch((error) => { - if (!isPasswordChange) { + if (formType !== 'change-password') { if ( error.response.status === 403 && error.response?.data?.ErrorDescription === 'Password change expected.' ) { - setIsChangePassword(true); + setFormType('change-password'); } setLoginResponse({ text: t('login.login_error'), @@ -279,6 +303,95 @@ const Login = () => { } }; + const validateCode = (code) => { + const options = { + headers: { + Accept: 'application/json', + }, + }; + + const parameters = { + uuid: formType.split('-').slice(2).join('-'), + answer: code, + }; + + let token = ''; + + return axiosInstance + .post( + `${fields.ucentralsecurl.value}/api/v1/oauth2?completeMFAChallenge=true`, + parameters, + options, + ) + .then((response) => { + if (response.data.userMustChangePassword) { + setFormType('change-password'); + return null; + } + setItem('access_token', response.data.access_token); + token = response.data.access_token; + return axiosInstance.get(`${fields.ucentralsecurl.value}/api/v1/systemEndpoints`, { + headers: { + Accept: 'application/json', + Authorization: `Bearer ${response.data.access_token}`, + }, + }); + }) + .then((response) => { + if (response) { + const endpoints = { + owsec: fields.ucentralsecurl.value, + }; + for (const endpoint of response.data.endpoints) { + endpoints[endpoint.type] = endpoint.uri; + } + if (endpoints.owgw) getGatewayUIUrl(token, endpoints.owgw); + setItem('gateway_endpoints', JSON.stringify(endpoints)); + setEndpoints(endpoints); + setCurrentToken(token); + } + }) + .catch(() => false) + .finally(() => { + setLoading(false); + return true; + }); + }; + + const resendValidationCode = () => { + const options = { + headers: { + Accept: 'application/json', + }, + }; + + const parameters = { + uuid: formType.split('-').slice(2).join('-'), + }; + + return axiosInstance + .post(`${fields.ucentralsecurl.value}/api/v1/oauth2?resendMFACode=true`, parameters, options) + .then(() => { + addToast({ + title: t('common.success'), + body: t('user.new_code_sent'), + color: 'success', + autohide: true, + }); + return true; + }) + .catch((e) => { + addToast({ + title: t('common.error'), + body: t('login.authentication_expired'), + color: 'danger', + autohide: true, + }); + if (e.response?.data?.ErrorCode === 403) setFormType('login'); + return false; + }); + }; + useEffect(() => { getDefaultConfig(); }, []); @@ -287,21 +400,22 @@ const Login = () => { ); }; diff --git a/src/pages/ProfilePage/index.js b/src/pages/ProfilePage/index.js index 4409f74..0a23750 100644 --- a/src/pages/ProfilePage/index.js +++ b/src/pages/ProfilePage/index.js @@ -1,8 +1,8 @@ import React, { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { CCard, CCardBody, CCardHeader, CButton, CPopover } from '@coreui/react'; -import CIcon from '@coreui/icons-react'; import { cilSave } from '@coreui/icons'; +import CIcon from '@coreui/icons-react'; import axiosInstance from 'utils/axiosInstance'; import { testRegex } from 'utils/helper'; import { useUser, EditMyProfile, useAuth, useToast } from 'ucentral-libs'; @@ -42,6 +42,14 @@ const initialState = { value: [], editable: false, }, + userTypeProprietaryInfo: { + value: {}, + error: false, + }, + mfaMethod: { + value: '', + error: false, + }, }; const ProfilePage = () => { @@ -49,7 +57,6 @@ const ProfilePage = () => { const { currentToken, endpoints, user, getAvatar, avatar } = useAuth(); const { addToast } = useToast(); const [loading, setLoading] = useState(false); - const [initialUser, setInitialUser] = useState({}); const [userForm, updateWithId, updateWithKey, setUser] = useUser(initialState); const [newAvatar, setNewAvatar] = useState(''); const [newAvatarFile, setNewAvatarFile] = useState(null); @@ -93,10 +100,24 @@ const ProfilePage = () => { }; } } - setInitialUser({ ...initialState, ...newUser }); + + newUser.mfaMethod = { + value: response.data.userTypeProprietaryInfo.mfa.enabled + ? response.data.userTypeProprietaryInfo.mfa.method + : '', + error: false, + }; + setUser({ ...initialState, ...newUser }); }) - .catch(() => {}); + .catch((e) => { + addToast({ + title: t('common.error'), + body: t('user.error_fetching_users', { error: e }), + color: 'danger', + autohide: true, + }); + }); }; const uploadAvatar = () => { @@ -124,10 +145,10 @@ const ProfilePage = () => { setNewAvatarFile(null); setFileInputKey(fileInputKey + 1); }) - .catch((e) => { + .catch(() => { addToast({ title: t('user.update_failure_title'), - body: t('user.update_failure', { error: e.response?.data?.ErrorDescription }), + body: t('user.update_failure'), color: 'danger', autohide: true, }); @@ -137,34 +158,38 @@ const ProfilePage = () => { const updateUser = () => { setLoading(true); - const parameters = { - id: user.Id, - }; - - let newData = true; - - for (const key of Object.keys(userForm)) { - if (userForm[key].editable && userForm[key].value !== initialUser[key].value) { - if ( - key === 'currentPassword' && - !testRegex(userForm[key].value, policies.passwordPattern) - ) { - updateWithKey('currentPassword', { - error: true, - }); - newData = false; - break; - } else { - parameters[key] = userForm[key].value; - } - } - } - if (newAvatarFile !== null) { uploadAvatar(); } - if (newData) { + if ( + userForm.currentPassword.value !== '' && + !testRegex(userForm.currentPassword.value, policies.passwordPattern) + ) { + updateWithKey('currentPassword', { + error: true, + }); + setLoading(false); + } else { + const newNotes = []; + + for (let i = 0; i < userForm.notes.value.length; i += 1) { + if (userForm.notes.value[i].new) newNotes.push({ note: userForm.notes.value[i].note }); + } + + const propInfo = { ...userForm.userTypeProprietaryInfo.value }; + propInfo.mfa.method = userForm.mfaMethod.value === '' ? undefined : userForm.mfaMethod.value; + propInfo.mfa.enabled = userForm.mfaMethod.value !== ''; + + const parameters = { + id: user.Id, + description: userForm.description.value, + name: userForm.name.value, + userRole: userForm.userRole.value, + notes: newNotes, + userTypeProprietaryInfo: propInfo, + }; + const options = { headers: { Accept: 'application/json', @@ -194,35 +219,18 @@ const ProfilePage = () => { getUser(); setLoading(false); }); - } else { - setLoading(false); } }; const addNote = (currentNote) => { - setLoading(true); - - const parameters = { - id: user.Id, - notes: [{ note: currentNote }], - }; - - const options = { - headers: { - Accept: 'application/json', - Authorization: `Bearer ${currentToken}`, - }, - }; - - axiosInstance - .put(`${endpoints.owsec}/api/v1/user/${user.Id}`, parameters, options) - .then(() => { - getUser(); - }) - .catch(() => {}) - .finally(() => { - setLoading(false); - }); + const newNotes = [...userForm.notes.value]; + newNotes.unshift({ + note: currentNote, + new: true, + created: new Date().getTime() / 1000, + createdBy: '', + }); + updateWithKey('notes', { value: newNotes }); }; const showPreview = (e) => { @@ -239,6 +247,7 @@ const ProfilePage = () => { Authorization: `Bearer ${currentToken}`, }, }; + return axiosInstance .delete(`${endpoints.owsec}/api/v1/avatar/${user.Id}`, options) .then(() => { @@ -250,6 +259,54 @@ const ProfilePage = () => { }); }; + const sendPhoneNumberTest = async (phoneNumber) => { + const options = { + headers: { + Accept: 'application/json', + Authorization: `Bearer ${currentToken}`, + }, + }; + + return axiosInstance + .post(`${endpoints.owsec}/api/v1/sms?validateNumber=true`, { to: phoneNumber }, options) + .then(() => true) + .catch(() => { + addToast({ + title: t('common.error'), + body: t('user.error_sending_code'), + color: 'danger', + autohide: true, + }); + return false; + }); + }; + + const testVerificationCode = async (phoneNumber, code) => { + const options = { + headers: { + Accept: 'application/json', + Authorization: `Bearer ${currentToken}`, + }, + }; + + return axiosInstance + .post( + `${endpoints.owsec}/api/v1/sms?completeValidation=true&validationCode=${code}`, + { to: phoneNumber }, + options, + ) + .then(() => true) + .catch(() => { + addToast({ + title: t('common.error'), + body: t('user.wrong_validation_code'), + color: 'danger', + autohide: true, + }); + return false; + }); + }; + useEffect(() => { if (user.Id) { getAvatar(); @@ -262,11 +319,12 @@ const ProfilePage = () => { return ( - -
+ +
{t('user.my_profile')}
+
- - + +
@@ -276,6 +334,7 @@ const ProfilePage = () => { t={t} user={userForm} updateUserWithId={updateWithId} + updateWithKey={updateWithKey} loading={loading} policies={policies} addNote={addNote} @@ -284,6 +343,8 @@ const ProfilePage = () => { showPreview={showPreview} deleteAvatar={deleteAvatar} fileInputKey={fileInputKey} + sendPhoneNumberTest={sendPhoneNumberTest} + testVerificationCode={testVerificationCode} /> diff --git a/src/router/index.js b/src/router/index.js index 475dca1..3136cbe 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,4 +1,4 @@ -import { useAuth } from 'ucentral-libs'; +import { useAuth, ToastProvider } from 'ucentral-libs'; import { Route } from 'react-router-dom'; import React from 'react'; @@ -16,7 +16,9 @@ const Routes = () => { currentToken !== '' && Object.keys(endpoints).length !== 0 ? ( ) : ( - + + + ) } /> diff --git a/src/utils/axiosInstance.js b/src/utils/axiosInstance.js index e179807..060383a 100644 --- a/src/utils/axiosInstance.js +++ b/src/utils/axiosInstance.js @@ -20,6 +20,8 @@ axiosInstance.interceptors.response.use( case 401: break; case 403: + localStorage.removeItem('access_token'); + localStorage.removeItem('gateway_endpoints'); sessionStorage.clear(); window.location.href = '/'; break;