KEYCLOAK-3626 - CreatedDate and lastUpdatedDate on user consent

This commit is contained in:
Geir Ole Hiåsen Stevning 2016-10-06 12:43:25 +02:00 committed by mposolda
parent 4593d89a05
commit 95f62c6aeb
16 changed files with 134 additions and 2 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -47,7 +47,11 @@
<dropColumn tableName="REALM" columnName="PUBLIC_KEY" />
<dropColumn tableName="REALM" columnName="CERTIFICATE" />
<addColumn tableName="USER_CONSENT">
<column name="CREATED_DATE" type="BIGINT"/>
<column name="LAST_UPDATED_DATE" type="BIGINT"/>
</addColumn>
</changeSet>
</databaseChangeLog>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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