diff --git a/model/legacy-private/src/main/java/org/keycloak/storage/adapter/InMemoryUserAdapter.java b/model/legacy-private/src/main/java/org/keycloak/storage/adapter/InMemoryUserAdapter.java
index 76cd17a762..04a891a132 100644
--- a/model/legacy-private/src/main/java/org/keycloak/storage/adapter/InMemoryUserAdapter.java
+++ b/model/legacy-private/src/main/java/org/keycloak/storage/adapter/InMemoryUserAdapter.java
@@ -16,296 +16,23 @@
*/
package org.keycloak.storage.adapter;
-import org.keycloak.common.util.MultivaluedHashMap;
-import org.keycloak.common.util.Time;
import org.keycloak.credential.LegacyUserCredentialManager;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
import org.keycloak.models.SubjectCredentialManager;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserModelDefaultMethods;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.models.utils.RoleUtils;
-import org.keycloak.storage.ReadOnlyException;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Stream;
/**
* @author Bill Burke
* @version $Revision: 1 $
*/
-public class InMemoryUserAdapter extends UserModelDefaultMethods {
- private Long createdTimestamp = Time.currentTimeMillis();
- private boolean emailVerified;
- private boolean enabled;
-
- private Set roleIds = new HashSet<>();
- private Set groupIds = new HashSet<>();
-
- private MultivaluedHashMap attributes = new MultivaluedHashMap<>();
- private Set requiredActions = new HashSet<>();
- private String federationLink;
- private String serviceAccountClientLink;
-
- private KeycloakSession session;
- private RealmModel realm;
- private String id;
- private boolean readonly;
+public class InMemoryUserAdapter extends AbstractInMemoryUserAdapter {
public InMemoryUserAdapter(KeycloakSession session, RealmModel realm, String id) {
- this.session = session;
- this.realm = realm;
- this.id = id;
- }
-
- @Override
- public String getUsername() {
- return getFirstAttribute(UserModel.USERNAME);
- }
-
- @Override
- public void setUsername(String username) {
- username = username==null ? null : username.toLowerCase();
- setSingleAttribute(UserModel.USERNAME, username);
- }
-
- public void addDefaults() {
- this.grantRole(realm.getDefaultRole());
-
- realm.getDefaultGroupsStream().forEach(this::joinGroup);
- }
-
- public void setReadonly(boolean flag) {
- readonly = flag;
- }
-
- protected void checkReadonly() {
- if (readonly) throw new ReadOnlyException("In memory user model is not writable");
- }
-
- @Override
- public String getId() {
- return id;
- }
-
- @Override
- public Long getCreatedTimestamp() {
- return createdTimestamp;
- }
-
- @Override
- public void setCreatedTimestamp(Long timestamp) {
- checkReadonly();
- this.createdTimestamp = timestamp;
- }
-
- @Override
- public boolean isEnabled() {
- return enabled;
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- checkReadonly();
- this.enabled = enabled;
-
- }
-
- @Override
- public void setSingleAttribute(String name, String value) {
- checkReadonly();
- if (UserModel.USERNAME.equals(name) || UserModel.EMAIL.equals(name)) {
- value = KeycloakModelUtils.toLowerCaseSafe(value);
- }
- attributes.putSingle(name, value);
-
- }
-
- @Override
- public void setAttribute(String name, List values) {
- checkReadonly();
- if (UserModel.USERNAME.equals(name) || UserModel.EMAIL.equals(name)) {
- String lowerCasedFirstValue = KeycloakModelUtils.toLowerCaseSafe((values != null && values.size() > 0) ? values.get(0) : null);
- if (lowerCasedFirstValue != null) values.set(0, lowerCasedFirstValue);
- }
- attributes.put(name, values);
-
- }
-
- @Override
- public void removeAttribute(String name) {
- checkReadonly();
- attributes.remove(name);
-
- }
-
- @Override
- public String getFirstAttribute(String name) {
- return attributes.getFirst(name);
- }
-
- @Override
- public Stream getAttributeStream(String name) {
- List value = this.attributes.get(name);
- return value != null ? value.stream() : Stream.empty();
- }
-
- @Override
- public Map> getAttributes() {
- return attributes;
- }
-
- @Override
- public Stream getRequiredActionsStream() {
- return this.requiredActions.stream();
- }
-
- @Override
- public void addRequiredAction(String action) {
- checkReadonly();
- requiredActions.add(action);
-
- }
-
- @Override
- public void removeRequiredAction(String action) {
- checkReadonly();
- requiredActions.remove(action);
-
- }
-
- @Override
- public void addRequiredAction(RequiredAction action) {
- checkReadonly();
- requiredActions.add(action.name());
-
- }
-
- @Override
- public void removeRequiredAction(RequiredAction action) {
- checkReadonly();
- requiredActions.remove(action.name());
- }
-
- @Override
- public boolean isEmailVerified() {
- return emailVerified;
- }
-
- @Override
- public void setEmailVerified(boolean verified) {
- checkReadonly();
- this.emailVerified = verified;
-
- }
-
- @Override
- public Stream getGroupsStream() {
- return groupIds.stream().map(realm::getGroupById);
- }
-
- @Override
- public void joinGroup(GroupModel group) {
- checkReadonly();
- groupIds.add(group.getId());
-
- }
-
- @Override
- public void leaveGroup(GroupModel group) {
- checkReadonly();
- groupIds.remove(group.getId());
-
- }
-
- @Override
- public boolean isMemberOf(GroupModel group) {
- if (groupIds == null) return false;
- if (groupIds.contains(group.getId())) return true;
- return RoleUtils.isMember(getGroupsStream(), group);
- }
-
- @Override
- public String getFederationLink() {
- return federationLink;
- }
-
- @Override
- public void setFederationLink(String link) {
- checkReadonly();
- this.federationLink = link;
-
- }
-
- @Override
- public String getServiceAccountClientLink() {
- return serviceAccountClientLink;
- }
-
- @Override
- public void setServiceAccountClientLink(String clientInternalId) {
- checkReadonly();
- this.serviceAccountClientLink = clientInternalId;
-
+ super(session, realm, id);
}
@Override
public SubjectCredentialManager credentialManager() {
return new LegacyUserCredentialManager(session, realm, this);
}
-
- @Override
- public Stream getRealmRoleMappingsStream() {
- return getRoleMappingsStream().filter(RoleUtils::isRealmRole);
- }
-
- @Override
- public Stream getClientRoleMappingsStream(ClientModel app) {
- return getRoleMappingsStream().filter(r -> RoleUtils.isClientRole(r, app));
- }
-
- @Override
- public boolean hasRole(RoleModel role) {
- return RoleUtils.hasRole(getRoleMappingsStream(), role)
- || RoleUtils.hasRoleFromGroup(getGroupsStream(), role, true);
- }
-
- @Override
- public void grantRole(RoleModel role) {
- roleIds.add(role.getId());
-
- }
-
- @Override
- public Stream getRoleMappingsStream() {
- return roleIds.stream().map(realm::getRoleById);
- }
-
- @Override
- public void deleteRoleMapping(RoleModel role) {
- roleIds.remove(role.getId());
-
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || !(o instanceof UserModel)) return false;
-
- UserModel that = (UserModel) o;
- return that.getId().equals(getId());
- }
-
- @Override
- public int hashCode() {
- return getId().hashCode();
- }
-
}
diff --git a/model/legacy/src/main/java/org/keycloak/models/UserModelDefaultMethods.java b/server-spi-private/src/main/java/org/keycloak/models/UserModelDefaultMethods.java
similarity index 100%
rename from model/legacy/src/main/java/org/keycloak/models/UserModelDefaultMethods.java
rename to server-spi-private/src/main/java/org/keycloak/models/UserModelDefaultMethods.java
diff --git a/server-spi-private/src/main/java/org/keycloak/storage/adapter/AbstractInMemoryUserAdapter.java b/server-spi-private/src/main/java/org/keycloak/storage/adapter/AbstractInMemoryUserAdapter.java
new file mode 100644
index 0000000000..4928d3e839
--- /dev/null
+++ b/server-spi-private/src/main/java/org/keycloak/storage/adapter/AbstractInMemoryUserAdapter.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2016 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.storage.adapter;
+
+import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.common.util.Time;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.GroupModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserModelDefaultMethods;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.RoleUtils;
+import org.keycloak.storage.ReadOnlyException;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
+
+/**
+ * @author Bill Burke
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractInMemoryUserAdapter extends UserModelDefaultMethods {
+ private Long createdTimestamp = Time.currentTimeMillis();
+ private boolean emailVerified;
+ private boolean enabled;
+
+ private Set roleIds = new HashSet<>();
+ private Set groupIds = new HashSet<>();
+
+ private MultivaluedHashMap attributes = new MultivaluedHashMap<>();
+ private Set requiredActions = new HashSet<>();
+ private String federationLink;
+ private String serviceAccountClientLink;
+
+ protected KeycloakSession session;
+ protected RealmModel realm;
+ protected String id;
+ private boolean readonly;
+
+ protected AbstractInMemoryUserAdapter() {
+ }
+
+ protected AbstractInMemoryUserAdapter(KeycloakSession session, RealmModel realm, String id) {
+ this.session = session;
+ this.realm = realm;
+ this.id = id;
+ }
+
+ @Override
+ public String getUsername() {
+ return getFirstAttribute(UserModel.USERNAME);
+ }
+
+ @Override
+ public void setUsername(String username) {
+ username = username==null ? null : username.toLowerCase();
+ setSingleAttribute(UserModel.USERNAME, username);
+ }
+
+ public void addDefaults() {
+ this.grantRole(realm.getDefaultRole());
+
+ realm.getDefaultGroupsStream().forEach(this::joinGroup);
+ }
+
+ public void setReadonly(boolean flag) {
+ readonly = flag;
+ }
+
+ protected void checkReadonly() {
+ if (readonly) throw new ReadOnlyException("In-memory user model is not writable");
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public Long getCreatedTimestamp() {
+ return createdTimestamp;
+ }
+
+ @Override
+ public void setCreatedTimestamp(Long timestamp) {
+ checkReadonly();
+ this.createdTimestamp = timestamp;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ checkReadonly();
+ this.enabled = enabled;
+
+ }
+
+ @Override
+ public void setSingleAttribute(String name, String value) {
+ checkReadonly();
+ if (UserModel.USERNAME.equals(name) || UserModel.EMAIL.equals(name)) {
+ value = KeycloakModelUtils.toLowerCaseSafe(value);
+ }
+ attributes.putSingle(name, value);
+
+ }
+
+ @Override
+ public void setAttribute(String name, List values) {
+ checkReadonly();
+ if (UserModel.USERNAME.equals(name) || UserModel.EMAIL.equals(name)) {
+ String lowerCasedFirstValue = KeycloakModelUtils.toLowerCaseSafe((values != null && values.size() > 0) ? values.get(0) : null);
+ if (lowerCasedFirstValue != null) values.set(0, lowerCasedFirstValue);
+ }
+ attributes.put(name, values);
+
+ }
+
+ @Override
+ public void removeAttribute(String name) {
+ checkReadonly();
+ attributes.remove(name);
+
+ }
+
+ @Override
+ public String getFirstAttribute(String name) {
+ return attributes.getFirst(name);
+ }
+
+ @Override
+ public Stream getAttributeStream(String name) {
+ List value = this.attributes.get(name);
+ return value != null ? value.stream() : Stream.empty();
+ }
+
+ @Override
+ public Map> getAttributes() {
+ return attributes;
+ }
+
+ @Override
+ public Stream getRequiredActionsStream() {
+ return this.requiredActions.stream();
+ }
+
+ @Override
+ public void addRequiredAction(String action) {
+ checkReadonly();
+ requiredActions.add(action);
+
+ }
+
+ @Override
+ public void removeRequiredAction(String action) {
+ checkReadonly();
+ requiredActions.remove(action);
+
+ }
+
+ @Override
+ public void addRequiredAction(RequiredAction action) {
+ checkReadonly();
+ requiredActions.add(action.name());
+
+ }
+
+ @Override
+ public void removeRequiredAction(RequiredAction action) {
+ checkReadonly();
+ requiredActions.remove(action.name());
+ }
+
+ @Override
+ public boolean isEmailVerified() {
+ return emailVerified;
+ }
+
+ @Override
+ public void setEmailVerified(boolean verified) {
+ checkReadonly();
+ this.emailVerified = verified;
+
+ }
+
+ @Override
+ public Stream getGroupsStream() {
+ return groupIds.stream().map(realm::getGroupById);
+ }
+
+ @Override
+ public void joinGroup(GroupModel group) {
+ checkReadonly();
+ groupIds.add(group.getId());
+
+ }
+
+ @Override
+ public void leaveGroup(GroupModel group) {
+ checkReadonly();
+ groupIds.remove(group.getId());
+
+ }
+
+ @Override
+ public boolean isMemberOf(GroupModel group) {
+ if (groupIds == null) return false;
+ if (groupIds.contains(group.getId())) return true;
+ return RoleUtils.isMember(getGroupsStream(), group);
+ }
+
+ @Override
+ public String getFederationLink() {
+ return federationLink;
+ }
+
+ @Override
+ public void setFederationLink(String link) {
+ checkReadonly();
+ this.federationLink = link;
+
+ }
+
+ @Override
+ public String getServiceAccountClientLink() {
+ return serviceAccountClientLink;
+ }
+
+ @Override
+ public void setServiceAccountClientLink(String clientInternalId) {
+ checkReadonly();
+ this.serviceAccountClientLink = clientInternalId;
+
+ }
+
+ @Override
+ public Stream getRealmRoleMappingsStream() {
+ return getRoleMappingsStream().filter(RoleUtils::isRealmRole);
+ }
+
+ @Override
+ public Stream getClientRoleMappingsStream(ClientModel app) {
+ return getRoleMappingsStream().filter(r -> RoleUtils.isClientRole(r, app));
+ }
+
+ @Override
+ public boolean hasRole(RoleModel role) {
+ return RoleUtils.hasRole(getRoleMappingsStream(), role)
+ || RoleUtils.hasRoleFromGroup(getGroupsStream(), role, true);
+ }
+
+ @Override
+ public void grantRole(RoleModel role) {
+ roleIds.add(role.getId());
+
+ }
+
+ @Override
+ public Stream getRoleMappingsStream() {
+ return roleIds.stream().map(realm::getRoleById);
+ }
+
+ @Override
+ public void deleteRoleMapping(RoleModel role) {
+ roleIds.remove(role.getId());
+
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || !(o instanceof UserModel)) return false;
+
+ UserModel that = (UserModel) o;
+ return that.getId().equals(getId());
+ }
+
+ @Override
+ public int hashCode() {
+ return getId().hashCode();
+ }
+}