Prevent user from removing built-in client scopes (#27134)
Closes #26937 Signed-off-by: Kaustubh B <kbawanka@redhat.com>
This commit is contained in:
parent
83af01c4c0
commit
03f6cda85a
5 changed files with 57 additions and 27 deletions
|
@ -282,6 +282,7 @@ samlKeysExportError=无法导出密钥,因为:{{error}}
|
|||
webAuthnPolicyCreateTimeout=超时
|
||||
comparison=对比
|
||||
deletedSuccessClientScope=客户端作用域已删除
|
||||
notAllowedToDeleteAllClientScopes=您不能删除所有客户端作用域
|
||||
notBeforeError=清除领域的“不早于”时出错\: {{error}}
|
||||
columnDisplayName=展示名称
|
||||
noUsersFoundErrorStorage=找不到用户,可能是由于错误配置了联合提供程序{{error}}
|
||||
|
|
|
@ -305,6 +305,7 @@ webAuthnPolicyCreateTimeout=Timeout
|
|||
comparison=Comparison
|
||||
passwordPoliciesHelp.digits=The number of numerical digits required in the password string.
|
||||
deletedSuccessClientScope=The client scope has been deleted
|
||||
notAllowedToDeleteAllClientScopes=You are not allowed to delete all the client scopes.
|
||||
columnDisplayName=Display name
|
||||
noUsersFoundErrorStorage=No users found, could be due to wrongly configured federated provider {{error}}
|
||||
lookAround=Look around window
|
||||
|
|
|
@ -157,22 +157,28 @@ export default function ClientScopesSection() {
|
|||
continueButtonLabel: "delete",
|
||||
continueButtonVariant: ButtonVariant.danger,
|
||||
onConfirm: async () => {
|
||||
try {
|
||||
for (const scope of selectedScopes) {
|
||||
try {
|
||||
await removeScope(scope);
|
||||
} catch (error: any) {
|
||||
console.warn(
|
||||
"could not remove scope",
|
||||
error.response?.data?.errorMessage || error,
|
||||
);
|
||||
const clientScopes = await adminClient.clientScopes.find();
|
||||
const clientScopeLength = Object.keys(clientScopes).length;
|
||||
if (clientScopeLength - selectedScopes.length > 0) {
|
||||
try {
|
||||
for (const scope of selectedScopes) {
|
||||
try {
|
||||
await removeScope(scope);
|
||||
} catch (error: any) {
|
||||
console.warn(
|
||||
"could not remove scope",
|
||||
error.response?.data?.errorMessage || error,
|
||||
);
|
||||
}
|
||||
await adminClient.clientScopes.del({ id: scope.id! });
|
||||
}
|
||||
await adminClient.clientScopes.del({ id: scope.id! });
|
||||
addAlert(t("deletedSuccessClientScope"), AlertVariant.success);
|
||||
refresh();
|
||||
} catch (error) {
|
||||
addError("deleteErrorClientScope", error);
|
||||
}
|
||||
addAlert(t("deletedSuccessClientScope"), AlertVariant.success);
|
||||
refresh();
|
||||
} catch (error) {
|
||||
addError("deleteErrorClientScope", error);
|
||||
} else {
|
||||
addError(t("notAllowedToDeleteAllClientScopes"), "error");
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -47,6 +47,7 @@ import jakarta.ws.rs.Produces;
|
|||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -148,14 +149,19 @@ public class ClientScopeResource {
|
|||
@Tag(name = KeycloakOpenAPI.Admin.Tags.CLIENT_SCOPES)
|
||||
@Operation(summary = "Delete the client scope")
|
||||
public Response deleteClientScope() {
|
||||
auth.clients().requireManage(clientScope);
|
||||
|
||||
try {
|
||||
realm.removeClientScope(clientScope.getId());
|
||||
adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).success();
|
||||
return Response.noContent().build();
|
||||
} catch (ModelException me) {
|
||||
throw ErrorResponse.error(me.getMessage(), Response.Status.BAD_REQUEST);
|
||||
auth.clients().requireManage(clientScope);
|
||||
long clientScopesCount = Arrays.stream(realm.getClientScopesStream().toArray()).count();
|
||||
if (clientScopesCount > 1) {
|
||||
try {
|
||||
realm.removeClientScope(clientScope.getId());
|
||||
adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).success();
|
||||
return Response.noContent().build();
|
||||
} catch (ModelException me) {
|
||||
throw ErrorResponse.error(me.getMessage(), Response.Status.BAD_REQUEST);
|
||||
}
|
||||
} else {
|
||||
throw ErrorResponse.error("You are not allowed to delete all the client scopes.", Response.Status.FORBIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,12 +33,7 @@ import org.keycloak.models.ClientScopeModel;
|
|||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.protocol.saml.SamlProtocol;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.ClientScopeRepresentation;
|
||||
import org.keycloak.representations.idm.ErrorRepresentation;
|
||||
import org.keycloak.representations.idm.MappingsRepresentation;
|
||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.*;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.arquillian.annotation.DisableFeature;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
|
@ -841,6 +836,19 @@ public class ClientScopeTest extends AbstractClientTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteAllClientScopesMustFail() {
|
||||
List<ClientScopeRepresentation> clientScopes = clientScopes().findAll();
|
||||
for (int i = 0; i < clientScopes.size(); i++) {
|
||||
ClientScopeRepresentation clientScope = clientScopes.get(i);
|
||||
if (i != clientScopes.size() - 1) {
|
||||
removeClientScope(clientScope.getId());
|
||||
} else {
|
||||
removeClientScopeMustFail(clientScope.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleExpectedCreateFailure(ClientScopeRepresentation scopeRep, int expectedErrorCode, String expectedErrorMessage) {
|
||||
try(Response resp = clientScopes().create(scopeRep)) {
|
||||
Assert.assertEquals(expectedErrorCode, resp.getStatus());
|
||||
|
@ -876,4 +884,12 @@ public class ClientScopeTest extends AbstractClientTest {
|
|||
assertAdminEvents.assertEvent(getRealmId(), OperationType.DELETE, AdminEventPaths.clientScopeResourcePath(clientScopeId), ResourceType.CLIENT_SCOPE);
|
||||
}
|
||||
|
||||
private void removeClientScopeMustFail(String clientScopeId) {
|
||||
try {
|
||||
clientScopes().get(clientScopeId).remove();
|
||||
} catch (Exception expected) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue