Propagate SecurityContext into @Transactional methods. (#1979)

Closes #1944.
This commit is contained in:
Michael Reiche
2024-10-09 17:46:32 -07:00
committed by GitHub
parent 2ff18ebc2b
commit 98d39b153f
6 changed files with 147 additions and 7 deletions

View File

@@ -18,6 +18,7 @@ package org.springframework.data.couchbase.transactions;
import static com.couchbase.client.java.query.QueryScanConsistency.REQUEST_PLUS;
import org.springframework.data.couchbase.util.Util;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
@@ -119,6 +120,7 @@ public class CouchbasePersonTransactionReactiveIntegrationTests extends JavaInte
@Test
public void commitShouldPersistTxEntries() {
System.err.println("parent SecurityContext: " + System.identityHashCode(Util.getSecurityContext()));
personService.savePerson(WalterWhite) //
.as(StepVerifier::create) //
.expectNextCount(1) //
@@ -130,6 +132,17 @@ public class CouchbasePersonTransactionReactiveIntegrationTests extends JavaInte
.verifyComplete();
}
@Test
public void commitShouldPersistTxEntriesBlocking() {
System.err.println("parent SecurityContext: " + System.identityHashCode(Util.getSecurityContext()));
Person p = personService.savePersonBlocking(WalterWhite);
operations.findByQuery(Person.class).withConsistency(REQUEST_PLUS).count() //
.as(StepVerifier::create) //
.expectNext(1L) //
.verifyComplete();
}
@Test
public void commitShouldPersistTxEntriesOfTxAnnotatedMethod() {

View File

@@ -21,6 +21,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import org.springframework.data.couchbase.core.TransactionalSupport;
import org.springframework.data.couchbase.domain.PersonWithoutVersion;
import org.springframework.data.couchbase.transaction.CouchbaseResourceHolder;
import org.springframework.data.couchbase.util.Util;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -31,6 +33,9 @@ import org.springframework.data.couchbase.domain.Person;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.reactive.TransactionalOperator;
import java.lang.reflect.InvocationTargetException;
import java.util.Optional;
/**
* reactive PersonService for tests
*
@@ -57,8 +62,15 @@ class PersonServiceReactive {
.<Person> flatMap(it -> Mono.error(new SimulateFailureException()));
}
@Transactional
public Person savePersonBlocking(Person person) {
System.err.println("savePerson: "+Thread.currentThread().getName() +" "+ System.identityHashCode(Util.getSecurityContext()));
return personOperations.insertById(Person.class).one(person);
}
@Transactional
public Mono<Person> savePerson(Person person) {
System.err.println("savePerson: "+Thread.currentThread().getName() +" "+ System.identityHashCode(Util.getSecurityContext()));
return TransactionalSupport.checkForTransactionInThreadLocalStorage().map(stat -> {
assertTrue(stat.isPresent(), "Not in transaction");
System.err.println("In a transaction!!");

View File

@@ -20,6 +20,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import static org.awaitility.Awaitility.with;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.time.Duration;
import java.util.Arrays;
import java.util.LinkedList;
@@ -170,4 +171,26 @@ public class Util {
+ " but expected in-annotation-transaction = " + inTransaction);
}
static public Object getSecurityContext(){
Object sc = null;
try {
Class<?> securityContextHolderClass = Class
.forName("org.springframework.security.core.context.SecurityContextHolder");
sc = securityContextHolderClass.getMethod("getContext").invoke(null);
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
| InvocationTargetException cnfe) {}
System.err.println(Thread.currentThread().getName() +" Util.get "+ System.identityHashCode(sc));
return sc;
}
static public void setSecurityContext(Object sc) {
System.err.println(Thread.currentThread().getName() +" Util.set "+ System.identityHashCode(sc));
try {
Class<?> securityContextHolderClass = Class
.forName("org.springframework.security.core.context.SecurityContextHolder");
sc = securityContextHolderClass.getMethod("setContext", new Class[]{securityContextHolderClass}).invoke(sc);
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
| InvocationTargetException cnfe) {}
}
}