#119 - Added example for use of SpEL expressions in JPQL update statements.

This commit is contained in:
Thomas Darimont
2015-08-01 15:50:11 +02:00
committed by Oliver Gierke
parent fbcded19e6
commit 50faabb2af
3 changed files with 105 additions and 16 deletions

View File

@@ -15,7 +15,12 @@
*/
package example.springdata.jpa.security;
import javax.persistence.*;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
/**
* @author Thomas Darimont
@@ -26,27 +31,76 @@ public class BusinessObject {
@Id @GeneratedValue Long id;
String data;
@ManyToOne User owner;
@ManyToOne
User owner;
String lastModifiedByUsername;
Date lastModifiedDate;
public BusinessObject() {}
public BusinessObject(String data, User owner) {
this.data = data;
this.owner = owner;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public User getOwner() {
return owner;
}
public void setOwner(User owner) {
this.owner = owner;
}
public String getLastModifiedByUsername() {
return lastModifiedByUsername;
}
public void setLastModifiedByUsername(String lastModifiedByUsername) {
this.lastModifiedByUsername = lastModifiedByUsername;
}
public Date getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(Date lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
BusinessObject that = (BusinessObject) o;
if (data != null ? !data.equals(that.data) : that.data != null) return false;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
if (owner != null ? !owner.equals(that.owner) : that.owner != null) return false;
if (data != null ? !data.equals(that.data) : that.data != null)
return false;
if (id != null ? !id.equals(that.id) : that.id != null)
return false;
if (owner != null ? !owner.equals(that.owner) : that.owner != null)
return false;
return true;
}

View File

@@ -17,6 +17,7 @@ package example.springdata.jpa.security;
import java.util.List;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
@@ -51,4 +52,11 @@ public interface SecureBusinessObjectRepository extends Repository<BusinessObjec
*/
@Query("select o from BusinessObject o where o.owner.id = ?#{principal.id} or 1=?#{hasRole('ROLE_ADMIN') ? 1 : 0}")
List<BusinessObject> findBusinessObjectsForCurrentUserById();
/**
* Here we demonstrate the use of SecurityContext information in dynamic SPEL parameters in a JPAQL update statement.
*/
@Modifying
@Query("update BusinessObject b set b.data = upper(b.data), b.lastModifiedByUsername = :#{#security.principal.firstname}, b.lastModifiedDate = :#{new java.util.Date()}")
void modifiyDataWithRecordingSecurityContext();
}

View File

@@ -21,6 +21,8 @@ import static org.junit.Assert.*;
import java.util.List;
import javax.persistence.EntityManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -46,10 +48,15 @@ public class SecurityIntegrationTests {
@Autowired UserRepository userRepository;
@Autowired BusinessObjectRepository businessObjectRepository;
@Autowired SecureBusinessObjectRepository secureBusinessObjectRepository;
@Autowired EntityManager em;
User tom;
User olli;
User admin;
UsernamePasswordAuthenticationToken olliAuth;
UsernamePasswordAuthenticationToken tomAuth;
UsernamePasswordAuthenticationToken adminAuth;
BusinessObject object1;
BusinessObject object2;
@@ -65,12 +72,16 @@ public class SecurityIntegrationTests {
object1 = businessObjectRepository.save(new BusinessObject("object1", olli));
object2 = businessObjectRepository.save(new BusinessObject("object2", olli));
object3 = businessObjectRepository.save(new BusinessObject("object3", tom));
olliAuth = new UsernamePasswordAuthenticationToken(olli, "x");
tomAuth = new UsernamePasswordAuthenticationToken(tom, "x");
adminAuth = new UsernamePasswordAuthenticationToken(admin, "x", singleton(new SimpleGrantedAuthority("ROLE_ADMIN")));
}
@Test
public void findBusinessObjectsForCurrentUserShouldReturnOnlyBusinessObjectsWhereCurrentUserIsOwner() {
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(tom, "x"));
SecurityContextHolder.getContext().setAuthentication(tomAuth);
List<BusinessObject> businessObjects = secureBusinessObjectRepository.findBusinessObjectsForCurrentUser();
@@ -88,8 +99,7 @@ public class SecurityIntegrationTests {
@Test
public void findBusinessObjectsForCurrentUserShouldReturnAllObjectsForAdmin() {
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(admin, "x", singleton(new SimpleGrantedAuthority("ROLE_ADMIN"))));
SecurityContextHolder.getContext().setAuthentication(adminAuth);
List<BusinessObject> businessObjects = secureBusinessObjectRepository.findBusinessObjectsForCurrentUser();
@@ -100,14 +110,14 @@ public class SecurityIntegrationTests {
@Test
public void findBusinessObjectsForCurrentUserByIdShouldReturnOnlyBusinessObjectsWhereCurrentUserIsOwner() {
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(tom, "x"));
SecurityContextHolder.getContext().setAuthentication(tomAuth);
List<BusinessObject> businessObjects = secureBusinessObjectRepository.findBusinessObjectsForCurrentUserById();
assertThat(businessObjects, hasSize(1));
assertThat(businessObjects, contains(object3));
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(olli, "x"));
SecurityContextHolder.getContext().setAuthentication(olliAuth);
businessObjects = secureBusinessObjectRepository.findBusinessObjectsForCurrentUserById();
@@ -118,13 +128,30 @@ public class SecurityIntegrationTests {
@Test
public void findBusinessObjectsForCurrentUserByIdShouldReturnAllObjectsForAdmin() {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(admin, "x",
singleton(new SimpleGrantedAuthority("ROLE_ADMIN")));
SecurityContextHolder.getContext().setAuthentication(auth);
SecurityContextHolder.getContext().setAuthentication(adminAuth);
List<BusinessObject> businessObjects = secureBusinessObjectRepository.findBusinessObjectsForCurrentUserById();
assertThat(businessObjects, hasSize(3));
assertThat(businessObjects, contains(object1, object2, object3));
}
@Test
public void customUpdateStatementShouldAllowToUseSecurityContextInformationViaSpelParameters() {
SecurityContextHolder.getContext().setAuthentication(adminAuth);
//Detaching items to get them out of the query cache in order to see the updated values.
em.detach(object1);
em.detach(object2);
em.detach(object3);
secureBusinessObjectRepository.modifiyDataWithRecordingSecurityContext();
for(BusinessObject bo : businessObjectRepository.findAll()) {
assertThat(bo.getLastModifiedDate(), is(notNullValue()));
assertThat(bo.getLastModifiedByUsername(), is("admin"));
}
}
}