diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/DecisionStrategy.java b/core/src/main/java/org/keycloak/representations/idm/authorization/DecisionStrategy.java index bd66bea40c..ace8ef51c9 100644 --- a/core/src/main/java/org/keycloak/representations/idm/authorization/DecisionStrategy.java +++ b/core/src/main/java/org/keycloak/representations/idm/authorization/DecisionStrategy.java @@ -16,27 +16,48 @@ */ 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 * is obtained. * * @author Pedro Igor */ -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. */ - AFFIRMATIVE, + AFFIRMATIVE(0), /** * 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, * the final decision will be negative. */ - CONSENSUS + CONSENSUS(2); + + private final int stableIndex; + private static final Map 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); + } } diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/Logic.java b/core/src/main/java/org/keycloak/representations/idm/authorization/Logic.java index 70c382e952..e66b147b84 100644 --- a/core/src/main/java/org/keycloak/representations/idm/authorization/Logic.java +++ b/core/src/main/java/org/keycloak/representations/idm/authorization/Logic.java @@ -16,21 +16,42 @@ */ 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 * is obtained. * * @author Pedro Igor */ -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. */ - 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. */ - NEGATIVE, + NEGATIVE(1); + + private final int stableIndex; + private static final Map 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); + } } diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/PolicyEnforcementMode.java b/core/src/main/java/org/keycloak/representations/idm/authorization/PolicyEnforcementMode.java index 4d1eef67ed..ee303b4554 100644 --- a/core/src/main/java/org/keycloak/representations/idm/authorization/PolicyEnforcementMode.java +++ b/core/src/main/java/org/keycloak/representations/idm/authorization/PolicyEnforcementMode.java @@ -16,25 +16,46 @@ */ 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. * * @author Pedro Igor */ -public enum PolicyEnforcementMode { +public enum PolicyEnforcementMode implements EnumWithStableIndex { /** * 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. */ - PERMISSIVE, + PERMISSIVE(1), /** * Completely disables the evaluation of policies and allow access to any resource. */ - DISABLED + DISABLED(2); + + private final int stableIndex; + private static final Map 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); + } } diff --git a/core/src/main/java/org/keycloak/util/EnumWithStableIndex.java b/core/src/main/java/org/keycloak/util/EnumWithStableIndex.java new file mode 100644 index 0000000000..f3b14a5d73 --- /dev/null +++ b/core/src/main/java/org/keycloak/util/EnumWithStableIndex.java @@ -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 Map getReverseIndex(E[] values) { + return Stream.of(values).collect(Collectors.toMap(EnumWithStableIndex::getStableIndex, Function.identity())); + } +} diff --git a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/hibernate/jsonb/JsonbType.java b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/hibernate/jsonb/JsonbType.java index 98681bc4c4..c970b6d1a4 100644 --- a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/hibernate/jsonb/JsonbType.java +++ b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/hibernate/jsonb/JsonbType.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.DeserializationFeature; 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.MapWebAuthnPolicyEntity; import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntityImpl; - -import static org.keycloak.models.map.storage.jpa.hibernate.jsonb.JpaEntityMigration.MIGRATIONS; +import org.keycloak.util.EnumWithStableIndex; public class JsonbType extends AbstractSingleColumnStandardBasicType implements DynamicParameterizedType { @@ -105,7 +105,9 @@ public class JsonbType extends AbstractSingleColumnStandardBasicType imp .addAbstractTypeMapping(MapWebAuthnPolicyEntity.class, MapWebAuthnPolicyEntityImpl.class)) .addMixIn(UpdatableEntity.class, IgnoreUpdatedMixIn.class) .addMixIn(DeepCloner.class, IgnoredTypeMixIn.class) - .addMixIn(EntityWithAttributes.class, IgnoredMetadataFieldsMixIn.class); + .addMixIn(EntityWithAttributes.class, IgnoredMetadataFieldsMixIn.class) + .addMixIn(EnumWithStableIndex.class, EnumsMixIn.class) + ; abstract class IgnoredMetadataFieldsMixIn { @JsonIgnore public abstract String getId(); @@ -115,6 +117,13 @@ public class JsonbType extends AbstractSingleColumnStandardBasicType imp @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() { super(JsonbSqlTypeDescriptor.INSTANCE, new JsonbJavaTypeDescriptor()); } @@ -232,7 +241,7 @@ public class JsonbType extends AbstractSingleColumnStandardBasicType imp } 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 diff --git a/model/map/src/main/java/org/keycloak/models/map/events/EventUtils.java b/model/map/src/main/java/org/keycloak/models/map/events/EventUtils.java index 4e0f155bf1..e5fa0334a8 100644 --- a/model/map/src/main/java/org/keycloak/models/map/events/EventUtils.java +++ b/model/map/src/main/java/org/keycloak/models/map/events/EventUtils.java @@ -20,8 +20,6 @@ package org.keycloak.models.map.events; import org.keycloak.events.Event; import org.keycloak.events.admin.AdminEvent; 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.Map; diff --git a/model/map/src/main/java/org/keycloak/models/map/events/MapAdminEventQuery.java b/model/map/src/main/java/org/keycloak/models/map/events/MapAdminEventQuery.java index 73667eee35..a2d966c657 100644 --- a/model/map/src/main/java/org/keycloak/models/map/events/MapAdminEventQuery.java +++ b/model/map/src/main/java/org/keycloak/models/map/events/MapAdminEventQuery.java @@ -90,7 +90,7 @@ public class MapAdminEventQuery implements AdminEventQuery { @Override 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; } diff --git a/model/map/src/main/java/org/keycloak/models/map/realm/MapRealmAdapter.java b/model/map/src/main/java/org/keycloak/models/map/realm/MapRealmAdapter.java index 0c599e0710..c1ea867a23 100644 --- a/model/map/src/main/java/org/keycloak/models/map/realm/MapRealmAdapter.java +++ b/model/map/src/main/java/org/keycloak/models/map/realm/MapRealmAdapter.java @@ -1771,10 +1771,12 @@ public class MapRealmAdapter extends AbstractRealmModel implemen return String.format("%s@%08x", getId(), hashCode()); } + @Override public CibaConfig getCibaPolicy() { return new CibaConfig(this); } + @Override public ParConfig getParPolicy() { return new ParConfig(this); } diff --git a/model/map/src/main/java/org/keycloak/models/map/userSession/MapUserSessionEntity.java b/model/map/src/main/java/org/keycloak/models/map/userSession/MapUserSessionEntity.java index a9f37ea7d0..c37d11f53f 100644 --- a/model/map/src/main/java/org/keycloak/models/map/userSession/MapUserSessionEntity.java +++ b/model/map/src/main/java/org/keycloak/models/map/userSession/MapUserSessionEntity.java @@ -19,7 +19,6 @@ package org.keycloak.models.map.userSession; import org.keycloak.models.UserSessionModel; import org.keycloak.models.map.annotations.GenerateEntityImplementations; import org.keycloak.models.map.common.AbstractEntity; - import org.keycloak.models.map.common.DeepCloner; import org.keycloak.models.map.common.ExpirableEntity; import org.keycloak.models.map.common.UpdatableEntity; diff --git a/pom.xml b/pom.xml index 1201a7972f..81c15dbb32 100644 --- a/pom.xml +++ b/pom.xml @@ -87,8 +87,8 @@ 12.1.7.Final 4.4.1.Final 1.3.2 - 2.12.1 - 2.12.6.1 + 2.13.2 + 2.13.2.2 ${jackson.databind.version} 1.6.5 2.0.1.Final @@ -177,7 +177,7 @@ 1.9.0 1.0.4 1.7.6 - 2.3.7 + 2.4.0 2.0.1.Final 1.6.5 1.12.0 diff --git a/server-spi-private/src/main/java/org/keycloak/events/EventType.java b/server-spi-private/src/main/java/org/keycloak/events/EventType.java index 85444c1eae..870636efb1 100755 --- a/server-spi-private/src/main/java/org/keycloak/events/EventType.java +++ b/server-spi-private/src/main/java/org/keycloak/events/EventType.java @@ -17,149 +17,162 @@ package org.keycloak.events; +import java.util.Map; +import java.util.Objects; +import org.keycloak.util.EnumWithStableIndex; + /** * @author Stian Thorgersen */ -public enum EventType { +public enum EventType implements EnumWithStableIndex { - LOGIN(true), - LOGIN_ERROR(true), - REGISTER(true), - REGISTER_ERROR(true), - LOGOUT(true), - LOGOUT_ERROR(true), + LOGIN(0, true), + LOGIN_ERROR(0x10000 + LOGIN.getStableIndex(), true), + REGISTER(1, true), + REGISTER_ERROR(0x10000 + REGISTER.getStableIndex(), true), + LOGOUT(2, true), + LOGOUT_ERROR(0x10000 + LOGOUT.getStableIndex(), true), - CODE_TO_TOKEN(true), - CODE_TO_TOKEN_ERROR(true), + CODE_TO_TOKEN(3, true), + CODE_TO_TOKEN_ERROR(0x10000 + CODE_TO_TOKEN.getStableIndex(), true), - CLIENT_LOGIN(true), - CLIENT_LOGIN_ERROR(true), + CLIENT_LOGIN(4, true), + CLIENT_LOGIN_ERROR(0x10000 + CLIENT_LOGIN.getStableIndex(), true), - REFRESH_TOKEN(false), - REFRESH_TOKEN_ERROR(false), + REFRESH_TOKEN(5, false), + REFRESH_TOKEN_ERROR(0x10000 + REFRESH_TOKEN.getStableIndex(), false), /** * @deprecated see KEYCLOAK-2266 */ @Deprecated - VALIDATE_ACCESS_TOKEN(false), + VALIDATE_ACCESS_TOKEN(6, false), @Deprecated - VALIDATE_ACCESS_TOKEN_ERROR(false), - INTROSPECT_TOKEN(false), - INTROSPECT_TOKEN_ERROR(false), + VALIDATE_ACCESS_TOKEN_ERROR(0x10000 + VALIDATE_ACCESS_TOKEN.getStableIndex(), false), + INTROSPECT_TOKEN(7, false), + INTROSPECT_TOKEN_ERROR(0x10000 + INTROSPECT_TOKEN.getStableIndex(), false), - FEDERATED_IDENTITY_LINK(true), - FEDERATED_IDENTITY_LINK_ERROR(true), - REMOVE_FEDERATED_IDENTITY(true), - REMOVE_FEDERATED_IDENTITY_ERROR(true), + FEDERATED_IDENTITY_LINK(8, true), + FEDERATED_IDENTITY_LINK_ERROR(0x10000 + FEDERATED_IDENTITY_LINK.getStableIndex(), true), + REMOVE_FEDERATED_IDENTITY(9, true), + REMOVE_FEDERATED_IDENTITY_ERROR(0x10000 + REMOVE_FEDERATED_IDENTITY.getStableIndex(), true), - UPDATE_EMAIL(true), - UPDATE_EMAIL_ERROR(true), - UPDATE_PROFILE(true), - UPDATE_PROFILE_ERROR(true), - UPDATE_PASSWORD(true), - UPDATE_PASSWORD_ERROR(true), - UPDATE_TOTP(true), - UPDATE_TOTP_ERROR(true), - VERIFY_EMAIL(true), - VERIFY_EMAIL_ERROR(true), - VERIFY_PROFILE(true), - VERIFY_PROFILE_ERROR(true), + UPDATE_EMAIL(10, true), + UPDATE_EMAIL_ERROR(0x10000 + UPDATE_EMAIL.getStableIndex(), true), + UPDATE_PROFILE(11, true), + UPDATE_PROFILE_ERROR(0x10000 + UPDATE_PROFILE.getStableIndex(), true), + UPDATE_PASSWORD(12, true), + UPDATE_PASSWORD_ERROR(0x10000 + UPDATE_PASSWORD.getStableIndex(), true), + UPDATE_TOTP(13, true), + UPDATE_TOTP_ERROR(0x10000 + UPDATE_TOTP.getStableIndex(), true), + VERIFY_EMAIL(14, true), + VERIFY_EMAIL_ERROR(0x10000 + VERIFY_EMAIL.getStableIndex(), true), + VERIFY_PROFILE(15, true), + VERIFY_PROFILE_ERROR(0x10000 + VERIFY_PROFILE.getStableIndex(), true), - REMOVE_TOTP(true), - REMOVE_TOTP_ERROR(true), + REMOVE_TOTP(16, true), + REMOVE_TOTP_ERROR(0x10000 + REMOVE_TOTP.getStableIndex(), true), - GRANT_CONSENT(true), - GRANT_CONSENT_ERROR(true), - UPDATE_CONSENT(true), - UPDATE_CONSENT_ERROR(true), - REVOKE_GRANT(true), - REVOKE_GRANT_ERROR(true), + GRANT_CONSENT(17, true), + GRANT_CONSENT_ERROR(0x10000 + GRANT_CONSENT.getStableIndex(), true), + UPDATE_CONSENT(18, true), + UPDATE_CONSENT_ERROR(0x10000 + UPDATE_CONSENT.getStableIndex(), true), + REVOKE_GRANT(19, true), + REVOKE_GRANT_ERROR(0x10000 + REVOKE_GRANT.getStableIndex(), true), - SEND_VERIFY_EMAIL(true), - SEND_VERIFY_EMAIL_ERROR(true), - SEND_RESET_PASSWORD(true), - SEND_RESET_PASSWORD_ERROR(true), - SEND_IDENTITY_PROVIDER_LINK(true), - SEND_IDENTITY_PROVIDER_LINK_ERROR(true), - RESET_PASSWORD(true), - RESET_PASSWORD_ERROR(true), + SEND_VERIFY_EMAIL(20, true), + SEND_VERIFY_EMAIL_ERROR(0x10000 + SEND_VERIFY_EMAIL.getStableIndex(), true), + SEND_RESET_PASSWORD(21, true), + SEND_RESET_PASSWORD_ERROR(0x10000 + SEND_RESET_PASSWORD.getStableIndex(), true), + SEND_IDENTITY_PROVIDER_LINK(22, true), + SEND_IDENTITY_PROVIDER_LINK_ERROR(0x10000 + SEND_IDENTITY_PROVIDER_LINK.getStableIndex(), true), + RESET_PASSWORD(23, true), + RESET_PASSWORD_ERROR(0x10000 + RESET_PASSWORD.getStableIndex(), true), - RESTART_AUTHENTICATION(true), - RESTART_AUTHENTICATION_ERROR(true), + RESTART_AUTHENTICATION(24, true), + RESTART_AUTHENTICATION_ERROR(0x10000 + RESTART_AUTHENTICATION.getStableIndex(), true), - INVALID_SIGNATURE(false), - INVALID_SIGNATURE_ERROR(false), - REGISTER_NODE(false), - REGISTER_NODE_ERROR(false), - UNREGISTER_NODE(false), - UNREGISTER_NODE_ERROR(false), + INVALID_SIGNATURE(25, false), + INVALID_SIGNATURE_ERROR(0x10000 + INVALID_SIGNATURE.getStableIndex(), false), + REGISTER_NODE(26, false), + REGISTER_NODE_ERROR(0x10000 + REGISTER_NODE.getStableIndex(), false), + UNREGISTER_NODE(27, false), + UNREGISTER_NODE_ERROR(0x10000 + UNREGISTER_NODE.getStableIndex(), false), - USER_INFO_REQUEST(false), - USER_INFO_REQUEST_ERROR(false), + USER_INFO_REQUEST(28, false), + USER_INFO_REQUEST_ERROR(0x10000 + USER_INFO_REQUEST.getStableIndex(), false), - IDENTITY_PROVIDER_LINK_ACCOUNT(true), - IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR(true), - IDENTITY_PROVIDER_LOGIN(false), - IDENTITY_PROVIDER_LOGIN_ERROR(false), - IDENTITY_PROVIDER_FIRST_LOGIN(true), - IDENTITY_PROVIDER_FIRST_LOGIN_ERROR(true), - IDENTITY_PROVIDER_POST_LOGIN(true), - IDENTITY_PROVIDER_POST_LOGIN_ERROR(true), - IDENTITY_PROVIDER_RESPONSE(false), - IDENTITY_PROVIDER_RESPONSE_ERROR(false), - IDENTITY_PROVIDER_RETRIEVE_TOKEN(false), - IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR(false), - IMPERSONATE(true), - IMPERSONATE_ERROR(true), - CUSTOM_REQUIRED_ACTION(true), - CUSTOM_REQUIRED_ACTION_ERROR(true), - EXECUTE_ACTIONS(true), - EXECUTE_ACTIONS_ERROR(true), - EXECUTE_ACTION_TOKEN(true), - EXECUTE_ACTION_TOKEN_ERROR(true), + IDENTITY_PROVIDER_LINK_ACCOUNT(29, true), + IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR(0x10000 + IDENTITY_PROVIDER_LINK_ACCOUNT.getStableIndex(), true), + IDENTITY_PROVIDER_LOGIN(30, false), + IDENTITY_PROVIDER_LOGIN_ERROR(0x10000 + IDENTITY_PROVIDER_LOGIN.getStableIndex(), false), + IDENTITY_PROVIDER_FIRST_LOGIN(31, true), + IDENTITY_PROVIDER_FIRST_LOGIN_ERROR(0x10000 + IDENTITY_PROVIDER_FIRST_LOGIN.getStableIndex(), true), + IDENTITY_PROVIDER_POST_LOGIN(32, true), + IDENTITY_PROVIDER_POST_LOGIN_ERROR(0x10000 + IDENTITY_PROVIDER_POST_LOGIN.getStableIndex(), true), + IDENTITY_PROVIDER_RESPONSE(33, false), + IDENTITY_PROVIDER_RESPONSE_ERROR(0x10000 + IDENTITY_PROVIDER_RESPONSE.getStableIndex(), false), + IDENTITY_PROVIDER_RETRIEVE_TOKEN(34, false), + IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR(0x10000 + IDENTITY_PROVIDER_RETRIEVE_TOKEN.getStableIndex(), false), + IMPERSONATE(35, true), + IMPERSONATE_ERROR(0x10000 + IMPERSONATE.getStableIndex(), true), + CUSTOM_REQUIRED_ACTION(36, true), + CUSTOM_REQUIRED_ACTION_ERROR(0x10000 + CUSTOM_REQUIRED_ACTION.getStableIndex(), true), + EXECUTE_ACTIONS(37, true), + EXECUTE_ACTIONS_ERROR(0x10000 + EXECUTE_ACTIONS.getStableIndex(), true), + EXECUTE_ACTION_TOKEN(38, true), + EXECUTE_ACTION_TOKEN_ERROR(0x10000 + EXECUTE_ACTION_TOKEN.getStableIndex(), true), - CLIENT_INFO(false), - CLIENT_INFO_ERROR(false), - CLIENT_REGISTER(true), - CLIENT_REGISTER_ERROR(true), - CLIENT_UPDATE(true), - CLIENT_UPDATE_ERROR(true), - CLIENT_DELETE(true), - CLIENT_DELETE_ERROR(true), + CLIENT_INFO(39, false), + CLIENT_INFO_ERROR(0x10000 + CLIENT_INFO.getStableIndex(), false), + CLIENT_REGISTER(40, true), + CLIENT_REGISTER_ERROR(0x10000 + CLIENT_REGISTER.getStableIndex(), true), + CLIENT_UPDATE(41, true), + CLIENT_UPDATE_ERROR(0x10000 + CLIENT_UPDATE.getStableIndex(), true), + CLIENT_DELETE(42, true), + CLIENT_DELETE_ERROR(0x10000 + CLIENT_DELETE.getStableIndex(), true), - CLIENT_INITIATED_ACCOUNT_LINKING(true), - CLIENT_INITIATED_ACCOUNT_LINKING_ERROR(true), - TOKEN_EXCHANGE(true), - TOKEN_EXCHANGE_ERROR(true), + CLIENT_INITIATED_ACCOUNT_LINKING(43, true), + CLIENT_INITIATED_ACCOUNT_LINKING_ERROR(0x10000 + CLIENT_INITIATED_ACCOUNT_LINKING.getStableIndex(), true), + TOKEN_EXCHANGE(44, true), + TOKEN_EXCHANGE_ERROR(0x10000 + TOKEN_EXCHANGE.getStableIndex(), true), - OAUTH2_DEVICE_AUTH(true), - OAUTH2_DEVICE_AUTH_ERROR(true), - OAUTH2_DEVICE_VERIFY_USER_CODE(true), - OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR(true), - OAUTH2_DEVICE_CODE_TO_TOKEN(true), - OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR(true), + OAUTH2_DEVICE_AUTH(45, true), + OAUTH2_DEVICE_AUTH_ERROR(0x10000 + OAUTH2_DEVICE_AUTH.getStableIndex(), true), + OAUTH2_DEVICE_VERIFY_USER_CODE(46, true), + OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR(0x10000 + OAUTH2_DEVICE_VERIFY_USER_CODE.getStableIndex(), true), + OAUTH2_DEVICE_CODE_TO_TOKEN(47, true), + OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR(0x10000 + OAUTH2_DEVICE_CODE_TO_TOKEN.getStableIndex(), true), - AUTHREQID_TO_TOKEN(true), - AUTHREQID_TO_TOKEN_ERROR(true), + AUTHREQID_TO_TOKEN(48, true), + AUTHREQID_TO_TOKEN_ERROR(0x10000 + AUTHREQID_TO_TOKEN.getStableIndex(), true), - PERMISSION_TOKEN(true), - PERMISSION_TOKEN_ERROR(false), + PERMISSION_TOKEN(49, true), + PERMISSION_TOKEN_ERROR(0x10000 + PERMISSION_TOKEN.getStableIndex(), false), - DELETE_ACCOUNT(true), - DELETE_ACCOUNT_ERROR(true), + DELETE_ACCOUNT(50, true), + DELETE_ACCOUNT_ERROR(0x10000 + DELETE_ACCOUNT.getStableIndex(), true), // PAR request. - PUSHED_AUTHORIZATION_REQUEST(false), - PUSHED_AUTHORIZATION_REQUEST_ERROR(false); + PUSHED_AUTHORIZATION_REQUEST(51, 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 BY_ID = EnumWithStableIndex.getReverseIndex(values()); - EventType(boolean saveByDefault) { + EventType(int stableIndex, boolean saveByDefault) { + Objects.requireNonNull(stableIndex); + this.stableIndex = stableIndex; 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. * @return @@ -168,4 +181,7 @@ public enum EventType { return saveByDefault; } + public static EventType valueOfInteger(Integer id) { + return id == null ? null : BY_ID.get(id); + } } diff --git a/server-spi-private/src/main/java/org/keycloak/events/admin/OperationType.java b/server-spi-private/src/main/java/org/keycloak/events/admin/OperationType.java index e3a95c5136..c82987217e 100755 --- a/server-spi-private/src/main/java/org/keycloak/events/admin/OperationType.java +++ b/server-spi-private/src/main/java/org/keycloak/events/admin/OperationType.java @@ -17,14 +17,34 @@ package org.keycloak.events.admin; +import java.util.Map; +import java.util.Objects; +import org.keycloak.util.EnumWithStableIndex; + /** * @author Stian Thorgersen */ -public enum OperationType { +public enum OperationType implements EnumWithStableIndex { - CREATE, - UPDATE, - DELETE, - ACTION; + CREATE(0), + UPDATE(1), + DELETE(2), + ACTION(3); + private final int stableIndex; + private static final Map 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); + } } diff --git a/server-spi/src/main/java/org/keycloak/models/AuthenticationExecutionModel.java b/server-spi/src/main/java/org/keycloak/models/AuthenticationExecutionModel.java index 465e9dde74..c4b039fef8 100755 --- a/server-spi/src/main/java/org/keycloak/models/AuthenticationExecutionModel.java +++ b/server-spi/src/main/java/org/keycloak/models/AuthenticationExecutionModel.java @@ -19,6 +19,9 @@ package org.keycloak.models; import java.io.Serializable; import java.util.Comparator; +import java.util.Map; +import java.util.Objects; +import org.keycloak.util.EnumWithStableIndex; /** * @author Bill Burke @@ -118,11 +121,28 @@ public class AuthenticationExecutionModel implements Serializable { this.authenticatorFlow = authenticatorFlow; } - public enum Requirement { - REQUIRED, - CONDITIONAL, - ALTERNATIVE, - DISABLED + public enum Requirement implements EnumWithStableIndex { + REQUIRED(0), + CONDITIONAL(1), + ALTERNATIVE(2), + DISABLED(3); + + private final int stableIndex; + private static final Map 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() { diff --git a/server-spi/src/main/java/org/keycloak/models/UserSessionModel.java b/server-spi/src/main/java/org/keycloak/models/UserSessionModel.java index 359e376243..cf487143f9 100755 --- a/server-spi/src/main/java/org/keycloak/models/UserSessionModel.java +++ b/server-spi/src/main/java/org/keycloak/models/UserSessionModel.java @@ -21,6 +21,8 @@ import org.keycloak.storage.SearchableModelField; import java.util.Collection; import java.util.Map; +import java.util.Objects; +import org.keycloak.util.EnumWithStableIndex; /** * @author Stian Thorgersen @@ -110,11 +112,28 @@ public interface UserSessionModel { // 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); - enum State { - LOGGED_IN, - LOGGING_OUT, - LOGGED_OUT, - LOGGED_OUT_UNCONFIRMED; + enum State implements EnumWithStableIndex { + LOGGED_IN(0), + LOGGING_OUT(1), + LOGGED_OUT(2), + LOGGED_OUT_UNCONFIRMED(3); + + private final int stableIndex; + private static final Map 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); + } } /** diff --git a/server-spi/src/main/java/org/keycloak/sessions/CommonClientSessionModel.java b/server-spi/src/main/java/org/keycloak/sessions/CommonClientSessionModel.java index 3d2d130a77..d2dc511805 100644 --- a/server-spi/src/main/java/org/keycloak/sessions/CommonClientSessionModel.java +++ b/server-spi/src/main/java/org/keycloak/sessions/CommonClientSessionModel.java @@ -17,8 +17,11 @@ package org.keycloak.sessions; +import java.util.Map; +import java.util.Objects; import org.keycloak.models.ClientModel; 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... @@ -48,14 +51,31 @@ public interface CommonClientSessionModel { USER_CODE_VERIFICATION } - enum ExecutionStatus { - FAILED, - SUCCESS, - SETUP_REQUIRED, - ATTEMPTED, - SKIPPED, - CHALLENGED, - EVALUATED_TRUE, - EVALUATED_FALSE + enum ExecutionStatus implements EnumWithStableIndex { + FAILED(0), + SUCCESS(1), + SETUP_REQUIRED(2), + ATTEMPTED(3), + SKIPPED(4), + CHALLENGED(5), + EVALUATED_TRUE(6), + EVALUATED_FALSE(7); + + private final int stableIndex; + private static final Map 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); + } } }