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:
parent
2f27dc91e0
commit
703f16ea86
3 changed files with 32 additions and 5 deletions
|
@ -207,7 +207,7 @@ export const SigningIn = () => {
|
||||||
aria-label={t("updateCredAriaLabel")}
|
aria-label={t("updateCredAriaLabel")}
|
||||||
aria-labelledby={`cred-${meta.credential.id}`}
|
aria-labelledby={`cred-${meta.credential.id}`}
|
||||||
>
|
>
|
||||||
{container.removeable ? (
|
{container.removeable && (
|
||||||
<Button
|
<Button
|
||||||
variant="danger"
|
variant="danger"
|
||||||
data-testrole="remove"
|
data-testrole="remove"
|
||||||
|
@ -221,12 +221,12 @@ export const SigningIn = () => {
|
||||||
>
|
>
|
||||||
{t("delete")}
|
{t("delete")}
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
)}
|
||||||
|
{container.updateAction && (
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (container.updateAction)
|
login({ action: container.updateAction });
|
||||||
login({ action: container.updateAction });
|
|
||||||
}}
|
}}
|
||||||
data-testrole="update"
|
data-testrole="update"
|
||||||
>
|
>
|
||||||
|
|
|
@ -244,6 +244,9 @@ public class CredentialTypeMetadata implements Comparable<CredentialTypeMetadata
|
||||||
if (instance.createAction != null && instance.updateAction != null) {
|
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);
|
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;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.keycloak.admin.client.resource.RealmResource;
|
||||||
import org.keycloak.admin.client.resource.UserResource;
|
import org.keycloak.admin.client.resource.UserResource;
|
||||||
import org.keycloak.authentication.authenticators.browser.WebAuthnAuthenticatorFactory;
|
import org.keycloak.authentication.authenticators.browser.WebAuthnAuthenticatorFactory;
|
||||||
import org.keycloak.authentication.authenticators.browser.WebAuthnPasswordlessAuthenticatorFactory;
|
import org.keycloak.authentication.authenticators.browser.WebAuthnPasswordlessAuthenticatorFactory;
|
||||||
|
import org.keycloak.authentication.requiredactions.DeleteCredentialAction;
|
||||||
import org.keycloak.authentication.requiredactions.WebAuthnPasswordlessRegisterFactory;
|
import org.keycloak.authentication.requiredactions.WebAuthnPasswordlessRegisterFactory;
|
||||||
import org.keycloak.authentication.requiredactions.WebAuthnRegisterFactory;
|
import org.keycloak.authentication.requiredactions.WebAuthnRegisterFactory;
|
||||||
import org.keycloak.broker.provider.util.SimpleHttp;
|
import org.keycloak.broker.provider.util.SimpleHttp;
|
||||||
|
@ -987,10 +988,33 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
||||||
assertEquals(204, response.getStatus());
|
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);
|
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) {
|
private void setRequiredActionEnabledStatus(String requiredActionProviderId, boolean enabled) {
|
||||||
RequiredActionProviderRepresentation requiredActionRep = testRealm().flows().getRequiredAction(requiredActionProviderId);
|
RequiredActionProviderRepresentation requiredActionRep = testRealm().flows().getRequiredAction(requiredActionProviderId);
|
||||||
requiredActionRep.setEnabled(enabled);
|
requiredActionRep.setEnabled(enabled);
|
||||||
|
|
Loading…
Reference in a new issue