Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
060a90197e
54 changed files with 591 additions and 301 deletions
|
@ -70,7 +70,7 @@ public class AuthenticationProviderManager {
|
||||||
AuthenticationLinkModel authLink = user.getAuthenticationLink();
|
AuthenticationLinkModel authLink = user.getAuthenticationLink();
|
||||||
if (authLink == null) {
|
if (authLink == null) {
|
||||||
// User not yet linked with any authenticationProvider. Find provider with biggest priority where he is and link
|
// User not yet linked with any authenticationProvider. Find provider with biggest priority where he is and link
|
||||||
AuthUser authUser = getUser(user.getLoginName());
|
AuthUser authUser = getUser(user.getUsername());
|
||||||
authLink = new AuthenticationLinkModel(authUser.getProviderName(), authUser.getId());
|
authLink = new AuthenticationLinkModel(authUser.getProviderName(), authUser.getId());
|
||||||
user.setAuthenticationLink(authLink);
|
user.setAuthenticationLink(authLink);
|
||||||
logger.infof("User '%s' linked with provider '%s'", authUser.getUsername(), authUser.getProviderName());
|
logger.infof("User '%s' linked with provider '%s'", authUser.getUsername(), authUser.getProviderName());
|
||||||
|
@ -85,10 +85,10 @@ public class AuthenticationProviderManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
checkCorrectAuthLink(delegate, providerModel, authLink, user.getLoginName());
|
checkCorrectAuthLink(delegate, providerModel, authLink, user.getUsername());
|
||||||
|
|
||||||
AuthProviderStatus currentResult = delegate.validatePassword(realm, providerModel.getConfig(), user.getLoginName(), password);
|
AuthProviderStatus currentResult = delegate.validatePassword(realm, providerModel.getConfig(), user.getUsername(), password);
|
||||||
logger.debugf("Authentication provider '%s' finished with '%s' for authentication of '%s'", delegate.getName(), currentResult.toString(), user.getLoginName());
|
logger.debugf("Authentication provider '%s' finished with '%s' for authentication of '%s'", delegate.getName(), currentResult.toString(), user.getUsername());
|
||||||
return currentResult;
|
return currentResult;
|
||||||
} catch (AuthenticationProviderException ape) {
|
} catch (AuthenticationProviderException ape) {
|
||||||
logger.warn(ape.getMessage(), ape);
|
logger.warn(ape.getMessage(), ape);
|
||||||
|
@ -105,7 +105,7 @@ public class AuthenticationProviderManager {
|
||||||
if (providerModel.isPasswordUpdateSupported()) {
|
if (providerModel.isPasswordUpdateSupported()) {
|
||||||
AuthenticationProvider delegate = getProvider(providerModel.getProviderName());
|
AuthenticationProvider delegate = getProvider(providerModel.getProviderName());
|
||||||
if (delegate != null) {
|
if (delegate != null) {
|
||||||
AuthUser authUser = delegate.getUser(realm, providerModel.getConfig(), user.getLoginName());
|
AuthUser authUser = delegate.getUser(realm, providerModel.getConfig(), user.getUsername());
|
||||||
if (authUser != null) {
|
if (authUser != null) {
|
||||||
// Linking existing user supported just for "model" provider. In other cases throw exception
|
// Linking existing user supported just for "model" provider. In other cases throw exception
|
||||||
if (providerModel.getProviderName().equals(AuthenticationProviderModel.DEFAULT_PROVIDER.getProviderName())) {
|
if (providerModel.getProviderName().equals(AuthenticationProviderModel.DEFAULT_PROVIDER.getProviderName())) {
|
||||||
|
@ -120,7 +120,7 @@ public class AuthenticationProviderManager {
|
||||||
String userIdInProvider = delegate.registerUser(realm, providerModel.getConfig(), user);
|
String userIdInProvider = delegate.registerUser(realm, providerModel.getConfig(), user);
|
||||||
authLink = new AuthenticationLinkModel(providerModel.getProviderName(), userIdInProvider);
|
authLink = new AuthenticationLinkModel(providerModel.getProviderName(), userIdInProvider);
|
||||||
user.setAuthenticationLink(authLink);
|
user.setAuthenticationLink(authLink);
|
||||||
logger.infof("User '%s' registered in provider '%s' and linked", user.getLoginName(), providerModel.getProviderName());
|
logger.infof("User '%s' registered in provider '%s' and linked", user.getUsername(), providerModel.getProviderName());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ public class AuthenticationProviderManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authLink == null) {
|
if (authLink == null) {
|
||||||
logger.warnf("No providers found where password update is supported for user '%s'", user.getLoginName());
|
logger.warnf("No providers found where password update is supported for user '%s'", user.getUsername());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ public class AuthenticationProviderManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String username = user.getLoginName();
|
String username = user.getUsername();
|
||||||
|
|
||||||
// Update just if password update is supported
|
// Update just if password update is supported
|
||||||
if (providerModel.isPasswordUpdateSupported()) {
|
if (providerModel.isPasswordUpdateSupported()) {
|
||||||
|
@ -152,7 +152,7 @@ public class AuthenticationProviderManager {
|
||||||
|
|
||||||
checkCorrectAuthLink(delegate, providerModel, authLink, username);
|
checkCorrectAuthLink(delegate, providerModel, authLink, username);
|
||||||
|
|
||||||
if (delegate.updateCredential(realm,providerModel.getConfig(), user.getLoginName(), password)) {
|
if (delegate.updateCredential(realm,providerModel.getConfig(), user.getUsername(), password)) {
|
||||||
logger.debugf("Updated password in authentication provider '%s' for user '%s'", providerName, username);
|
logger.debugf("Updated password in authentication provider '%s' for user '%s'", providerName, username);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -32,7 +32,7 @@ public abstract class AbstractModelAuthenticationProvider implements Authenticat
|
||||||
@Override
|
@Override
|
||||||
public String registerUser(RealmModel currentRealm, Map<String, String> config, UserModel user) throws AuthenticationProviderException {
|
public String registerUser(RealmModel currentRealm, Map<String, String> config, UserModel user) throws AuthenticationProviderException {
|
||||||
RealmModel realm = getRealm(currentRealm, config);
|
RealmModel realm = getRealm(currentRealm, config);
|
||||||
UserModel newUser = realm.addUser(user.getLoginName());
|
UserModel newUser = realm.addUser(user.getUsername());
|
||||||
newUser.setFirstName(user.getFirstName());
|
newUser.setFirstName(user.getFirstName());
|
||||||
newUser.setLastName(user.getLastName());
|
newUser.setLastName(user.getLastName());
|
||||||
newUser.setEmail(user.getEmail());
|
newUser.setEmail(user.getEmail());
|
||||||
|
@ -80,7 +80,7 @@ public abstract class AbstractModelAuthenticationProvider implements Authenticat
|
||||||
protected abstract RealmModel getRealm(RealmModel currentRealm, Map<String, String> config) throws AuthenticationProviderException;
|
protected abstract RealmModel getRealm(RealmModel currentRealm, Map<String, String> config) throws AuthenticationProviderException;
|
||||||
|
|
||||||
protected AuthUser createAuthenticatedUserInstance(UserModel user) {
|
protected AuthUser createAuthenticatedUserInstance(UserModel user) {
|
||||||
return new AuthUser(user.getId(), user.getLoginName(), getName())
|
return new AuthUser(user.getId(), user.getUsername(), getName())
|
||||||
.setName(user.getFirstName(), user.getLastName())
|
.setName(user.getFirstName(), user.getLastName())
|
||||||
.setEmail(user.getEmail());
|
.setEmail(user.getEmail());
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ public class PicketlinkAuthenticationProvider implements AuthenticationProvider
|
||||||
IdentityManager identityManager = getIdentityManager(realm);
|
IdentityManager identityManager = getIdentityManager(realm);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
User picketlinkUser = new User(user.getLoginName());
|
User picketlinkUser = new User(user.getUsername());
|
||||||
picketlinkUser.setFirstName(user.getFirstName());
|
picketlinkUser.setFirstName(user.getFirstName());
|
||||||
picketlinkUser.setLastName(user.getLastName());
|
picketlinkUser.setLastName(user.getLastName());
|
||||||
picketlinkUser.setEmail(user.getEmail());
|
picketlinkUser.setEmail(user.getEmail());
|
||||||
|
|
|
@ -48,7 +48,7 @@ public class PropertiesAuthenticationProvider implements AuthenticationProvider
|
||||||
@Override
|
@Override
|
||||||
public String registerUser(RealmModel realm, Map<String, String> configuration, UserModel user) throws AuthenticationProviderException {
|
public String registerUser(RealmModel realm, Map<String, String> configuration, UserModel user) throws AuthenticationProviderException {
|
||||||
// Registration ignored
|
// Registration ignored
|
||||||
return user.getLoginName();
|
return user.getUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -211,7 +211,7 @@ public class ModelExporter {
|
||||||
|
|
||||||
this.propertiesManager.setBasicPropertiesFromModel(userModel, userEntity);
|
this.propertiesManager.setBasicPropertiesFromModel(userModel, userEntity);
|
||||||
|
|
||||||
userEntity.setLoginName(userModel.getLoginName());
|
userEntity.setUsername(userModel.getUsername());
|
||||||
userEntity.setRealmId(realm.getId());
|
userEntity.setRealmId(realm.getId());
|
||||||
|
|
||||||
// authentication links
|
// authentication links
|
||||||
|
|
|
@ -243,7 +243,7 @@ public class ModelImporter {
|
||||||
List<UserEntity> users = this.importReader.readEntities(fileName, UserEntity.class);
|
List<UserEntity> users = this.importReader.readEntities(fileName, UserEntity.class);
|
||||||
for (UserEntity userEntity : users) {
|
for (UserEntity userEntity : users) {
|
||||||
RealmModel realm = session.getRealm(userEntity.getRealmId());
|
RealmModel realm = session.getRealm(userEntity.getRealmId());
|
||||||
UserModel user = realm.addUser(userEntity.getId(), userEntity.getLoginName());
|
UserModel user = realm.addUser(userEntity.getId(), userEntity.getUsername());
|
||||||
|
|
||||||
// We need to remove defaultRoles here as realm.addUser is automatically adding them. We may add them later during roles mapping processing
|
// We need to remove defaultRoles here as realm.addUser is automatically adding them. We may add them later during roles mapping processing
|
||||||
for (RoleModel role : user.getRoleMappings()) {
|
for (RoleModel role : user.getRoleMappings()) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class AccountBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
return user.getLoginName();
|
return user.getUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEmail() {
|
public String getEmail() {
|
||||||
|
|
|
@ -16,9 +16,9 @@ public interface UserModel {
|
||||||
|
|
||||||
String getId();
|
String getId();
|
||||||
|
|
||||||
String getLoginName();
|
String getUsername();
|
||||||
|
|
||||||
void setLoginName(String loginName);
|
void setUsername(String username);
|
||||||
|
|
||||||
boolean isEnabled();
|
boolean isEnabled();
|
||||||
|
|
||||||
|
@ -58,9 +58,6 @@ public interface UserModel {
|
||||||
|
|
||||||
void setTotp(boolean totp);
|
void setTotp(boolean totp);
|
||||||
|
|
||||||
int getNotBefore();
|
|
||||||
void setNotBefore(int notBefore);
|
|
||||||
|
|
||||||
void updateCredential(UserCredentialModel cred);
|
void updateCredential(UserCredentialModel cred);
|
||||||
|
|
||||||
List<UserCredentialValueModel> getCredentialsDirectly();
|
List<UserCredentialValueModel> getCredentialsDirectly();
|
||||||
|
|
|
@ -11,14 +11,13 @@ import org.keycloak.models.UserModel;
|
||||||
*/
|
*/
|
||||||
public class UserEntity extends AbstractIdentifiableEntity {
|
public class UserEntity extends AbstractIdentifiableEntity {
|
||||||
|
|
||||||
private String loginName;
|
private String username;
|
||||||
private String firstName;
|
private String firstName;
|
||||||
private String lastName;
|
private String lastName;
|
||||||
private String email;
|
private String email;
|
||||||
private boolean emailVerified;
|
private boolean emailVerified;
|
||||||
private boolean totp;
|
private boolean totp;
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
private int notBefore;
|
|
||||||
|
|
||||||
private String realmId;
|
private String realmId;
|
||||||
|
|
||||||
|
@ -30,12 +29,12 @@ public class UserEntity extends AbstractIdentifiableEntity {
|
||||||
private List<SocialLinkEntity> socialLinks;
|
private List<SocialLinkEntity> socialLinks;
|
||||||
private AuthenticationLinkEntity authenticationLink;
|
private AuthenticationLinkEntity authenticationLink;
|
||||||
|
|
||||||
public String getLoginName() {
|
public String getUsername() {
|
||||||
return loginName;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLoginName(String loginName) {
|
public void setUsername(String username) {
|
||||||
this.loginName = loginName;
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFirstName() {
|
public String getFirstName() {
|
||||||
|
@ -86,14 +85,6 @@ public class UserEntity extends AbstractIdentifiableEntity {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNotBefore() {
|
|
||||||
return notBefore;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNotBefore(int notBefore) {
|
|
||||||
this.notBefore = notBefore;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRealmId() {
|
public String getRealmId() {
|
||||||
return realmId;
|
return realmId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,15 +47,15 @@ public class UserAdapter implements UserModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getLoginName() {
|
public String getUsername() {
|
||||||
if (updated != null) return updated.getLoginName();
|
if (updated != null) return updated.getUsername();
|
||||||
return cached.getLoginName();
|
return cached.getUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLoginName(String loginName) {
|
public void setUsername(String username) {
|
||||||
getDelegateForUpdate();
|
getDelegateForUpdate();
|
||||||
updated.setLoginName(loginName);
|
updated.setUsername(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -172,18 +172,6 @@ public class UserAdapter implements UserModel {
|
||||||
updated.setTotp(totp);
|
updated.setTotp(totp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getNotBefore() {
|
|
||||||
if (updated != null) return updated.getNotBefore();
|
|
||||||
return cached.getNotBefore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setNotBefore(int notBefore) {
|
|
||||||
getDelegateForUpdate();
|
|
||||||
updated.setNotBefore(notBefore);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateCredential(UserCredentialModel cred) {
|
public void updateCredential(UserCredentialModel cred) {
|
||||||
getDelegateForUpdate();
|
getDelegateForUpdate();
|
||||||
|
|
|
@ -19,14 +19,13 @@ import java.util.Set;
|
||||||
*/
|
*/
|
||||||
public class CachedUser {
|
public class CachedUser {
|
||||||
private String id;
|
private String id;
|
||||||
private String loginName;
|
private String username;
|
||||||
private String usernameKey;
|
private String usernameKey;
|
||||||
private String firstName;
|
private String firstName;
|
||||||
private String lastName;
|
private String lastName;
|
||||||
private String email;
|
private String email;
|
||||||
private String emailKey;
|
private String emailKey;
|
||||||
private boolean emailVerified;
|
private boolean emailVerified;
|
||||||
private int notBefore;
|
|
||||||
private List<UserCredentialValueModel> credentials = new LinkedList<UserCredentialValueModel>();
|
private List<UserCredentialValueModel> credentials = new LinkedList<UserCredentialValueModel>();
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
private boolean totp;
|
private boolean totp;
|
||||||
|
@ -38,8 +37,8 @@ public class CachedUser {
|
||||||
|
|
||||||
public CachedUser(RealmModel realm, UserModel user) {
|
public CachedUser(RealmModel realm, UserModel user) {
|
||||||
this.id = user.getId();
|
this.id = user.getId();
|
||||||
this.loginName = user.getLoginName();
|
this.username = user.getUsername();
|
||||||
this.usernameKey = realm.getId() + "." + this.loginName;
|
this.usernameKey = realm.getId() + "." + this.username;
|
||||||
this.firstName = user.getFirstName();
|
this.firstName = user.getFirstName();
|
||||||
this.lastName = user.getLastName();
|
this.lastName = user.getLastName();
|
||||||
this.attributes.putAll(user.getAttributes());
|
this.attributes.putAll(user.getAttributes());
|
||||||
|
@ -48,7 +47,6 @@ public class CachedUser {
|
||||||
this.emailKey = realm.getId() + "." + this.email;
|
this.emailKey = realm.getId() + "." + this.email;
|
||||||
}
|
}
|
||||||
this.emailVerified = user.isEmailVerified();
|
this.emailVerified = user.isEmailVerified();
|
||||||
this.notBefore = user.getNotBefore();
|
|
||||||
this.credentials.addAll(user.getCredentialsDirectly());
|
this.credentials.addAll(user.getCredentialsDirectly());
|
||||||
this.enabled = user.isEnabled();
|
this.enabled = user.isEnabled();
|
||||||
this.totp = user.isTotp();
|
this.totp = user.isTotp();
|
||||||
|
@ -63,8 +61,8 @@ public class CachedUser {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLoginName() {
|
public String getUsername() {
|
||||||
return loginName;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUsernameKey() {
|
public String getUsernameKey() {
|
||||||
|
@ -91,10 +89,6 @@ public class CachedUser {
|
||||||
return emailVerified;
|
return emailVerified;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNotBefore() {
|
|
||||||
return notBefore;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<UserCredentialValueModel> getCredentials() {
|
public List<UserCredentialValueModel> getCredentials() {
|
||||||
return credentials;
|
return credentials;
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,8 +93,8 @@ public class JpaModelProvider implements ModelProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserModel getUserByUsername(String username, RealmModel realmModel) {
|
public UserModel getUserByUsername(String username, RealmModel realmModel) {
|
||||||
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByLoginName", UserEntity.class);
|
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByUsername", UserEntity.class);
|
||||||
query.setParameter("loginName", username);
|
query.setParameter("username", username);
|
||||||
RealmEntity realm = em.getReference(RealmEntity.class, realmModel.getId());
|
RealmEntity realm = em.getReference(RealmEntity.class, realmModel.getId());
|
||||||
query.setParameter("realm", realm);
|
query.setParameter("realm", realm);
|
||||||
List<UserEntity> results = query.getResultList();
|
List<UserEntity> results = query.getResultList();
|
||||||
|
@ -130,7 +130,7 @@ public class JpaModelProvider implements ModelProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (UserEntity u : em.createQuery("from UserEntity u where u.realm = :realm", UserEntity.class).setParameter("realm", realm).getResultList()) {
|
for (UserEntity u : em.createQuery("from UserEntity u where u.realm = :realm", UserEntity.class).setParameter("realm", realm).getResultList()) {
|
||||||
adapter.removeUser(u.getLoginName());
|
adapter.removeUser(u.getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
em.remove(realm);
|
em.remove(realm);
|
||||||
|
@ -185,7 +185,7 @@ public class JpaModelProvider implements ModelProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
||||||
TypedQuery<UserEntity> query = em.createQuery("select u from UserEntity u where u.realm = :realm and ( lower(u.loginName) like :search or lower(concat(u.firstName, ' ', u.lastName)) like :search or u.email like :search )", UserEntity.class);
|
TypedQuery<UserEntity> query = em.createQuery("select u from UserEntity u where u.realm = :realm and ( lower(u.username) like :search or lower(concat(u.firstName, ' ', u.lastName)) like :search or u.email like :search )", UserEntity.class);
|
||||||
RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
|
RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
|
||||||
query.setParameter("realm", realmEntity);
|
query.setParameter("realm", realmEntity);
|
||||||
query.setParameter("search", "%" + search.toLowerCase() + "%");
|
query.setParameter("search", "%" + search.toLowerCase() + "%");
|
||||||
|
@ -202,7 +202,7 @@ public class JpaModelProvider implements ModelProvider {
|
||||||
for (Map.Entry<String, String> entry : attributes.entrySet()) {
|
for (Map.Entry<String, String> entry : attributes.entrySet()) {
|
||||||
String attribute = null;
|
String attribute = null;
|
||||||
if (entry.getKey().equals(UserModel.LOGIN_NAME)) {
|
if (entry.getKey().equals(UserModel.LOGIN_NAME)) {
|
||||||
attribute = "lower(loginName)";
|
attribute = "lower(username)";
|
||||||
} else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
|
} else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
|
||||||
attribute = "lower(firstName)";
|
attribute = "lower(firstName)";
|
||||||
} else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) {
|
} else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) {
|
||||||
|
|
|
@ -463,7 +463,7 @@ public class RealmAdapter implements RealmModel {
|
||||||
public UserModel addUser(String id, String username) {
|
public UserModel addUser(String id, String username) {
|
||||||
UserEntity entity = new UserEntity();
|
UserEntity entity = new UserEntity();
|
||||||
entity.setId(id);
|
entity.setId(id);
|
||||||
entity.setLoginName(username);
|
entity.setUsername(username);
|
||||||
entity.setRealm(realm);
|
entity.setRealm(realm);
|
||||||
em.persist(entity);
|
em.persist(entity);
|
||||||
em.flush();
|
em.flush();
|
||||||
|
@ -484,8 +484,8 @@ public class RealmAdapter implements RealmModel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeUser(String name) {
|
public boolean removeUser(String name) {
|
||||||
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByLoginName", UserEntity.class);
|
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByUsername", UserEntity.class);
|
||||||
query.setParameter("loginName", name);
|
query.setParameter("username", name);
|
||||||
query.setParameter("realm", realm);
|
query.setParameter("realm", realm);
|
||||||
List<UserEntity> results = query.getResultList();
|
List<UserEntity> results = query.getResultList();
|
||||||
if (results.size() == 0) return false;
|
if (results.size() == 0) return false;
|
||||||
|
|
|
@ -54,13 +54,13 @@ public class UserAdapter implements UserModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getLoginName() {
|
public String getUsername() {
|
||||||
return user.getLoginName();
|
return user.getUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLoginName(String loginName) {
|
public void setUsername(String username) {
|
||||||
user.setLoginName(loginName);
|
user.setUsername(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -174,16 +174,6 @@ public class UserAdapter implements UserModel {
|
||||||
user.setTotp(totp);
|
user.setTotp(totp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getNotBefore() {
|
|
||||||
return user.getNotBefore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setNotBefore(int notBefore) {
|
|
||||||
user.setNotBefore(notBefore);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateCredential(UserCredentialModel cred) {
|
public void updateCredential(UserCredentialModel cred) {
|
||||||
CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
|
CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
|
||||||
|
|
|
@ -35,28 +35,27 @@ import java.util.Set;
|
||||||
*/
|
*/
|
||||||
@NamedQueries({
|
@NamedQueries({
|
||||||
@NamedQuery(name="getRealmUserById", query="select u from UserEntity u where u.id = :id and u.realm = :realm"),
|
@NamedQuery(name="getRealmUserById", query="select u from UserEntity u where u.id = :id and u.realm = :realm"),
|
||||||
@NamedQuery(name="getRealmUserByLoginName", query="select u from UserEntity u where u.loginName = :loginName and u.realm = :realm"),
|
@NamedQuery(name="getRealmUserByUsername", query="select u from UserEntity u where u.username = :username and u.realm = :realm"),
|
||||||
@NamedQuery(name="getRealmUserByEmail", query="select u from UserEntity u where u.email = :email and u.realm = :realm"),
|
@NamedQuery(name="getRealmUserByEmail", query="select u from UserEntity u where u.email = :email and u.realm = :realm"),
|
||||||
@NamedQuery(name="getRealmUserByLastName", query="select u from UserEntity u where u.lastName = :lastName and u.realm = :realm"),
|
@NamedQuery(name="getRealmUserByLastName", query="select u from UserEntity u where u.lastName = :lastName and u.realm = :realm"),
|
||||||
@NamedQuery(name="getRealmUserByFirstLastName", query="select u from UserEntity u where u.firstName = :first and u.lastName = :last and u.realm = :realm")
|
@NamedQuery(name="getRealmUserByFirstLastName", query="select u from UserEntity u where u.firstName = :first and u.lastName = :last and u.realm = :realm")
|
||||||
})
|
})
|
||||||
@Entity
|
@Entity
|
||||||
@Table(uniqueConstraints = {
|
@Table(uniqueConstraints = {
|
||||||
@UniqueConstraint(columnNames = { "realm", "loginName" }),
|
@UniqueConstraint(columnNames = { "realm", "username" }),
|
||||||
@UniqueConstraint(columnNames = { "realm", "emailConstraint" })
|
@UniqueConstraint(columnNames = { "realm", "emailConstraint" })
|
||||||
})
|
})
|
||||||
public class UserEntity {
|
public class UserEntity {
|
||||||
@Id
|
@Id
|
||||||
protected String id;
|
protected String id;
|
||||||
|
|
||||||
protected String loginName;
|
protected String username;
|
||||||
protected String firstName;
|
protected String firstName;
|
||||||
protected String lastName;
|
protected String lastName;
|
||||||
protected String email;
|
protected String email;
|
||||||
protected boolean enabled;
|
protected boolean enabled;
|
||||||
protected boolean totp;
|
protected boolean totp;
|
||||||
protected boolean emailVerified;
|
protected boolean emailVerified;
|
||||||
protected int notBefore;
|
|
||||||
|
|
||||||
// Hack just to workaround the fact that on MS-SQL you can't have unique constraint with multiple NULL values TODO: Find better solution (like unique index with 'where' but that's proprietary)
|
// Hack just to workaround the fact that on MS-SQL you can't have unique constraint with multiple NULL values TODO: Find better solution (like unique index with 'where' but that's proprietary)
|
||||||
protected String emailConstraint = KeycloakModelUtils.generateId();
|
protected String emailConstraint = KeycloakModelUtils.generateId();
|
||||||
|
@ -89,12 +88,12 @@ public class UserEntity {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLoginName() {
|
public String getUsername() {
|
||||||
return loginName;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLoginName(String loginName) {
|
public void setUsername(String username) {
|
||||||
this.loginName = loginName;
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFirstName() {
|
public String getFirstName() {
|
||||||
|
@ -194,11 +193,4 @@ public class UserEntity {
|
||||||
this.authenticationLink = authenticationLink;
|
this.authenticationLink = authenticationLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNotBefore() {
|
|
||||||
return notBefore;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNotBefore(int notBefore) {
|
|
||||||
this.notBefore = notBefore;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ public class MongoModelProvider implements ModelProvider {
|
||||||
@Override
|
@Override
|
||||||
public UserModel getUserByUsername(String username, RealmModel realm) {
|
public UserModel getUserByUsername(String username, RealmModel realm) {
|
||||||
DBObject query = new QueryBuilder()
|
DBObject query = new QueryBuilder()
|
||||||
.and("loginName").is(username)
|
.and("username").is(username)
|
||||||
.and("realmId").is(realm.getId())
|
.and("realmId").is(realm.getId())
|
||||||
.get();
|
.get();
|
||||||
MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
|
MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
|
||||||
|
@ -226,7 +226,7 @@ public class MongoModelProvider implements ModelProvider {
|
||||||
QueryBuilder builder = new QueryBuilder().and(
|
QueryBuilder builder = new QueryBuilder().and(
|
||||||
new QueryBuilder().and("realmId").is(realm.getId()).get(),
|
new QueryBuilder().and("realmId").is(realm.getId()).get(),
|
||||||
new QueryBuilder().or(
|
new QueryBuilder().or(
|
||||||
new QueryBuilder().put("loginName").regex(caseInsensitivePattern).get(),
|
new QueryBuilder().put("username").regex(caseInsensitivePattern).get(),
|
||||||
new QueryBuilder().put("email").regex(caseInsensitivePattern).get(),
|
new QueryBuilder().put("email").regex(caseInsensitivePattern).get(),
|
||||||
nameBuilder.get()
|
nameBuilder.get()
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ public class MongoModelProvider implements ModelProvider {
|
||||||
|
|
||||||
for (Map.Entry<String, String> entry : attributes.entrySet()) {
|
for (Map.Entry<String, String> entry : attributes.entrySet()) {
|
||||||
if (entry.getKey().equals(UserModel.LOGIN_NAME)) {
|
if (entry.getKey().equals(UserModel.LOGIN_NAME)) {
|
||||||
queryBuilder.and("loginName").regex(Pattern.compile("(?i:" + entry.getValue() + "$)"));
|
queryBuilder.and("username").regex(Pattern.compile("(?i:" + entry.getValue() + "$)"));
|
||||||
} else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
|
} else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
|
||||||
queryBuilder.and(UserModel.FIRST_NAME).regex(Pattern.compile("(?i:" + entry.getValue() + "$)"));
|
queryBuilder.and(UserModel.FIRST_NAME).regex(Pattern.compile("(?i:" + entry.getValue() + "$)"));
|
||||||
|
|
||||||
|
|
|
@ -504,7 +504,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
||||||
protected UserAdapter addUserEntity(String id, String username) {
|
protected UserAdapter addUserEntity(String id, String username) {
|
||||||
MongoUserEntity userEntity = new MongoUserEntity();
|
MongoUserEntity userEntity = new MongoUserEntity();
|
||||||
userEntity.setId(id);
|
userEntity.setId(id);
|
||||||
userEntity.setLoginName(username);
|
userEntity.setUsername(username);
|
||||||
// Compatibility with JPA model, which has user disabled by default
|
// Compatibility with JPA model, which has user disabled by default
|
||||||
// userEntity.setEnabled(true);
|
// userEntity.setEnabled(true);
|
||||||
userEntity.setRealmId(getId());
|
userEntity.setRealmId(getId());
|
||||||
|
@ -516,7 +516,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
||||||
@Override
|
@Override
|
||||||
public boolean removeUser(String name) {
|
public boolean removeUser(String name) {
|
||||||
DBObject query = new QueryBuilder()
|
DBObject query = new QueryBuilder()
|
||||||
.and("loginName").is(name)
|
.and("username").is(name)
|
||||||
.and("realmId").is(getId())
|
.and("realmId").is(getId())
|
||||||
.get();
|
.get();
|
||||||
return getMongoStore().removeEntities(MongoUserEntity.class, query, invocationContext);
|
return getMongoStore().removeEntities(MongoUserEntity.class, query, invocationContext);
|
||||||
|
|
|
@ -50,13 +50,13 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getLoginName() {
|
public String getUsername() {
|
||||||
return user.getLoginName();
|
return user.getUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLoginName(String loginName) {
|
public void setUsername(String username) {
|
||||||
user.setLoginName(loginName);
|
user.setUsername(username);
|
||||||
updateUser();
|
updateUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,16 +71,6 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
|
||||||
updateUser();
|
updateUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getNotBefore() {
|
|
||||||
return user.getNotBefore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setNotBefore(int notBefore) {
|
|
||||||
user.setNotBefore(notBefore);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFirstName() {
|
public String getFirstName() {
|
||||||
return user.getFirstName();
|
return user.getFirstName();
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class MongoRoleEntity extends RoleEntity implements MongoIdentifiableEnti
|
||||||
|
|
||||||
List<MongoUserEntity> users = mongoStore.loadEntities(MongoUserEntity.class, query, invContext);
|
List<MongoUserEntity> users = mongoStore.loadEntities(MongoUserEntity.class, query, invContext);
|
||||||
for (MongoUserEntity user : users) {
|
for (MongoUserEntity user : users) {
|
||||||
logger.info("Removing role " + getName() + " from user " + user.getLoginName());
|
logger.info("Removing role " + getName() + " from user " + user.getUsername());
|
||||||
mongoStore.pullItemFromList(user, "roleIds", getId(), invContext);
|
mongoStore.pullItemFromList(user, "roleIds", getId(), invContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public class MongoRoleEntity extends RoleEntity implements MongoIdentifiableEnti
|
||||||
|
|
||||||
users = mongoStore.loadEntities(MongoUserEntity.class, query, invContext);
|
users = mongoStore.loadEntities(MongoUserEntity.class, query, invContext);
|
||||||
for (MongoUserEntity user : users) {
|
for (MongoUserEntity user : users) {
|
||||||
logger.info("Removing scope " + getName() + " from user " + user.getLoginName());
|
logger.info("Removing scope " + getName() + " from user " + user.getUsername());
|
||||||
mongoStore.pullItemFromList(user, "scopeIds", getId(), invContext);
|
mongoStore.pullItemFromList(user, "scopeIds", getId(), invContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
|
||||||
*/
|
*/
|
||||||
@MongoCollection(collectionName = "users")
|
@MongoCollection(collectionName = "users")
|
||||||
@MongoIndexes({
|
@MongoIndexes({
|
||||||
@MongoIndex(fields = { "realmId", "loginName" }, unique = true),
|
@MongoIndex(fields = { "realmId", "username" }, unique = true),
|
||||||
@MongoIndex(fields = { "emailIndex" }, unique = true, sparse = true),
|
@MongoIndex(fields = { "emailIndex" }, unique = true, sparse = true),
|
||||||
})
|
})
|
||||||
public class MongoUserEntity extends UserEntity implements MongoIdentifiableEntity {
|
public class MongoUserEntity extends UserEntity implements MongoIdentifiableEntity {
|
||||||
|
|
|
@ -169,7 +169,7 @@ public class AdapterTest extends AbstractModelTest {
|
||||||
RoleModel appRole = app.addRole("test");
|
RoleModel appRole = app.addRole("test");
|
||||||
user.grantRole(appRole);
|
user.grantRole(appRole);
|
||||||
|
|
||||||
SocialLinkModel socialLink = new SocialLinkModel("google", "google1", user.getLoginName());
|
SocialLinkModel socialLink = new SocialLinkModel("google", "google1", user.getUsername());
|
||||||
realmModel.addSocialLink(user, socialLink);
|
realmModel.addSocialLink(user, socialLink);
|
||||||
|
|
||||||
UserCredentialModel cred = new UserCredentialModel();
|
UserCredentialModel cred = new UserCredentialModel();
|
||||||
|
@ -321,7 +321,7 @@ public class AdapterTest extends AbstractModelTest {
|
||||||
{
|
{
|
||||||
ArrayList<String> users = new ArrayList<String>();
|
ArrayList<String> users = new ArrayList<String>();
|
||||||
for (UserModel u : adapter.searchUsers("ole alver", realmModel)) {
|
for (UserModel u : adapter.searchUsers("ole alver", realmModel)) {
|
||||||
users.add(u.getLoginName());
|
users.add(u.getUsername());
|
||||||
}
|
}
|
||||||
String[] usernames = users.toArray(new String[users.size()]);
|
String[] usernames = users.toArray(new String[users.size()]);
|
||||||
Arrays.sort(usernames);
|
Arrays.sort(usernames);
|
||||||
|
@ -634,7 +634,7 @@ public class AdapterTest extends AbstractModelTest {
|
||||||
realmManager.getRealmByName("JUGGLER1").addUser("user2");
|
realmManager.getRealmByName("JUGGLER1").addUser("user2");
|
||||||
commit();
|
commit();
|
||||||
try {
|
try {
|
||||||
realmManager.getRealmByName("JUGGLER1").getUser("user2").setLoginName("user1");
|
realmManager.getRealmByName("JUGGLER1").getUser("user2").setUsername("user1");
|
||||||
commit();
|
commit();
|
||||||
Assert.fail("Expected exception");
|
Assert.fail("Expected exception");
|
||||||
} catch (ModelDuplicateException e) {
|
} catch (ModelDuplicateException e) {
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class AuthProvidersExternalModelTest extends AbstractModelTest {
|
||||||
Assert.assertEquals(AuthenticationManager.AuthenticationStatus.SUCCESS, am.authenticateForm(null, realm2, formData));
|
Assert.assertEquals(AuthenticationManager.AuthenticationStatus.SUCCESS, am.authenticateForm(null, realm2, formData));
|
||||||
UserModel john2 = realm2.getUser("john");
|
UserModel john2 = realm2.getUser("john");
|
||||||
Assert.assertNotNull(john2);
|
Assert.assertNotNull(john2);
|
||||||
Assert.assertEquals("john", john2.getLoginName());
|
Assert.assertEquals("john", john2.getUsername());
|
||||||
Assert.assertEquals("John", john2.getFirstName());
|
Assert.assertEquals("John", john2.getFirstName());
|
||||||
Assert.assertEquals("Doe", john2.getLastName());
|
Assert.assertEquals("Doe", john2.getLastName());
|
||||||
Assert.assertEquals("john@email.org", john2.getEmail());
|
Assert.assertEquals("john@email.org", john2.getEmail());
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class AuthProvidersLDAPTest extends AbstractModelTest {
|
||||||
Assert.assertEquals(AuthenticationManager.AuthenticationStatus.SUCCESS, am.authenticateForm(null, realm, formData));
|
Assert.assertEquals(AuthenticationManager.AuthenticationStatus.SUCCESS, am.authenticateForm(null, realm, formData));
|
||||||
UserModel john = realm.getUser("johnkeycloak");
|
UserModel john = realm.getUser("johnkeycloak");
|
||||||
Assert.assertNotNull(john);
|
Assert.assertNotNull(john);
|
||||||
Assert.assertEquals("johnkeycloak", john.getLoginName());
|
Assert.assertEquals("johnkeycloak", john.getUsername());
|
||||||
Assert.assertEquals("John", john.getFirstName());
|
Assert.assertEquals("John", john.getFirstName());
|
||||||
Assert.assertEquals("Doe", john.getLastName());
|
Assert.assertEquals("Doe", john.getLastName());
|
||||||
Assert.assertEquals("john@email.org", john.getEmail());
|
Assert.assertEquals("john@email.org", john.getEmail());
|
||||||
|
|
|
@ -173,7 +173,7 @@ public class ImportTest extends AbstractModelTest {
|
||||||
Assert.assertTrue(facebookFound && twitterFound && googleFound);
|
Assert.assertTrue(facebookFound && twitterFound && googleFound);
|
||||||
|
|
||||||
UserModel foundSocialUser = realm.getUserBySocialLink(new SocialLinkModel("facebook", "facebook1", "fbuser1"));
|
UserModel foundSocialUser = realm.getUserBySocialLink(new SocialLinkModel("facebook", "facebook1", "fbuser1"));
|
||||||
Assert.assertEquals(foundSocialUser.getLoginName(), socialUser.getLoginName());
|
Assert.assertEquals(foundSocialUser.getUsername(), socialUser.getUsername());
|
||||||
Assert.assertNull(realm.getUserBySocialLink(new SocialLinkModel("facebook", "not-existing", "not-existing")));
|
Assert.assertNull(realm.getUserBySocialLink(new SocialLinkModel("facebook", "not-existing", "not-existing")));
|
||||||
|
|
||||||
SocialLinkModel foundSocialLink = realm.getSocialLink(socialUser, "facebook");
|
SocialLinkModel foundSocialLink = realm.getSocialLink(socialUser, "facebook");
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class MultipleRealmsTest extends AbstractModelTest {
|
||||||
public void testUsers() {
|
public void testUsers() {
|
||||||
UserModel r1user1 = realm1.getUser("user1");
|
UserModel r1user1 = realm1.getUser("user1");
|
||||||
UserModel r2user1 = realm2.getUser("user1");
|
UserModel r2user1 = realm2.getUser("user1");
|
||||||
Assert.assertEquals(r1user1.getLoginName(), r2user1.getLoginName());
|
Assert.assertEquals(r1user1.getUsername(), r2user1.getUsername());
|
||||||
Assert.assertNotEquals(r1user1.getId(), r2user1.getId());
|
Assert.assertNotEquals(r1user1.getId(), r2user1.getId());
|
||||||
|
|
||||||
// Test password
|
// Test password
|
||||||
|
|
|
@ -111,7 +111,7 @@ public class UserModelTest extends AbstractModelTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertEquals(UserModel expected, UserModel actual) {
|
public static void assertEquals(UserModel expected, UserModel actual) {
|
||||||
Assert.assertEquals(expected.getLoginName(), actual.getLoginName());
|
Assert.assertEquals(expected.getUsername(), actual.getUsername());
|
||||||
Assert.assertEquals(expected.getFirstName(), actual.getFirstName());
|
Assert.assertEquals(expected.getFirstName(), actual.getFirstName());
|
||||||
Assert.assertEquals(expected.getLastName(), actual.getLastName());
|
Assert.assertEquals(expected.getLastName(), actual.getLastName());
|
||||||
Assert.assertArrayEquals(expected.getRequiredActions().toArray(), actual.getRequiredActions().toArray());
|
Assert.assertArrayEquals(expected.getRequiredActions().toArray(), actual.getRequiredActions().toArray());
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class UpsSecurityApplication extends KeycloakApplication {
|
||||||
RealmManager manager = new RealmManager(session);
|
RealmManager manager = new RealmManager(session);
|
||||||
RealmModel master = manager.getKeycloakAdminstrationRealm();
|
RealmModel master = manager.getKeycloakAdminstrationRealm();
|
||||||
UserModel admin = master.getUser("admin");
|
UserModel admin = master.getUser("admin");
|
||||||
if (admin != null) master.removeUser(admin.getLoginName());
|
if (admin != null) master.removeUser(admin.getUsername());
|
||||||
session.getTransaction().commit();
|
session.getTransaction().commit();
|
||||||
} finally {
|
} finally {
|
||||||
session.close();
|
session.close();
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class AuthenticationManager {
|
||||||
if (session == null) return;
|
if (session == null) return;
|
||||||
UserModel user = session.getUser();
|
UserModel user = session.getUser();
|
||||||
|
|
||||||
logger.infov("Logging out: {0} ({1})", user.getLoginName(), session.getId());
|
logger.infov("Logging out: {0} ({1})", user.getUsername(), session.getId());
|
||||||
|
|
||||||
realm.removeUserSession(session);
|
realm.removeUserSession(session);
|
||||||
expireIdentityCookie(realm, uriInfo);
|
expireIdentityCookie(realm, uriInfo);
|
||||||
|
@ -205,11 +205,6 @@ public class AuthenticationManager {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.getIssuedAt() < user.getNotBefore()) {
|
|
||||||
logger.info("Stale cookie");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
UserSessionModel session = realm.getUserSession(token.getSessionState());
|
UserSessionModel session = realm.getUserSession(token.getSessionState());
|
||||||
if (!isSessionValid(realm, session)) {
|
if (!isSessionValid(realm, session)) {
|
||||||
if (session != null) logout(realm, session, uriInfo);
|
if (session != null) logout(realm, session, uriInfo);
|
||||||
|
@ -343,7 +338,7 @@ public class AuthenticationManager {
|
||||||
|
|
||||||
private boolean checkEnabled(UserModel user) {
|
private boolean checkEnabled(UserModel user) {
|
||||||
if (!user.isEnabled()) {
|
if (!user.isEnabled()) {
|
||||||
logger.warn("AccountProvider is disabled, contact admin. " + user.getLoginName());
|
logger.warn("AccountProvider is disabled, contact admin. " + user.getUsername());
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -38,7 +38,7 @@ public class ModelToRepresentation {
|
||||||
public static UserRepresentation toRepresentation(UserModel user) {
|
public static UserRepresentation toRepresentation(UserModel user) {
|
||||||
UserRepresentation rep = new UserRepresentation();
|
UserRepresentation rep = new UserRepresentation();
|
||||||
rep.setId(user.getId());
|
rep.setId(user.getId());
|
||||||
rep.setUsername(user.getLoginName());
|
rep.setUsername(user.getUsername());
|
||||||
rep.setLastName(user.getLastName());
|
rep.setLastName(user.getLastName());
|
||||||
rep.setFirstName(user.getFirstName());
|
rep.setFirstName(user.getFirstName());
|
||||||
rep.setEmail(user.getEmail());
|
rep.setEmail(user.getEmail());
|
||||||
|
@ -190,7 +190,7 @@ public class ModelToRepresentation {
|
||||||
rep.setId(session.getId());
|
rep.setId(session.getId());
|
||||||
rep.setStart(((long)session.getStarted()) * 1000L);
|
rep.setStart(((long)session.getStarted()) * 1000L);
|
||||||
rep.setLastAccess(((long)session.getLastSessionRefresh())* 1000L);
|
rep.setLastAccess(((long)session.getLastSessionRefresh())* 1000L);
|
||||||
rep.setUser(session.getUser().getLoginName());
|
rep.setUser(session.getUser().getUsername());
|
||||||
rep.setIpAddress(session.getIpAddress());
|
rep.setIpAddress(session.getIpAddress());
|
||||||
for (ClientModel client : session.getClientAssociations()) {
|
for (ClientModel client : session.getClientAssociations()) {
|
||||||
if (client instanceof ApplicationModel) {
|
if (client instanceof ApplicationModel) {
|
||||||
|
|
|
@ -370,7 +370,7 @@ public class RealmManager {
|
||||||
if (rep.getUsers() != null) {
|
if (rep.getUsers() != null) {
|
||||||
for (UserRepresentation userRep : rep.getUsers()) {
|
for (UserRepresentation userRep : rep.getUsers()) {
|
||||||
UserModel user = createUser(newRealm, userRep);
|
UserModel user = createUser(newRealm, userRep);
|
||||||
userMap.put(user.getLoginName(), user);
|
userMap.put(user.getUsername(), user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ public class ResourceAdminManager {
|
||||||
for (Map.Entry<String, UserStats> entry : stats.getUsers().entrySet()) {
|
for (Map.Entry<String, UserStats> entry : stats.getUsers().entrySet()) {
|
||||||
UserModel user = realm.getUserById(entry.getKey());
|
UserModel user = realm.getUserById(entry.getKey());
|
||||||
if (user == null) continue;
|
if (user == null) continue;
|
||||||
newUsers.put(user.getLoginName(), entry.getValue());
|
newUsers.put(user.getUsername(), entry.getValue());
|
||||||
|
|
||||||
}
|
}
|
||||||
stats.setUsers(newUsers);
|
stats.setUsers(newUsers);
|
||||||
|
|
|
@ -155,7 +155,7 @@ public class TokenManager {
|
||||||
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients");
|
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refreshToken.getIssuedAt() < client.getNotBefore() || refreshToken.getIssuedAt() < user.getNotBefore()) {
|
if (refreshToken.getIssuedAt() < client.getNotBefore()) {
|
||||||
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
|
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ public class TokenManager {
|
||||||
|
|
||||||
public void initClaims(IDToken token, ClientModel model, UserModel user) {
|
public void initClaims(IDToken token, ClientModel model, UserModel user) {
|
||||||
if (ClaimMask.hasUsername(model.getAllowedClaimsMask())) {
|
if (ClaimMask.hasUsername(model.getAllowedClaimsMask())) {
|
||||||
token.setPreferredUsername(user.getLoginName());
|
token.setPreferredUsername(user.getUsername());
|
||||||
}
|
}
|
||||||
if (ClaimMask.hasEmail(model.getAllowedClaimsMask())) {
|
if (ClaimMask.hasEmail(model.getAllowedClaimsMask())) {
|
||||||
token.setEmail(user.getEmail());
|
token.setEmail(user.getEmail());
|
||||||
|
@ -284,7 +284,7 @@ public class TokenManager {
|
||||||
token.subject(user.getId());
|
token.subject(user.getId());
|
||||||
token.audience(realm.getName());
|
token.audience(realm.getName());
|
||||||
token.issuedNow();
|
token.issuedNow();
|
||||||
token.issuedFor(client.getLoginName());
|
token.issuedFor(client.getUsername());
|
||||||
token.issuer(realm.getName());
|
token.issuer(realm.getName());
|
||||||
if (realm.getAccessTokenLifespan() > 0) {
|
if (realm.getAccessTokenLifespan() > 0) {
|
||||||
token.expiration(Time.currentTime() + realm.getAccessTokenLifespan());
|
token.expiration(Time.currentTime() + realm.getAccessTokenLifespan());
|
||||||
|
|
|
@ -514,7 +514,7 @@ public class AccountService {
|
||||||
if (realm.getSocialLinks(user).size() > 1 || user.getAuthenticationLink() != null) {
|
if (realm.getSocialLinks(user).size() > 1 || user.getAuthenticationLink() != null) {
|
||||||
realm.removeSocialLink(user, providerId);
|
realm.removeSocialLink(user, providerId);
|
||||||
|
|
||||||
logger.debug("Social provider " + providerId + " removed successfully from user " + user.getLoginName());
|
logger.debug("Social provider " + providerId + " removed successfully from user " + user.getUsername());
|
||||||
|
|
||||||
audit.event(EventType.REMOVE_SOCIAL_LINK).client(auth.getClient()).user(auth.getUser())
|
audit.event(EventType.REMOVE_SOCIAL_LINK).client(auth.getClient()).user(auth.getUser())
|
||||||
.detail(Details.USERNAME, link.getSocialUserId() + "@" + link.getSocialProvider())
|
.detail(Details.USERNAME, link.getSocialUserId() + "@" + link.getSocialProvider())
|
||||||
|
|
|
@ -381,7 +381,7 @@ public class RequiredActionsService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private UserModel getUser(AccessCodeEntry accessCode) {
|
private UserModel getUser(AccessCodeEntry accessCode) {
|
||||||
return realm.getUser(accessCode.getUser().getLoginName());
|
return realm.getUser(accessCode.getUser().getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response redirectOauth(UserModel user, AccessCodeEntry accessCode) {
|
private Response redirectOauth(UserModel user, AccessCodeEntry accessCode) {
|
||||||
|
|
|
@ -212,7 +212,7 @@ public class SocialResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
realm.addSocialLink(authenticatedUser, socialLink);
|
realm.addSocialLink(authenticatedUser, socialLink);
|
||||||
logger.debug("Social provider " + provider.getId() + " linked with user " + authenticatedUser.getLoginName());
|
logger.debug("Social provider " + provider.getId() + " linked with user " + authenticatedUser.getUsername());
|
||||||
|
|
||||||
audit.success();
|
audit.success();
|
||||||
return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build();
|
return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build();
|
||||||
|
|
|
@ -830,7 +830,7 @@ public class TokenService {
|
||||||
UserModel user = authResult.getUser();
|
UserModel user = authResult.getUser();
|
||||||
UserSessionModel session = authResult.getSession();
|
UserSessionModel session = authResult.getSession();
|
||||||
|
|
||||||
logger.debug(user.getLoginName() + " already logged in.");
|
logger.debug(user.getUsername() + " already logged in.");
|
||||||
audit.user(user).session(session).detail(Details.AUTH_METHOD, "sso");
|
audit.user(user).session(session).detail(Details.AUTH_METHOD, "sso");
|
||||||
return oauth.processAccessCode(scopeParam, state, redirect, client, user, session, null, false, "sso", audit);
|
return oauth.processAccessCode(scopeParam, state, redirect, client, user, session, null, false, "sso", audit);
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,7 +185,7 @@ public class AdminConsole {
|
||||||
displayName = displayName != null ? displayName + " " + user.getLastName() : user.getLastName();
|
displayName = displayName != null ? displayName + " " + user.getLastName() : user.getLastName();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
displayName = user.getLoginName();
|
displayName = user.getUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
RealmModel masterRealm = getAdminstrationRealm(realmManager);
|
RealmModel masterRealm = getAdminstrationRealm(realmManager);
|
||||||
|
|
|
@ -182,7 +182,7 @@ public class AdminRoot {
|
||||||
|
|
||||||
AdminAuth auth = authenticateRealmAdminRequest(headers);
|
AdminAuth auth = authenticateRealmAdminRequest(headers);
|
||||||
if (auth != null) {
|
if (auth != null) {
|
||||||
logger.info("authenticated admin access for: " + auth.getUser().getLoginName());
|
logger.info("authenticated admin access for: " + auth.getUser().getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
Cors.add(request).allowedOrigins(auth.getToken()).allowedMethods("GET", "PUT", "POST", "DELETE").auth().build(response);
|
Cors.add(request).allowedOrigins(auth.getToken()).allowedMethods("GET", "PUT", "POST", "DELETE").auth().build(response);
|
||||||
|
|
|
@ -127,7 +127,7 @@ public class UsersResource {
|
||||||
UserModel user = realm.addUser(rep.getUsername());
|
UserModel user = realm.addUser(rep.getUsername());
|
||||||
updateUserFromRep(user, rep);
|
updateUserFromRep(user, rep);
|
||||||
|
|
||||||
return Response.created(uriInfo.getAbsolutePathBuilder().path(user.getLoginName()).build()).build();
|
return Response.created(uriInfo.getAbsolutePathBuilder().path(user.getUsername()).build()).build();
|
||||||
} catch (ModelDuplicateException e) {
|
} catch (ModelDuplicateException e) {
|
||||||
return Flows.errors().exists("User exists with same username or email");
|
return Flows.errors().exists("User exists with same username or email");
|
||||||
}
|
}
|
||||||
|
@ -277,8 +277,6 @@ public class UsersResource {
|
||||||
throw new NotFoundException("User not found");
|
throw new NotFoundException("User not found");
|
||||||
}
|
}
|
||||||
realm.removeUserSessions(user);
|
realm.removeUserSessions(user);
|
||||||
// set notBefore so that user will be forced to log in.
|
|
||||||
user.setNotBefore(Time.currentTime());
|
|
||||||
new ResourceAdminManager().logoutUser(uriInfo.getRequestUri(), realm, user.getId(), null);
|
new ResourceAdminManager().logoutUser(uriInfo.getRequestUri(), realm, user.getId(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -201,6 +201,10 @@ public class KeycloakServer {
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KeycloakServerConfig getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
public void importRealm(InputStream realm) {
|
public void importRealm(InputStream realm) {
|
||||||
RealmRepresentation rep = loadJson(realm, RealmRepresentation.class);
|
RealmRepresentation rep = loadJson(realm, RealmRepresentation.class);
|
||||||
importRealm(rep);
|
importRealm(rep);
|
||||||
|
|
|
@ -53,10 +53,20 @@ http://localhost:8081/keycloak-tools/perf/perf-realm/get-users-count?prefix=user
|
||||||
|
|
||||||
For adding 10000 new users into your database (will start from last added user, so you don't need to explicitly check how many users to create are needed:
|
For adding 10000 new users into your database (will start from last added user, so you don't need to explicitly check how many users to create are needed:
|
||||||
```shell
|
```shell
|
||||||
http://localhost:8081/keycloak-tools/perf/perf-realm/create-available-users?prefix=user&count=10000&batch=100&roles=user
|
http://localhost:8081/keycloak-tools/perf/perf-realm/create-available-users?prefix=user&count=10000&batch=100&async=true&roles=role-0,role-1
|
||||||
````
|
````
|
||||||
|
|
||||||
Seeing progress of job for creating users
|
For update role mappings of all users:
|
||||||
|
```shell
|
||||||
|
http://localhost:8081/keycloak-tools/perf/perf-realm/update-all-users?prefix=user&async=true&roles=role-3,perf-app:approle-3,perf-app:approle-4
|
||||||
|
````
|
||||||
|
|
||||||
|
For deleting all users:
|
||||||
|
```shell
|
||||||
|
http://localhost:8081/keycloak-tools/perf/perf-realm/delete-all-users?prefix=user
|
||||||
|
````
|
||||||
|
|
||||||
|
Seeing progress of job for creating/updating/deleting users
|
||||||
```shell
|
```shell
|
||||||
http://localhost:8081/keycloak-tools/perf/jobs
|
http://localhost:8081/keycloak-tools/perf/jobs
|
||||||
````
|
````
|
||||||
|
|
|
@ -216,11 +216,11 @@
|
||||||
<preserveDirectories>false</preserveDirectories>
|
<preserveDirectories>false</preserveDirectories>
|
||||||
|
|
||||||
<requestGroups>
|
<requestGroups>
|
||||||
<requestGroup>
|
<requestGroup implementation="com.lazerycode.jmeter.analyzer.config.RequestGroup">
|
||||||
<name>aggregatedRequests</name>
|
<name>aggregatedRequests</name>
|
||||||
<pattern>* request</pattern>
|
<pattern>* request</pattern>
|
||||||
</requestGroup>
|
</requestGroup>
|
||||||
<requestGroup>
|
<requestGroup implementation="com.lazerycode.jmeter.analyzer.config.RequestGroup">
|
||||||
<name>codes</name>
|
<name>codes</name>
|
||||||
<pattern>**/perf-app/perf-servlet?code=*</pattern>
|
<pattern>**/perf-app/perf-servlet?code=*</pattern>
|
||||||
</requestGroup>
|
</requestGroup>
|
||||||
|
|
|
@ -85,6 +85,7 @@ public class KeycloakPerfServer {
|
||||||
|
|
||||||
ServletInfo servlet = new ServletInfo("PerfAppServlet", PerfAppServlet.class);
|
ServletInfo servlet = new ServletInfo("PerfAppServlet", PerfAppServlet.class);
|
||||||
servlet.addMapping("/perf-servlet/*");
|
servlet.addMapping("/perf-servlet/*");
|
||||||
|
servlet.addInitParam(PerfAppServlet.BASE_URL_INIT_PARAM, "http://" + keycloakServer.getConfig().getHost() + ":" + keycloakServer.getConfig().getPort());
|
||||||
|
|
||||||
deploymentInfo.addServlet(servlet);
|
deploymentInfo.addServlet(servlet);
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ import org.keycloak.util.BasicAuthHelper;
|
||||||
*/
|
*/
|
||||||
public class OAuthClient {
|
public class OAuthClient {
|
||||||
|
|
||||||
private String baseUrl = "http://localhost:8081/auth";
|
private String baseUrl;
|
||||||
|
|
||||||
private String realm = "perf-realm";
|
private String realm = "perf-realm";
|
||||||
|
|
||||||
|
@ -52,16 +52,19 @@ public class OAuthClient {
|
||||||
|
|
||||||
private String clientId = "perf-app";
|
private String clientId = "perf-app";
|
||||||
|
|
||||||
private String redirectUri = "http://localhost:8081/perf-app/perf-servlet";
|
private String redirectUri;
|
||||||
|
|
||||||
private String state = "123";
|
private String state = "123";
|
||||||
|
|
||||||
private PublicKey realmPublicKey;
|
private PublicKey realmPublicKey;
|
||||||
|
|
||||||
public OAuthClient() {
|
public OAuthClient(String baseUrl) {
|
||||||
try {
|
try {
|
||||||
JSONObject realmJson = new JSONObject(IOUtils.toString(getClass().getResourceAsStream("/perfrealm.json")));
|
JSONObject realmJson = new JSONObject(IOUtils.toString(getClass().getResourceAsStream("/perfrealm.json")));
|
||||||
realmPublicKey = PemUtils.decodePublicKey(realmJson.getString("publicKey"));
|
realmPublicKey = PemUtils.decodePublicKey(realmJson.getString("publicKey"));
|
||||||
|
|
||||||
|
this.baseUrl = (baseUrl != null) ? baseUrl + "/auth" : "http://localhost:8081/auth";
|
||||||
|
this.redirectUri = baseUrl + "/perf-app/perf-servlet";
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Failed to retrieve realm public key", e);
|
throw new RuntimeException("Failed to retrieve realm public key", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ import org.keycloak.util.Time;
|
||||||
*/
|
*/
|
||||||
public class PerfAppServlet extends HttpServlet {
|
public class PerfAppServlet extends HttpServlet {
|
||||||
|
|
||||||
|
public static final String BASE_URL_INIT_PARAM = "baseUrl";
|
||||||
|
|
||||||
private Template indexTemplate;
|
private Template indexTemplate;
|
||||||
private OAuthClient oauthClient;
|
private OAuthClient oauthClient;
|
||||||
|
|
||||||
|
@ -35,7 +37,8 @@ public class PerfAppServlet extends HttpServlet {
|
||||||
cfg.setTemplateLoader(new ClassTemplateLoader(getClass(), "/"));
|
cfg.setTemplateLoader(new ClassTemplateLoader(getClass(), "/"));
|
||||||
indexTemplate = cfg.getTemplate("perf-app-resources/index.ftl");
|
indexTemplate = cfg.getTemplate("perf-app-resources/index.ftl");
|
||||||
|
|
||||||
oauthClient = new OAuthClient();
|
String baseUrl = getInitParameter(BASE_URL_INIT_PARAM);
|
||||||
|
oauthClient = new OAuthClient(baseUrl);
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
throw new ServletException(ioe);
|
throw new ServletException(ioe);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
"privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
|
"privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
|
||||||
"publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
"publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||||
"requiredCredentials": [ "password" ],
|
"requiredCredentials": [ "password" ],
|
||||||
"defaultRoles": [ "user" ],
|
|
||||||
"smtpServer": {
|
"smtpServer": {
|
||||||
"from": "auto@keycloak.org",
|
"from": "auto@keycloak.org",
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
|
@ -30,7 +29,7 @@
|
||||||
"name" : "third-party",
|
"name" : "third-party",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"redirectUris": [
|
"redirectUris": [
|
||||||
"http://localhost:8081/app/*"
|
"/app/*"
|
||||||
],
|
],
|
||||||
"secret": "password"
|
"secret": "password"
|
||||||
}
|
}
|
||||||
|
@ -48,41 +47,55 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"client": "perf-app",
|
"client": "perf-app",
|
||||||
"roles": ["user"]
|
"roles": [ "role-0", "role-1", "role-2", "role-3", "role-4" ]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applications": [
|
"applications": [
|
||||||
{
|
{
|
||||||
"name": "perf-app",
|
"name": "perf-app",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"baseUrl": "http://localhost:8081/perf-app",
|
"baseUrl": "/perf-app",
|
||||||
"redirectUris": [
|
"redirectUris": [
|
||||||
"http://localhost:8081/perf-app/*"
|
"/perf-app/*"
|
||||||
],
|
],
|
||||||
"adminUrl": "http://localhost:8081/perf-app/perf-servlet",
|
"adminUrl": "/perf-app/perf-servlet",
|
||||||
"secret": "password"
|
"secret": "password"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"roles" : {
|
"roles" : {
|
||||||
"realm" : [
|
"realm" : [
|
||||||
{
|
{
|
||||||
"name": "user",
|
"name": "role-0"
|
||||||
"description": "Have User privileges"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "admin",
|
"name": "role-1"
|
||||||
"description": "Have Administrator privileges"
|
},
|
||||||
|
{
|
||||||
|
"name": "role-2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "role-3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "role-4"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"application" : {
|
"application" : {
|
||||||
"perf-app" : [
|
"perf-app" : [
|
||||||
{
|
{
|
||||||
"name": "customer-user",
|
"name": "approle-0"
|
||||||
"description": "Have Customer User privileges"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "customer-admin",
|
"name": "approle-1"
|
||||||
"description": "Have Customer Admin privileges"
|
},
|
||||||
|
{
|
||||||
|
"name": "approle-2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "approle-3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "approle-4"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<jmeterTestPlan version="1.2" properties="2.6" jmeter="2.11 r1554548">
|
<jmeterTestPlan version="1.2" properties="2.5" jmeter="2.10 r1533061">
|
||||||
<hashTree>
|
<hashTree>
|
||||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
|
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
|
||||||
<stringProp name="TestPlan.comments"></stringProp>
|
<stringProp name="TestPlan.comments"></stringProp>
|
||||||
|
@ -166,7 +166,7 @@
|
||||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||||
<stringProp name="HTTPSampler.path">/auth/realms/perf-realm/tokens/auth/request/login?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8081%2Fperf-app%2Fperf-servlet&state=123&client_id=perf-app</stringProp>
|
<stringProp name="HTTPSampler.path">/auth/realms/perf-realm/tokens/auth/request/login?response_type=code&redirect_uri=http%3A%2F%2F${host}%3A${port}%2Fperf-app%2Fperf-servlet&state=123&client_id=perf-app</stringProp>
|
||||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||||
|
@ -322,6 +322,32 @@
|
||||||
<bytes>true</bytes>
|
<bytes>true</bytes>
|
||||||
</value>
|
</value>
|
||||||
</objProp>
|
</objProp>
|
||||||
|
<objProp>
|
||||||
|
<value class="SampleSaveConfiguration">
|
||||||
|
<time>true</time>
|
||||||
|
<latency>true</latency>
|
||||||
|
<timestamp>true</timestamp>
|
||||||
|
<success>true</success>
|
||||||
|
<label>true</label>
|
||||||
|
<code>true</code>
|
||||||
|
<message>true</message>
|
||||||
|
<threadName>true</threadName>
|
||||||
|
<dataType>true</dataType>
|
||||||
|
<encoding>false</encoding>
|
||||||
|
<assertions>true</assertions>
|
||||||
|
<subresults>true</subresults>
|
||||||
|
<responseData>false</responseData>
|
||||||
|
<samplerData>false</samplerData>
|
||||||
|
<xml>false</xml>
|
||||||
|
<fieldNames>false</fieldNames>
|
||||||
|
<responseHeaders>false</responseHeaders>
|
||||||
|
<requestHeaders>false</requestHeaders>
|
||||||
|
<responseDataOnError>false</responseDataOnError>
|
||||||
|
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
|
||||||
|
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||||
|
<bytes>true</bytes>
|
||||||
|
</value>
|
||||||
|
</objProp>
|
||||||
<stringProp name="filename"></stringProp>
|
<stringProp name="filename"></stringProp>
|
||||||
</ResultCollector>
|
</ResultCollector>
|
||||||
<hashTree/>
|
<hashTree/>
|
||||||
|
|
|
@ -5,8 +5,11 @@ import org.keycloak.exportimport.ExportImportProvider;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.test.tools.jobs.CreateUsersJob;
|
||||||
import org.keycloak.test.tools.jobs.CreateUsers;
|
import org.keycloak.test.tools.jobs.DeleteUsersJob;
|
||||||
|
import org.keycloak.test.tools.jobs.UpdateUsersJob;
|
||||||
|
import org.keycloak.test.tools.jobs.UsersJob;
|
||||||
|
import org.keycloak.test.tools.jobs.UsersJobInitializer;
|
||||||
import org.keycloak.util.ProviderLoader;
|
import org.keycloak.util.ProviderLoader;
|
||||||
|
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
|
@ -18,11 +21,11 @@ import javax.ws.rs.WebApplicationException;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
@ -41,7 +44,7 @@ public class PerfTools {
|
||||||
@Context
|
@Context
|
||||||
private KeycloakSession session;
|
private KeycloakSession session;
|
||||||
|
|
||||||
private List<Job> jobs = new LinkedList<Job>();
|
private List<JobRepresentation> jobs = new LinkedList<JobRepresentation>();
|
||||||
|
|
||||||
public PerfTools(KeycloakSessionFactory sessionFactory) {
|
public PerfTools(KeycloakSessionFactory sessionFactory) {
|
||||||
this.sessionFactory = sessionFactory;
|
this.sessionFactory = sessionFactory;
|
||||||
|
@ -50,16 +53,16 @@ public class PerfTools {
|
||||||
@GET
|
@GET
|
||||||
@Path("jobs")
|
@Path("jobs")
|
||||||
@Produces("application/json")
|
@Produces("application/json")
|
||||||
public List<Job> jobs() {
|
public List<JobRepresentation> jobs() {
|
||||||
return jobs;
|
return jobs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("delete-jobs")
|
@Path("delete-jobs")
|
||||||
public void deleteJobs() {
|
public void deleteJobs() {
|
||||||
Iterator<Job> itr = jobs.iterator();
|
Iterator<JobRepresentation> itr = jobs.iterator();
|
||||||
while(itr.hasNext()) {
|
while(itr.hasNext()) {
|
||||||
Job j = itr.next();
|
JobRepresentation j = itr.next();
|
||||||
if (j.getError() != null || j.getCount() == j.getTotal()) {
|
if (j.getError() != null || j.getCount() == j.getTotal()) {
|
||||||
itr.remove();
|
itr.remove();
|
||||||
}
|
}
|
||||||
|
@ -68,7 +71,116 @@ public class PerfTools {
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("{realm}/create-users")
|
@Path("{realm}/create-users")
|
||||||
public void createUsers(@PathParam("realm") String realmName, @QueryParam("count") Integer count, @QueryParam("batch") Integer batch, @QueryParam("start") Integer start, @QueryParam("prefix") String prefix, @QueryParam("roles") String roles) throws InterruptedException {
|
public void createUsers(@PathParam("realm") String realmName, @QueryParam("count") Integer count,
|
||||||
|
@QueryParam("batch") Integer batch, @QueryParam("start") Integer start, @QueryParam("prefix") String prefix,
|
||||||
|
@QueryParam("async") Boolean async, @QueryParam("roles") String roles) throws InterruptedException {
|
||||||
|
final String[] rolesArray = roles != null ? roles.split(",") : new String[0];
|
||||||
|
|
||||||
|
createAndRunJob(realmName, count, batch, start, prefix, async, "Create users", new UsersJobInitializer() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UsersJob instantiateJob() {
|
||||||
|
return new CreateUsersJob(rolesArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as createUsers, but dynamically compute "start" (Next available user)
|
||||||
|
@GET
|
||||||
|
@Path("{realm}/create-available-users")
|
||||||
|
public void createAvailableUsers(@PathParam("realm") String realmName, @QueryParam("count") Integer count,
|
||||||
|
@QueryParam("batch") Integer batch, @QueryParam("prefix") String prefix,
|
||||||
|
@QueryParam("async") Boolean async, @QueryParam("roles") String roles) throws InterruptedException {
|
||||||
|
int start = getUsersCount(realmName, prefix);
|
||||||
|
createUsers(realmName, count, batch, start, prefix, async, roles);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("{realm}/delete-users")
|
||||||
|
public void deleteUsers(@PathParam("realm") String realmName, @QueryParam("count") Integer count,
|
||||||
|
@QueryParam("batch") Integer batch, @QueryParam("start") Integer start, @QueryParam("prefix") String prefix,
|
||||||
|
@QueryParam("async") Boolean async) throws InterruptedException {
|
||||||
|
createAndRunJob(realmName, count, batch, start, prefix, async, "Delete users", new UsersJobInitializer() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UsersJob instantiateJob() {
|
||||||
|
return new DeleteUsersJob();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("{realm}/delete-all-users")
|
||||||
|
public void deleteUsers(@PathParam("realm") String realmName, @QueryParam("prefix") String prefix, @QueryParam("async") Boolean async) throws InterruptedException {
|
||||||
|
int count = getUsersCount(realmName, prefix);
|
||||||
|
if (count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int batch = count / 10;
|
||||||
|
if (batch == 0) {
|
||||||
|
batch = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteUsers(realmName, count, batch, 0, prefix, async);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("{realm}/update-users")
|
||||||
|
public void updateUsers(@PathParam("realm") String realmName, @QueryParam("count") Integer count,
|
||||||
|
@QueryParam("batch") Integer batch, @QueryParam("start") Integer start, @QueryParam("prefix") String prefix,
|
||||||
|
@QueryParam("async") Boolean async, @QueryParam("roles") String roles) throws InterruptedException {
|
||||||
|
final String[] rolesArray = roles != null ? roles.split(",") : new String[0];
|
||||||
|
|
||||||
|
createAndRunJob(realmName, count, batch, start, prefix, async, "Update users", new UsersJobInitializer() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UsersJob instantiateJob() {
|
||||||
|
return new UpdateUsersJob(rolesArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("{realm}/update-all-users")
|
||||||
|
public void updateAllUsers(@PathParam("realm") String realmName, @QueryParam("prefix") String prefix, @QueryParam("async") Boolean async,
|
||||||
|
@QueryParam("roles") String roles) throws InterruptedException {
|
||||||
|
int count = getUsersCount(realmName, prefix);
|
||||||
|
if (count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int batch = count / 10;
|
||||||
|
if (batch == 0) {
|
||||||
|
batch = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateUsers(realmName, count, batch, 0, prefix, async, roles);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("{realm}/get-users-count")
|
||||||
|
public Response getUsersCountReq(@PathParam("realm") String realmName, @QueryParam("prefix") String prefix) {
|
||||||
|
int usersCount = getUsersCount(realmName, prefix);
|
||||||
|
return Response.ok(String.valueOf(usersCount)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getUsersCount(String realmName, String prefix) {
|
||||||
|
RealmModel realm = session.getRealmByName(realmName);
|
||||||
|
|
||||||
|
// TODO: method for count on model
|
||||||
|
if (prefix == null) {
|
||||||
|
return realm.getUsers().size();
|
||||||
|
} else {
|
||||||
|
return realm.searchForUser(prefix).size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAndRunJob(String realmName, Integer count, Integer batch, Integer start, String prefix, Boolean async, String jobName, UsersJobInitializer initializer) throws InterruptedException {
|
||||||
if (count == null) {
|
if (count == null) {
|
||||||
count = 1;
|
count = 1;
|
||||||
}
|
}
|
||||||
|
@ -81,51 +193,34 @@ public class PerfTools {
|
||||||
if (prefix == null) {
|
if (prefix == null) {
|
||||||
prefix = String.valueOf(System.currentTimeMillis());
|
prefix = String.valueOf(System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
if (async == null) {
|
||||||
|
async = true;
|
||||||
|
}
|
||||||
|
|
||||||
String[] rolesArray = roles != null ? roles.split(",") : new String[0];
|
int executorsCount = count / batch;
|
||||||
|
if (count % batch > 0) {
|
||||||
|
executorsCount++;
|
||||||
|
}
|
||||||
|
CountDownLatch latch = new CountDownLatch(executorsCount);
|
||||||
|
|
||||||
Job job = new Job("Create users " + prefix + "-" + start + " to " + prefix + "-" + (start + count), count);
|
JobRepresentation job = new JobRepresentation(jobName + " " + prefix + "-" + start + " to " + prefix + "-" + (start + count), count);
|
||||||
jobs.add(job);
|
jobs.add(job);
|
||||||
|
|
||||||
|
List<UsersJob> usersJobs = new ArrayList<UsersJob>();
|
||||||
for (int s = start; s < (start + count); s += batch) {
|
for (int s = start; s < (start + count); s += batch) {
|
||||||
int c = s + batch <= (start + count) ? batch : (start + count) - s;
|
int c = s + batch <= (start + count) ? batch : (start + count) - s;
|
||||||
executor.submit(new CreateUsers(job, sessionFactory, realmName, s, c, prefix, rolesArray));
|
UsersJob usersJob = initializer.instantiateJob();
|
||||||
}
|
usersJob.init(job, sessionFactory, realmName, s, c, prefix, latch);
|
||||||
|
usersJobs.add(usersJob);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
// Run executors once all are initialized
|
||||||
@Path("{realm}/delete-users")
|
for (UsersJob usersJob : usersJobs) {
|
||||||
public void deleteUsers(@PathParam("realm") String realmName) {
|
executor.submit(usersJob);
|
||||||
RealmModel realm = session.getRealmByName(realmName);
|
|
||||||
for (UserModel user : realm.getUsers()) {
|
|
||||||
realm.removeUser(user.getLoginName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!async) {
|
||||||
@GET
|
latch.await();
|
||||||
@Path("{realm}/get-users-count")
|
|
||||||
public Response getUsersCountReq(@PathParam("realm") String realmName, @QueryParam("prefix") String prefix) {
|
|
||||||
int usersCount = getUsersCount(realmName, prefix);
|
|
||||||
return Response.ok(String.valueOf(usersCount)).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Same as createUsers, but dynamically compute "start" (Next available user)
|
|
||||||
@GET
|
|
||||||
@Path("{realm}/create-available-users")
|
|
||||||
public void createAvailableUsers(@PathParam("realm") String realmName, @QueryParam("count") Integer count, @QueryParam("batch") Integer batch, @QueryParam("prefix") String prefix, @QueryParam("roles") String roles) throws InterruptedException {
|
|
||||||
int start = getUsersCount(realmName, prefix);
|
|
||||||
createUsers(realmName, count, batch, start, prefix, roles);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getUsersCount(String realmName, String prefix) {
|
|
||||||
RealmModel realm = session.getRealmByName(realmName);
|
|
||||||
|
|
||||||
// TODO: method for count on model
|
|
||||||
if (prefix == null) {
|
|
||||||
return realm.getUsers().size();
|
|
||||||
} else {
|
|
||||||
return realm.searchForUser(prefix).size();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +241,7 @@ public class PerfTools {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Job {
|
public static class JobRepresentation {
|
||||||
private final String description;
|
private final String description;
|
||||||
private final int total;
|
private final int total;
|
||||||
private AtomicInteger count = new AtomicInteger();
|
private AtomicInteger count = new AtomicInteger();
|
||||||
|
@ -154,7 +249,7 @@ public class PerfTools {
|
||||||
private AtomicLong started = new AtomicLong();
|
private AtomicLong started = new AtomicLong();
|
||||||
private AtomicLong completed = new AtomicLong();
|
private AtomicLong completed = new AtomicLong();
|
||||||
|
|
||||||
public Job(String description, int total) {
|
public JobRepresentation(String description, int total) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.total = total;
|
this.total = total;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
package org.keycloak.test.tools.jobs;
|
|
||||||
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.UserCredentialModel;
|
|
||||||
import org.keycloak.models.UserModel;
|
|
||||||
import org.keycloak.services.managers.RealmManager;
|
|
||||||
import org.keycloak.test.tools.PerfTools;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
|
||||||
*/
|
|
||||||
public class CreateUsers implements Runnable {
|
|
||||||
|
|
||||||
private PerfTools.Job job;
|
|
||||||
private final KeycloakSessionFactory sessionFactory;
|
|
||||||
private final String realmName;
|
|
||||||
private int start;
|
|
||||||
private int count;
|
|
||||||
private String prefix;
|
|
||||||
private String[] roles;
|
|
||||||
|
|
||||||
public CreateUsers(PerfTools.Job job, KeycloakSessionFactory sessionFactory, String realmName, int start, int count, String prefix, String[] roles) {
|
|
||||||
this.job = job;
|
|
||||||
this.sessionFactory = sessionFactory;
|
|
||||||
this.realmName = realmName;
|
|
||||||
this.start = start;
|
|
||||||
this.count = count;
|
|
||||||
this.prefix = prefix;
|
|
||||||
this.roles = roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
job.start();
|
|
||||||
|
|
||||||
KeycloakSession session = sessionFactory.create();
|
|
||||||
try {
|
|
||||||
session.getTransaction().begin();
|
|
||||||
|
|
||||||
RealmModel realm = new RealmManager(session).getRealmByName(realmName);
|
|
||||||
|
|
||||||
for (int i = start; i < (start + count); i++) {
|
|
||||||
UserModel user = realm.addUser(prefix + "-" + i);
|
|
||||||
user.setEnabled(true);
|
|
||||||
user.setFirstName("First");
|
|
||||||
user.setLastName("Last");
|
|
||||||
user.setEmail(prefix + "-" + i + "@localhost");
|
|
||||||
|
|
||||||
UserCredentialModel password = new UserCredentialModel();
|
|
||||||
password.setType(UserCredentialModel.PASSWORD);
|
|
||||||
password.setValue("password");
|
|
||||||
|
|
||||||
user.updateCredential(password);
|
|
||||||
|
|
||||||
for (String r : roles) {
|
|
||||||
user.grantRole(realm.getRole(r));
|
|
||||||
}
|
|
||||||
|
|
||||||
job.increment();
|
|
||||||
}
|
|
||||||
|
|
||||||
session.getTransaction().commit();
|
|
||||||
} catch (Throwable t) {
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
t.printStackTrace(new PrintWriter(sw));
|
|
||||||
job.setError(sw.toString());
|
|
||||||
} finally {
|
|
||||||
session.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package org.keycloak.test.tools.jobs;
|
||||||
|
|
||||||
|
import org.keycloak.models.ApplicationModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.UserCredentialModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
*/
|
||||||
|
public class CreateUsersJob extends UsersJob {
|
||||||
|
|
||||||
|
private String[] roles;
|
||||||
|
|
||||||
|
public CreateUsersJob(String[] roles) {
|
||||||
|
this.roles = roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void before(KeycloakSession session) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void runIteration(RealmModel realm, Map<String, ApplicationModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter) {
|
||||||
|
String username = prefix + "-" + counter;
|
||||||
|
UserModel user = realm.addUser(username);
|
||||||
|
user.setEnabled(true);
|
||||||
|
user.setFirstName("First");
|
||||||
|
user.setLastName("Last");
|
||||||
|
user.setEmail(username + "@localhost");
|
||||||
|
|
||||||
|
UserCredentialModel password = new UserCredentialModel();
|
||||||
|
password.setType(UserCredentialModel.PASSWORD);
|
||||||
|
password.setValue("password");
|
||||||
|
|
||||||
|
user.updateCredential(password);
|
||||||
|
|
||||||
|
for (String r : roles) {
|
||||||
|
grantRole(user, r, realmRoles, appRoles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package org.keycloak.test.tools.jobs;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.keycloak.models.ApplicationModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.services.managers.RealmManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class DeleteUsersJob extends UsersJob {
|
||||||
|
|
||||||
|
private Iterator<UserModel> users;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void before(KeycloakSession session) {
|
||||||
|
RealmModel realm = new RealmManager(session).getRealmByName(realmName);
|
||||||
|
|
||||||
|
// TODO: pagination
|
||||||
|
List<UserModel> users = (prefix==null) ? realm.getUsers() : realm.searchForUser(prefix);
|
||||||
|
users = users.subList(start, start + count);
|
||||||
|
|
||||||
|
this.users = users.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void runIteration(RealmModel realm, Map<String, ApplicationModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter) {
|
||||||
|
String username = users.next().getUsername();
|
||||||
|
realm.removeUser(username);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.keycloak.test.tools.jobs;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.keycloak.models.ApplicationModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.services.managers.RealmManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class UpdateUsersJob extends UsersJob {
|
||||||
|
|
||||||
|
private String[] roles;
|
||||||
|
private Iterator<UserModel> users;
|
||||||
|
|
||||||
|
public UpdateUsersJob(String[] roles) {
|
||||||
|
this.roles = roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void before(KeycloakSession session) {
|
||||||
|
RealmModel realm = new RealmManager(session).getRealmByName(realmName);
|
||||||
|
|
||||||
|
// TODO: pagination
|
||||||
|
List<UserModel> users = (prefix==null) ? realm.getUsers() : realm.searchForUser(prefix);
|
||||||
|
users = users.subList(start, start + count);
|
||||||
|
|
||||||
|
this.users = users.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void runIteration(RealmModel realm, Map<String, ApplicationModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter) {
|
||||||
|
String username = users.next().getUsername();
|
||||||
|
|
||||||
|
// Remove all role mappings first
|
||||||
|
UserModel user = realm.getUser(username);
|
||||||
|
Set<RoleModel> currRoles = user.getRoleMappings();
|
||||||
|
for (RoleModel role : currRoles) {
|
||||||
|
user.deleteRoleMapping(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new roles now
|
||||||
|
for (String r : roles) {
|
||||||
|
grantRole(user, r, realmRoles, appRoles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
package org.keycloak.test.tools.jobs;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
import org.keycloak.models.ApplicationModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.services.managers.RealmManager;
|
||||||
|
import org.keycloak.test.tools.PerfTools;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public abstract class UsersJob implements Runnable {
|
||||||
|
|
||||||
|
protected PerfTools.JobRepresentation job;
|
||||||
|
protected KeycloakSessionFactory sessionFactory;
|
||||||
|
protected String realmName;
|
||||||
|
protected int start;
|
||||||
|
protected int count;
|
||||||
|
protected String prefix;
|
||||||
|
protected CountDownLatch latch;
|
||||||
|
|
||||||
|
public void init(PerfTools.JobRepresentation job, KeycloakSessionFactory sessionFactory, String realmName, int start, int count, String prefix, CountDownLatch latch) {
|
||||||
|
this.sessionFactory = sessionFactory;
|
||||||
|
this.realmName = realmName;
|
||||||
|
this.start = start;
|
||||||
|
this.count = count;
|
||||||
|
this.prefix = prefix;
|
||||||
|
this.job = job;
|
||||||
|
this.latch = latch;
|
||||||
|
|
||||||
|
KeycloakSession session = sessionFactory.create();
|
||||||
|
try {
|
||||||
|
session.getTransaction().begin();
|
||||||
|
|
||||||
|
before(session);
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
handleThrowable(t, session);
|
||||||
|
} finally {
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
job.start();
|
||||||
|
|
||||||
|
KeycloakSession session = sessionFactory.create();
|
||||||
|
try {
|
||||||
|
session.getTransaction().begin();
|
||||||
|
|
||||||
|
RealmModel realm = new RealmManager(session).getRealmByName(realmName);
|
||||||
|
Map<String, ApplicationModel> apps = realm.getApplicationNameMap();
|
||||||
|
|
||||||
|
Set<RoleModel> realmRoles = realm.getRoles();
|
||||||
|
Map<String, Set<RoleModel>> appRoles = new HashMap<String, Set<RoleModel>>();
|
||||||
|
for (Map.Entry<String, ApplicationModel> appEntry : apps.entrySet()) {
|
||||||
|
appRoles.put(appEntry.getKey(), appEntry.getValue().getRoles());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = start; i < (start + count); i++) {
|
||||||
|
runIteration(realm, apps, realmRoles, appRoles, i);
|
||||||
|
job.increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
handleThrowable(t, session);
|
||||||
|
} finally {
|
||||||
|
latch.countDown();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void before(KeycloakSession keycloakSession);
|
||||||
|
|
||||||
|
protected abstract void runIteration(RealmModel realm, Map<String, ApplicationModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter);
|
||||||
|
|
||||||
|
protected RoleModel findRole(Set<RoleModel> roles, String roleName) {
|
||||||
|
for (RoleModel role : roles) {
|
||||||
|
if (role.getName().equals(roleName)) {
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void grantRole(UserModel user, String roleName, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles) {
|
||||||
|
if (roleName.indexOf(':') == -1) {
|
||||||
|
// We expect "realmRoleName"
|
||||||
|
RoleModel realmRole = findRole(realmRoles, roleName);
|
||||||
|
user.grantRole(realmRole);
|
||||||
|
} else {
|
||||||
|
// We expect "appName:appRoleName"
|
||||||
|
String[] parts = roleName.split(":");
|
||||||
|
Set<RoleModel> currentAppRoles = appRoles.get(parts[0]);
|
||||||
|
if (currentAppRoles == null) {
|
||||||
|
throw new IllegalStateException("Application '" + parts[0] + "' not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
RoleModel appRole = findRole(currentAppRoles, parts[1]);
|
||||||
|
user.grantRole(appRole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleThrowable(Throwable t, KeycloakSession session) {
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
t.printStackTrace(new PrintWriter(sw));
|
||||||
|
job.setError(sw.toString());
|
||||||
|
session.getTransaction().rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package org.keycloak.test.tools.jobs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public interface UsersJobInitializer {
|
||||||
|
|
||||||
|
UsersJob instantiateJob();
|
||||||
|
}
|
Loading…
Reference in a new issue