Merge pull request #3852 from tkyjovsk/user-storage-tests
UserStorageTest migrated to Arquillian testsuite
This commit is contained in:
commit
089bde3571
16 changed files with 1426 additions and 45 deletions
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* 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.testsuite.federation;
|
||||
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.credential.CredentialInput;
|
||||
import org.keycloak.credential.CredentialInputUpdater;
|
||||
import org.keycloak.credential.CredentialInputValidator;
|
||||
import org.keycloak.credential.CredentialModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.storage.StorageId;
|
||||
import org.keycloak.storage.UserStorageProvider;
|
||||
import org.keycloak.storage.adapter.AbstractUserAdapterFederatedStorage;
|
||||
import org.keycloak.storage.user.UserLookupProvider;
|
||||
import org.keycloak.storage.user.UserRegistrationProvider;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class UserMapStorage implements UserLookupProvider, UserStorageProvider, UserRegistrationProvider, CredentialInputUpdater, CredentialInputValidator {
|
||||
|
||||
private static final Logger log = Logger.getLogger(UserMapStorage.class);
|
||||
|
||||
protected Map<String, String> userPasswords;
|
||||
protected ComponentModel model;
|
||||
protected KeycloakSession session;
|
||||
|
||||
public static final AtomicInteger allocations = new AtomicInteger(0);
|
||||
public static final AtomicInteger closings = new AtomicInteger(0);
|
||||
public static final AtomicInteger realmRemovals = new AtomicInteger(0);
|
||||
public static final AtomicInteger groupRemovals = new AtomicInteger(0);
|
||||
public static final AtomicInteger roleRemovals = new AtomicInteger(0);
|
||||
|
||||
public UserMapStorage(KeycloakSession session, ComponentModel model, Map<String, String> userPasswords) {
|
||||
this.session = session;
|
||||
this.model = model;
|
||||
this.userPasswords = userPasswords;
|
||||
allocations.incrementAndGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserById(String id, RealmModel realm) {
|
||||
StorageId storageId = new StorageId(id);
|
||||
final String username = storageId.getExternalId();
|
||||
if (!userPasswords.containsKey(username)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return createUser(realm, username);
|
||||
}
|
||||
|
||||
private UserModel createUser(RealmModel realm, String username) {
|
||||
return new AbstractUserAdapterFederatedStorage(session, realm, model) {
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsername(String username) {
|
||||
throw new RuntimeException("Unsupported");
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCredentialType(String credentialType) {
|
||||
return CredentialModel.PASSWORD.equals(credentialType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
|
||||
if (!(input instanceof UserCredentialModel)) {
|
||||
return false;
|
||||
}
|
||||
if (input.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
userPasswords.put(user.getUsername(), ((UserCredentialModel) input).getValue());
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableCredentialType(RealmModel realm, UserModel user, String credentialType) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getDisableableCredentialTypes(RealmModel realm, UserModel user) {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType) {
|
||||
return CredentialModel.PASSWORD.equals(credentialType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
|
||||
if (!(input instanceof UserCredentialModel)) {
|
||||
return false;
|
||||
}
|
||||
if (input.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
String pw = userPasswords.get(user.getUsername());
|
||||
return pw != null && pw.equals(((UserCredentialModel) input).getValue());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByUsername(String username, RealmModel realm) {
|
||||
if (!userPasswords.containsKey(username)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return createUser(realm, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByEmail(String email, RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel addUser(RealmModel realm, String username) {
|
||||
userPasswords.put(username, "");
|
||||
return createUser(realm, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeUser(RealmModel realm, UserModel user) {
|
||||
return userPasswords.remove(user.getUsername()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm) {
|
||||
log.infof("preRemove: realm=%s", realm.getName());
|
||||
realmRemovals.incrementAndGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, GroupModel group) {
|
||||
log.infof("preRemove: realm=%s, group=%s", realm.getName(), group.getName());
|
||||
groupRemovals.incrementAndGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, RoleModel role) {
|
||||
log.infof("preRemove: realm=%s, role=%s", realm.getName(), role.getName());
|
||||
roleRemovals.incrementAndGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
closings.incrementAndGet();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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.testsuite.federation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.storage.UserStorageProviderFactory;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class UserMapStorageFactory implements UserStorageProviderFactory<UserMapStorage> {
|
||||
|
||||
|
||||
public static final String PROVIDER_ID = "user-password-map-arq";
|
||||
|
||||
protected Map<String, String> userPasswords = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public UserMapStorage create(KeycloakSession session, ComponentModel model) {
|
||||
return new UserMapStorage(session, model, userPasswords);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* 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.testsuite.federation;
|
||||
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.credential.CredentialInput;
|
||||
import org.keycloak.credential.CredentialInputValidator;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.storage.StorageId;
|
||||
import org.keycloak.storage.UserStorageProvider;
|
||||
import org.keycloak.storage.adapter.AbstractUserAdapter;
|
||||
import org.keycloak.storage.adapter.AbstractUserAdapterFederatedStorage;
|
||||
import org.keycloak.storage.user.UserLookupProvider;
|
||||
import org.keycloak.storage.user.UserQueryProvider;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class UserPropertyFileStorage implements UserLookupProvider, UserStorageProvider, UserQueryProvider, CredentialInputValidator {
|
||||
|
||||
protected Properties userPasswords;
|
||||
protected ComponentModel model;
|
||||
protected KeycloakSession session;
|
||||
protected boolean federatedStorageEnabled;
|
||||
|
||||
public UserPropertyFileStorage(KeycloakSession session, ComponentModel model, Properties userPasswords) {
|
||||
this.session = session;
|
||||
this.model = model;
|
||||
this.userPasswords = userPasswords;
|
||||
this.federatedStorageEnabled = model.getConfig().containsKey("federatedStorage") && Boolean.valueOf(model.getConfig().getFirst("federatedStorage")).booleanValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UserModel getUserById(String id, RealmModel realm) {
|
||||
StorageId storageId = new StorageId(id);
|
||||
final String username = storageId.getExternalId();
|
||||
if (!userPasswords.containsKey(username)) return null;
|
||||
|
||||
return createUser(realm, username);
|
||||
}
|
||||
|
||||
private UserModel createUser(RealmModel realm, String username) {
|
||||
if (federatedStorageEnabled) {
|
||||
return new AbstractUserAdapterFederatedStorage(session, realm, model) {
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUsername(String username) {
|
||||
throw new RuntimeException("Unsupported");
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return new AbstractUserAdapter(session, realm, model) {
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByUsername(String username, RealmModel realm) {
|
||||
if (!userPasswords.containsKey(username)) return null;
|
||||
|
||||
return createUser(realm, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserByEmail(String email, RealmModel realm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, GroupModel group) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, RoleModel role) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsCredentialType(String credentialType) {
|
||||
return credentialType.equals(UserCredentialModel.PASSWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType) {
|
||||
return credentialType.equals(UserCredentialModel.PASSWORD) && userPasswords.get(user.getUsername()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
|
||||
if (!(input instanceof UserCredentialModel)) return false;
|
||||
if (input.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||
String pw = (String)userPasswords.get(user.getUsername());
|
||||
return pw != null && pw.equals( ((UserCredentialModel)input).getValue());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getUsersCount(RealmModel realm) {
|
||||
return userPasswords.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm) {
|
||||
List<UserModel> users = new LinkedList<>();
|
||||
for (Object username : userPasswords.keySet()) {
|
||||
users.add(createUser(realm, (String)username));
|
||||
}
|
||||
return users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(Map<String, String> attributes, RealmModel realm) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
||||
if (maxResults == 0) return Collections.EMPTY_LIST;
|
||||
List<UserModel> users = new LinkedList<>();
|
||||
int count = 0;
|
||||
for (Object un : userPasswords.keySet()) {
|
||||
if (count++ < firstResult) continue;
|
||||
String username = (String)un;
|
||||
users.add(createUser(realm, username));
|
||||
if (users.size() + 1 > maxResults) break;
|
||||
}
|
||||
return users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
|
||||
if (maxResults == 0) return Collections.EMPTY_LIST;
|
||||
List<UserModel> users = new LinkedList<>();
|
||||
int count = 0;
|
||||
for (Object un : userPasswords.keySet()) {
|
||||
String username = (String)un;
|
||||
if (username.contains(search)) {
|
||||
if (count++ < firstResult) {
|
||||
continue;
|
||||
}
|
||||
users.add(createUser(realm, username));
|
||||
if (users.size() + 1 > maxResults) break;
|
||||
}
|
||||
}
|
||||
return users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
|
||||
if (attributes.size() != 1) return Collections.EMPTY_LIST;
|
||||
String username = attributes.get(UserModel.USERNAME);
|
||||
if (username == null) return Collections.EMPTY_LIST;
|
||||
return searchForUser(username, realm, firstResult, maxResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
||||
return getUsers(realm, 0, Integer.MAX_VALUE - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* 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.testsuite.federation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.storage.UserStorageProviderFactory;
|
||||
import org.keycloak.storage.UserStorageProviderModel;
|
||||
import org.keycloak.storage.user.ImportSynchronization;
|
||||
import org.keycloak.storage.user.SynchronizationResult;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import org.keycloak.common.util.EnvUtil;
|
||||
import org.keycloak.component.ComponentValidationException;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.provider.ProviderConfigurationBuilder;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class UserPropertyFileStorageFactory implements UserStorageProviderFactory<UserPropertyFileStorage>, ImportSynchronization {
|
||||
|
||||
public static final String PROVIDER_ID = "user-password-props-arq";
|
||||
public static final String PROPERTY_FILE = "propertyFile";
|
||||
|
||||
public static final String VALIDATION_PROP_FILE_NOT_CONFIGURED = "user property file is not configured";
|
||||
public static final String VALIDATION_PROP_FILE_DOESNT_EXIST = "user property file does not exist";
|
||||
|
||||
protected static final List<ProviderConfigProperty> CONFIG_PROPERTIES;
|
||||
|
||||
static {
|
||||
CONFIG_PROPERTIES = ProviderConfigurationBuilder.create()
|
||||
.property().name(PROPERTY_FILE)
|
||||
.type(ProviderConfigProperty.STRING_TYPE)
|
||||
.label("Property File")
|
||||
.helpText("File that contains name value pairs")
|
||||
.defaultValue(null)
|
||||
.add()
|
||||
.property().name("federatedStorage")
|
||||
.type(ProviderConfigProperty.BOOLEAN_TYPE)
|
||||
.label("User Federated Storage")
|
||||
.helpText("User Federated Storage")
|
||||
.defaultValue(null)
|
||||
.add()
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateConfiguration(KeycloakSession session, RealmModel realm, ComponentModel config) throws ComponentValidationException {
|
||||
String fp = config.getConfig().getFirst(PROPERTY_FILE);
|
||||
if (fp == null) {
|
||||
throw new ComponentValidationException(VALIDATION_PROP_FILE_NOT_CONFIGURED);
|
||||
}
|
||||
fp = EnvUtil.replace(fp);
|
||||
File file = new File(fp);
|
||||
if (!file.exists()) {
|
||||
throw new ComponentValidationException(VALIDATION_PROP_FILE_DOESNT_EXIST);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserPropertyFileStorage create(KeycloakSession session, ComponentModel model) {
|
||||
String path = model.getConfig().getFirst(PROPERTY_FILE);
|
||||
path = EnvUtil.replace(path);
|
||||
|
||||
Properties props = new Properties();
|
||||
try (InputStream is = new FileInputStream(path)) {
|
||||
props.load(is);
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return new UserPropertyFileStorage(session, model, props);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return CONFIG_PROPERTIES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SynchronizationResult sync(KeycloakSessionFactory sessionFactory, String realmId, UserStorageProviderModel model) {
|
||||
return SynchronizationResult.ignored();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SynchronizationResult syncSince(Date lastSync, KeycloakSessionFactory sessionFactory, String realmId, UserStorageProviderModel model) {
|
||||
return SynchronizationResult.ignored();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,2 +1,4 @@
|
|||
org.keycloak.testsuite.federation.DummyUserFederationProviderFactory
|
||||
org.keycloak.testsuite.federation.UserMapStorageFactory
|
||||
org.keycloak.testsuite.federation.UserPropertyFileStorageFactory
|
||||
org.keycloak.testsuite.federation.PassThroughFederatedUserStorageProviderFactory
|
|
@ -14,7 +14,6 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.arquillian.undertow;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -83,7 +82,6 @@ class UndertowDeployerHelper {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private ResourceManager getResourceManager(final String appServerRoot, final WebArchive archive) throws IOException {
|
||||
return new ResourceManager() {
|
||||
|
||||
|
@ -139,7 +137,6 @@ class UndertowDeployerHelper {
|
|||
throw UndertowMessages.MESSAGES.resourceChangeListenerNotSupported();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// TODO: Should close open streams?
|
||||
|
@ -148,7 +145,6 @@ class UndertowDeployerHelper {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
private Document loadXML(InputStream is) {
|
||||
try {
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
|
@ -159,7 +155,6 @@ class UndertowDeployerHelper {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void addAnnotatedServlets(DeploymentInfo di, Archive<?> archive) {
|
||||
Map<ArchivePath, Node> classNodes = archive.getContent((ArchivePath path) -> {
|
||||
|
||||
|
@ -170,6 +165,7 @@ class UndertowDeployerHelper {
|
|||
|
||||
for (Map.Entry<ArchivePath, Node> entry : classNodes.entrySet()) {
|
||||
Node n = entry.getValue();
|
||||
if (n.getAsset() instanceof ClassAsset) {
|
||||
ClassAsset classAsset = (ClassAsset) n.getAsset();
|
||||
Class<?> clazz = classAsset.getSource();
|
||||
|
||||
|
@ -187,8 +183,8 @@ class UndertowDeployerHelper {
|
|||
di.addServlet(undertowServlet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -68,11 +68,16 @@ public abstract class AbstractAuthTest extends AbstractKeycloakTest {
|
|||
testRealms.add(testRealmRep);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeAuthTest() {
|
||||
@Override
|
||||
public void setDefaultPageUriParameters() {
|
||||
super.setDefaultPageUriParameters();
|
||||
testRealmPage.setAuthRealm(TEST);
|
||||
testRealmLoginPage.setAuthRealm(testRealmPage);
|
||||
testRealmAccountPage.setAuthRealm(testRealmPage);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeAuthTest() {
|
||||
testUser = createUserRepresentation("test", "test@email.test", "test", "user", true);
|
||||
setPasswordFor(testUser, PASSWORD);
|
||||
|
||||
|
@ -82,6 +87,7 @@ public abstract class AbstractAuthTest extends AbstractKeycloakTest {
|
|||
deleteAllCookiesForTestRealm();
|
||||
}
|
||||
|
||||
|
||||
public void createTestUserWithAdminClient() {
|
||||
log.debug("creating test user");
|
||||
String id = createUserAndResetPasswordWithAdminClient(testRealmResource(), testUser, PASSWORD);
|
||||
|
|
|
@ -53,8 +53,8 @@ public class ApiUtil {
|
|||
URI location = response.getLocation();
|
||||
if (!response.getStatusInfo().equals(Status.CREATED)) {
|
||||
StatusType statusInfo = response.getStatusInfo();
|
||||
throw new WebApplicationException("Create method returned status " +
|
||||
statusInfo.getReasonPhrase() + " (Code: " + statusInfo.getStatusCode() + "); expected status: Created (201)", response);
|
||||
throw new WebApplicationException("Create method returned status "
|
||||
+ statusInfo.getReasonPhrase() + " (Code: " + statusInfo.getStatusCode() + "); expected status: Created (201)", response);
|
||||
}
|
||||
if (location == null) {
|
||||
return null;
|
||||
|
@ -118,14 +118,16 @@ public class ApiUtil {
|
|||
|
||||
public static UserRepresentation findUserByUsername(RealmResource realm, String username) {
|
||||
UserRepresentation user = null;
|
||||
List<UserRepresentation> ur = realm.users().search(username, null, null);
|
||||
List<UserRepresentation> ur = realm.users().search(username, null, null, null, 0, Integer.MAX_VALUE);
|
||||
if (ur.size() == 1) {
|
||||
user = ur.get(0);
|
||||
}
|
||||
|
||||
if (ur.size() > 1) { // try to be more specific
|
||||
for (UserRepresentation rep : ur) {
|
||||
if (rep.getUsername().equalsIgnoreCase(username)) return rep;
|
||||
if (rep.getUsername().equalsIgnoreCase(username)) {
|
||||
return rep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,6 +159,21 @@ public class ApiUtil {
|
|||
userResource.resetPassword(newCredential);
|
||||
}
|
||||
|
||||
public static void assignRealmRoles(RealmResource realm, String userId, String... roles) {
|
||||
String realmName = realm.toRepresentation().getRealm();
|
||||
|
||||
List<RoleRepresentation> roleRepresentations = new ArrayList<>();
|
||||
for (String roleName : roles) {
|
||||
RoleRepresentation role = realm.roles().get(roleName).toRepresentation();
|
||||
roleRepresentations.add(role);
|
||||
}
|
||||
|
||||
UserResource userResource = realm.users().get(userId);
|
||||
log.info("assigning roles " + Arrays.toString(roles) + " to user: \""
|
||||
+ userResource.toRepresentation().getUsername() + "\" in realm: \"" + realmName + "\"");
|
||||
userResource.roles().realmLevel().add(roleRepresentations);
|
||||
}
|
||||
|
||||
public static void assignClientRoles(RealmResource realm, String userId, String clientName, String... roles) {
|
||||
String realmName = realm.toRepresentation().getRealm();
|
||||
String clientId = "";
|
||||
|
@ -176,7 +193,7 @@ public class ApiUtil {
|
|||
}
|
||||
|
||||
UserResource userResource = realm.users().get(userId);
|
||||
log.debug("assigning role: " + Arrays.toString(roles) + " to user: \""
|
||||
log.info("assigning role: " + Arrays.toString(roles) + " to user: \""
|
||||
+ userResource.toRepresentation().getUsername() + "\" of client: \""
|
||||
+ clientName + "\" in realm: \"" + realmName + "\"");
|
||||
userResource.roles().clientLevel(clientId).add(roleRepresentations);
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.keycloak.testsuite.util.RealmBuilder;
|
|||
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.List;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -46,6 +47,14 @@ public abstract class AbstractClientTest extends AbstractAuthTest {
|
|||
@Rule
|
||||
public AssertAdminEvents assertAdminEvents = new AssertAdminEvents(this);
|
||||
|
||||
@Override
|
||||
public void setDefaultPageUriParameters() {
|
||||
super.setDefaultPageUriParameters();
|
||||
testRealmPage.setAuthRealm(MASTER);
|
||||
testRealmLoginPage.setAuthRealm(testRealmPage);
|
||||
testRealmAccountPage.setAuthRealm(testRealmPage);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setupAdminEvents() {
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
|
@ -66,7 +75,7 @@ public abstract class AbstractClientTest extends AbstractAuthTest {
|
|||
}
|
||||
|
||||
protected String getRealmId() {
|
||||
return "master";
|
||||
return MASTER;
|
||||
}
|
||||
|
||||
// returns UserRepresentation retrieved from server, with all fields, including id
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.admin.event;
|
||||
|
||||
import org.junit.Before;
|
||||
|
@ -23,6 +22,7 @@ import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
|
|||
import org.keycloak.testsuite.AbstractAuthTest;
|
||||
|
||||
import java.util.Collections;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -32,6 +32,14 @@ public abstract class AbstractEventTest extends AbstractAuthTest {
|
|||
|
||||
protected RealmEventsConfigRepresentation configRep;
|
||||
|
||||
@Override
|
||||
public void setDefaultPageUriParameters() {
|
||||
super.setDefaultPageUriParameters();
|
||||
testRealmPage.setAuthRealm(MASTER);
|
||||
testRealmLoginPage.setAuthRealm(testRealmPage);
|
||||
testRealmAccountPage.setAuthRealm(testRealmPage);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setConfigRep() {
|
||||
RealmResource testRsc = testRealmResource();
|
||||
|
|
|
@ -339,9 +339,9 @@ public class PartialImportTest extends AbstractAuthTest {
|
|||
@Test
|
||||
public void testAddUsersWithDuplicateEmailsAllowed() {
|
||||
|
||||
RealmRepresentation realmRep = new RealmRepresentation();
|
||||
RealmRepresentation realmRep = testRealmResource().toRepresentation();
|
||||
realmRep.setDuplicateEmailsAllowed(true);
|
||||
adminClient.realm(realmId).update(realmRep);
|
||||
testRealmResource().update(realmRep);
|
||||
|
||||
assertAdminEvents.clear();
|
||||
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
package org.keycloak.testsuite.federation.storage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Assert;
|
||||
import static org.junit.Assert.fail;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.exportimport.ExportImportConfig;
|
||||
import org.keycloak.exportimport.ExportImportManager;
|
||||
import org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory;
|
||||
import org.keycloak.representations.idm.ComponentRepresentation;
|
||||
import org.keycloak.storage.UserStorageProvider;
|
||||
import org.keycloak.testsuite.AbstractAuthTest;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||
import org.keycloak.testsuite.federation.UserMapStorageFactory;
|
||||
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tkyjovsk
|
||||
*/
|
||||
public class ComponentExportImportTest extends AbstractAuthTest implements Serializable {
|
||||
|
||||
private File exportFile;
|
||||
|
||||
@Deployment
|
||||
public static WebArchive deploy() {
|
||||
return RunOnServerDeployment.create(ComponentExportImportTest.class, AbstractAuthTest.class, RealmResource.class)
|
||||
.addPackages(true, "org.keycloak.testsuite");
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setDirs() {
|
||||
exportFile = new File (new File(System.getProperty("auth.server.config.dir", "target")), "singleFile-full.json");
|
||||
log.infof("Export file: %s", exportFile);
|
||||
}
|
||||
|
||||
public void clearExportImportProperties() {
|
||||
// Clear export/import properties after test
|
||||
Properties systemProps = System.getProperties();
|
||||
Set<String> propsToRemove = new HashSet<>();
|
||||
|
||||
for (Object key : systemProps.keySet()) {
|
||||
if (key.toString().startsWith(ExportImportConfig.PREFIX)) {
|
||||
propsToRemove.add(key.toString());
|
||||
}
|
||||
}
|
||||
|
||||
for (String propToRemove : propsToRemove) {
|
||||
systemProps.remove(propToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
protected String addComponent(ComponentRepresentation component) {
|
||||
return ApiUtil.getCreatedId(testRealmResource().components().add(component));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testSingleFile() {
|
||||
clearExportImportProperties();
|
||||
|
||||
String realmId = testRealmResource().toRepresentation().getId();
|
||||
String realmName = testRealmResource().toRepresentation().getRealm();
|
||||
|
||||
ComponentRepresentation parentComponent = new ComponentRepresentation();
|
||||
parentComponent.setParentId(realmId);
|
||||
parentComponent.setName("parent");
|
||||
parentComponent.setSubType("subtype");
|
||||
parentComponent.setProviderId(UserMapStorageFactory.PROVIDER_ID);
|
||||
parentComponent.setProviderType(UserStorageProvider.class.getName());
|
||||
parentComponent.setConfig(new MultivaluedHashMap<>());
|
||||
parentComponent.getConfig().putSingle("priority", Integer.toString(0));
|
||||
parentComponent.getConfig().putSingle("attr", "value");
|
||||
String parentComponentId = addComponent(parentComponent);
|
||||
|
||||
ComponentRepresentation subcomponent = new ComponentRepresentation();
|
||||
subcomponent.setParentId(parentComponentId);
|
||||
subcomponent.setName("child");
|
||||
subcomponent.setSubType("subtype2");
|
||||
subcomponent.setProviderId(UserMapStorageFactory.PROVIDER_ID);
|
||||
subcomponent.setProviderType(UserStorageProvider.class.getName());
|
||||
subcomponent.setConfig(new MultivaluedHashMap<>());
|
||||
subcomponent.getConfig().putSingle("priority", Integer.toString(0));
|
||||
subcomponent.getConfig().putSingle("attr", "value2");
|
||||
String subcomponentId = addComponent(subcomponent);
|
||||
|
||||
// export
|
||||
testingClient.server().run(session -> {
|
||||
ExportImportConfig.setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
|
||||
ExportImportConfig.setFile(exportFile.getAbsolutePath());
|
||||
ExportImportConfig.setRealmName(realmName);
|
||||
ExportImportConfig.setAction(ExportImportConfig.ACTION_EXPORT);
|
||||
new ExportImportManager(session).runExport();
|
||||
});
|
||||
|
||||
// import
|
||||
testingClient.server().run(session -> {
|
||||
Assert.assertNull(session.realms().getRealmByName(TEST));
|
||||
ExportImportConfig.setAction(ExportImportConfig.ACTION_IMPORT);
|
||||
new ExportImportManager(session).runImport();
|
||||
Assert.assertNotNull(session.realms().getRealmByName(TEST));
|
||||
});
|
||||
|
||||
try {
|
||||
parentComponent = testRealmResource().components().component(parentComponentId).toRepresentation();
|
||||
subcomponent = testRealmResource().components().component(subcomponentId).toRepresentation();
|
||||
} catch (NotFoundException nfe) {
|
||||
fail("Components not found after import.");
|
||||
}
|
||||
|
||||
Assert.assertEquals(parentComponent.getParentId(), realmId);
|
||||
Assert.assertEquals(parentComponent.getName(), "parent");
|
||||
Assert.assertEquals(parentComponent.getSubType(), "subtype");
|
||||
Assert.assertEquals(parentComponent.getProviderId(), UserMapStorageFactory.PROVIDER_ID);
|
||||
Assert.assertEquals(parentComponent.getProviderType(), UserStorageProvider.class.getName());
|
||||
Assert.assertEquals(parentComponent.getConfig().getFirst("attr"), "value");
|
||||
|
||||
Assert.assertEquals(subcomponent.getParentId(), realmId);
|
||||
Assert.assertEquals(subcomponent.getName(), "child");
|
||||
Assert.assertEquals(subcomponent.getSubType(), "subtype2");
|
||||
Assert.assertEquals(subcomponent.getProviderId(), UserMapStorageFactory.PROVIDER_ID);
|
||||
Assert.assertEquals(subcomponent.getProviderType(), UserStorageProvider.class.getName());
|
||||
Assert.assertEquals(subcomponent.getConfig().getFirst("attr"), "value2");
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,585 @@
|
|||
package org.keycloak.testsuite.federation.storage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import static java.util.Calendar.DAY_OF_WEEK;
|
||||
import static java.util.Calendar.HOUR_OF_DAY;
|
||||
import static java.util.Calendar.MINUTE;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Assert;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import static org.keycloak.models.UserModel.RequiredAction.UPDATE_PROFILE;
|
||||
import org.keycloak.models.cache.CachedUserModel;
|
||||
import org.keycloak.representations.idm.ComponentRepresentation;
|
||||
import org.keycloak.representations.idm.GroupRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.storage.UserStorageProvider;
|
||||
import static org.keycloak.storage.UserStorageProviderModel.CACHE_POLICY;
|
||||
import org.keycloak.storage.UserStorageProviderModel.CachePolicy;
|
||||
import static org.keycloak.storage.UserStorageProviderModel.EVICTION_DAY;
|
||||
import static org.keycloak.storage.UserStorageProviderModel.EVICTION_HOUR;
|
||||
import static org.keycloak.storage.UserStorageProviderModel.EVICTION_MINUTE;
|
||||
import static org.keycloak.storage.UserStorageProviderModel.MAX_LIFESPAN;
|
||||
import org.keycloak.testsuite.AbstractAuthTest;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.federation.UserMapStorage;
|
||||
import org.keycloak.testsuite.federation.UserMapStorageFactory;
|
||||
import org.keycloak.testsuite.federation.UserPropertyFileStorageFactory;
|
||||
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlDoesntStartWith;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tkyjovsk
|
||||
*/
|
||||
public class UserStorageTest extends AbstractAuthTest {
|
||||
|
||||
private String memProviderId;
|
||||
private String propProviderROId;
|
||||
private String propProviderRWId;
|
||||
|
||||
private static final File CONFIG_DIR = new File(System.getProperty("auth.server.config.dir", ""));
|
||||
|
||||
@Before
|
||||
public void addProvidersBeforeTest() throws URISyntaxException, IOException {
|
||||
ComponentRepresentation memProvider = new ComponentRepresentation();
|
||||
memProvider.setName("memory");
|
||||
memProvider.setProviderId(UserMapStorageFactory.PROVIDER_ID);
|
||||
memProvider.setProviderType(UserStorageProvider.class.getName());
|
||||
memProvider.setConfig(new MultivaluedHashMap<>());
|
||||
memProvider.getConfig().putSingle("priority", Integer.toString(0));
|
||||
|
||||
memProviderId = addComponent(memProvider);
|
||||
|
||||
// copy files used by the following RO/RW user providers
|
||||
File stResDir = new File(getClass().getResource("/storage-test").toURI());
|
||||
if (stResDir.exists() && stResDir.isDirectory() && CONFIG_DIR.exists() && CONFIG_DIR.isDirectory()) {
|
||||
for (File f : stResDir.listFiles()) {
|
||||
log.infof("Copying %s to %s", f.getName(), CONFIG_DIR.getAbsolutePath());
|
||||
FileUtils.copyFileToDirectory(f, CONFIG_DIR);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Property `auth.server.config.dir` must be set to run UserStorageTests.");
|
||||
}
|
||||
|
||||
ComponentRepresentation propProviderRO = new ComponentRepresentation();
|
||||
propProviderRO.setName("read-only-user-props");
|
||||
propProviderRO.setProviderId(UserPropertyFileStorageFactory.PROVIDER_ID);
|
||||
propProviderRO.setProviderType(UserStorageProvider.class.getName());
|
||||
propProviderRO.setConfig(new MultivaluedHashMap<>());
|
||||
propProviderRO.getConfig().putSingle("priority", Integer.toString(1));
|
||||
propProviderRO.getConfig().putSingle("propertyFile",
|
||||
CONFIG_DIR.getAbsolutePath() + File.separator + "read-only-user-password.properties");
|
||||
|
||||
propProviderROId = addComponent(propProviderRO);
|
||||
|
||||
propProviderRWId = addComponent(newPropProviderRW());
|
||||
|
||||
}
|
||||
|
||||
protected ComponentRepresentation newPropProviderRW() {
|
||||
ComponentRepresentation propProviderRW = new ComponentRepresentation();
|
||||
propProviderRW.setName("user-props");
|
||||
propProviderRW.setProviderId(UserPropertyFileStorageFactory.PROVIDER_ID);
|
||||
propProviderRW.setProviderType(UserStorageProvider.class.getName());
|
||||
propProviderRW.setConfig(new MultivaluedHashMap<>());
|
||||
propProviderRW.getConfig().putSingle("priority", Integer.toString(2));
|
||||
propProviderRW.getConfig().putSingle("propertyFile", CONFIG_DIR.getAbsolutePath() + File.separator + "user-password.properties");
|
||||
propProviderRW.getConfig().putSingle("federatedStorage", "true");
|
||||
return propProviderRW;
|
||||
}
|
||||
|
||||
protected String addComponent(ComponentRepresentation component) {
|
||||
return ApiUtil.getCreatedId(testRealmResource().components().add(component));
|
||||
}
|
||||
|
||||
private void loginSuccessAndLogout(String username, String password) {
|
||||
testRealmAccountPage.navigateTo();
|
||||
testRealmLoginPage.form().login(username, password);
|
||||
assertCurrentUrlStartsWith(testRealmAccountPage);
|
||||
testRealmAccountPage.logOut();
|
||||
}
|
||||
|
||||
public void loginBadPassword(String username) {
|
||||
testRealmAccountPage.navigateTo();
|
||||
testRealmLoginPage.form().login(username, "badpassword");
|
||||
assertCurrentUrlDoesntStartWith(testRealmAccountPage);
|
||||
}
|
||||
|
||||
// @Test
|
||||
public void listComponents() {
|
||||
log.info("COMPONENTS:");
|
||||
testRealmResource().components().query().forEach((c) -> {
|
||||
log.infof("%s - %s - %s", c.getId(), c.getProviderType(), c.getName());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoginSuccess() {
|
||||
loginSuccessAndLogout("tbrady", "goat");
|
||||
loginSuccessAndLogout("thor", "hammer");
|
||||
loginBadPassword("tbrady");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdate() {
|
||||
UserRepresentation thor = ApiUtil.findUserByUsername(testRealmResource(), "thor");
|
||||
|
||||
// update entity
|
||||
thor.setFirstName("Stian");
|
||||
thor.setLastName("Thorgersen");
|
||||
thor.setEmailVerified(true);
|
||||
long thorCreated = System.currentTimeMillis() - 100;
|
||||
thor.setCreatedTimestamp(thorCreated);
|
||||
thor.setEmail("thor@hammer.com");
|
||||
thor.setAttributes(new HashMap<>());
|
||||
thor.getAttributes().put("test-attribute", Arrays.asList("value"));
|
||||
thor.setRequiredActions(new ArrayList<>());
|
||||
thor.getRequiredActions().add(UPDATE_PROFILE.name());
|
||||
testRealmResource().users().get(thor.getId()).update(thor);
|
||||
|
||||
// check entity
|
||||
thor = ApiUtil.findUserByUsername(testRealmResource(), "thor");
|
||||
Assert.assertEquals("Stian", thor.getFirstName());
|
||||
Assert.assertEquals("Thorgersen", thor.getLastName());
|
||||
Assert.assertEquals("thor@hammer.com", thor.getEmail());
|
||||
Assert.assertTrue(thor.getAttributes().containsKey("test-attribute"));
|
||||
Assert.assertEquals(1, thor.getAttributes().get("test-attribute").size());
|
||||
Assert.assertEquals("value", thor.getAttributes().get("test-attribute").get(0));
|
||||
Assert.assertTrue(thor.isEmailVerified());
|
||||
|
||||
// update group
|
||||
GroupRepresentation g = new GroupRepresentation();
|
||||
g.setName("my-group");
|
||||
String gid = ApiUtil.getCreatedId(testRealmResource().groups().add(g));
|
||||
|
||||
testRealmResource().users().get(thor.getId()).joinGroup(gid);
|
||||
|
||||
// check group
|
||||
boolean foundGroup = false;
|
||||
for (GroupRepresentation ug : testRealmResource().users().get(thor.getId()).groups()) {
|
||||
if (ug.getId().equals(gid)) {
|
||||
foundGroup = true;
|
||||
}
|
||||
}
|
||||
Assert.assertTrue(foundGroup);
|
||||
|
||||
// check required actions
|
||||
assertTrue(thor.getRequiredActions().contains(UPDATE_PROFILE.name()));
|
||||
// remove req. actions
|
||||
thor.getRequiredActions().remove(UPDATE_PROFILE.name());
|
||||
testRealmResource().users().get(thor.getId()).update(thor);
|
||||
|
||||
// change pass
|
||||
ApiUtil.resetUserPassword(testRealmResource().users().get(thor.getId()), "lightning", false);
|
||||
loginSuccessAndLogout("thor", "lightning");
|
||||
|
||||
// update role
|
||||
RoleRepresentation r = new RoleRepresentation("foo-role", "foo role", false);
|
||||
testRealmResource().roles().create(r);
|
||||
ApiUtil.assignRealmRoles(testRealmResource(), thor.getId(), "foo-role");
|
||||
|
||||
// check role
|
||||
boolean foundRole = false;
|
||||
for (RoleRepresentation rr : user(thor.getId()).roles().getAll().getRealmMappings()) {
|
||||
if ("foo-role".equals(rr.getName())) {
|
||||
foundRole = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertTrue(foundRole);
|
||||
|
||||
// test removal of provider
|
||||
testRealmResource().components().component(propProviderRWId).remove();
|
||||
propProviderRWId = addComponent(newPropProviderRW());
|
||||
loginSuccessAndLogout("thor", "hammer");
|
||||
|
||||
thor = ApiUtil.findUserByUsername(testRealmResource(), "thor");
|
||||
|
||||
Assert.assertNull(thor.getFirstName());
|
||||
Assert.assertNull(thor.getLastName());
|
||||
Assert.assertNull(thor.getEmail());
|
||||
Assert.assertNull(thor.getAttributes());
|
||||
Assert.assertFalse(thor.isEmailVerified());
|
||||
|
||||
foundGroup = false;
|
||||
for (GroupRepresentation ug : testRealmResource().users().get(thor.getId()).groups()) {
|
||||
if (ug.getId().equals(gid)) {
|
||||
foundGroup = true;
|
||||
}
|
||||
}
|
||||
Assert.assertFalse(foundGroup);
|
||||
|
||||
foundRole = false;
|
||||
for (RoleRepresentation rr : user(thor.getId()).roles().getAll().getRealmMappings()) {
|
||||
if ("foo-role".equals(rr.getName())) {
|
||||
foundRole = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertFalse(foundRole);
|
||||
}
|
||||
|
||||
public UserResource user(String userId) {
|
||||
return testRealmResource().users().get(userId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegistration() {
|
||||
UserRepresentation memuser = new UserRepresentation();
|
||||
memuser.setUsername("memuser");
|
||||
String uid = ApiUtil.createUserAndResetPasswordWithAdminClient(testRealmResource(), memuser, "password");
|
||||
loginSuccessAndLogout("memuser", "password");
|
||||
loginSuccessAndLogout("memuser", "password");
|
||||
loginSuccessAndLogout("memuser", "password");
|
||||
|
||||
memuser = user(uid).toRepresentation();
|
||||
assertNotNull(memuser);
|
||||
assertNotNull(memuser.getOrigin());
|
||||
ComponentRepresentation origin = testRealmResource().components().component(memuser.getOrigin()).toRepresentation();
|
||||
Assert.assertEquals("memory", origin.getName());
|
||||
|
||||
testRealmResource().users().get(memuser.getId()).remove();
|
||||
try {
|
||||
user(uid).toRepresentation(); // provider doesn't implement UserQueryProvider --> have to lookup by uid
|
||||
fail("`memuser` wasn't removed");
|
||||
} catch (NotFoundException nfe) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuery() {
|
||||
Set<UserRepresentation> queried = new HashSet<>();
|
||||
int first = 0;
|
||||
while (queried.size() < 8) {
|
||||
List<UserRepresentation> results = testRealmResource().users().search("", first, 3);
|
||||
log.debugf("first=%s, results: %s", first, results.size());
|
||||
if (results.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
first += results.size();
|
||||
queried.addAll(results);
|
||||
}
|
||||
Set<String> usernames = new HashSet<>();
|
||||
for (UserRepresentation user : queried) {
|
||||
usernames.add(user.getUsername());
|
||||
log.info(user.getUsername());
|
||||
}
|
||||
Assert.assertEquals(8, queried.size());
|
||||
Assert.assertTrue(usernames.contains("thor"));
|
||||
Assert.assertTrue(usernames.contains("zeus"));
|
||||
Assert.assertTrue(usernames.contains("apollo"));
|
||||
Assert.assertTrue(usernames.contains("perseus"));
|
||||
Assert.assertTrue(usernames.contains("tbrady"));
|
||||
Assert.assertTrue(usernames.contains("rob"));
|
||||
Assert.assertTrue(usernames.contains("jules"));
|
||||
Assert.assertTrue(usernames.contains("danny"));
|
||||
|
||||
// test searchForUser
|
||||
List<UserRepresentation> users = testRealmResource().users().search("tbrady", 0, Integer.MAX_VALUE);
|
||||
Assert.assertTrue(users.size() == 1);
|
||||
Assert.assertTrue(users.get(0).getUsername().equals("tbrady"));
|
||||
|
||||
// test getGroupMembers()
|
||||
GroupRepresentation g = new GroupRepresentation();
|
||||
g.setName("gods");
|
||||
String gid = ApiUtil.getCreatedId(testRealmResource().groups().add(g));
|
||||
|
||||
UserRepresentation user = ApiUtil.findUserByUsername(testRealmResource(), "apollo");
|
||||
testRealmResource().users().get(user.getId()).joinGroup(gid);
|
||||
user = ApiUtil.findUserByUsername(testRealmResource(), "zeus");
|
||||
testRealmResource().users().get(user.getId()).joinGroup(gid);
|
||||
user = ApiUtil.findUserByUsername(testRealmResource(), "thor");
|
||||
testRealmResource().users().get(user.getId()).joinGroup(gid);
|
||||
queried.clear();
|
||||
usernames.clear();
|
||||
|
||||
first = 0;
|
||||
while (queried.size() < 8) {
|
||||
List<UserRepresentation> results = testRealmResource().groups().group(gid).members(first, 1);
|
||||
log.debugf("first=%s, results: %s", first, results.size());
|
||||
if (results.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
first += results.size();
|
||||
queried.addAll(results);
|
||||
}
|
||||
for (UserRepresentation u : queried) {
|
||||
usernames.add(u.getUsername());
|
||||
log.info(u.getUsername());
|
||||
}
|
||||
Assert.assertEquals(3, queried.size());
|
||||
Assert.assertTrue(usernames.contains("apollo"));
|
||||
Assert.assertTrue(usernames.contains("zeus"));
|
||||
Assert.assertTrue(usernames.contains("thor"));
|
||||
|
||||
// search by single attribute
|
||||
// FIXME - no equivalent for model in REST
|
||||
}
|
||||
|
||||
@Deployment
|
||||
public static WebArchive deploy() {
|
||||
return RunOnServerDeployment.create(UserResource.class)
|
||||
.addPackages(true, "org.keycloak.testsuite");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDailyEviction() {
|
||||
ApiUtil.findUserByUsername(testRealmResource(), "thor");
|
||||
|
||||
// set eviction to 1 hour from now
|
||||
Calendar eviction = Calendar.getInstance();
|
||||
eviction.add(Calendar.HOUR, 1);
|
||||
ComponentRepresentation propProviderRW = testRealmResource().components().component(propProviderRWId).toRepresentation();
|
||||
propProviderRW.getConfig().putSingle(CACHE_POLICY, CachePolicy.EVICT_DAILY.name());
|
||||
propProviderRW.getConfig().putSingle(EVICTION_HOUR, Integer.toString(eviction.get(HOUR_OF_DAY)));
|
||||
propProviderRW.getConfig().putSingle(EVICTION_MINUTE, Integer.toString(eviction.get(MINUTE)));
|
||||
testRealmResource().components().component(propProviderRWId).update(propProviderRW);
|
||||
|
||||
// now
|
||||
testingClient.server().run(session -> {
|
||||
RealmModel realm = session.realms().getRealmByName("test");
|
||||
UserModel user = session.users().getUserByUsername("thor", realm);
|
||||
System.out.println("User class: " + user.getClass());
|
||||
Assert.assertTrue(user instanceof CachedUserModel); // should still be cached
|
||||
});
|
||||
|
||||
setTimeOffset(2 * 60 * 60); // 2 hours in future
|
||||
|
||||
testingClient.server().run(session -> {
|
||||
RealmModel realm = session.realms().getRealmByName("test");
|
||||
UserModel user = session.users().getUserByUsername("thor", realm);
|
||||
System.out.println("User class: " + user.getClass());
|
||||
Assert.assertFalse(user instanceof CachedUserModel); // should be evicted
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWeeklyEviction() {
|
||||
ApiUtil.findUserByUsername(testRealmResource(), "thor");
|
||||
|
||||
// set eviction to 4 days from now
|
||||
Calendar eviction = Calendar.getInstance();
|
||||
eviction.add(Calendar.HOUR, 4 * 24);
|
||||
ComponentRepresentation propProviderRW = testRealmResource().components().component(propProviderRWId).toRepresentation();
|
||||
propProviderRW.getConfig().putSingle(CACHE_POLICY, CachePolicy.EVICT_WEEKLY.name());
|
||||
propProviderRW.getConfig().putSingle(EVICTION_DAY, Integer.toString(eviction.get(DAY_OF_WEEK)));
|
||||
propProviderRW.getConfig().putSingle(EVICTION_HOUR, Integer.toString(eviction.get(HOUR_OF_DAY)));
|
||||
propProviderRW.getConfig().putSingle(EVICTION_MINUTE, Integer.toString(eviction.get(MINUTE)));
|
||||
testRealmResource().components().component(propProviderRWId).update(propProviderRW);
|
||||
|
||||
// now
|
||||
testingClient.server().run(session -> {
|
||||
RealmModel realm = session.realms().getRealmByName("test");
|
||||
UserModel user = session.users().getUserByUsername("thor", realm);
|
||||
System.out.println("User class: " + user.getClass());
|
||||
Assert.assertTrue(user instanceof CachedUserModel); // should still be cached
|
||||
});
|
||||
|
||||
setTimeOffset(2 * 24 * 60 * 60); // 2 days in future
|
||||
|
||||
// now
|
||||
testingClient.server().run(session -> {
|
||||
RealmModel realm = session.realms().getRealmByName("test");
|
||||
UserModel user = session.users().getUserByUsername("thor", realm);
|
||||
System.out.println("User class: " + user.getClass());
|
||||
Assert.assertTrue(user instanceof CachedUserModel); // should still be cached
|
||||
});
|
||||
|
||||
setTimeOffset(5 * 24 * 60 * 60); // 5 days in future
|
||||
|
||||
testingClient.server().run(session -> {
|
||||
RealmModel realm = session.realms().getRealmByName("test");
|
||||
UserModel user = session.users().getUserByUsername("thor", realm);
|
||||
System.out.println("User class: " + user.getClass());
|
||||
Assert.assertFalse(user instanceof CachedUserModel); // should be evicted
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testMaxLifespan() {
|
||||
ApiUtil.findUserByUsername(testRealmResource(), "thor");
|
||||
|
||||
// set eviction to 1 hour from now
|
||||
ComponentRepresentation propProviderRW = testRealmResource().components().component(propProviderRWId).toRepresentation();
|
||||
propProviderRW.getConfig().putSingle(CACHE_POLICY, CachePolicy.MAX_LIFESPAN.name());
|
||||
propProviderRW.getConfig().putSingle(MAX_LIFESPAN, Long.toString(1 * 60 * 60 * 1000)); // 1 hour in milliseconds
|
||||
testRealmResource().components().component(propProviderRWId).update(propProviderRW);
|
||||
|
||||
// now
|
||||
testingClient.server().run(session -> {
|
||||
RealmModel realm = session.realms().getRealmByName("test");
|
||||
UserModel user = session.users().getUserByUsername("thor", realm);
|
||||
System.out.println("User class: " + user.getClass());
|
||||
Assert.assertTrue(user instanceof CachedUserModel); // should still be cached
|
||||
});
|
||||
|
||||
setTimeOffset(1/2 * 60 * 60); // 1/2 hour in future
|
||||
|
||||
testingClient.server().run(session -> {
|
||||
RealmModel realm = session.realms().getRealmByName("test");
|
||||
UserModel user = session.users().getUserByUsername("thor", realm);
|
||||
System.out.println("User class: " + user.getClass());
|
||||
Assert.assertTrue(user instanceof CachedUserModel); // should still be cached
|
||||
});
|
||||
|
||||
setTimeOffset(2 * 60 * 60); // 2 hours in future
|
||||
|
||||
testingClient.server().run(session -> {
|
||||
RealmModel realm = session.realms().getRealmByName("test");
|
||||
UserModel user = session.users().getUserByUsername("thor", realm);
|
||||
System.out.println("User class: " + user.getClass());
|
||||
Assert.assertFalse(user instanceof CachedUserModel); // should be evicted
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoCache() {
|
||||
ApiUtil.findUserByUsername(testRealmResource(), "thor");
|
||||
|
||||
// set NO_CACHE policy
|
||||
ComponentRepresentation propProviderRW = testRealmResource().components().component(propProviderRWId).toRepresentation();
|
||||
propProviderRW.getConfig().putSingle(CACHE_POLICY, CachePolicy.NO_CACHE.name());
|
||||
testRealmResource().components().component(propProviderRWId).update(propProviderRW);
|
||||
|
||||
testingClient.server().run(session -> {
|
||||
RealmModel realm = session.realms().getRealmByName("test");
|
||||
UserModel user = session.users().getUserByUsername("thor", realm);
|
||||
System.out.println("User class: " + user.getClass());
|
||||
Assert.assertFalse(user instanceof CachedUserModel); // should be evicted
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycle() {
|
||||
|
||||
testingClient.server().run(session -> {
|
||||
UserMapStorage.allocations.set(0);
|
||||
UserMapStorage.closings.set(0);
|
||||
|
||||
RealmModel realm = session.realms().getRealmByName("test");
|
||||
UserModel user = session.users().addUser(realm, "memuser");
|
||||
Assert.assertNotNull(user);
|
||||
user = session.users().getUserByUsername("nonexistent", realm);
|
||||
Assert.assertNull(user);
|
||||
|
||||
Assert.assertEquals(1, UserMapStorage.allocations.get());
|
||||
Assert.assertEquals(0, UserMapStorage.closings.get());
|
||||
});
|
||||
|
||||
testingClient.server().run(session -> {
|
||||
Assert.assertEquals(1, UserMapStorage.allocations.get());
|
||||
Assert.assertEquals(1, UserMapStorage.closings.get());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEntityRemovalHooks() {
|
||||
testingClient.server().run(session -> {
|
||||
UserMapStorage.realmRemovals.set(0);
|
||||
UserMapStorage.groupRemovals.set(0);
|
||||
UserMapStorage.roleRemovals.set(0);
|
||||
});
|
||||
|
||||
// remove group
|
||||
GroupRepresentation g1 = new GroupRepresentation();
|
||||
g1.setName("group1");
|
||||
GroupRepresentation g2 = new GroupRepresentation();
|
||||
g2.setName("group2");
|
||||
String gid1 = ApiUtil.getCreatedId(testRealmResource().groups().add(g1));
|
||||
String gid2 = ApiUtil.getCreatedId(testRealmResource().groups().add(g2));
|
||||
testRealmResource().groups().group(gid1).remove();
|
||||
testRealmResource().groups().group(gid2).remove();
|
||||
testingClient.server().run(session -> {
|
||||
Assert.assertEquals(2, UserMapStorage.groupRemovals.get());
|
||||
UserMapStorage.realmRemovals.set(0);
|
||||
});
|
||||
|
||||
// remove role
|
||||
RoleRepresentation role1 = new RoleRepresentation();
|
||||
role1.setName("role1");
|
||||
RoleRepresentation role2 = new RoleRepresentation();
|
||||
role2.setName("role2");
|
||||
testRealmResource().roles().create(role1);
|
||||
testRealmResource().roles().create(role2);
|
||||
testRealmResource().roles().get("role1").remove();
|
||||
testRealmResource().roles().get("role2").remove();
|
||||
testingClient.server().run(session -> {
|
||||
Assert.assertEquals(2, UserMapStorage.roleRemovals.get());
|
||||
UserMapStorage.realmRemovals.set(0);
|
||||
});
|
||||
|
||||
// remove realm
|
||||
RealmRepresentation testRealmRepresentation = testRealmResource().toRepresentation();
|
||||
testRealmResource().remove();
|
||||
testingClient.server().run(session -> {
|
||||
Assert.assertEquals(1, UserMapStorage.realmRemovals.get());
|
||||
UserMapStorage.realmRemovals.set(0);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testEntityRemovalHooksCascade() {
|
||||
testingClient.server().run(session -> {
|
||||
UserMapStorage.realmRemovals.set(0);
|
||||
UserMapStorage.groupRemovals.set(0);
|
||||
UserMapStorage.roleRemovals.set(0);
|
||||
});
|
||||
|
||||
GroupRepresentation g1 = new GroupRepresentation();
|
||||
g1.setName("group1");
|
||||
GroupRepresentation g2 = new GroupRepresentation();
|
||||
g2.setName("group2");
|
||||
String gid1 = ApiUtil.getCreatedId(testRealmResource().groups().add(g1));
|
||||
String gid2 = ApiUtil.getCreatedId(testRealmResource().groups().add(g2));
|
||||
|
||||
RoleRepresentation role1 = new RoleRepresentation();
|
||||
role1.setName("role1");
|
||||
RoleRepresentation role2 = new RoleRepresentation();
|
||||
role2.setName("role2");
|
||||
testRealmResource().roles().create(role1);
|
||||
testRealmResource().roles().create(role2);
|
||||
|
||||
// remove realm with groups and roles in it
|
||||
testRealmResource().remove();
|
||||
testingClient.server().run(session -> {
|
||||
Assert.assertEquals(1, UserMapStorage.realmRemovals.get());
|
||||
Assert.assertEquals(2, UserMapStorage.groupRemovals.get()); // check if group removal hooks were called
|
||||
Assert.assertEquals(2, UserMapStorage.roleRemovals.get()); // check if role removal hooks were called
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
tbrady=goat
|
||||
rob=pw
|
||||
jules=pw
|
||||
danny=pw
|
|
@ -0,0 +1,4 @@
|
|||
thor=hammer
|
||||
zeus=pw
|
||||
apollo=pw
|
||||
perseus=pw
|
Loading…
Reference in a new issue