Introduce unique index for enums stored by storages

Closes #12277
This commit is contained in:
vramik 2022-05-31 16:40:21 +02:00 committed by Hynek Mlnařík
parent 06dfb45c39
commit df41f233d5
15 changed files with 362 additions and 153 deletions

View file

@ -16,27 +16,48 @@
*/ */
package org.keycloak.representations.idm.authorization; package org.keycloak.representations.idm.authorization;
import java.util.Map;
import java.util.Objects;
import org.keycloak.util.EnumWithStableIndex;
/** /**
* The decision strategy dictates how the policies associated with a given policy are evaluated and how a final decision * The decision strategy dictates how the policies associated with a given policy are evaluated and how a final decision
* is obtained. * is obtained.
* *
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/ */
public enum DecisionStrategy { public enum DecisionStrategy implements EnumWithStableIndex {
/** /**
* Defines that at least one policy must evaluate to a positive decision in order to the overall decision be also positive. * Defines that at least one policy must evaluate to a positive decision in order to the overall decision be also positive.
*/ */
AFFIRMATIVE, AFFIRMATIVE(0),
/** /**
* Defines that all policies must evaluate to a positive decision in order to the overall decision be also positive. * Defines that all policies must evaluate to a positive decision in order to the overall decision be also positive.
*/ */
UNANIMOUS, UNANIMOUS(1),
/** /**
* Defines that the number of positive decisions must be greater than the number of negative decisions. If the number of positive and negative is the same, * Defines that the number of positive decisions must be greater than the number of negative decisions. If the number of positive and negative is the same,
* the final decision will be negative. * the final decision will be negative.
*/ */
CONSENSUS CONSENSUS(2);
private final int stableIndex;
private static final Map<Integer, DecisionStrategy> BY_ID = EnumWithStableIndex.getReverseIndex(values());
private DecisionStrategy(int stableIndex) {
Objects.requireNonNull(stableIndex);
this.stableIndex = stableIndex;
}
@Override
public int getStableIndex() {
return stableIndex;
}
public static DecisionStrategy valueOfInteger(Integer id) {
return id == null ? null : BY_ID.get(id);
}
} }

View file

@ -16,21 +16,42 @@
*/ */
package org.keycloak.representations.idm.authorization; package org.keycloak.representations.idm.authorization;
import java.util.Map;
import java.util.Objects;
import org.keycloak.util.EnumWithStableIndex;
/** /**
* The decision strategy dictates how the policies associated with a given policy are evaluated and how a final decision * The decision strategy dictates how the policies associated with a given policy are evaluated and how a final decision
* is obtained. * is obtained.
* *
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/ */
public enum Logic { public enum Logic implements EnumWithStableIndex {
/** /**
* Defines that this policy follows a positive logic. In other words, the final decision is the policy outcome. * Defines that this policy follows a positive logic. In other words, the final decision is the policy outcome.
*/ */
POSITIVE, POSITIVE(0),
/** /**
* Defines that this policy uses a logical negation. In other words, the final decision would be a negative of the policy outcome. * Defines that this policy uses a logical negation. In other words, the final decision would be a negative of the policy outcome.
*/ */
NEGATIVE, NEGATIVE(1);
private final int stableIndex;
private static final Map<Integer, Logic> BY_ID = EnumWithStableIndex.getReverseIndex(values());
private Logic(int stableIndex) {
Objects.requireNonNull(stableIndex);
this.stableIndex = stableIndex;
}
@Override
public int getStableIndex() {
return stableIndex;
}
public static Logic valueOfInteger(Integer id) {
return id == null ? null : BY_ID.get(id);
}
} }

View file

@ -16,25 +16,46 @@
*/ */
package org.keycloak.representations.idm.authorization; package org.keycloak.representations.idm.authorization;
import java.util.Map;
import java.util.Objects;
import org.keycloak.util.EnumWithStableIndex;
/** /**
* The policy enforcement mode dictates how authorization requests are handled by the server. * The policy enforcement mode dictates how authorization requests are handled by the server.
* *
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/ */
public enum PolicyEnforcementMode { public enum PolicyEnforcementMode implements EnumWithStableIndex {
/** /**
* Requests are denied by default even when there is no policy associated with a given resource. * Requests are denied by default even when there is no policy associated with a given resource.
*/ */
ENFORCING, ENFORCING(0),
/** /**
* Requests are allowed even when there is no policy associated with a given resource. * Requests are allowed even when there is no policy associated with a given resource.
*/ */
PERMISSIVE, PERMISSIVE(1),
/** /**
* Completely disables the evaluation of policies and allow access to any resource. * Completely disables the evaluation of policies and allow access to any resource.
*/ */
DISABLED DISABLED(2);
private final int stableIndex;
private static final Map<Integer, PolicyEnforcementMode> BY_ID = EnumWithStableIndex.getReverseIndex(values());
private PolicyEnforcementMode(int stableIndex) {
Objects.requireNonNull(stableIndex);
this.stableIndex = stableIndex;
}
@Override
public int getStableIndex() {
return stableIndex;
}
public static PolicyEnforcementMode valueOfInteger(Integer id) {
return id == null ? null : BY_ID.get(id);
}
} }

View file

@ -0,0 +1,43 @@
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.util;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Classes implementing this interface guarantee that for each instance of this class,
* there exists an mutually unique integer which is stable in time, and identifies
* always the same instance of this class.
* The index might be used for persistence, hence the index of a particular item
* cannot be changed.
* This is mostly usable for @{code enum}s.
*/
public interface EnumWithStableIndex {
/**
* @return Unique numeric index which is stable in time and identifies an instance.
* Reusing the same index for two distinct entries of the same class is forbidden even
* if they cannot exist at the same time (e.g. one is deleted before other is introduced).
*/
public int getStableIndex();
public static <E extends EnumWithStableIndex> Map<Integer, E> getReverseIndex(E[] values) {
return Stream.of(values).collect(Collectors.toMap(EnumWithStableIndex::getStableIndex, Function.identity()));
}
}

View file

@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
@ -77,8 +78,7 @@ import org.keycloak.models.map.realm.entity.MapRequiredCredentialEntity;
import org.keycloak.models.map.realm.entity.MapRequiredCredentialEntityImpl; import org.keycloak.models.map.realm.entity.MapRequiredCredentialEntityImpl;
import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntity; import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntity;
import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntityImpl; import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntityImpl;
import org.keycloak.util.EnumWithStableIndex;
import static org.keycloak.models.map.storage.jpa.hibernate.jsonb.JpaEntityMigration.MIGRATIONS;
public class JsonbType extends AbstractSingleColumnStandardBasicType<Object> implements DynamicParameterizedType { public class JsonbType extends AbstractSingleColumnStandardBasicType<Object> implements DynamicParameterizedType {
@ -105,7 +105,9 @@ public class JsonbType extends AbstractSingleColumnStandardBasicType<Object> imp
.addAbstractTypeMapping(MapWebAuthnPolicyEntity.class, MapWebAuthnPolicyEntityImpl.class)) .addAbstractTypeMapping(MapWebAuthnPolicyEntity.class, MapWebAuthnPolicyEntityImpl.class))
.addMixIn(UpdatableEntity.class, IgnoreUpdatedMixIn.class) .addMixIn(UpdatableEntity.class, IgnoreUpdatedMixIn.class)
.addMixIn(DeepCloner.class, IgnoredTypeMixIn.class) .addMixIn(DeepCloner.class, IgnoredTypeMixIn.class)
.addMixIn(EntityWithAttributes.class, IgnoredMetadataFieldsMixIn.class); .addMixIn(EntityWithAttributes.class, IgnoredMetadataFieldsMixIn.class)
.addMixIn(EnumWithStableIndex.class, EnumsMixIn.class)
;
abstract class IgnoredMetadataFieldsMixIn { abstract class IgnoredMetadataFieldsMixIn {
@JsonIgnore public abstract String getId(); @JsonIgnore public abstract String getId();
@ -115,6 +117,13 @@ public class JsonbType extends AbstractSingleColumnStandardBasicType<Object> imp
@JsonIgnore public abstract Boolean isClientRole(); @JsonIgnore public abstract Boolean isClientRole();
} }
abstract static class EnumsMixIn implements EnumWithStableIndex {
// we convert enums to its index and vice versa
@Override
@JsonValue public abstract int getStableIndex();
}
public JsonbType() { public JsonbType() {
super(JsonbSqlTypeDescriptor.INSTANCE, new JsonbJavaTypeDescriptor()); super(JsonbSqlTypeDescriptor.INSTANCE, new JsonbJavaTypeDescriptor());
} }
@ -232,7 +241,7 @@ public class JsonbType extends AbstractSingleColumnStandardBasicType<Object> imp
} }
private ObjectNode migrate(ObjectNode tree, Integer entityVersion) { private ObjectNode migrate(ObjectNode tree, Integer entityVersion) {
return MIGRATIONS.getOrDefault(valueType, (node, version) -> node).apply(tree, entityVersion); return JpaEntityMigration.MIGRATIONS.getOrDefault(valueType, (node, version) -> node).apply(tree, entityVersion);
} }
@Override @Override

View file

@ -20,8 +20,6 @@ package org.keycloak.models.map.events;
import org.keycloak.events.Event; import org.keycloak.events.Event;
import org.keycloak.events.admin.AdminEvent; import org.keycloak.events.admin.AdminEvent;
import org.keycloak.events.admin.AuthDetails; import org.keycloak.events.admin.AuthDetails;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.map.common.TimeAdapter;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;

View file

@ -90,7 +90,7 @@ public class MapAdminEventQuery implements AdminEventQuery {
@Override @Override
public AdminEventQuery resourceType(ResourceType... resourceTypes) { public AdminEventQuery resourceType(ResourceType... resourceTypes) {
mcb = mcb.compare(SearchableFields.RESOURCE_TYPE, EQ, Arrays.stream(resourceTypes)); mcb = mcb.compare(SearchableFields.RESOURCE_TYPE, IN, Arrays.stream(resourceTypes));
return this; return this;
} }

View file

@ -1771,10 +1771,12 @@ public class MapRealmAdapter extends AbstractRealmModel<MapRealmEntity> implemen
return String.format("%s@%08x", getId(), hashCode()); return String.format("%s@%08x", getId(), hashCode());
} }
@Override
public CibaConfig getCibaPolicy() { public CibaConfig getCibaPolicy() {
return new CibaConfig(this); return new CibaConfig(this);
} }
@Override
public ParConfig getParPolicy() { public ParConfig getParPolicy() {
return new ParConfig(this); return new ParConfig(this);
} }

View file

@ -19,7 +19,6 @@ package org.keycloak.models.map.userSession;
import org.keycloak.models.UserSessionModel; import org.keycloak.models.UserSessionModel;
import org.keycloak.models.map.annotations.GenerateEntityImplementations; import org.keycloak.models.map.annotations.GenerateEntityImplementations;
import org.keycloak.models.map.common.AbstractEntity; import org.keycloak.models.map.common.AbstractEntity;
import org.keycloak.models.map.common.DeepCloner; import org.keycloak.models.map.common.DeepCloner;
import org.keycloak.models.map.common.ExpirableEntity; import org.keycloak.models.map.common.ExpirableEntity;
import org.keycloak.models.map.common.UpdatableEntity; import org.keycloak.models.map.common.UpdatableEntity;

View file

@ -87,8 +87,8 @@
<infinispan.version>12.1.7.Final</infinispan.version> <infinispan.version>12.1.7.Final</infinispan.version>
<infinispan.protostream.processor.version>4.4.1.Final</infinispan.protostream.processor.version> <infinispan.protostream.processor.version>4.4.1.Final</infinispan.protostream.processor.version>
<javax.annotation-api.version>1.3.2</javax.annotation-api.version> <javax.annotation-api.version>1.3.2</javax.annotation-api.version>
<jackson.version>2.12.1</jackson.version> <jackson.version>2.13.2</jackson.version>
<jackson.databind.version>2.12.6.1</jackson.databind.version> <jackson.databind.version>2.13.2.2</jackson.databind.version>
<jackson.annotations.version>${jackson.databind.version}</jackson.annotations.version> <jackson.annotations.version>${jackson.databind.version}</jackson.annotations.version>
<jakarta.mail.version>1.6.5</jakarta.mail.version> <jakarta.mail.version>1.6.5</jakarta.mail.version>
<jboss-jaxrs-api_2.1_spec>2.0.1.Final</jboss-jaxrs-api_2.1_spec> <jboss-jaxrs-api_2.1_spec>2.0.1.Final</jboss-jaxrs-api_2.1_spec>
@ -177,7 +177,7 @@
<jmeter.plugin.version>1.9.0</jmeter.plugin.version> <jmeter.plugin.version>1.9.0</jmeter.plugin.version>
<jmeter.analysis.plugin.version>1.0.4</jmeter.analysis.plugin.version> <jmeter.analysis.plugin.version>1.0.4</jmeter.analysis.plugin.version>
<minify.plugin.version>1.7.6</minify.plugin.version> <minify.plugin.version>1.7.6</minify.plugin.version>
<osgi.bundle.plugin.version>2.3.7</osgi.bundle.plugin.version> <osgi.bundle.plugin.version>2.4.0</osgi.bundle.plugin.version>
<wildfly.plugin.version>2.0.1.Final</wildfly.plugin.version> <wildfly.plugin.version>2.0.1.Final</wildfly.plugin.version>
<nexus.staging.plugin.version>1.6.5</nexus.staging.plugin.version> <nexus.staging.plugin.version>1.6.5</nexus.staging.plugin.version>
<frontend.plugin.version>1.12.0</frontend.plugin.version> <frontend.plugin.version>1.12.0</frontend.plugin.version>

View file

@ -17,149 +17,162 @@
package org.keycloak.events; package org.keycloak.events;
import java.util.Map;
import java.util.Objects;
import org.keycloak.util.EnumWithStableIndex;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/ */
public enum EventType { public enum EventType implements EnumWithStableIndex {
LOGIN(true), LOGIN(0, true),
LOGIN_ERROR(true), LOGIN_ERROR(0x10000 + LOGIN.getStableIndex(), true),
REGISTER(true), REGISTER(1, true),
REGISTER_ERROR(true), REGISTER_ERROR(0x10000 + REGISTER.getStableIndex(), true),
LOGOUT(true), LOGOUT(2, true),
LOGOUT_ERROR(true), LOGOUT_ERROR(0x10000 + LOGOUT.getStableIndex(), true),
CODE_TO_TOKEN(true), CODE_TO_TOKEN(3, true),
CODE_TO_TOKEN_ERROR(true), CODE_TO_TOKEN_ERROR(0x10000 + CODE_TO_TOKEN.getStableIndex(), true),
CLIENT_LOGIN(true), CLIENT_LOGIN(4, true),
CLIENT_LOGIN_ERROR(true), CLIENT_LOGIN_ERROR(0x10000 + CLIENT_LOGIN.getStableIndex(), true),
REFRESH_TOKEN(false), REFRESH_TOKEN(5, false),
REFRESH_TOKEN_ERROR(false), REFRESH_TOKEN_ERROR(0x10000 + REFRESH_TOKEN.getStableIndex(), false),
/** /**
* @deprecated see KEYCLOAK-2266 * @deprecated see KEYCLOAK-2266
*/ */
@Deprecated @Deprecated
VALIDATE_ACCESS_TOKEN(false), VALIDATE_ACCESS_TOKEN(6, false),
@Deprecated @Deprecated
VALIDATE_ACCESS_TOKEN_ERROR(false), VALIDATE_ACCESS_TOKEN_ERROR(0x10000 + VALIDATE_ACCESS_TOKEN.getStableIndex(), false),
INTROSPECT_TOKEN(false), INTROSPECT_TOKEN(7, false),
INTROSPECT_TOKEN_ERROR(false), INTROSPECT_TOKEN_ERROR(0x10000 + INTROSPECT_TOKEN.getStableIndex(), false),
FEDERATED_IDENTITY_LINK(true), FEDERATED_IDENTITY_LINK(8, true),
FEDERATED_IDENTITY_LINK_ERROR(true), FEDERATED_IDENTITY_LINK_ERROR(0x10000 + FEDERATED_IDENTITY_LINK.getStableIndex(), true),
REMOVE_FEDERATED_IDENTITY(true), REMOVE_FEDERATED_IDENTITY(9, true),
REMOVE_FEDERATED_IDENTITY_ERROR(true), REMOVE_FEDERATED_IDENTITY_ERROR(0x10000 + REMOVE_FEDERATED_IDENTITY.getStableIndex(), true),
UPDATE_EMAIL(true), UPDATE_EMAIL(10, true),
UPDATE_EMAIL_ERROR(true), UPDATE_EMAIL_ERROR(0x10000 + UPDATE_EMAIL.getStableIndex(), true),
UPDATE_PROFILE(true), UPDATE_PROFILE(11, true),
UPDATE_PROFILE_ERROR(true), UPDATE_PROFILE_ERROR(0x10000 + UPDATE_PROFILE.getStableIndex(), true),
UPDATE_PASSWORD(true), UPDATE_PASSWORD(12, true),
UPDATE_PASSWORD_ERROR(true), UPDATE_PASSWORD_ERROR(0x10000 + UPDATE_PASSWORD.getStableIndex(), true),
UPDATE_TOTP(true), UPDATE_TOTP(13, true),
UPDATE_TOTP_ERROR(true), UPDATE_TOTP_ERROR(0x10000 + UPDATE_TOTP.getStableIndex(), true),
VERIFY_EMAIL(true), VERIFY_EMAIL(14, true),
VERIFY_EMAIL_ERROR(true), VERIFY_EMAIL_ERROR(0x10000 + VERIFY_EMAIL.getStableIndex(), true),
VERIFY_PROFILE(true), VERIFY_PROFILE(15, true),
VERIFY_PROFILE_ERROR(true), VERIFY_PROFILE_ERROR(0x10000 + VERIFY_PROFILE.getStableIndex(), true),
REMOVE_TOTP(true), REMOVE_TOTP(16, true),
REMOVE_TOTP_ERROR(true), REMOVE_TOTP_ERROR(0x10000 + REMOVE_TOTP.getStableIndex(), true),
GRANT_CONSENT(true), GRANT_CONSENT(17, true),
GRANT_CONSENT_ERROR(true), GRANT_CONSENT_ERROR(0x10000 + GRANT_CONSENT.getStableIndex(), true),
UPDATE_CONSENT(true), UPDATE_CONSENT(18, true),
UPDATE_CONSENT_ERROR(true), UPDATE_CONSENT_ERROR(0x10000 + UPDATE_CONSENT.getStableIndex(), true),
REVOKE_GRANT(true), REVOKE_GRANT(19, true),
REVOKE_GRANT_ERROR(true), REVOKE_GRANT_ERROR(0x10000 + REVOKE_GRANT.getStableIndex(), true),
SEND_VERIFY_EMAIL(true), SEND_VERIFY_EMAIL(20, true),
SEND_VERIFY_EMAIL_ERROR(true), SEND_VERIFY_EMAIL_ERROR(0x10000 + SEND_VERIFY_EMAIL.getStableIndex(), true),
SEND_RESET_PASSWORD(true), SEND_RESET_PASSWORD(21, true),
SEND_RESET_PASSWORD_ERROR(true), SEND_RESET_PASSWORD_ERROR(0x10000 + SEND_RESET_PASSWORD.getStableIndex(), true),
SEND_IDENTITY_PROVIDER_LINK(true), SEND_IDENTITY_PROVIDER_LINK(22, true),
SEND_IDENTITY_PROVIDER_LINK_ERROR(true), SEND_IDENTITY_PROVIDER_LINK_ERROR(0x10000 + SEND_IDENTITY_PROVIDER_LINK.getStableIndex(), true),
RESET_PASSWORD(true), RESET_PASSWORD(23, true),
RESET_PASSWORD_ERROR(true), RESET_PASSWORD_ERROR(0x10000 + RESET_PASSWORD.getStableIndex(), true),
RESTART_AUTHENTICATION(true), RESTART_AUTHENTICATION(24, true),
RESTART_AUTHENTICATION_ERROR(true), RESTART_AUTHENTICATION_ERROR(0x10000 + RESTART_AUTHENTICATION.getStableIndex(), true),
INVALID_SIGNATURE(false), INVALID_SIGNATURE(25, false),
INVALID_SIGNATURE_ERROR(false), INVALID_SIGNATURE_ERROR(0x10000 + INVALID_SIGNATURE.getStableIndex(), false),
REGISTER_NODE(false), REGISTER_NODE(26, false),
REGISTER_NODE_ERROR(false), REGISTER_NODE_ERROR(0x10000 + REGISTER_NODE.getStableIndex(), false),
UNREGISTER_NODE(false), UNREGISTER_NODE(27, false),
UNREGISTER_NODE_ERROR(false), UNREGISTER_NODE_ERROR(0x10000 + UNREGISTER_NODE.getStableIndex(), false),
USER_INFO_REQUEST(false), USER_INFO_REQUEST(28, false),
USER_INFO_REQUEST_ERROR(false), USER_INFO_REQUEST_ERROR(0x10000 + USER_INFO_REQUEST.getStableIndex(), false),
IDENTITY_PROVIDER_LINK_ACCOUNT(true), IDENTITY_PROVIDER_LINK_ACCOUNT(29, true),
IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR(true), IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR(0x10000 + IDENTITY_PROVIDER_LINK_ACCOUNT.getStableIndex(), true),
IDENTITY_PROVIDER_LOGIN(false), IDENTITY_PROVIDER_LOGIN(30, false),
IDENTITY_PROVIDER_LOGIN_ERROR(false), IDENTITY_PROVIDER_LOGIN_ERROR(0x10000 + IDENTITY_PROVIDER_LOGIN.getStableIndex(), false),
IDENTITY_PROVIDER_FIRST_LOGIN(true), IDENTITY_PROVIDER_FIRST_LOGIN(31, true),
IDENTITY_PROVIDER_FIRST_LOGIN_ERROR(true), IDENTITY_PROVIDER_FIRST_LOGIN_ERROR(0x10000 + IDENTITY_PROVIDER_FIRST_LOGIN.getStableIndex(), true),
IDENTITY_PROVIDER_POST_LOGIN(true), IDENTITY_PROVIDER_POST_LOGIN(32, true),
IDENTITY_PROVIDER_POST_LOGIN_ERROR(true), IDENTITY_PROVIDER_POST_LOGIN_ERROR(0x10000 + IDENTITY_PROVIDER_POST_LOGIN.getStableIndex(), true),
IDENTITY_PROVIDER_RESPONSE(false), IDENTITY_PROVIDER_RESPONSE(33, false),
IDENTITY_PROVIDER_RESPONSE_ERROR(false), IDENTITY_PROVIDER_RESPONSE_ERROR(0x10000 + IDENTITY_PROVIDER_RESPONSE.getStableIndex(), false),
IDENTITY_PROVIDER_RETRIEVE_TOKEN(false), IDENTITY_PROVIDER_RETRIEVE_TOKEN(34, false),
IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR(false), IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR(0x10000 + IDENTITY_PROVIDER_RETRIEVE_TOKEN.getStableIndex(), false),
IMPERSONATE(true), IMPERSONATE(35, true),
IMPERSONATE_ERROR(true), IMPERSONATE_ERROR(0x10000 + IMPERSONATE.getStableIndex(), true),
CUSTOM_REQUIRED_ACTION(true), CUSTOM_REQUIRED_ACTION(36, true),
CUSTOM_REQUIRED_ACTION_ERROR(true), CUSTOM_REQUIRED_ACTION_ERROR(0x10000 + CUSTOM_REQUIRED_ACTION.getStableIndex(), true),
EXECUTE_ACTIONS(true), EXECUTE_ACTIONS(37, true),
EXECUTE_ACTIONS_ERROR(true), EXECUTE_ACTIONS_ERROR(0x10000 + EXECUTE_ACTIONS.getStableIndex(), true),
EXECUTE_ACTION_TOKEN(true), EXECUTE_ACTION_TOKEN(38, true),
EXECUTE_ACTION_TOKEN_ERROR(true), EXECUTE_ACTION_TOKEN_ERROR(0x10000 + EXECUTE_ACTION_TOKEN.getStableIndex(), true),
CLIENT_INFO(false), CLIENT_INFO(39, false),
CLIENT_INFO_ERROR(false), CLIENT_INFO_ERROR(0x10000 + CLIENT_INFO.getStableIndex(), false),
CLIENT_REGISTER(true), CLIENT_REGISTER(40, true),
CLIENT_REGISTER_ERROR(true), CLIENT_REGISTER_ERROR(0x10000 + CLIENT_REGISTER.getStableIndex(), true),
CLIENT_UPDATE(true), CLIENT_UPDATE(41, true),
CLIENT_UPDATE_ERROR(true), CLIENT_UPDATE_ERROR(0x10000 + CLIENT_UPDATE.getStableIndex(), true),
CLIENT_DELETE(true), CLIENT_DELETE(42, true),
CLIENT_DELETE_ERROR(true), CLIENT_DELETE_ERROR(0x10000 + CLIENT_DELETE.getStableIndex(), true),
CLIENT_INITIATED_ACCOUNT_LINKING(true), CLIENT_INITIATED_ACCOUNT_LINKING(43, true),
CLIENT_INITIATED_ACCOUNT_LINKING_ERROR(true), CLIENT_INITIATED_ACCOUNT_LINKING_ERROR(0x10000 + CLIENT_INITIATED_ACCOUNT_LINKING.getStableIndex(), true),
TOKEN_EXCHANGE(true), TOKEN_EXCHANGE(44, true),
TOKEN_EXCHANGE_ERROR(true), TOKEN_EXCHANGE_ERROR(0x10000 + TOKEN_EXCHANGE.getStableIndex(), true),
OAUTH2_DEVICE_AUTH(true), OAUTH2_DEVICE_AUTH(45, true),
OAUTH2_DEVICE_AUTH_ERROR(true), OAUTH2_DEVICE_AUTH_ERROR(0x10000 + OAUTH2_DEVICE_AUTH.getStableIndex(), true),
OAUTH2_DEVICE_VERIFY_USER_CODE(true), OAUTH2_DEVICE_VERIFY_USER_CODE(46, true),
OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR(true), OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR(0x10000 + OAUTH2_DEVICE_VERIFY_USER_CODE.getStableIndex(), true),
OAUTH2_DEVICE_CODE_TO_TOKEN(true), OAUTH2_DEVICE_CODE_TO_TOKEN(47, true),
OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR(true), OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR(0x10000 + OAUTH2_DEVICE_CODE_TO_TOKEN.getStableIndex(), true),
AUTHREQID_TO_TOKEN(true), AUTHREQID_TO_TOKEN(48, true),
AUTHREQID_TO_TOKEN_ERROR(true), AUTHREQID_TO_TOKEN_ERROR(0x10000 + AUTHREQID_TO_TOKEN.getStableIndex(), true),
PERMISSION_TOKEN(true), PERMISSION_TOKEN(49, true),
PERMISSION_TOKEN_ERROR(false), PERMISSION_TOKEN_ERROR(0x10000 + PERMISSION_TOKEN.getStableIndex(), false),
DELETE_ACCOUNT(true), DELETE_ACCOUNT(50, true),
DELETE_ACCOUNT_ERROR(true), DELETE_ACCOUNT_ERROR(0x10000 + DELETE_ACCOUNT.getStableIndex(), true),
// PAR request. // PAR request.
PUSHED_AUTHORIZATION_REQUEST(false), PUSHED_AUTHORIZATION_REQUEST(51, false),
PUSHED_AUTHORIZATION_REQUEST_ERROR(false); PUSHED_AUTHORIZATION_REQUEST_ERROR(0x10000 + PUSHED_AUTHORIZATION_REQUEST.getStableIndex(), false);
private boolean saveByDefault; private final int stableIndex;
private final boolean saveByDefault;
private static final Map<Integer, EventType> BY_ID = EnumWithStableIndex.getReverseIndex(values());
EventType(boolean saveByDefault) { EventType(int stableIndex, boolean saveByDefault) {
Objects.requireNonNull(stableIndex);
this.stableIndex = stableIndex;
this.saveByDefault = saveByDefault; this.saveByDefault = saveByDefault;
} }
@Override
public int getStableIndex() {
return stableIndex;
}
/** /**
* Determines whether this event is stored when the admin has not set a specific set of event types to save. * Determines whether this event is stored when the admin has not set a specific set of event types to save.
* @return * @return
@ -168,4 +181,7 @@ public enum EventType {
return saveByDefault; return saveByDefault;
} }
public static EventType valueOfInteger(Integer id) {
return id == null ? null : BY_ID.get(id);
}
} }

View file

@ -17,14 +17,34 @@
package org.keycloak.events.admin; package org.keycloak.events.admin;
import java.util.Map;
import java.util.Objects;
import org.keycloak.util.EnumWithStableIndex;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/ */
public enum OperationType { public enum OperationType implements EnumWithStableIndex {
CREATE, CREATE(0),
UPDATE, UPDATE(1),
DELETE, DELETE(2),
ACTION; ACTION(3);
private final int stableIndex;
private static final Map<Integer, OperationType> BY_ID = EnumWithStableIndex.getReverseIndex(values());
private OperationType(int stableIndex) {
Objects.requireNonNull(stableIndex);
this.stableIndex = stableIndex;
}
@Override
public int getStableIndex() {
return stableIndex;
}
public static OperationType valueOfInteger(Integer id) {
return id == null ? null : BY_ID.get(id);
}
} }

View file

@ -19,6 +19,9 @@ package org.keycloak.models;
import java.io.Serializable; import java.io.Serializable;
import java.util.Comparator; import java.util.Comparator;
import java.util.Map;
import java.util.Objects;
import org.keycloak.util.EnumWithStableIndex;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -118,11 +121,28 @@ public class AuthenticationExecutionModel implements Serializable {
this.authenticatorFlow = authenticatorFlow; this.authenticatorFlow = authenticatorFlow;
} }
public enum Requirement { public enum Requirement implements EnumWithStableIndex {
REQUIRED, REQUIRED(0),
CONDITIONAL, CONDITIONAL(1),
ALTERNATIVE, ALTERNATIVE(2),
DISABLED DISABLED(3);
private final int stableIndex;
private static final Map<Integer, Requirement> BY_ID = EnumWithStableIndex.getReverseIndex(values());
private Requirement(int stableIndex) {
Objects.requireNonNull(stableIndex);
this.stableIndex = stableIndex;
}
@Override
public int getStableIndex() {
return stableIndex;
}
public static Requirement valueOfInteger(Integer id) {
return id == null ? null : BY_ID.get(id);
}
} }
public boolean isRequired() { public boolean isRequired() {

View file

@ -21,6 +21,8 @@ import org.keycloak.storage.SearchableModelField;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import org.keycloak.util.EnumWithStableIndex;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -110,11 +112,28 @@ public interface UserSessionModel {
// Will completely restart whole state of user session. It will just keep same ID. // Will completely restart whole state of user session. It will just keep same ID.
void restartSession(RealmModel realm, UserModel user, String loginUsername, String ipAddress, String authMethod, boolean rememberMe, String brokerSessionId, String brokerUserId); void restartSession(RealmModel realm, UserModel user, String loginUsername, String ipAddress, String authMethod, boolean rememberMe, String brokerSessionId, String brokerUserId);
enum State { enum State implements EnumWithStableIndex {
LOGGED_IN, LOGGED_IN(0),
LOGGING_OUT, LOGGING_OUT(1),
LOGGED_OUT, LOGGED_OUT(2),
LOGGED_OUT_UNCONFIRMED; LOGGED_OUT_UNCONFIRMED(3);
private final int stableIndex;
private static final Map<Integer, State> BY_ID = EnumWithStableIndex.getReverseIndex(values());
private State(int stableIndex) {
Objects.requireNonNull(stableIndex);
this.stableIndex = stableIndex;
}
@Override
public int getStableIndex() {
return stableIndex;
}
public static State valueOfInteger(Integer id) {
return id == null ? null : BY_ID.get(id);
}
} }
/** /**

View file

@ -17,8 +17,11 @@
package org.keycloak.sessions; package org.keycloak.sessions;
import java.util.Map;
import java.util.Objects;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.util.EnumWithStableIndex;
/** /**
* Predecesor of AuthenticationSessionModel, ClientLoginSessionModel and ClientSessionModel (then action tickets). Maybe we will remove it later... * Predecesor of AuthenticationSessionModel, ClientLoginSessionModel and ClientSessionModel (then action tickets). Maybe we will remove it later...
@ -48,14 +51,31 @@ public interface CommonClientSessionModel {
USER_CODE_VERIFICATION USER_CODE_VERIFICATION
} }
enum ExecutionStatus { enum ExecutionStatus implements EnumWithStableIndex {
FAILED, FAILED(0),
SUCCESS, SUCCESS(1),
SETUP_REQUIRED, SETUP_REQUIRED(2),
ATTEMPTED, ATTEMPTED(3),
SKIPPED, SKIPPED(4),
CHALLENGED, CHALLENGED(5),
EVALUATED_TRUE, EVALUATED_TRUE(6),
EVALUATED_FALSE EVALUATED_FALSE(7);
private final int stableIndex;
private static final Map<Integer, ExecutionStatus> BY_ID = EnumWithStableIndex.getReverseIndex(values());
private ExecutionStatus(int stableIndex) {
Objects.requireNonNull(stableIndex);
this.stableIndex = stableIndex;
}
@Override
public int getStableIndex() {
return stableIndex;
}
public static ExecutionStatus valueOfInteger(Integer id) {
return id == null ? null : BY_ID.get(id);
}
} }
} }