parent
06dfb45c39
commit
df41f233d5
15 changed files with 362 additions and 153 deletions
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
6
pom.xml
6
pom.xml
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue