diff --git a/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialEditDialog.java b/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialEditDialog.java index ba404d8e08c..bfccc0f2014 100644 --- a/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialEditDialog.java +++ b/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialEditDialog.java @@ -12,20 +12,13 @@ *******************************************************************************/ package org.eclipse.kapua.app.console.module.authentication.client.tabs.credentials; -import com.extjs.gxt.ui.client.event.BaseEvent; -import com.extjs.gxt.ui.client.event.Events; -import com.extjs.gxt.ui.client.event.Listener; import com.extjs.gxt.ui.client.widget.Label; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.rpc.AsyncCallback; - import org.eclipse.kapua.app.console.module.api.client.util.ConsoleInfo; import org.eclipse.kapua.app.console.module.api.client.util.DateUtils; import org.eclipse.kapua.app.console.module.api.client.util.DialogUtils; -import org.eclipse.kapua.app.console.module.api.client.util.FailureHandler; import org.eclipse.kapua.app.console.module.api.client.util.KapuaSafeHtmlUtils; -import org.eclipse.kapua.app.console.module.api.client.util.validator.ConfirmPasswordUpdateFieldValidator; -import org.eclipse.kapua.app.console.module.api.client.util.validator.PasswordUpdateFieldValidator; import org.eclipse.kapua.app.console.module.api.shared.model.session.GwtSession; import org.eclipse.kapua.app.console.module.authentication.shared.model.GwtCredential; import org.eclipse.kapua.app.console.module.authentication.shared.model.GwtCredentialType; @@ -106,37 +99,17 @@ private void loadCredential() { @Override protected void onRender(Element parent, int pos) { super.onRender(parent, pos); + password.setVisible(false); + confirmPassword.setVisible(false); + passwordTooltip.setVisible(false); credentialFormPanel.remove(credentialType); credentialTypeLabel.setVisible(true); credentialTypeLabel.setValue(selectedCredential.getCredentialType()); - password.setFieldLabel(MSGS.dialogEditFieldNewPassword()); - password.setAllowBlank(true); - password.addListener(Events.Change, new Listener() { - - @Override - public void handleEvent(BaseEvent be) { - confirmPassword.setAllowBlank(password.getValue() == null || password.getValue().equals("")); - } - }); - confirmPassword.setFieldLabel(MSGS.dialogEditFieldConfirmNewPassword()); - confirmPassword.setAllowBlank(true); if (selectedCredential.getLockoutReset() != null && selectedCredential.getLockoutReset().after(new Date())) { lockedUntil.setText(MSGS.dialogEditLockedUntil(DateUtils.formatDateTime(selectedCredential.getLockoutReset()))); credentialFormPanel.add(lockedUntil); } - GWT_CREDENTIAL_SERVICE.getMinPasswordLength(selectedCredential.getScopeId(), new AsyncCallback() { - - @Override - public void onFailure(Throwable caught) { - FailureHandler.handle(caught); - } - - @Override - public void onSuccess(Integer result) { - confirmPassword.setValidator(new ConfirmPasswordUpdateFieldValidator(confirmPassword, password, result)); - password.setValidator(new PasswordUpdateFieldValidator(password, result)); - } - }); + DialogUtils.resizeDialog(this, 400, 230); } @Override diff --git a/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialGrid.java b/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialGrid.java index e7c8944764f..47125daddac 100644 --- a/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialGrid.java +++ b/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialGrid.java @@ -39,6 +39,7 @@ import org.eclipse.kapua.app.console.module.authentication.client.messages.ConsoleCredentialMessages; import org.eclipse.kapua.app.console.module.authentication.shared.model.GwtCredential; import org.eclipse.kapua.app.console.module.authentication.shared.model.GwtCredentialQuery; +import org.eclipse.kapua.app.console.module.authentication.shared.model.GwtCredentialType; import org.eclipse.kapua.app.console.module.authentication.shared.model.permission.CredentialSessionPermission; import org.eclipse.kapua.app.console.module.authentication.shared.service.GwtCredentialService; import org.eclipse.kapua.app.console.module.authentication.shared.service.GwtCredentialServiceAsync; @@ -237,6 +238,10 @@ private void updateToolbarButtons() { getSelectionModel().getSelectedItem() != null && getSelectionModel().getSelectedItem().getLockoutReset() != null && currentSession.hasPermission(CredentialSessionPermission.write())); + getToolbar().getResetPasswordButton().setEnabled( + getSelectionModel().getSelectedItem() != null && + getSelectionModel().getSelectedItem().getCredentialTypeEnum().equals(GwtCredentialType.PASSWORD) && + currentSession.hasPermission(CredentialSessionPermission.write())); } @Override diff --git a/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialResetDialog.java b/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialResetDialog.java new file mode 100644 index 00000000000..026f2b05ef4 --- /dev/null +++ b/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialResetDialog.java @@ -0,0 +1,172 @@ +/******************************************************************************* + * Copyright (c) 2023, 2022 Eurotech and/or its affiliates and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Eurotech - initial API and implementation + *******************************************************************************/ +package org.eclipse.kapua.app.console.module.authentication.client.tabs.credentials; + +import com.extjs.gxt.ui.client.event.BaseEvent; +import com.extjs.gxt.ui.client.event.Events; +import com.extjs.gxt.ui.client.event.Listener; +import com.extjs.gxt.ui.client.widget.Label; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.rpc.AsyncCallback; +import org.eclipse.kapua.app.console.module.api.client.util.ConsoleInfo; +import org.eclipse.kapua.app.console.module.api.client.util.DateUtils; +import org.eclipse.kapua.app.console.module.api.client.util.DialogUtils; +import org.eclipse.kapua.app.console.module.api.client.util.FailureHandler; +import org.eclipse.kapua.app.console.module.api.client.util.validator.ConfirmPasswordUpdateFieldValidator; +import org.eclipse.kapua.app.console.module.api.client.util.validator.PasswordUpdateFieldValidator; +import org.eclipse.kapua.app.console.module.api.shared.model.session.GwtSession; +import org.eclipse.kapua.app.console.module.authentication.shared.model.GwtCredential; +import org.eclipse.kapua.app.console.module.authentication.shared.model.GwtCredentialType; + +import java.util.Date; + +public class CredentialResetDialog extends CredentialAddDialog { + private final GwtCredential selectedCredential; + + private final Label lockedUntil = new Label(); + + + public CredentialResetDialog(GwtSession currentSession, String selectedUserId, String selectedUserName, GwtCredential selectedCredential) { + super(currentSession, selectedUserId, selectedUserName); + this.selectedCredential = selectedCredential; + } + + + @Override + public void submit() { + selectedCredential.setCredentialKey(password.getValue()); + selectedCredential.setExpirationDate(expirationDate.getValue()); + selectedCredential.setCredentialStatus(credentialStatus.getValue().getValue().toString()); + selectedCredential.setOptlock(optlock.getValue().intValue()); + GWT_CREDENTIAL_SERVICE.resetPassword(xsrfToken, selectedCredential.getScopeId(), selectedCredential.getId(), password.getValue(), new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + unmask(); + + submitButton.enable(); + cancelButton.enable(); + status.hide(); + + exitStatus = false; + if (!isPermissionErrorMessage(caught)) { + exitMessage = MSGS.dialogEditError(caught.getLocalizedMessage()); + } + } + + @Override + public void onSuccess(Void result) { + exitStatus = true; + exitMessage = MSGS.dialogEditConfirmationPassword(); + + hide(); + } + }); + } + + + @Override + public void createBody() { + super.createBody(); + loadCredential(); + } + + + private void loadCredential() { + credentialType.setSimpleValue(selectedCredential.getCredentialTypeEnum()); + expirationDate.setValue(selectedCredential.getExpirationDate()); + credentialStatus.setSimpleValue(selectedCredential.getCredentialStatusEnum()); + optlock.setValue(selectedCredential.getOptlock()); + if (selectedCredential.getCredentialTypeEnum() == GwtCredentialType.API_KEY) { + expirationDate.setToolTip(MSGS.dialogAddFieldExpirationDateApiKeyTooltip()); + credentialStatus.setToolTip(MSGS.dialogAddStatusApiKeyTooltip()); + } else if (selectedCredential.getCredentialTypeEnum() == GwtCredentialType.PASSWORD) { + passwordTooltip.show(); + DialogUtils.resizeDialog(CredentialResetDialog.this, 400, 355); + expirationDate.setToolTip(MSGS.dialogAddFieldExpirationDatePasswordTooltip()); + credentialStatus.setToolTip(MSGS.dialogAddStatusPasswordTooltip()); + } + } + + + @Override + protected void onRender(Element parent, int pos) { + super.onRender(parent, pos); + DialogUtils.resizeDialog(this, 400, 250); + password.setVisible(true); + confirmPassword.setVisible(true); + passwordTooltip.setVisible(true); + credentialFormPanel.remove(credentialType); + credentialTypeLabel.setVisible(false); + expirationDate.setVisible(false); + credentialStatus.setVisible(false); + password.setFieldLabel(MSGS.dialogEditFieldNewPassword()); + password.setAllowBlank(true); + password.addListener(Events.Change, new Listener() { + + @Override + public void handleEvent(BaseEvent be) { + confirmPassword.setAllowBlank(password.getValue() == null || password.getValue().equals("")); + } + }); + confirmPassword.setFieldLabel(MSGS.dialogEditFieldConfirmNewPassword()); + confirmPassword.setAllowBlank(true); + if (selectedCredential.getLockoutReset() != null && selectedCredential.getLockoutReset().after(new Date())) { + lockedUntil.setText(MSGS.dialogEditLockedUntil(DateUtils.formatDateTime(selectedCredential.getLockoutReset()))); + credentialFormPanel.add(lockedUntil); + } + GWT_CREDENTIAL_SERVICE.getMinPasswordLength(selectedCredential.getScopeId(), new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + FailureHandler.handle(caught); + } + + @Override + public void onSuccess(Integer result) { + confirmPassword.setValidator(new ConfirmPasswordUpdateFieldValidator(confirmPassword, password, result)); + password.setValidator(new PasswordUpdateFieldValidator(password, result)); + } + }); + } + + + @Override + public void validateUserCredential() { + if (password.getValue() != null && confirmPassword.getValue() == null) { + ConsoleInfo.display(CMSGS.popupError(), MSGS.credentialConfirmPasswordRequired()); + } else if (!password.isValid()) { + ConsoleInfo.display(CMSGS.popupError(), password.getErrorMessage()); + } else if (password.getValue() != null && !password.getValue().equals(confirmPassword.getValue())) { + ConsoleInfo.display(CMSGS.popupError(), confirmPassword.getErrorMessage()); + } + } + + + @Override + protected void preSubmit() { + super.preSubmit(); + } + + + @Override + public String getHeaderMessage() { + return MSGS.dialogResetPasswordHeader(selectedCredential.getUsername()); + } + + + @Override + public String getInfoMessage() { + return MSGS.dialogResetPassword(); + } +} diff --git a/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialToolbar.java b/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialToolbar.java index 20f2c7a2043..2eeb08e0d8f 100644 --- a/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialToolbar.java +++ b/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/client/tabs/credentials/CredentialToolbar.java @@ -33,6 +33,7 @@ public class CredentialToolbar extends EntityCRUDToolbar { private String selectedUserName; private final KapuaButton unlockButton; + private final KapuaButton resetPasswordButton; private static final ConsoleCredentialMessages MSGS = GWT.create(ConsoleCredentialMessages.class); @@ -48,6 +49,16 @@ public void componentSelected(ButtonEvent buttonEvent) { } } }); + resetPasswordButton = new KapuaButton(MSGS.resetPasswordButton(), new KapuaIcon(IconSet.UNDO), new SelectionListener() { + + @Override + public void componentSelected(ButtonEvent buttonEvent) { + GwtCredential selectedCredential = gridSelectionModel.getSelectedItem(); + if (selectedUserId != null && selectedCredential != null) { + showResetPasswordDialog(selectedCredential); + } + } + }); } @Override @@ -55,6 +66,8 @@ protected void onRender(Element target, int index) { super.onRender(target, index); add(new SeparatorToolItem()); add(getUnlockButton()); + add(new SeparatorToolItem()); + add(getResetPasswordButton()); updateButtonsEnabled(); getEditEntityButton().disable(); @@ -64,6 +77,7 @@ protected void onRender(Element target, int index) { if (getFilterButton() != null) { getFilterButton().hide(); } + resetPasswordButton.disable(); setBorders(true); } @@ -115,10 +129,22 @@ public KapuaButton getUnlockButton() { return unlockButton; } + + public KapuaButton getResetPasswordButton() { + return resetPasswordButton; + } + + private void showUnlockDialog(GwtCredential selectedCredential) { CredentialUnlockDialog dialog = new CredentialUnlockDialog(selectedCredential); dialog.addListener(Events.Hide, getHideDialogListener()); dialog.show(); } + + private void showResetPasswordDialog(GwtCredential selectedCredential) { + CredentialResetDialog dialog = new CredentialResetDialog(currentSession, selectedUserId, selectedUserName, selectedCredential); + dialog.addListener(Events.Hide, getHideDialogListener()); + dialog.show(); + } } diff --git a/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/server/GwtCredentialServiceImpl.java b/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/server/GwtCredentialServiceImpl.java index fe4b689c06b..7c4653443d9 100644 --- a/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/server/GwtCredentialServiceImpl.java +++ b/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/server/GwtCredentialServiceImpl.java @@ -49,6 +49,7 @@ import org.eclipse.kapua.service.authentication.shiro.utils.AuthenticationUtils; import org.eclipse.kapua.service.authentication.shiro.utils.CryptAlgorithm; import org.eclipse.kapua.service.authentication.user.PasswordChangeRequest; +import org.eclipse.kapua.service.authentication.user.PasswordResetRequest; import org.eclipse.kapua.service.authentication.user.UserCredentialsFactory; import org.eclipse.kapua.service.authentication.user.UserCredentialsService; import org.eclipse.kapua.service.user.User; @@ -124,7 +125,7 @@ public UserListResult call() throws Exception { } } catch (Throwable t) { - KapuaExceptionHandler.handle(t); + throw KapuaExceptionHandler.buildExceptionFromError(t); } return new BasePagingLoadResult(gwtCredentials, loadConfig.getOffset(), totalLength); @@ -140,7 +141,7 @@ public void delete(GwtXSRFToken xsrfToken, String stringAccountId, String gwtCre CREDENTIAL_SERVICE.delete(scopeId, credentialId); } catch (Throwable t) { - KapuaExceptionHandler.handle(t); + throw KapuaExceptionHandler.buildExceptionFromError(t); } } @@ -166,7 +167,7 @@ public GwtCredential create(GwtXSRFToken xsrfToken, GwtCredentialCreator gwtCred gwtCredential.setCredentialKey(credential.getCredentialKey()); } catch (Throwable t) { - KapuaExceptionHandler.handle(t); + throw KapuaExceptionHandler.buildExceptionFromError(t); } // @@ -204,7 +205,7 @@ public GwtCredential update(GwtXSRFToken gwtXsrfToken, GwtCredential gwtCredenti gwtCredentialUpdated = KapuaGwtAuthenticationModelConverter.convertCredential(credentialUpdated, user); } catch (Throwable t) { - KapuaExceptionHandler.handle(t); + throw KapuaExceptionHandler.buildExceptionFromError(t); } // @@ -244,14 +245,14 @@ private void fixPasswordValidationBypass(GwtCredential gwtCredential) ); } catch (Throwable t) { - KapuaExceptionHandler.handle(t); + throw KapuaExceptionHandler.buildExceptionFromError(t); } } @Override public void changePassword(GwtXSRFToken gwtXsrfToken, String oldPassword, final String newPassword, String mfaCode, String stringUserId, String stringScopeId) throws GwtKapuaException { - String username = null; + String username; try { final KapuaId scopeId = GwtKapuaCommonsModelConverter.convertKapuaId(stringScopeId); final KapuaId userId = GwtKapuaCommonsModelConverter.convertKapuaId(stringUserId); @@ -280,10 +281,28 @@ public User call() throws Exception { USER_CREDENTIALS_SERVICE.changePasswordRequest(passwordChangeRequest); } catch (Exception e) { - KapuaExceptionHandler.handle(e); + throw KapuaExceptionHandler.buildExceptionFromError(e); } } + + @Override + public void resetPassword(GwtXSRFToken gwtXsrfToken, String stringScopeId, String gwtCredentialId, final String newPassword) throws GwtKapuaException { + checkXSRFToken(gwtXsrfToken); + + try { + final KapuaId scopeId = GwtKapuaCommonsModelConverter.convertKapuaId(stringScopeId); + final KapuaId credentialId = GwtKapuaCommonsModelConverter.convertKapuaId(gwtCredentialId); + + PasswordResetRequest passwordResetRequest = USER_CREDENTIALS_FACTORY.newPasswordResetRequest(); + passwordResetRequest.setNewPassword(newPassword); + USER_CREDENTIALS_SERVICE.resetPassword(scopeId, credentialId, passwordResetRequest); + } catch (KapuaException e) { + throw KapuaExceptionHandler.buildExceptionFromError(e); + } + } + + @Override public void unlock(GwtXSRFToken xsrfToken, String stringScopeId, String gwtCredentialId) throws GwtKapuaException { @@ -297,7 +316,7 @@ public void unlock(GwtXSRFToken xsrfToken, String stringScopeId, String gwtCrede CREDENTIAL_SERVICE.unlock(scopeId, credentialId); } catch (Throwable t) { - KapuaExceptionHandler.handle(t); + throw KapuaExceptionHandler.buildExceptionFromError(t); } } diff --git a/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/shared/service/GwtCredentialService.java b/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/shared/service/GwtCredentialService.java index d5a76548432..a97ed907f23 100644 --- a/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/shared/service/GwtCredentialService.java +++ b/console/module/authentication/src/main/java/org/eclipse/kapua/app/console/module/authentication/shared/service/GwtCredentialService.java @@ -12,17 +12,16 @@ *******************************************************************************/ package org.eclipse.kapua.app.console.module.authentication.shared.service; +import com.extjs.gxt.ui.client.data.PagingLoadConfig; +import com.extjs.gxt.ui.client.data.PagingLoadResult; +import com.google.gwt.user.client.rpc.RemoteService; +import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; import org.eclipse.kapua.app.console.module.api.client.GwtKapuaException; import org.eclipse.kapua.app.console.module.api.shared.model.GwtXSRFToken; import org.eclipse.kapua.app.console.module.authentication.shared.model.GwtCredential; import org.eclipse.kapua.app.console.module.authentication.shared.model.GwtCredentialCreator; import org.eclipse.kapua.app.console.module.authentication.shared.model.GwtCredentialQuery; -import com.extjs.gxt.ui.client.data.PagingLoadConfig; -import com.extjs.gxt.ui.client.data.PagingLoadResult; -import com.google.gwt.user.client.rpc.RemoteService; -import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; - @RemoteServiceRelativePath("credential") public interface GwtCredentialService extends RemoteService { @@ -33,7 +32,7 @@ public interface GwtCredentialService extends RemoteService { * @return * @throws GwtKapuaException */ - public PagingLoadResult query(PagingLoadConfig loadConfig, GwtCredentialQuery gwtCredentialQuery) + PagingLoadResult query(PagingLoadConfig loadConfig, GwtCredentialQuery gwtCredentialQuery) throws GwtKapuaException; /** @@ -42,19 +41,21 @@ public PagingLoadResult query(PagingLoadConfig loadConfig, GwtCre * @param gwtCredentialId * @throws GwtKapuaException */ - public void delete(GwtXSRFToken xsfrToken, String stringScopeId, String gwtCredentialId) + void delete(GwtXSRFToken xsfrToken, String stringScopeId, String gwtCredentialId) throws GwtKapuaException; - public GwtCredential create(GwtXSRFToken gwtXsrfToken, GwtCredentialCreator gwtRoleCreator) + GwtCredential create(GwtXSRFToken gwtXsrfToken, GwtCredentialCreator gwtRoleCreator) throws GwtKapuaException; - public GwtCredential update(GwtXSRFToken gwtXsrfToken, GwtCredential gwtCredential) + GwtCredential update(GwtXSRFToken gwtXsrfToken, GwtCredential gwtCredential) throws GwtKapuaException; - public void changePassword(GwtXSRFToken gwtXsrfToken, String oldPassword, String newPassword, String mfaCode, String stringUserId, String stringScopeId) + void changePassword(GwtXSRFToken gwtXsrfToken, String oldPassword, String newPassword, String mfaCode, String stringUserId, String stringScopeId) throws GwtKapuaException; - public void unlock(GwtXSRFToken xsfrToken, String stringScopeId, String gwtCredentialId) + void resetPassword(GwtXSRFToken gwtXsrfToken, String stringScopeId, String gwtCredentialId, String newPassword) throws GwtKapuaException; + + void unlock(GwtXSRFToken xsfrToken, String stringScopeId, String gwtCredentialId) throws GwtKapuaException; Integer getMinPasswordLength(String scopeId) diff --git a/console/module/authentication/src/main/resources/org/eclipse/kapua/app/console/module/authentication/client/messages/ConsoleCredentialMessages.properties b/console/module/authentication/src/main/resources/org/eclipse/kapua/app/console/module/authentication/client/messages/ConsoleCredentialMessages.properties index 8a5363c4255..a3dc645c226 100644 --- a/console/module/authentication/src/main/resources/org/eclipse/kapua/app/console/module/authentication/client/messages/ConsoleCredentialMessages.properties +++ b/console/module/authentication/src/main/resources/org/eclipse/kapua/app/console/module/authentication/client/messages/ConsoleCredentialMessages.properties @@ -76,6 +76,8 @@ dialogEditError=Credentials edit failed: {0} dialogEditFieldNewPassword=New Password dialogEditFieldConfirmNewPassword=Confirm New Password dialogEditLockedUntil=These credentials are locked until {0} +dialogResetPassword=Reset the password for the selected user. +dialogResetPasswordHeader=Reset Password: {0} # # Delete dialog @@ -96,6 +98,11 @@ dialogUnlockInfo=Are you sure you want to unlock selected credential? dialogUnlockConfirmation=Credentials successfully unlocked. dialogUnlockError=Credentials unlock failed: {0} +# +# Reset password dialog +resetPasswordButton=Reset +dialogPasswordResetHeader=Reset password: {0} + # # Credential Filter filterHeader=Credentials Filter