Hide the 'Delete' button in the account console when DeleteCredentialAction is disabled or unavailable

closes #30204

Signed-off-by: mposolda <mposolda@gmail.com>
This commit is contained in:
mposolda 2024-10-21 16:01:41 +02:00 committed by Marek Posolda
parent 2f27dc91e0
commit 703f16ea86
3 changed files with 32 additions and 5 deletions

View file

@ -207,7 +207,7 @@ export const SigningIn = () => {
aria-label={t("updateCredAriaLabel")}
aria-labelledby={`cred-${meta.credential.id}`}
>
{container.removeable ? (
{container.removeable && (
<Button
variant="danger"
data-testrole="remove"
@ -221,12 +221,12 @@ export const SigningIn = () => {
>
{t("delete")}
</Button>
) : (
)}
{container.updateAction && (
<Button
variant="secondary"
onClick={() => {
if (container.updateAction)
login({ action: container.updateAction });
login({ action: container.updateAction });
}}
data-testrole="update"
>

View file

@ -244,6 +244,9 @@ public class CredentialTypeMetadata implements Comparable<CredentialTypeMetadata
if (instance.createAction != null && instance.updateAction != null) {
throw new IllegalStateException("Both createAction and updateAction are not null when building CredentialTypeMetadata for the credential type '" + instance.type);
}
if (!verifyRequiredAction(session, "delete_credential")) {
instance.removeable = false;
}
return instance;
}

View file

@ -31,6 +31,7 @@ import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.authentication.authenticators.browser.WebAuthnAuthenticatorFactory;
import org.keycloak.authentication.authenticators.browser.WebAuthnPasswordlessAuthenticatorFactory;
import org.keycloak.authentication.requiredactions.DeleteCredentialAction;
import org.keycloak.authentication.requiredactions.WebAuthnPasswordlessRegisterFactory;
import org.keycloak.authentication.requiredactions.WebAuthnRegisterFactory;
import org.keycloak.broker.provider.util.SimpleHttp;
@ -987,10 +988,33 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
assertEquals(204, response.getStatus());
}
// Revert - re-enable requiredAction and remove OTP credential from the user
// Revert - re-enable requiredAction
setRequiredActionEnabledStatus(UserModel.RequiredAction.CONFIGURE_TOTP.name(), true);
}
// Issue 30204
@Test
public void testCredentialsGetWithDisabledDeleteCredentialAction() throws IOException {
// Assert OTP will be returned by default
List<AccountCredentialResource.CredentialContainer> credentials = getCredentials();
assertExpectedCredentialTypes(credentials, PasswordCredentialModel.TYPE, OTPCredentialModel.TYPE);
// Assert OTP removeable
AccountCredentialResource.CredentialContainer otpCredential = credentials.get(1);
assertTrue(otpCredential.isRemoveable());
// Disable "Delete credential" action
setRequiredActionEnabledStatus(DeleteCredentialAction.PROVIDER_ID, false);
// Assert OTP not removeable
credentials = getCredentials();
otpCredential = credentials.get(1);
assertFalse(otpCredential.isRemoveable());
// Revert - re-enable requiredAction
setRequiredActionEnabledStatus(DeleteCredentialAction.PROVIDER_ID, true);
}
private void setRequiredActionEnabledStatus(String requiredActionProviderId, boolean enabled) {
RequiredActionProviderRepresentation requiredActionRep = testRealm().flows().getRequiredAction(requiredActionProviderId);
requiredActionRep.setEnabled(enabled);