Merge pull request #3852 from tkyjovsk/user-storage-tests

UserStorageTest migrated to Arquillian testsuite
This commit is contained in:
Pavel Drozd 2017-02-22 16:09:57 +01:00 committed by GitHub
commit 089bde3571
16 changed files with 1426 additions and 45 deletions

View file

@ -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();
}
}

View file

@ -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() {
}
}

View file

@ -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() {
}
}

View file

@ -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();
}
}

View file

@ -1,2 +1,4 @@
org.keycloak.testsuite.federation.DummyUserFederationProviderFactory
org.keycloak.testsuite.federation.PassThroughFederatedUserStorageProviderFactory
org.keycloak.testsuite.federation.UserMapStorageFactory
org.keycloak.testsuite.federation.UserPropertyFileStorageFactory
org.keycloak.testsuite.federation.PassThroughFederatedUserStorageProviderFactory

View file

@ -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,25 +165,26 @@ class UndertowDeployerHelper {
for (Map.Entry<ArchivePath, Node> entry : classNodes.entrySet()) {
Node n = entry.getValue();
ClassAsset classAsset = (ClassAsset) n.getAsset();
Class<?> clazz = classAsset.getSource();
if (n.getAsset() instanceof ClassAsset) {
ClassAsset classAsset = (ClassAsset) n.getAsset();
Class<?> clazz = classAsset.getSource();
WebServlet annotation = clazz.getAnnotation(WebServlet.class);
if (annotation != null) {
ServletInfo undertowServlet = new ServletInfo(clazz.getSimpleName(), (Class<? extends Servlet>) clazz);
WebServlet annotation = clazz.getAnnotation(WebServlet.class);
if (annotation != null) {
ServletInfo undertowServlet = new ServletInfo(clazz.getSimpleName(), (Class<? extends Servlet>) clazz);
String[] mappings = annotation.value();
if (mappings != null) {
for (String urlPattern : mappings) {
undertowServlet.addMapping(urlPattern);
String[] mappings = annotation.value();
if (mappings != null) {
for (String urlPattern : mappings) {
undertowServlet.addMapping(urlPattern);
}
}
}
di.addServlet(undertowServlet);
di.addServlet(undertowServlet);
}
}
}
}
}

View file

@ -1,20 +1,20 @@
<?xml version="1.0"?>
<!--
~ 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.
-->
~ 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.
-->
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

View file

@ -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);
@ -116,4 +122,4 @@ public abstract class AbstractAuthTest extends AbstractKeycloakTest {
return adminClient.realm(testRealmPage.getAuthRealm());
}
}
}

View file

@ -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);

View file

@ -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

View file

@ -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();

View file

@ -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();

View file

@ -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");
}
}

View file

@ -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
});
}
}

View file

@ -0,0 +1,4 @@
tbrady=goat
rob=pw
jules=pw
danny=pw

View file

@ -0,0 +1,4 @@
thor=hammer
zeus=pw
apollo=pw
perseus=pw