diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
index 4e0f53ca08..92773f856d 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
@@ -17,20 +17,19 @@ import java.util.Set;
/**
* @author Stian Thorgersen
*/
-public class ClientSessionAdapter implements ClientSessionModel {
+public class ClientSessionAdapter extends AbstractMongoAdapter implements ClientSessionModel {
private KeycloakSession session;
private MongoUserSessionProvider provider;
private RealmModel realm;
private MongoClientSessionEntity entity;
- private MongoStoreInvocationContext invContext;
public ClientSessionAdapter(KeycloakSession session, MongoUserSessionProvider provider, RealmModel realm, MongoClientSessionEntity entity, MongoStoreInvocationContext invContext) {
+ super(invContext);
this.session = session;
this.provider = provider;
this.realm = realm;
this.entity = entity;
- this.invContext = invContext;
}
@Override
@@ -58,13 +57,15 @@ public class ClientSessionAdapter implements ClientSessionModel {
public void setUserSession(UserSessionModel userSession) {
MongoUserSessionEntity userSessionEntity = provider.getUserSessionEntity(realm, userSession.getId());
entity.setSessionId(userSessionEntity.getId());
- provider.getMongoStore().pushItemToList(userSessionEntity, "clientSessions", entity.getId(), true, invContext);
+ updateMongoEntity();
+
+ provider.getMongoStore().pushItemToList(userSessionEntity, "clientSessions", entity.getId(), true, invocationContext);
}
@Override
public void setRedirectUri(String uri) {
entity.setRedirectUri(uri);
-
+ updateMongoEntity();
}
@Override
@@ -72,6 +73,7 @@ public class ClientSessionAdapter implements ClientSessionModel {
List list = new LinkedList();
list.addAll(roles);
entity.setRoles(list);
+ updateMongoEntity();
}
@Override
@@ -87,6 +89,7 @@ public class ClientSessionAdapter implements ClientSessionModel {
@Override
public void setTimestamp(int timestamp) {
entity.setTimestamp(timestamp);
+ updateMongoEntity();
}
@Override
@@ -97,6 +100,7 @@ public class ClientSessionAdapter implements ClientSessionModel {
@Override
public void setAction(Action action) {
entity.setAction(action);
+ updateMongoEntity();
}
@Override
@@ -112,13 +116,13 @@ public class ClientSessionAdapter implements ClientSessionModel {
@Override
public void setNote(String name, String value) {
entity.getNotes().put(name, value);
-
+ updateMongoEntity();
}
@Override
public void removeNote(String name) {
entity.getNotes().remove(name);
-
+ updateMongoEntity();
}
@Override
@@ -129,5 +133,11 @@ public class ClientSessionAdapter implements ClientSessionModel {
@Override
public void setAuthMethod(String method) {
entity.setAuthMethod(method);
+ updateMongoEntity();
+ }
+
+ @Override
+ protected MongoClientSessionEntity getMongoEntity() {
+ return entity;
}
}
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java
index 9c5f6fd3bd..c032e1b17b 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java
@@ -19,6 +19,7 @@ import org.keycloak.models.sessions.mongo.entities.MongoUsernameLoginFailureEnti
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.util.Time;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -49,6 +50,9 @@ public class MongoUserSessionProvider implements UserSessionProvider {
entity.setTimestamp(Time.currentTime());
entity.setClientId(client.getId());
entity.setRealmId(realm.getId());
+
+ mongoStore.insertEntity(entity, invocationContext);
+
return new ClientSessionAdapter(session, this, realm, entity, invocationContext);
}
@@ -125,24 +129,22 @@ public class MongoUserSessionProvider implements UserSessionProvider {
public List getUserSessions(RealmModel realm, ClientModel client, int firstResult, int maxResults) {
DBObject query = new QueryBuilder()
- .and("clientSessions.clientId").is(client.getId())
+ .and("clientId").is(client.getId())
.get();
- DBObject sort = new BasicDBObject("started", 1).append("id", 1);
+ DBObject sort = new BasicDBObject("timestamp", 1).append("id", 1);
- List sessions = mongoStore.loadEntities(MongoUserSessionEntity.class, query, sort, firstResult, maxResults, invocationContext);
+ List clientSessions = mongoStore.loadEntities(MongoClientSessionEntity.class, query, sort, firstResult, maxResults, invocationContext);
List result = new LinkedList();
- for (MongoUserSessionEntity session : sessions) {
- result.add(new UserSessionAdapter(this.session, this, session, realm, invocationContext));
+ for (MongoClientSessionEntity clientSession : clientSessions) {
+ MongoUserSessionEntity userSession = mongoStore.loadEntity(MongoUserSessionEntity.class, clientSession.getSessionId(), invocationContext);
+ result.add(new UserSessionAdapter(session, this, userSession, realm, invocationContext));
}
return result;
}
@Override
public int getActiveUserSessions(RealmModel realm, ClientModel client) {
- DBObject query = new QueryBuilder()
- .and("clientSessions.clientId").is(client.getId())
- .get();
- return mongoStore.countEntities(MongoUserSessionEntity.class, query, invocationContext);
+ return getUserSessions(realm, client).size();
}
@Override
@@ -232,7 +234,14 @@ public class MongoUserSessionProvider implements UserSessionProvider {
DBObject query = new QueryBuilder()
.and("clientId").is(client.getId())
.get();
- mongoStore.removeEntities(MongoUserSessionEntity.class, query, invocationContext);
+ DBObject sort = new BasicDBObject("timestamp", 1).append("id", 1);
+
+ List clientSessions = mongoStore.loadEntities(MongoClientSessionEntity.class, query, sort, -1, -1, invocationContext);
+ for (MongoClientSessionEntity clientSession : clientSessions) {
+ MongoUserSessionEntity userSession = mongoStore.loadEntity(MongoUserSessionEntity.class, clientSession.getSessionId(), invocationContext);
+ getMongoStore().pullItemFromList(userSession, "clientSessions", clientSession.getId(), invocationContext);
+ mongoStore.removeEntity(clientSession, invocationContext);
+ }
}
@Override
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UserSessionAdapter.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UserSessionAdapter.java
index 70ba85a095..0f30e5aa72 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UserSessionAdapter.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UserSessionAdapter.java
@@ -1,13 +1,11 @@
package org.keycloak.models.sessions.mongo;
-import org.jboss.logging.Logger;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity;
import org.keycloak.models.sessions.mongo.entities.MongoUserSessionEntity;
import java.util.LinkedList;
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java
index 6dd1c0913c..91ec6820cb 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java
@@ -1,5 +1,6 @@
package org.keycloak.models.sessions.mongo.entities;
+import org.keycloak.connections.mongo.api.MongoCollection;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.ClientSessionModel;
@@ -12,6 +13,7 @@ import java.util.Map;
/**
* @author Stian Thorgersen
*/
+@MongoCollection(collectionName = "clientSessions")
public class MongoClientSessionEntity extends AbstractIdentifiableEntity implements MongoIdentifiableEntity {
private String id;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index 79bc1427d7..7900cc7db9 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -56,6 +56,7 @@ import javax.ws.rs.core.UriInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -189,10 +190,10 @@ public class UsersResource {
user.setAttribute(attr.getKey(), attr.getValue());
}
- for (String key : user.getAttributes().keySet()) {
- if (!rep.getAttributes().containsKey(key)) {
- user.removeAttribute(key);
- }
+ Set attrToRemove = new HashSet(user.getAttributes().keySet());
+ attrToRemove.removeAll(rep.getAttributes().keySet());
+ for (String attr : attrToRemove) {
+ user.removeAttribute(attr);
}
}
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
index 33d02c9ad8..353c70905e 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
@@ -406,6 +406,7 @@ public class OAuthClient {
private String refreshToken;
private String error;
+ private String errorDescription;
public AccessTokenResponse(HttpResponse response) throws Exception {
statusCode = response.getStatusLine().getStatusCode();
@@ -426,6 +427,7 @@ public class OAuthClient {
}
} else {
error = responseJson.getString(OAuth2Constants.ERROR);
+ errorDescription = responseJson.has(OAuth2Constants.ERROR_DESCRIPTION) ? responseJson.getString(OAuth2Constants.ERROR_DESCRIPTION) : null;
}
}
@@ -437,6 +439,10 @@ public class OAuthClient {
return error;
}
+ public String getErrorDescription() {
+ return errorDescription;
+ }
+
public int getExpiresIn() {
return expiresIn;
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java
index db16965193..2d9983e1f8 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java
@@ -66,7 +66,7 @@ public class UserSessionProviderTest {
@Test
public void testUpdateSession() {
UserSessionModel[] sessions = createSessions();
- sessions[0].setLastSessionRefresh(1000);
+ session.sessions().getUserSession(realm, sessions[0].getId()).setLastSessionRefresh(1000);
resetSession();
@@ -137,6 +137,8 @@ public class UserSessionProviderTest {
List clientSessionsRemoved = new LinkedList();
List clientSessionsKept = new LinkedList();
for (UserSessionModel s : sessions) {
+ s = session.sessions().getUserSession(realm, s.getId());
+
for (ClientSessionModel c : s.getClientSessions()) {
if (c.getUserSession().getUser().getUsername().equals("user1")) {
clientSessionsRemoved.add(c.getId());
@@ -349,8 +351,11 @@ public class UserSessionProviderTest {
resetSession();
+ failure1 = session.sessions().getUserLoginFailure(realm, "user1");
failure1.clearFailures();
+ resetSession();
+
failure1 = session.sessions().getUserLoginFailure(realm, "user1");
assertEquals(0, failure1.getNumFailures());
}