mirror of
https://github.com/corda/corda.git
synced 2024-12-21 13:57:54 +00:00
* ENT-6588 Restrict database operations platform flag Put the restricting of database operations in `RestrictedConnection` and `RestrictedEntityManager` behind a platform version flag. `RESTRICTED_DATABASE_OPERATIONS = 7` was added to signify this. If the version is less than 7, then the database operations will not be restricted. A warning is logged to indicate that they are using potentially dangerous methods. If the version is 7 or greater, then the database operations are restricted and throw an error if called. Co-authored-by: Dan Newton <dan.newton@r3.com> Co-authored-by: Dan Newton <dan.newton@r3.com>
This commit is contained in:
parent
48707e595a
commit
470bce8a6b
@ -16,4 +16,5 @@ object PlatformVersionSwitches {
|
|||||||
const val LIMIT_KEYS_IN_SIGNATURE_CONSTRAINTS = 5
|
const val LIMIT_KEYS_IN_SIGNATURE_CONSTRAINTS = 5
|
||||||
const val BATCH_DOWNLOAD_COUNTERPARTY_BACKCHAIN = 6
|
const val BATCH_DOWNLOAD_COUNTERPARTY_BACKCHAIN = 6
|
||||||
const val ENABLE_P2P_COMPRESSION = 7
|
const val ENABLE_P2P_COMPRESSION = 7
|
||||||
|
const val RESTRICTED_DATABASE_OPERATIONS = 7
|
||||||
}
|
}
|
@ -4,14 +4,15 @@ import co.paralleluniverse.fibers.Suspendable
|
|||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.flows.InitiatingFlow
|
import net.corda.core.flows.InitiatingFlow
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.internal.PLATFORM_VERSION
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.nodeapi.internal.persistence.RestrictedConnection
|
import net.corda.nodeapi.internal.persistence.RestrictedConnection
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import net.corda.testing.node.MockNetworkParameters
|
import net.corda.testing.node.MockNetworkParameters
|
||||||
import net.corda.testing.node.StartedMockNode
|
import net.corda.testing.node.StartedMockNode
|
||||||
|
import net.corda.testing.node.internal.enclosedCordapp
|
||||||
import org.assertj.core.api.Assertions
|
import org.assertj.core.api.Assertions
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
@ -38,40 +39,63 @@ class RestrictedConnectionFlowTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InitiatingFlow
|
@InitiatingFlow
|
||||||
class TestCloseMethodIsBlocked : FlowLogic<Unit>() {
|
class TestClearWarningsMethodIsBlocked : FlowLogic<Unit>() {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call() {
|
override fun call() {
|
||||||
val connection = serviceHub.jdbcSession()
|
val connection = serviceHub.jdbcSession()
|
||||||
connection.close()
|
connection.clearWarnings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
|
||||||
fun init() {
|
|
||||||
mockNetwork = MockNetwork(MockNetworkParameters())
|
|
||||||
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
@After
|
||||||
fun done() {
|
fun done() {
|
||||||
mockNetwork.stopNodes()
|
mockNetwork.stopNodes()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
@Test(timeout=300_000)
|
||||||
fun testIfItIsRestrictedConnection() {
|
fun `restricted connection is returned from ServiceHub#jdbcSession`() {
|
||||||
|
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION))))
|
||||||
|
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
|
||||||
assertTrue { aliceNode.startFlow(TestIfItIsRestrictedConnection()).get() }
|
assertTrue { aliceNode.startFlow(TestIfItIsRestrictedConnection()).get() }
|
||||||
mockNetwork.runNetwork()
|
mockNetwork.runNetwork()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
@Test(timeout=300_000)
|
||||||
fun testMethodsAreBlocked() {
|
fun `restricted methods are blocked when the target platform is the current corda version`() {
|
||||||
|
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION))))
|
||||||
|
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
|
||||||
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
|
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
|
||||||
.isThrownBy { aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow() }
|
.isThrownBy { aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow() }
|
||||||
.withMessageContaining("This method cannot be called via ServiceHub.jdbcSession.")
|
.withMessageContaining("ServiceHub.jdbcSession.setAutoCommit is restricted and cannot be called")
|
||||||
|
|
||||||
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
|
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
|
||||||
.isThrownBy { aliceNode.startFlow(TestCloseMethodIsBlocked()).getOrThrow() }
|
.isThrownBy { aliceNode.startFlow(TestClearWarningsMethodIsBlocked()).getOrThrow() }
|
||||||
.withMessageContaining("This method cannot be called via ServiceHub.jdbcSession.")
|
.withMessageContaining("ServiceHub.jdbcSession.clearWarnings is restricted and cannot be called")
|
||||||
|
|
||||||
|
mockNetwork.runNetwork()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `restricted methods are blocked when the target platform is 7`() {
|
||||||
|
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 7))))
|
||||||
|
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
|
||||||
|
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
|
||||||
|
.isThrownBy { aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow() }
|
||||||
|
.withMessageContaining("ServiceHub.jdbcSession.setAutoCommit is restricted and cannot be called")
|
||||||
|
|
||||||
|
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
|
||||||
|
.isThrownBy { aliceNode.startFlow(TestClearWarningsMethodIsBlocked()).getOrThrow() }
|
||||||
|
.withMessageContaining("ServiceHub.jdbcSession.clearWarnings is restricted and cannot be called")
|
||||||
|
|
||||||
|
mockNetwork.runNetwork()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `restricted methods are not blocked when the target platform is 6`() {
|
||||||
|
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 6))))
|
||||||
|
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
|
||||||
|
aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow()
|
||||||
|
aliceNode.startFlow(TestClearWarningsMethodIsBlocked()).getOrThrow()
|
||||||
|
|
||||||
mockNetwork.runNetwork()
|
mockNetwork.runNetwork()
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,15 @@ import co.paralleluniverse.fibers.Suspendable
|
|||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.flows.InitiatingFlow
|
import net.corda.core.flows.InitiatingFlow
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.internal.PLATFORM_VERSION
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.nodeapi.internal.persistence.RestrictedEntityManager
|
import net.corda.nodeapi.internal.persistence.RestrictedEntityManager
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import net.corda.testing.node.MockNetworkParameters
|
import net.corda.testing.node.MockNetworkParameters
|
||||||
import net.corda.testing.node.StartedMockNode
|
import net.corda.testing.node.StartedMockNode
|
||||||
|
import net.corda.testing.node.internal.enclosedCordapp
|
||||||
import org.assertj.core.api.Assertions
|
import org.assertj.core.api.Assertions
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ class RestrictedEntityManagerFlowTest {
|
|||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call() : Boolean {
|
override fun call() : Boolean {
|
||||||
var result = false
|
var result = false
|
||||||
serviceHub.withEntityManager() {
|
serviceHub.withEntityManager {
|
||||||
result = this is RestrictedEntityManager
|
result = this is RestrictedEntityManager
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
@ -33,11 +34,11 @@ class RestrictedEntityManagerFlowTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InitiatingFlow
|
@InitiatingFlow
|
||||||
class TestCloseMethodIsBlocked : FlowLogic<Unit>() {
|
class TestGetMetamodelMethodIsBlocked : FlowLogic<Unit>() {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call() {
|
override fun call() {
|
||||||
serviceHub.withEntityManager() {
|
serviceHub.withEntityManager {
|
||||||
this.close()
|
this.metamodel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,38 +47,61 @@ class RestrictedEntityManagerFlowTest {
|
|||||||
class TestJoinTransactionMethodIsBlocked : FlowLogic<Unit>() {
|
class TestJoinTransactionMethodIsBlocked : FlowLogic<Unit>() {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call() {
|
override fun call() {
|
||||||
serviceHub.withEntityManager() {
|
serviceHub.withEntityManager {
|
||||||
this.joinTransaction()
|
this.joinTransaction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
|
||||||
fun init() {
|
|
||||||
mockNetwork = MockNetwork(MockNetworkParameters())
|
|
||||||
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
@After
|
||||||
fun done() {
|
fun done() {
|
||||||
mockNetwork.stopNodes()
|
mockNetwork.stopNodes()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
@Test(timeout=300_000)
|
||||||
fun testIfItIsRestrictedConnection() {
|
fun `restricted connection is returned from ServiceHub#withEntityManager`() {
|
||||||
|
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION))))
|
||||||
|
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
|
||||||
assertTrue { aliceNode.startFlow(TestIfItIsRestrictedEntityManager()).get() }
|
assertTrue { aliceNode.startFlow(TestIfItIsRestrictedEntityManager()).get() }
|
||||||
mockNetwork.runNetwork()
|
mockNetwork.runNetwork()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
@Test(timeout=300_000)
|
||||||
fun testMethodsAreBlocked() {
|
fun `restricted methods are blocked when the target platform is the current corda version`() {
|
||||||
|
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION))))
|
||||||
|
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
|
||||||
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
|
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
|
||||||
.isThrownBy { aliceNode.startFlow(TestCloseMethodIsBlocked()).getOrThrow() }
|
.isThrownBy { aliceNode.startFlow(TestGetMetamodelMethodIsBlocked()).getOrThrow() }
|
||||||
.withMessageContaining("This method cannot be called via ServiceHub.withEntityManager.")
|
.withMessageContaining("ServiceHub.withEntityManager.getMetamodel is restricted and cannot be called")
|
||||||
|
|
||||||
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
|
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
|
||||||
.isThrownBy { aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow() }
|
.isThrownBy { aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow() }
|
||||||
.withMessageContaining("This method cannot be called via ServiceHub.withEntityManager.")
|
.withMessageContaining("ServiceHub.withEntityManager.joinTransaction is restricted and cannot be called")
|
||||||
|
|
||||||
|
mockNetwork.runNetwork()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `restricted methods are blocked when the target platform is 7`() {
|
||||||
|
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 7))))
|
||||||
|
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
|
||||||
|
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
|
||||||
|
.isThrownBy { aliceNode.startFlow(TestGetMetamodelMethodIsBlocked()).getOrThrow() }
|
||||||
|
.withMessageContaining("ServiceHub.withEntityManager.getMetamodel is restricted and cannot be called")
|
||||||
|
|
||||||
|
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
|
||||||
|
.isThrownBy { aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow() }
|
||||||
|
.withMessageContaining("ServiceHub.withEntityManager.joinTransaction is restricted and cannot be called")
|
||||||
|
|
||||||
|
mockNetwork.runNetwork()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `restricted methods are not blocked when the target platform is 6`() {
|
||||||
|
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 6))))
|
||||||
|
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
|
||||||
|
aliceNode.startFlow(TestGetMetamodelMethodIsBlocked()).getOrThrow()
|
||||||
|
aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow()
|
||||||
|
|
||||||
mockNetwork.runNetwork()
|
mockNetwork.runNetwork()
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.corda.nodeapi.internal.persistence
|
package net.corda.nodeapi.internal.persistence
|
||||||
|
|
||||||
|
import net.corda.core.node.ServiceHub
|
||||||
import java.sql.Connection
|
import java.sql.Connection
|
||||||
import java.sql.Savepoint
|
import java.sql.Savepoint
|
||||||
import java.util.concurrent.Executor
|
import java.util.concurrent.Executor
|
||||||
@ -8,73 +9,73 @@ import java.util.concurrent.Executor
|
|||||||
* A delegate of [Connection] which disallows some operations.
|
* A delegate of [Connection] which disallows some operations.
|
||||||
*/
|
*/
|
||||||
@Suppress("TooManyFunctions")
|
@Suppress("TooManyFunctions")
|
||||||
class RestrictedConnection(private val delegate : Connection) : Connection by delegate {
|
class RestrictedConnection(private val delegate: Connection, private val serviceHub: ServiceHub) : Connection by delegate {
|
||||||
|
|
||||||
override fun abort(executor: Executor?) {
|
override fun abort(executor: Executor?) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("abort", serviceHub) { delegate.abort(executor) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clearWarnings() {
|
override fun clearWarnings() {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("clearWarnings", serviceHub) { delegate.clearWarnings() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("close", serviceHub) { delegate.close() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun commit() {
|
override fun commit() {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("commit", serviceHub) { delegate.commit() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setSavepoint(): Savepoint? {
|
override fun setSavepoint(): Savepoint? {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
return restrictDatabaseOperationFromJdbcSession("setSavepoint", serviceHub) { delegate.setSavepoint() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setSavepoint(name : String?): Savepoint? {
|
override fun setSavepoint(name: String?): Savepoint? {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
return restrictDatabaseOperationFromJdbcSession("setSavepoint", serviceHub) { delegate.setSavepoint(name) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun releaseSavepoint(savepoint: Savepoint?) {
|
override fun releaseSavepoint(savepoint: Savepoint?) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("releaseSavepoint", serviceHub) { delegate.releaseSavepoint(savepoint) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun rollback() {
|
override fun rollback() {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("rollback", serviceHub) { delegate.rollback() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun rollback(savepoint: Savepoint?) {
|
override fun rollback(savepoint: Savepoint?) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("rollback", serviceHub) { delegate.rollback(savepoint) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setCatalog(catalog : String?) {
|
override fun setCatalog(catalog: String?) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("setCatalog", serviceHub) { delegate.catalog = catalog }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setTransactionIsolation(level: Int) {
|
override fun setTransactionIsolation(level: Int) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("setTransactionIsolation", serviceHub) { delegate.transactionIsolation = level }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setTypeMap(map: MutableMap<String, Class<*>>?) {
|
override fun setTypeMap(map: MutableMap<String, Class<*>>?) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("setTypeMap", serviceHub) { delegate.typeMap = map }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setHoldability(holdability: Int) {
|
override fun setHoldability(holdability: Int) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("setHoldability", serviceHub) { delegate.holdability = holdability }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setSchema(schema: String?) {
|
override fun setSchema(schema: String?) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("setSchema", serviceHub) { delegate.schema = schema }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setNetworkTimeout(executor: Executor?, milliseconds: Int) {
|
override fun setNetworkTimeout(executor: Executor?, milliseconds: Int) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("setNetworkTimeout", serviceHub) { delegate.setNetworkTimeout(executor, milliseconds) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setAutoCommit(autoCommit: Boolean) {
|
override fun setAutoCommit(autoCommit: Boolean) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("setAutoCommit", serviceHub) { delegate.autoCommit = autoCommit }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setReadOnly(readOnly: Boolean) {
|
override fun setReadOnly(readOnly: Boolean) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.")
|
restrictDatabaseOperationFromJdbcSession("setReadOnly", serviceHub) { delegate.isReadOnly = readOnly }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.corda.nodeapi.internal.persistence
|
||||||
|
|
||||||
|
import net.corda.core.internal.PlatformVersionSwitches.RESTRICTED_DATABASE_OPERATIONS
|
||||||
|
import net.corda.core.internal.warnOnce
|
||||||
|
import net.corda.core.node.ServiceHub
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
private val log = LoggerFactory.getLogger("RestrictedDatabaseOperations")
|
||||||
|
|
||||||
|
internal inline fun <T> restrictDatabaseOperationFromJdbcSession(method: String, serviceHub: ServiceHub, operation: () -> T): T {
|
||||||
|
return restrictDatabaseOperation("ServiceHub.jdbcSession.$method", serviceHub, operation)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline fun <T> restrictDatabaseOperationFromEntityManager(method: String, serviceHub: ServiceHub, operation: () -> T): T {
|
||||||
|
return restrictDatabaseOperation("ServiceHub.withEntityManager.$method", serviceHub, operation)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline fun <T> restrictDatabaseOperation(method: String, serviceHub: ServiceHub, operation: () -> T): T {
|
||||||
|
return if (serviceHub.getAppContext().cordapp.targetPlatformVersion >= RESTRICTED_DATABASE_OPERATIONS) {
|
||||||
|
throw UnsupportedOperationException("$method is restricted and cannot be called")
|
||||||
|
} else {
|
||||||
|
log.warnOnce(
|
||||||
|
"$method should not be called, as manipulating database transactions and connections breaks the Corda flow state machine in " +
|
||||||
|
"ways that only become evident in failure scenarios. Purely for API backwards compatibility reasons, the prior " +
|
||||||
|
"behaviour is continued for target platform versions less than $RESTRICTED_DATABASE_OPERATIONS. You should evolve " +
|
||||||
|
"the CorDapp away from using these problematic APIs as soon as possible. For target platform version of " +
|
||||||
|
"$RESTRICTED_DATABASE_OPERATIONS or above, an exception will be thrown instead."
|
||||||
|
)
|
||||||
|
operation()
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package net.corda.nodeapi.internal.persistence
|
package net.corda.nodeapi.internal.persistence
|
||||||
|
|
||||||
|
import net.corda.core.node.ServiceHub
|
||||||
import javax.persistence.EntityManager
|
import javax.persistence.EntityManager
|
||||||
import javax.persistence.EntityTransaction
|
import javax.persistence.EntityTransaction
|
||||||
import javax.persistence.LockModeType
|
import javax.persistence.LockModeType
|
||||||
@ -8,56 +9,59 @@ import javax.persistence.metamodel.Metamodel
|
|||||||
/**
|
/**
|
||||||
* A delegate of [EntityManager] which disallows some operations.
|
* A delegate of [EntityManager] which disallows some operations.
|
||||||
*/
|
*/
|
||||||
class RestrictedEntityManager(private val delegate: EntityManager) : EntityManager by delegate {
|
class RestrictedEntityManager(private val delegate: EntityManager, private val serviceHub: ServiceHub) : EntityManager by delegate {
|
||||||
|
|
||||||
override fun getTransaction(): EntityTransaction {
|
override fun getTransaction(): EntityTransaction {
|
||||||
return RestrictedEntityTransaction(delegate.transaction)
|
return RestrictedEntityTransaction(delegate.transaction, serviceHub)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.")
|
restrictDatabaseOperationFromEntityManager("close", serviceHub) { delegate.close() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : Any?> unwrap(cls: Class<T>?): T {
|
override fun <T : Any?> unwrap(cls: Class<T>?): T {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.")
|
return restrictDatabaseOperationFromEntityManager("unwrap", serviceHub) { delegate.unwrap(cls) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDelegate(): Any {
|
override fun getDelegate(): Any {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.")
|
return restrictDatabaseOperationFromEntityManager("getDelegate", serviceHub) { delegate.delegate }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMetamodel(): Metamodel? {
|
override fun getMetamodel(): Metamodel? {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.")
|
return restrictDatabaseOperationFromEntityManager("getMetamodel", serviceHub) { delegate.metamodel }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun joinTransaction() {
|
override fun joinTransaction() {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.")
|
restrictDatabaseOperationFromEntityManager("joinTransaction", serviceHub) { delegate.joinTransaction() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun lock(entity: Any?, lockMode: LockModeType?) {
|
override fun lock(entity: Any?, lockMode: LockModeType?) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.")
|
restrictDatabaseOperationFromEntityManager("lock", serviceHub) { delegate.lock(entity, lockMode) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun lock(entity: Any?, lockMode: LockModeType?, properties: MutableMap<String, Any>?) {
|
override fun lock(entity: Any?, lockMode: LockModeType?, properties: MutableMap<String, Any>?) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.")
|
restrictDatabaseOperationFromEntityManager("lock", serviceHub) { delegate.lock(entity, lockMode, properties) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setProperty(propertyName: String?, value: Any?) {
|
override fun setProperty(propertyName: String?, value: Any?) {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.")
|
restrictDatabaseOperationFromEntityManager("lock", serviceHub) { delegate.setProperty(propertyName, value) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RestrictedEntityTransaction(private val delegate: EntityTransaction) : EntityTransaction by delegate {
|
class RestrictedEntityTransaction(
|
||||||
|
private val delegate: EntityTransaction,
|
||||||
|
private val serviceHub: ServiceHub
|
||||||
|
) : EntityTransaction by delegate {
|
||||||
|
|
||||||
override fun rollback() {
|
override fun rollback() {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.")
|
restrictDatabaseOperationFromEntityManager("EntityTransaction.rollback", serviceHub) { delegate.rollback() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun commit() {
|
override fun commit() {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.")
|
restrictDatabaseOperationFromEntityManager("EntityTransaction.commit", serviceHub) { delegate.commit() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun begin() {
|
override fun begin() {
|
||||||
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.")
|
restrictDatabaseOperationFromEntityManager("EntityTransaction.begin", serviceHub) { delegate.begin() }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,104 +1,337 @@
|
|||||||
package net.corda.nodeapi.internal.persistence
|
package net.corda.nodeapi.internal.persistence
|
||||||
|
|
||||||
import com.nhaarman.mockito_kotlin.mock
|
import com.nhaarman.mockito_kotlin.mock
|
||||||
|
import com.nhaarman.mockito_kotlin.whenever
|
||||||
|
import net.corda.core.cordapp.Cordapp
|
||||||
|
import net.corda.core.cordapp.CordappContext
|
||||||
|
import net.corda.core.internal.PLATFORM_VERSION
|
||||||
|
import net.corda.core.node.ServiceHub
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.sql.Connection
|
import java.sql.Connection
|
||||||
import java.sql.Savepoint
|
import java.sql.Savepoint
|
||||||
|
|
||||||
class RestrictedConnectionTest {
|
class RestrictedConnectionTest {
|
||||||
|
|
||||||
private val connection : Connection = mock()
|
private val connection: Connection = mock()
|
||||||
private val savePoint : Savepoint = mock()
|
private val savePoint: Savepoint = mock()
|
||||||
private val restrictedConnection : RestrictedConnection = RestrictedConnection(connection)
|
private val cordapp = mock<Cordapp>()
|
||||||
|
private val cordappContext = CordappContext.create(cordapp, null, javaClass.classLoader, mock())
|
||||||
|
private val serviceHub = mock<ServiceHub>().apply {
|
||||||
|
whenever(getAppContext()).thenReturn(cordappContext)
|
||||||
|
}
|
||||||
|
private val restrictedConnection: RestrictedConnection = RestrictedConnection(connection, serviceHub)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TEST_STRING : String = "test"
|
private const val TEST_STRING: String = "test"
|
||||||
private const val TEST_INT : Int = 1
|
private const val TEST_INT: Int = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testAbort() {
|
fun `abort with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.abort { println("I'm just an executor for this test...") }
|
restrictedConnection.abort { println("I'm just an executor for this test...") }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testClearWarnings() {
|
fun `clearWarnings with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.clearWarnings()
|
restrictedConnection.clearWarnings()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testClose() {
|
fun `close with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.close()
|
restrictedConnection.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testCommit() {
|
fun `commit with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.commit()
|
restrictedConnection.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testSetSavepoint() {
|
fun `setSavepoint with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.setSavepoint()
|
restrictedConnection.setSavepoint()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testSetSavepointWithName() {
|
fun `setSavepoint with name with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.setSavepoint(TEST_STRING)
|
restrictedConnection.setSavepoint(TEST_STRING)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testReleaseSavepoint() {
|
fun `releaseSavepoint with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.releaseSavepoint(savePoint)
|
restrictedConnection.releaseSavepoint(savePoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testRollback() {
|
fun `rollback with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.rollback()
|
restrictedConnection.rollback()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testRollbackWithSavepoint() {
|
fun `rollbackWithSavepoint with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.rollback(savePoint)
|
restrictedConnection.rollback(savePoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testSetCatalog() {
|
fun `setCatalog with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.catalog = TEST_STRING
|
restrictedConnection.catalog = TEST_STRING
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testSetTransactionIsolation() {
|
fun `setTransactionIsolation with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.transactionIsolation = TEST_INT
|
restrictedConnection.transactionIsolation = TEST_INT
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testSetTypeMap() {
|
fun `setTypeMap with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
val map: MutableMap<String, Class<*>> = mutableMapOf()
|
val map: MutableMap<String, Class<*>> = mutableMapOf()
|
||||||
restrictedConnection.typeMap = map
|
restrictedConnection.typeMap = map
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testSetHoldability() {
|
fun `setHoldability with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.holdability = TEST_INT
|
restrictedConnection.holdability = TEST_INT
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testSetSchema() {
|
fun `setSchema with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.schema = TEST_STRING
|
restrictedConnection.schema = TEST_STRING
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testSetNetworkTimeout() {
|
fun `setNetworkTimeout with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT)
|
restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testSetAutoCommit() {
|
fun `setAutoCommit with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedConnection.autoCommit = true
|
restrictedConnection.autoCommit = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testSetReadOnly() {
|
fun `setReadOnly with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
|
restrictedConnection.isReadOnly = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `abort with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.abort { println("I'm just an executor for this test...") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `clearWarnings with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.clearWarnings()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `close with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `commit with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `setSavepoint with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.setSavepoint()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `setSavepoint with name with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.setSavepoint(TEST_STRING)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `releaseSavepoint with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.releaseSavepoint(savePoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `rollback with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.rollback()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `rollbackWithSavepoint with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.rollback(savePoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `setCatalog with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.catalog = TEST_STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `setTransactionIsolation with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.transactionIsolation = TEST_INT
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `setTypeMap with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
val map: MutableMap<String, Class<*>> = mutableMapOf()
|
||||||
|
restrictedConnection.typeMap = map
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `setHoldability with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.holdability = TEST_INT
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `setSchema with target platform version of current 7 unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.schema = TEST_STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `setNetworkTimeout with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `setAutoCommit with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.autoCommit = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `setReadOnly with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedConnection.isReadOnly = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `abort with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.abort { println("I'm just an executor for this test...") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `clearWarnings with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.clearWarnings()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `close with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `commit with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `setSavepoint with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.setSavepoint()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `setSavepoint with name with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.setSavepoint(TEST_STRING)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `releaseSavepoint with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.releaseSavepoint(savePoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `rollback with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.rollback()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `rollbackWithSavepoint with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.rollback(savePoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `setCatalog with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.catalog = TEST_STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `setTransactionIsolation with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.transactionIsolation = TEST_INT
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `setTypeMap with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
val map: MutableMap<String, Class<*>> = mutableMapOf()
|
||||||
|
restrictedConnection.typeMap = map
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `setHoldability with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.holdability = TEST_INT
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `setSchema with target platform version of current 6 unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.schema = TEST_STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `setNetworkTimeout with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `setAutoCommit with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedConnection.autoCommit = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `setReadOnly with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
restrictedConnection.isReadOnly = true
|
restrictedConnection.isReadOnly = true
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,6 +3,10 @@ package net.corda.nodeapi.internal.persistence
|
|||||||
import com.nhaarman.mockito_kotlin.doReturn
|
import com.nhaarman.mockito_kotlin.doReturn
|
||||||
import com.nhaarman.mockito_kotlin.mock
|
import com.nhaarman.mockito_kotlin.mock
|
||||||
import com.nhaarman.mockito_kotlin.whenever
|
import com.nhaarman.mockito_kotlin.whenever
|
||||||
|
import net.corda.core.cordapp.Cordapp
|
||||||
|
import net.corda.core.cordapp.CordappContext
|
||||||
|
import net.corda.core.internal.PLATFORM_VERSION
|
||||||
|
import net.corda.core.node.ServiceHub
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import javax.persistence.EntityManager
|
import javax.persistence.EntityManager
|
||||||
import javax.persistence.EntityTransaction
|
import javax.persistence.EntityTransaction
|
||||||
@ -12,47 +16,160 @@ import kotlin.test.assertTrue
|
|||||||
class RestrictedEntityManagerTest {
|
class RestrictedEntityManagerTest {
|
||||||
private val entitymanager = mock<EntityManager>()
|
private val entitymanager = mock<EntityManager>()
|
||||||
private val transaction = mock<EntityTransaction>()
|
private val transaction = mock<EntityTransaction>()
|
||||||
private val restrictedEntityManager = RestrictedEntityManager(entitymanager)
|
private val cordapp = mock<Cordapp>()
|
||||||
|
private val cordappContext = CordappContext.create(cordapp, null, javaClass.classLoader, mock())
|
||||||
|
private val serviceHub = mock<ServiceHub>().apply {
|
||||||
|
whenever(getAppContext()).thenReturn(cordappContext)
|
||||||
|
}
|
||||||
|
private val restrictedEntityManager = RestrictedEntityManager(entitymanager, serviceHub)
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testClose() {
|
fun `close with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedEntityManager.close()
|
restrictedEntityManager.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout = 300_000)
|
@Test(timeout = 300_000)
|
||||||
fun testClear() {
|
fun `clear with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedEntityManager.clear()
|
restrictedEntityManager.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testGetMetaModel() {
|
fun `getMetaModel with target platform version of current corda version throws unsupported exception`() {
|
||||||
restrictedEntityManager.getMetamodel()
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
|
restrictedEntityManager.metamodel
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout = 300_000)
|
@Test(timeout = 300_000)
|
||||||
fun testGetTransaction() {
|
fun `getTransaction with target platform version of current corda version executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
whenever(entitymanager.transaction).doReturn(transaction)
|
whenever(entitymanager.transaction).doReturn(transaction)
|
||||||
assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction)
|
assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testJoinTransaction() {
|
fun `joinTransaction with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedEntityManager.joinTransaction()
|
restrictedEntityManager.joinTransaction()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testLockWithTwoParameters() {
|
fun `lock with two parameters with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC)
|
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testLockWithThreeParameters() {
|
fun `lock with three parameters with target platform version of current corda version throws unsupported exception`() {
|
||||||
val map: MutableMap<String,Any> = mutableMapOf()
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC,map)
|
val map: MutableMap<String, Any> = mutableMapOf()
|
||||||
|
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC, map)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException::class, timeout=300_000)
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
fun testSetProperty() {
|
fun `setProperty with target platform version of current corda version throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
|
||||||
|
restrictedEntityManager.setProperty("number", 12)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `close with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedEntityManager.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `clear with target platform version of 7 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedEntityManager.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `getMetaModel with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedEntityManager.metamodel
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `getTransaction with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
whenever(entitymanager.transaction).doReturn(transaction)
|
||||||
|
assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `joinTransaction with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedEntityManager.joinTransaction()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `lock with two parameters with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `lock with three parameters with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
val map: MutableMap<String, Any> = mutableMapOf()
|
||||||
|
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
|
||||||
|
fun `setProperty with target platform version of 7 throws unsupported exception`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(7)
|
||||||
|
restrictedEntityManager.setProperty("number", 12)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `close with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedEntityManager.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `clear with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedEntityManager.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `getMetaModel with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedEntityManager.metamodel
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `getTransaction with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
whenever(entitymanager.transaction).doReturn(transaction)
|
||||||
|
assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `joinTransaction with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedEntityManager.joinTransaction()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `lock with two parameters with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `lock with three parameters with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
|
val map: MutableMap<String, Any> = mutableMapOf()
|
||||||
|
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `setProperty with target platform version of 6 executes successfully`() {
|
||||||
|
whenever(cordapp.targetPlatformVersion).thenReturn(6)
|
||||||
restrictedEntityManager.setProperty("number", 12)
|
restrictedEntityManager.setProperty("number", 12)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1273,7 +1273,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
|||||||
/**
|
/**
|
||||||
* Exposes the database connection as a [RestrictedConnection] to the users.
|
* Exposes the database connection as a [RestrictedConnection] to the users.
|
||||||
*/
|
*/
|
||||||
override fun jdbcSession(): Connection = RestrictedConnection(database.createSession())
|
override fun jdbcSession(): Connection = RestrictedConnection(database.createSession(), services)
|
||||||
|
|
||||||
@Suppress("TooGenericExceptionCaught")
|
@Suppress("TooGenericExceptionCaught")
|
||||||
override fun <T : Any?> withEntityManager(block: EntityManager.() -> T): T {
|
override fun <T : Any?> withEntityManager(block: EntityManager.() -> T): T {
|
||||||
@ -1283,7 +1283,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
|||||||
withSavePoint { savepoint ->
|
withSavePoint { savepoint ->
|
||||||
// Restrict what entity manager they can use inside the block
|
// Restrict what entity manager they can use inside the block
|
||||||
try {
|
try {
|
||||||
block(RestrictedEntityManager(manager)).also {
|
block(RestrictedEntityManager(manager, services)).also {
|
||||||
if (!manager.transaction.rollbackOnly) {
|
if (!manager.transaction.rollbackOnly) {
|
||||||
manager.flush()
|
manager.flush()
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user