keycloak-uncached
Changes
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUserConsent.java 12(+12 -0)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java 8(+8 -0)
Details
diff --git a/core/src/main/java/org/keycloak/representations/idm/UserConsentRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserConsentRepresentation.java
index a394b3c..681a03b 100644
--- a/core/src/main/java/org/keycloak/representations/idm/UserConsentRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/UserConsentRepresentation.java
@@ -35,6 +35,10 @@ public class UserConsentRepresentation {
// Key is clientId, Value is list of granted roles of this client
protected Map<String, List<String>> grantedClientRoles;
+ private Long createdDate;
+
+ private Long lastUpdatedDate;
+
public String getClientId() {
return clientId;
}
@@ -66,4 +70,20 @@ public class UserConsentRepresentation {
public void setGrantedClientRoles(Map<String, List<String>> grantedClientRoles) {
this.grantedClientRoles = grantedClientRoles;
}
+
+ public void setCreatedDate(Long createdDate) {
+ this.createdDate = createdDate;
+ }
+
+ public Long getCreatedDate() {
+ return createdDate;
+ }
+
+ public void setLastUpdatedDate(Long lastUpdatedDate) {
+ this.lastUpdatedDate = lastUpdatedDate;
+ }
+
+ public Long getLastUpdatedDate() {
+ return lastUpdatedDate;
+ }
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUserConsent.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUserConsent.java
index e57d456..4b24bd1 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUserConsent.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUserConsent.java
@@ -32,6 +32,8 @@ public class CachedUserConsent {
private final String clientDbId;
private final Set<ProtocolMapperModel> protocolMappers = new HashSet<>();
private final Set<String> roleIds = new HashSet<>();
+ private final Long createdDate;
+ private final Long lastUpdatedDate;
public CachedUserConsent(UserConsentModel consentModel) {
this.clientDbId = consentModel.getClient().getId();
@@ -39,6 +41,8 @@ public class CachedUserConsent {
for (RoleModel role : consentModel.getGrantedRoles()) {
this.roleIds.add(role.getId());
}
+ this.createdDate = consentModel.getCreatedDate();
+ this.lastUpdatedDate = consentModel.getLastUpdatedDate();
}
public String getClientDbId() {
@@ -52,4 +56,12 @@ public class CachedUserConsent {
public Set<String> getRoleIds() {
return roleIds;
}
+
+ public Long getCreatedDate() {
+ return createdDate;
+ }
+
+ public Long getLastUpdatedDate() {
+ return lastUpdatedDate;
+ }
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
index 16987d4..cdb79a7 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
@@ -555,6 +555,8 @@ public class UserCacheSession implements UserCache {
}
UserConsentModel consentModel = new UserConsentModel(client);
+ consentModel.setCreatedDate(cachedConsent.getCreatedDate());
+ consentModel.setLastUpdatedDate(cachedConsent.getLastUpdatedDate());
for (String roleId : cachedConsent.getRoleIds()) {
RoleModel role = session.realms().getRoleById(roleId, realm);
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java
index 34c272a..c2b7b02 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java
@@ -68,6 +68,12 @@ public class UserConsentEntity {
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "userConsent")
Collection<UserConsentProtocolMapperEntity> grantedProtocolMappers = new ArrayList<UserConsentProtocolMapperEntity>();
+ @Column(name = "CREATED_DATE")
+ private Long createdDate;
+
+ @Column(name = "LAST_UPDATED_DATE")
+ private Long lastUpdatedDate;
+
public String getId() {
return id;
}
@@ -108,6 +114,22 @@ public class UserConsentEntity {
this.grantedProtocolMappers = grantedProtocolMappers;
}
+ public Long getCreatedDate() {
+ return createdDate;
+ }
+
+ public void setCreatedDate(Long createdDate) {
+ this.createdDate = createdDate;
+ }
+
+ public Long getLastUpdatedDate() {
+ return lastUpdatedDate;
+ }
+
+ public void setLastUpdatedDate(Long lastUpdatedDate) {
+ this.lastUpdatedDate = lastUpdatedDate;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -125,5 +147,4 @@ public class UserConsentEntity {
public int hashCode() {
return id.hashCode();
}
-
}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
index 6f85e38..3aa71f0 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
@@ -18,6 +18,7 @@
package org.keycloak.models.jpa;
import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.common.util.Time;
import org.keycloak.component.ComponentModel;
import org.keycloak.credential.CredentialModel;
import org.keycloak.credential.UserCredentialStore;
@@ -201,10 +202,14 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
}
+ long currentTime = Time.currentTimeMillis();
+
consentEntity = new UserConsentEntity();
consentEntity.setId(KeycloakModelUtils.generateId());
consentEntity.setUser(em.getReference(UserEntity.class, user.getId()));
consentEntity.setClientId(clientId);
+ consentEntity.setCreatedDate(currentTime);
+ consentEntity.setLastUpdatedDate(currentTime);
em.persist(consentEntity);
em.flush();
@@ -277,6 +282,8 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
throw new ModelException("Client with id " + entity.getClientId() + " is not available");
}
UserConsentModel model = new UserConsentModel(client);
+ model.setCreatedDate(entity.getCreatedDate());
+ model.setLastUpdatedDate(entity.getLastUpdatedDate());
Collection<UserConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles();
if (grantedRoleEntities != null) {
@@ -346,6 +353,8 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
em.remove(toRemove);
}
+ consentEntity.setLastUpdatedDate(Time.currentTimeMillis());
+
em.flush();
}
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-2.3.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.3.0.xml
index bc2ef13..2f377c3 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-2.3.0.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.3.0.xml
@@ -47,7 +47,11 @@
<dropColumn tableName="REALM" columnName="PUBLIC_KEY" />
<dropColumn tableName="REALM" columnName="CERTIFICATE" />
- </changeSet>
+ <addColumn tableName="USER_CONSENT">
+ <column name="CREATED_DATE" type="BIGINT"/>
+ <column name="LAST_UPDATED_DATE" type="BIGINT"/>
+ </addColumn>
+ </changeSet>
</databaseChangeLog>
\ No newline at end of file
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
index 529aabe..af1b6be 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
@@ -21,6 +21,7 @@ import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.common.util.Time;
import org.keycloak.component.ComponentModel;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
@@ -524,9 +525,13 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
}
+ long currentTime = Time.currentTimeMillis();
+
MongoUserConsentEntity consentEntity = new MongoUserConsentEntity();
consentEntity.setUserId(user.getId());
consentEntity.setClientId(clientId);
+ consentEntity.setCreatedDate(currentTime);
+ consentEntity.setLastUpdatedDate(currentTime);
fillEntityFromModel(consent, consentEntity);
getMongoStore().insertEntity(consentEntity, invocationContext);
}
@@ -568,6 +573,8 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
throw new ModelException("Client with id " + entity.getClientId() + " is not available");
}
UserConsentModel model = new UserConsentModel(client);
+ model.setCreatedDate(entity.getCreatedDate());
+ model.setLastUpdatedDate(entity.getLastUpdatedDate());
for (String roleId : entity.getGrantedRoles()) {
RoleModel roleModel = realm.getRoleById(roleId);
@@ -596,6 +603,7 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
protMapperIds.add(protMapperModel.getId());
}
consentEntity.setGrantedProtocolMappers(protMapperIds);
+ consentEntity.setLastUpdatedDate(Time.currentTimeMillis());
}
@Override
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/UserConsentEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/UserConsentEntity.java
index c60faee..1ca9e64 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/UserConsentEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/UserConsentEntity.java
@@ -29,6 +29,8 @@ public class UserConsentEntity extends AbstractIdentifiableEntity {
private String clientId;
private List<String> grantedRoles = new ArrayList<String>();
private List<String> grantedProtocolMappers = new ArrayList<String>();
+ private Long createdDate;
+ private Long lastUpdatedDate;
public String getUserId() {
return userId;
@@ -61,4 +63,20 @@ public class UserConsentEntity extends AbstractIdentifiableEntity {
public void setGrantedProtocolMappers(List<String> grantedProtocolMappers) {
this.grantedProtocolMappers = grantedProtocolMappers;
}
+
+ public Long getCreatedDate() {
+ return createdDate;
+ }
+
+ public void setCreatedDate(Long createdDate) {
+ this.createdDate = createdDate;
+ }
+
+ public Long getLastUpdatedDate() {
+ return lastUpdatedDate;
+ }
+
+ public void setLastUpdatedDate(Long lastUpdatedDate) {
+ this.lastUpdatedDate = lastUpdatedDate;
+ }
}
diff --git a/server-spi/src/main/java/org/keycloak/models/UserConsentModel.java b/server-spi/src/main/java/org/keycloak/models/UserConsentModel.java
index d3c295b..847696d 100644
--- a/server-spi/src/main/java/org/keycloak/models/UserConsentModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserConsentModel.java
@@ -28,6 +28,8 @@ public class UserConsentModel {
private final ClientModel client;
private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
private Set<RoleModel> roles = new HashSet<RoleModel>();
+ private Long createdDate;
+ private Long lastUpdatedDate;
public UserConsentModel(ClientModel client) {
this.client = client;
@@ -67,4 +69,19 @@ public class UserConsentModel {
return false;
}
+ public Long getCreatedDate() {
+ return createdDate;
+ }
+
+ public void setCreatedDate(Long createdDate) {
+ this.createdDate = createdDate;
+ }
+
+ public Long getLastUpdatedDate() {
+ return lastUpdatedDate;
+ }
+
+ public void setLastUpdatedDate(Long lastUpdatedDate) {
+ this.lastUpdatedDate = lastUpdatedDate;
+ }
}
diff --git a/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 8703a05..9846d08 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -710,6 +710,8 @@ public class ModelToRepresentation {
consentRep.setGrantedProtocolMappers(grantedProtocolMappers);
consentRep.setGrantedRealmRoles(grantedRealmRoles);
consentRep.setGrantedClientRoles(grantedClientRoles);
+ consentRep.setCreatedDate(model.getCreatedDate());
+ consentRep.setLastUpdatedDate(model.getLastUpdatedDate());
return consentRep;
}
diff --git a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index ec516b6..c5e55a5 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -1571,6 +1571,8 @@ public class RepresentationToModel {
}
UserConsentModel consentModel = new UserConsentModel(client);
+ consentModel.setCreatedDate(consentRep.getCreatedDate());
+ consentModel.setLastUpdatedDate(consentRep.getLastUpdatedDate());
if (consentRep.getGrantedRealmRoles() != null) {
for (String roleName : consentRep.getGrantedRealmRoles()) {
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 2b06c4c..5325d8b 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
@@ -538,6 +538,8 @@ public class UsersResource {
currentRep.put("grantedProtocolMappers", (rep==null ? Collections.emptyMap() : rep.getGrantedProtocolMappers()));
currentRep.put("grantedRealmRoles", (rep==null ? Collections.emptyList() : rep.getGrantedRealmRoles()));
currentRep.put("grantedClientRoles", (rep==null ? Collections.emptyMap() : rep.getGrantedClientRoles()));
+ currentRep.put("createdDate", (rep==null ? null : rep.getCreatedDate()));
+ currentRep.put("lastUpdatedDate", (rep==null ? null : rep.getLastUpdatedDate()));
List<Map<String, String>> additionalGrants = new LinkedList<>();
if (hasOfflineToken) {
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java
index 4335c52..c65fee1 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java
@@ -105,12 +105,16 @@ public class UserConsentModelTest extends AbstractModelTest {
Assert.assertTrue(isRoleGranted(realm, "realm-role", johnFooConsent));
Assert.assertTrue(isRoleGranted(barClient, "bar-client-role", johnFooConsent));
Assert.assertTrue(isMapperGranted(fooClient, "foo", johnFooConsent));
+ Assert.assertNotNull("Created Date should be set", johnFooConsent.getCreatedDate());
+ Assert.assertNotNull("Last Updated Date should be set", johnFooConsent.getLastUpdatedDate());
UserConsentModel johnBarConsent = realmManager.getSession().users().getConsentByClient(realm, john, barClient.getId());
Assert.assertEquals(johnBarConsent.getGrantedRoles().size(), 1);
Assert.assertEquals(johnBarConsent.getGrantedProtocolMappers().size(), 1);
Assert.assertTrue(isRoleGranted(realm, "realm-role", johnBarConsent));
Assert.assertTrue(isMapperGranted(barClient, "bar", johnBarConsent));
+ Assert.assertNotNull("Created Date should be set", johnBarConsent.getCreatedDate());
+ Assert.assertNotNull("Last Updated Date should be set", johnBarConsent.getLastUpdatedDate());
UserConsentModel maryConsent = realmManager.getSession().users().getConsentByClient(realm, mary, fooClient.getId());
Assert.assertEquals(maryConsent.getGrantedRoles().size(), 1);
@@ -118,6 +122,8 @@ public class UserConsentModelTest extends AbstractModelTest {
Assert.assertTrue(isRoleGranted(realm, "realm-role", maryConsent));
Assert.assertFalse(isRoleGranted(barClient, "bar-client-role", maryConsent));
Assert.assertTrue(isMapperGranted(fooClient, "foo", maryConsent));
+ Assert.assertNotNull("Created Date should be set", maryConsent.getCreatedDate());
+ Assert.assertNotNull("Last Updated Date should be set", maryConsent.getLastUpdatedDate());
Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary, barClient.getId()));
}
@@ -176,6 +182,7 @@ public class UserConsentModelTest extends AbstractModelTest {
Assert.assertFalse(isRoleGranted(realm, "realm-role", johnConsent));
Assert.assertTrue(isRoleGranted(realm, "new-realm-role", johnConsent));
Assert.assertFalse(isMapperGranted(fooClient, "foo", johnConsent));
+ Assert.assertTrue("Created date should be less than last updated date", johnConsent.getCreatedDate() < johnConsent.getLastUpdatedDate());
}
@Test
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index ef27439..ef8ef74 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -896,6 +896,8 @@ spi=SPI
granted-roles=Granted Roles
granted-protocol-mappers=Granted Protocol Mappers
additional-grants=Additional Grants
+consent-created-date=Created
+consent-last-updated-date=Last updated
revoke=Revoke
new-password=New Password
password-confirmation=Password Confirmation
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_no.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_no.properties
index 574eb91..9b8a6cb 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_no.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_no.properties
@@ -863,6 +863,8 @@ spi=SPI
granted-roles=Tildelte roller
granted-protocol-mappers=Innvilgede protokollmappere
additional-grants=Tillegsrettigheter
+consent-created-date=Opprettet
+consent-last-updated-date=Sist oppdatert
revoke=Opphev
new-password=Nytt passord
password-confirmation=Passord bekreftelse
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/user-consents.html b/themes/src/main/resources/theme/base/admin/resources/partials/user-consents.html
index 63bfa7e..670d708 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/user-consents.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/user-consents.html
@@ -13,6 +13,8 @@
<th>{{:: 'granted-roles' | translate}}</th>
<th>{{:: 'granted-protocol-mappers' | translate}}</th>
<th>{{:: 'additional-grants' | translate}}</th>
+ <th>{{:: 'consent-created-date' | translate}}</th>
+ <th>{{:: 'consent-last-updated-date' | translate}}</th>
<th>{{:: 'action' | translate}}</th>
</tr>
</thead>
@@ -41,6 +43,8 @@
<span ng-if="!$first">, </span><a href="#/realms/{{realm.realm}}/users/{{user.id}}/offline-sessions/{{additionalGrant.client}}">{{additionalGrant.key}}</a>
</span>
</td>
+ <td>{{consent.createdDate | date :'short'}}</td>
+ <td>{{consent.lastUpdatedDate | date :'short'}}</td>
<td class="kc-action-cell" ng-click="revokeConsent(consent.clientId)">{{:: 'revoke' | translate}}</td>
</tr>
</tbody>