From cb641eb8c6f48ca31264d8feaefacc2c5704b4bd Mon Sep 17 00:00:00 2001
From: Michael Hoennig <michael@hoennig.de>
Date: Wed, 24 Aug 2022 11:32:51 +0200
Subject: [PATCH] introduce currentTask and ContextBasedTest

---
 sql/24-hs-domain.sql                          |  4 +-
 sql/25-hs-emailaddress.sql                    |  4 +-
 .../hsadminng/context/Context.java            | 10 ++++
 .../rbac/rbacgrant/RbacGrantController.java   |  2 +
 .../rbac/rbacuser/RbacUserController.java     |  4 +-
 .../resources/db/changelog/100-hs-base.sql    |  8 +++
 .../db/changelog/113-hs-customer-rbac.sql     |  3 ++
 .../changelog/138-hs-unixuser-test-data.sql   |  4 +-
 .../hsadminng/context/ContextBasedTest.java   | 38 +++++++++++++
 .../CustomerRepositoryIntegrationTest.java    | 45 +++++-----------
 .../RbacGrantControllerAcceptanceTest.java    | 23 ++++----
 .../RbacGrantRepositoryIntegrationTest.java   | 50 ++++++-----------
 .../RbacUserRepositoryIntegrationTest.java    | 53 +++++++------------
 .../java/net/hostsharing/test/JpaAttempt.java |  3 +-
 14 files changed, 131 insertions(+), 120 deletions(-)
 create mode 100644 src/test/java/net/hostsharing/hsadminng/context/ContextBasedTest.java

diff --git a/sql/24-hs-domain.sql b/sql/24-hs-domain.sql
index ece72c8a..e00a16b7 100644
--- a/sql/24-hs-domain.sql
+++ b/sql/24-hs-domain.sql
@@ -132,9 +132,9 @@ do language plpgsql $$
 
                             select * from package where uuid = uu.packageUuid into pac;
                             pacAdmin = 'admin@' || pac.name || '.example.com';
-                            set local hsadminng.currentUser to pacAdmin;
+                            execute format('set local hsadminng.currentTask to %L', currentTask);
+                            execute format('set local hsadminng.currentUser to %L', pacAdmin);
                             set local hsadminng.assumedRoles = '';
-                            set local hsadminng.currentTask to currentTask;
 
                             insert
                                 into Domain (name, unixUserUuid)
diff --git a/sql/25-hs-emailaddress.sql b/sql/25-hs-emailaddress.sql
index 9aa82621..542766ae 100644
--- a/sql/25-hs-emailaddress.sql
+++ b/sql/25-hs-emailaddress.sql
@@ -114,9 +114,9 @@ do language plpgsql $$
                         raise notice 'task: %', currentTask;
 
                         pacAdmin = 'admin@' || dom.packageName || '.example.com';
-                        set local hsadminng.currentUser to pacAdmin;
+                        execute format('set local hsadminng.currentTask to %L', currentTask);
+                        execute format('set local hsadminng.currentUser to %L', pacAdmin);
                         set local hsadminng.assumedRoles = '';
-                        set local hsadminng.currentTask to currentTask;
 
                         insert
                             into EMailAddress (localPart, domainUuid)
diff --git a/src/main/java/net/hostsharing/hsadminng/context/Context.java b/src/main/java/net/hostsharing/hsadminng/context/Context.java
index 20a40c2a..22a86f72 100644
--- a/src/main/java/net/hostsharing/hsadminng/context/Context.java
+++ b/src/main/java/net/hostsharing/hsadminng/context/Context.java
@@ -14,6 +14,16 @@ public class Context {
     @PersistenceContext
     private EntityManager em;
 
+    @Transactional(propagation = MANDATORY)
+    public void setCurrentTask(final String task) {
+        em.createNativeQuery(
+                String.format(
+                        "set local hsadminng.currentTask = '%s';",
+                        task
+                )
+        ).executeUpdate();
+    }
+
     @Transactional(propagation = MANDATORY)
     public void setCurrentUser(final String userName) {
         em.createNativeQuery(
diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantController.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantController.java
index 9bf51819..5270ec82 100644
--- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantController.java
+++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantController.java
@@ -66,6 +66,7 @@ public class RbacGrantController implements RbacgrantsApi {
             final String assumedRoles,
             final RbacGrantResource body) {
 
+        context.setCurrentTask("granting role to user");
         context.setCurrentUser(currentUser);
         if (assumedRoles != null && !assumedRoles.isBlank()) {
             context.assumeRoles(assumedRoles);
@@ -89,6 +90,7 @@ public class RbacGrantController implements RbacgrantsApi {
             final UUID grantedRoleUuid,
             final UUID granteeUserUuid) {
 
+        context.setCurrentTask("revoking role from user");
         context.setCurrentUser(currentUser);
         if (assumedRoles != null && !assumedRoles.isBlank()) {
             context.assumeRoles(assumedRoles);
diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserController.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserController.java
index a00f30cf..05d172de 100644
--- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserController.java
+++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserController.java
@@ -34,6 +34,8 @@ public class RbacUserController implements RbacusersApi {
     public ResponseEntity<RbacUserResource> createUser(
             @RequestBody final RbacUserResource body
     ) {
+        context.setCurrentTask("creating new user: " + body.getName());
+
         if (body.getUuid() == null) {
             body.setUuid(UUID.randomUUID());
         }
@@ -52,7 +54,7 @@ public class RbacUserController implements RbacusersApi {
             final String currentUser,
             final String assumedRoles,
             final String userName) {
-        return null;
+        return null; // TODO implement getUserById
     }
 
     @Override
diff --git a/src/main/resources/db/changelog/100-hs-base.sql b/src/main/resources/db/changelog/100-hs-base.sql
index 3b8b723f..33a803bb 100644
--- a/src/main/resources/db/changelog/100-hs-base.sql
+++ b/src/main/resources/db/changelog/100-hs-base.sql
@@ -21,6 +21,8 @@ grant select on global to restricted;
 /**
   A single row to be referenced as a global object.
  */
+set local hsadminng.currentUser to 'init';
+set local hsadminng.currentTask to 'initializing table "global"';
 insert
     into RbacObject (objecttable) values ('global');
 insert
@@ -91,6 +93,9 @@ create or replace function hostsharingAdmin()
     language sql as $$
 select 'global', (select uuid from RbacObject where objectTable = 'global'), 'admin'::RbacRoleType;
 $$;
+
+set local hsadminng.currentUser to 'init';
+set local hsadminng.currentTask to 'creating Hostsharing admin role';
 select createRole(hostsharingAdmin());
 
 -- ============================================================================
@@ -103,6 +108,9 @@ do language plpgsql $$
     declare
         admins uuid ;
     begin
+        set local hsadminng.currentUser to 'init';
+        set local hsadminng.currentTask to 'creating fake Hostsharing admin users';
+
         admins = findRoleId(hostsharingAdmin());
         call grantRoleToUserUnchecked(admins, admins, createRbacUser('mike@hostsharing.net'));
         call grantRoleToUserUnchecked(admins, admins, createRbacUser('sven@hostsharing.net'));
diff --git a/src/main/resources/db/changelog/113-hs-customer-rbac.sql b/src/main/resources/db/changelog/113-hs-customer-rbac.sql
index 391cfe5e..8ca69b0d 100644
--- a/src/main/resources/db/changelog/113-hs-customer-rbac.sql
+++ b/src/main/resources/db/changelog/113-hs-customer-rbac.sql
@@ -206,6 +206,9 @@ do language plpgsql $$
         hostsharingObjectUuid  uuid;
         hsAdminRoleUuid        uuid ;
     begin
+        set local hsadminng.currentUser to 'init';
+        set local hsadminng.currentTask to 'granting global add-customer permission to Hostsharing admin role';
+
         hsAdminRoleUuid := findRoleId(hostsharingAdmin());
         hostsharingObjectUuid := (select uuid from global);
         addCustomerPermissions := createPermissions(hostsharingObjectUuid, array ['add-customer']);
diff --git a/src/main/resources/db/changelog/138-hs-unixuser-test-data.sql b/src/main/resources/db/changelog/138-hs-unixuser-test-data.sql
index cc7803f3..b849b91f 100644
--- a/src/main/resources/db/changelog/138-hs-unixuser-test-data.sql
+++ b/src/main/resources/db/changelog/138-hs-unixuser-test-data.sql
@@ -31,9 +31,9 @@ begin
                     currentTask = 'creating RBAC test unixuser #' || t || ' for package ' || pac.name || ' #' || pac.uuid;
                     raise notice 'task: %', currentTask;
                     pacAdmin = 'admin@' || pac.name || '.example.com';
-                    set local hsadminng.currentUser to 'mike@hostsharing.net'; -- TODO: use a package-admin
+                    execute format('set local hsadminng.currentTask to %L', currentTask);
+                    execute format('set local hsadminng.currentUser to %L', pacAdmin);
                     set local hsadminng.assumedRoles = '';
-                    set local hsadminng.currentTask to currentTask;
 
                     insert
                         into unixuser (name, packageUuid)
diff --git a/src/test/java/net/hostsharing/hsadminng/context/ContextBasedTest.java b/src/test/java/net/hostsharing/hsadminng/context/ContextBasedTest.java
new file mode 100644
index 00000000..67340a18
--- /dev/null
+++ b/src/test/java/net/hostsharing/hsadminng/context/ContextBasedTest.java
@@ -0,0 +1,38 @@
+package net.hostsharing.hsadminng.context;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.TestInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ContextBasedTest {
+
+    @Autowired
+    Context context;
+
+    TestInfo test;
+
+    @BeforeEach
+    void init(TestInfo testInfo) {
+        this.test = testInfo;
+    }
+
+    protected void context(final String currentUser, final String assumedRoles) {
+        context.setCurrentTask(test.getDisplayName());
+
+        context.setCurrentUser(currentUser);
+        assertThat(context.getCurrentUser()).as("precondition").isEqualTo(currentUser);
+
+        if (assumedRoles != null) {
+            context.assumeRoles(assumedRoles);
+            assertThat(context.getAssumedRoles()).as("precondition").containsExactly(assumedRoles.split(";"));
+//        } else {
+//            context.assumeNoSpecialRole();
+        }
+    }
+
+    protected void context(final String currentUser) {
+        context(currentUser, null);
+    }
+}
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hscustomer/CustomerRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hscustomer/CustomerRepositoryIntegrationTest.java
index 6ac1d1bf..a8c60a82 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/hscustomer/CustomerRepositoryIntegrationTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/hscustomer/CustomerRepositoryIntegrationTest.java
@@ -1,6 +1,7 @@
 package net.hostsharing.hsadminng.hs.hscustomer;
 
 import net.hostsharing.hsadminng.context.Context;
+import net.hostsharing.hsadminng.context.ContextBasedTest;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -21,10 +22,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 @DataJpaTest
 @ComponentScan(basePackageClasses = { Context.class, CustomerRepository.class })
 @DirtiesContext
-class CustomerRepositoryIntegrationTest {
-
-    @Autowired
-    Context context;
+class CustomerRepositoryIntegrationTest extends ContextBasedTest {
 
     @Autowired
     CustomerRepository customerRepository;
@@ -37,7 +35,7 @@ class CustomerRepositoryIntegrationTest {
         @Test
         public void hostsharingAdmin_withoutAssumedRole_canCreateNewCustomer() {
             // given
-            currentUser("mike@hostsharing.net");
+            context("mike@hostsharing.net", null);
             final var count = customerRepository.count();
 
             // when
@@ -58,8 +56,7 @@ class CustomerRepositoryIntegrationTest {
         @Test
         public void hostsharingAdmin_withAssumedCustomerRole_cannotCreateNewCustomer() {
             // given
-            currentUser("mike@hostsharing.net");
-            assumedRoles("customer#aaa.admin");
+            context("mike@hostsharing.net", "customer#aaa.admin");
 
             // when
             final var result = attempt(em, () -> {
@@ -77,7 +74,7 @@ class CustomerRepositoryIntegrationTest {
         @Test
         public void customerAdmin_withoutAssumedRole_cannotCreateNewCustomer() {
             // given
-            currentUser("admin@aaa.example.com");
+            context("admin@aaa.example.com", null);
 
             // when
             final var result = attempt(em, () -> {
@@ -105,7 +102,7 @@ class CustomerRepositoryIntegrationTest {
         @Test
         public void hostsharingAdmin_withoutAssumedRole_canViewAllCustomers() {
             // given
-            currentUser("mike@hostsharing.net");
+            context("mike@hostsharing.net", null);
 
             // when
             final var result = customerRepository.findCustomerByOptionalPrefixLike(null);
@@ -117,8 +114,7 @@ class CustomerRepositoryIntegrationTest {
         @Test
         public void hostsharingAdmin_withAssumedHostsharingAdminRole_canViewAllCustomers() {
             given:
-            currentUser("mike@hostsharing.net");
-            assumedRoles("global#hostsharing.admin");
+            context("mike@hostsharing.net", "global#hostsharing.admin");
 
             // when
             final var result = customerRepository.findCustomerByOptionalPrefixLike(null);
@@ -130,7 +126,7 @@ class CustomerRepositoryIntegrationTest {
         @Test
         public void customerAdmin_withoutAssumedRole_canViewOnlyItsOwnCustomer() {
             // given:
-            currentUser("admin@aaa.example.com");
+            context("admin@aaa.example.com", null);
 
             // when:
             final var result = customerRepository.findCustomerByOptionalPrefixLike(null);
@@ -141,8 +137,7 @@ class CustomerRepositoryIntegrationTest {
 
         @Test
         public void customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyItsOwnCustomer() {
-            currentUser("admin@aaa.example.com");
-            assumedRoles("package#aaa00.admin");
+            context("admin@aaa.example.com", "package#aaa00.admin");
 
             final var result = customerRepository.findCustomerByOptionalPrefixLike(null);
 
@@ -152,8 +147,7 @@ class CustomerRepositoryIntegrationTest {
         @Test
         public void customerAdmin_withAssumedAlienPackageAdminRole_cannotViewAnyCustomer() {
             // given:
-            currentUser("admin@aaa.example.com");
-            assumedRoles("package#aab00.admin");
+            context("admin@aaa.example.com", "package#aab00.admin");
 
             // when
             final var result = attempt(
@@ -168,7 +162,7 @@ class CustomerRepositoryIntegrationTest {
 
         @Test
         void unknownUser_withoutAssumedRole_cannotViewAnyCustomers() {
-            currentUser("unknown@example.org");
+            context("unknown@example.org", null);
 
             final var result = attempt(
                 em,
@@ -182,8 +176,7 @@ class CustomerRepositoryIntegrationTest {
         @Test
         @Transactional
         void unknownUser_withAssumedCustomerRole_cannotViewAnyCustomers() {
-            currentUser("unknown@example.org");
-            assumedRoles("customer#aaa.admin");
+            context("unknown@example.org", "customer#aaa.admin");
 
             final var result = attempt(
                 em,
@@ -202,7 +195,7 @@ class CustomerRepositoryIntegrationTest {
         @Test
         public void hostsharingAdmin_withoutAssumedRole_canViewAllCustomers() {
             // given
-            currentUser("mike@hostsharing.net");
+            context("mike@hostsharing.net", null);
 
             // when
             final var result = customerRepository.findCustomerByOptionalPrefixLike("aab");
@@ -214,7 +207,7 @@ class CustomerRepositoryIntegrationTest {
         @Test
         public void customerAdmin_withoutAssumedRole_canViewOnlyItsOwnCustomer() {
             // given:
-            currentUser("admin@aaa.example.com");
+            context("admin@aaa.example.com", null);
 
             // when:
             final var result = customerRepository.findCustomerByOptionalPrefixLike("aab");
@@ -224,16 +217,6 @@ class CustomerRepositoryIntegrationTest {
         }
     }
 
-    void currentUser(final String currentUser) {
-        context.setCurrentUser(currentUser);
-        assertThat(context.getCurrentUser()).as("precondition").isEqualTo(currentUser);
-    }
-
-    void assumedRoles(final String assumedRoles) {
-        context.assumeRoles(assumedRoles);
-        assertThat(context.getAssumedRoles()).as("precondition").containsExactly(assumedRoles.split(";"));
-    }
-
     void exactlyTheseCustomersAreReturned(final List<CustomerEntity> actualResult, final String... customerPrefixes) {
         assertThat(actualResult)
             .hasSize(customerPrefixes.length)
diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantControllerAcceptanceTest.java
index b3fe77f2..7fc99c39 100644
--- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantControllerAcceptanceTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantControllerAcceptanceTest.java
@@ -5,7 +5,7 @@ import io.restassured.http.ContentType;
 import io.restassured.response.ValidatableResponse;
 import net.hostsharing.hsadminng.Accepts;
 import net.hostsharing.hsadminng.HsadminNgApplication;
-import net.hostsharing.hsadminng.context.Context;
+import net.hostsharing.hsadminng.context.ContextBasedTest;
 import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleEntity;
 import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository;
 import net.hostsharing.hsadminng.rbac.rbacuser.RbacUserEntity;
@@ -35,7 +35,7 @@ import static org.hamcrest.CoreMatchers.is;
 )
 @Accepts({ "GRT:S(Schema)" })
 @Transactional(readOnly = true, propagation = Propagation.NEVER)
-class RbacGrantControllerAcceptanceTest {
+class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
 
     @LocalServerPort
     Integer port;
@@ -43,9 +43,6 @@ class RbacGrantControllerAcceptanceTest {
     @Autowired
     EntityManager em;
 
-    @Autowired
-    Context context;
-
     @Autowired
     RbacUserRepository rbacUserRepository;
 
@@ -360,29 +357,29 @@ class RbacGrantControllerAcceptanceTest {
 
     List<RbacGrantEntity> findAllGrantsOf(final Subject grantingSubject) {
         return jpaAttempt.transacted(() -> {
-            context.setCurrentUser(grantingSubject.currentUser);
+            context(grantingSubject.currentUser, null);
             return rbacGrantRepository.findAll();
         }).returnedValue();
     }
 
     RbacUserEntity createRBacUser() {
-        return jpaAttempt.transacted(() ->
-                rbacUserRepository.create(new RbacUserEntity(
-                        UUID.randomUUID(),
-                        "test-user-" + RandomStringUtils.randomAlphabetic(8) + "@example.com"))
-        ).returnedValue();
+        return jpaAttempt.transacted(() -> {
+            final String newUserName = "test-user-" + RandomStringUtils.randomAlphabetic(8) + "@example.com";
+            context(newUserName, null);
+            return rbacUserRepository.create(new RbacUserEntity(UUID.randomUUID(), newUserName));
+        }).returnedValue();
     }
 
     RbacUserEntity findRbacUserByName(final String userName) {
         return jpaAttempt.transacted(() -> {
-            context.setCurrentUser("mike@hostsharing.net");
+            context("mike@hostsharing.net", null);
             return rbacUserRepository.findByName(userName);
         }).returnedValue();
     }
 
     RbacRoleEntity findRbacRoleByName(final String roleName) {
         return jpaAttempt.transacted(() -> {
-            context.setCurrentUser("mike@hostsharing.net");
+            context("mike@hostsharing.net", null);
             return rbacRoleRepository.findByRoleName(roleName);
         }).returnedValue();
     }
diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantRepositoryIntegrationTest.java
index 41ff47a8..18f847d3 100644
--- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantRepositoryIntegrationTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantRepositoryIntegrationTest.java
@@ -2,6 +2,7 @@ package net.hostsharing.hsadminng.rbac.rbacgrant;
 
 import net.hostsharing.hsadminng.Accepts;
 import net.hostsharing.hsadminng.context.Context;
+import net.hostsharing.hsadminng.context.ContextBasedTest;
 import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository;
 import net.hostsharing.hsadminng.rbac.rbacuser.RbacUserEntity;
 import net.hostsharing.hsadminng.rbac.rbacuser.RbacUserRepository;
@@ -27,7 +28,7 @@ import static org.assertj.core.api.Assumptions.assumeThat;
 @DataJpaTest
 @ComponentScan(basePackageClasses = { RbacGrantRepository.class, Context.class, JpaAttempt.class })
 @DirtiesContext
-class RbacGrantRepositoryIntegrationTest {
+class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
 
     @Autowired
     Context context;
@@ -54,7 +55,7 @@ class RbacGrantRepositoryIntegrationTest {
         @Accepts({ "GRT:L(List)" })
         public void packageAdmin_canViewItsRbacGrants() {
             // given
-            currentUser("aaa00@aaa.example.com");
+            context("aaa00@aaa.example.com", null);
 
             // when
             final var result = rbacGrantRepository.findAll();
@@ -69,7 +70,7 @@ class RbacGrantRepositoryIntegrationTest {
         @Accepts({ "GRT:L(List)" })
         public void customerAdmin_canViewItsRbacGrants() {
             // given
-            currentUser("admin@aaa.example.com");
+            context("admin@aaa.example.com", null);
 
             // when
             final var result = rbacGrantRepository.findAll();
@@ -87,8 +88,7 @@ class RbacGrantRepositoryIntegrationTest {
         @Accepts({ "GRT:L(List)" })
         public void customerAdmin_withAssumedRole_canOnlyViewRbacGrantsVisibleByAssumedRole() {
             // given:
-            currentUser("admin@aaa.example.com");
-            assumedRoles("package#aaa00.admin");
+            context("admin@aaa.example.com", "package#aaa00.admin");
 
             // when
             final var result = rbacGrantRepository.findAll();
@@ -106,8 +106,7 @@ class RbacGrantRepositoryIntegrationTest {
         @Test
         public void customerAdmin_canGrantOwnPackageAdminRole_toArbitraryUser() {
             // given
-            currentUser("admin@aaa.example.com");
-            assumedRoles("customer#aaa.admin");
+            context("admin@aaa.example.com", "customer#aaa.admin");
             final var givenArbitraryUserUuid = rbacUserRepository.findByName("aac00@aac.example.com").getUuid();
             final var givenOwnPackageRoleUuid = rbacRoleRepository.findByRoleName("package#aaa00.admin").getUuid();
 
@@ -135,18 +134,17 @@ class RbacGrantRepositoryIntegrationTest {
             record Given(RbacUserEntity arbitraryUser, UUID packageOwnerRoleUuid) {}
             final var given = jpaAttempt.transacted(() -> {
                 // to find the uuids of we need to have access rights to these
-                currentUser("admin@aaa.example.com");
+                context("admin@aaa.example.com", null);
                 return new Given(
                         createNewUser(),
                         rbacRoleRepository.findByRoleName("package#aaa00.owner").getUuid()
                 );
-            }).returnedValue();
+            }).assumeSuccessful().returnedValue();
 
             // when
             final var attempt = jpaAttempt.transacted(() -> {
                 // now we try to use these uuids as a less privileged user
-                currentUser("aaa00@aaa.example.com");
-                assumedRoles("package#aaa00.admin");
+                context("aaa00@aaa.example.com", "package#aaa00.admin");
                 final var grant = RbacGrantEntity.builder()
                         .granteeUserUuid(given.arbitraryUser.getUuid())
                         .grantedRoleUuid(given.packageOwnerRoleUuid)
@@ -162,7 +160,7 @@ class RbacGrantRepositoryIntegrationTest {
                             + " forbidden for {package#aaa00.admin}");
             jpaAttempt.transacted(() -> {
                 // finally, we use the new user to make sure, no roles were granted
-                currentUser(given.arbitraryUser.getName());
+                context(given.arbitraryUser.getName(), null);
                 assertThat(rbacGrantRepository.findAll())
                         .extracting(RbacGrantEntity::toDisplay)
                         .hasSize(0);
@@ -181,15 +179,13 @@ class RbacGrantRepositoryIntegrationTest {
                     .grantingRole("package#aaa00.admin").toUser("aac00@aac.example.com"));
 
             // when
-            currentUser("admin@aaa.example.com");
-            assumedRoles("customer#aaa.admin");
+            context("admin@aaa.example.com", "customer#aaa.admin");
             final var revokeAttempt = attempt(em, () -> {
                 rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId());
             });
 
             // then
-            currentUser("admin@aaa.example.com");
-            assumedRoles("customer#aaa.admin");
+            context("admin@aaa.example.com", "customer#aaa.admin");
             assertThat(revokeAttempt.caughtExceptionsRootCause()).isNull();
             assertThat(rbacGrantRepository.findAll())
                     .extracting(RbacGrantEntity::getGranteeUserName)
@@ -204,16 +200,14 @@ class RbacGrantRepositoryIntegrationTest {
                     .grantingRole("package#aaa00.admin").toUser(createNewUser().getName()));
 
             // when
-            currentUser("aaa00@aaa.example.com");
-            assumedRoles("package#aaa00.admin");
+            context("aaa00@aaa.example.com", "package#aaa00.admin");
             final var revokeAttempt = attempt(em, () -> {
                 rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId());
             });
 
             // then
             assertThat(revokeAttempt.caughtExceptionsRootCause()).isNull();
-            currentUser("admin@aaa.example.com");
-            assumedRoles("customer#aaa.admin");
+            context("admin@aaa.example.com", "customer#aaa.admin");
             assertThat(rbacGrantRepository.findAll())
                     .extracting(RbacGrantEntity::getGranteeUserName)
                     .doesNotContain("aac00@aac.example.com");
@@ -228,8 +222,7 @@ class RbacGrantRepositoryIntegrationTest {
             final var grantedByRole = rbacRoleRepository.findByRoleName("package#aaa00.owner");
 
             // when
-            currentUser("aaa00@aaa.example.com");
-            assumedRoles("package#aaa00.admin");
+            context("aaa00@aaa.example.com", "package#aaa00.admin");
             final var revokeAttempt = attempt(em, () -> {
                 rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId());
             });
@@ -243,8 +236,7 @@ class RbacGrantRepositoryIntegrationTest {
         }
 
         private RbacGrantEntity create(GrantBuilder with) {
-            currentUser(with.byUserName);
-            assumedRoles(with.assumedRole);
+            context(with.byUserName, with.assumedRole);
             final var givenArbitraryUserUuid = rbacUserRepository.findByName(with.granteeUserName).getUuid();
             final var givenOwnPackageRoleUuid = rbacRoleRepository.findByRoleName(with.grantedRole).getUuid();
 
@@ -304,16 +296,6 @@ class RbacGrantRepositoryIntegrationTest {
                 new RbacUserEntity(null, "test-user-" + System.currentTimeMillis() + "@example.com"));
     }
 
-    void currentUser(final String currentUser) {
-        context.setCurrentUser(currentUser);
-        assertThat(context.getCurrentUser()).as("precondition").isEqualTo(currentUser);
-    }
-
-    void assumedRoles(final String assumedRoles) {
-        context.assumeRoles(assumedRoles);
-        assertThat(context.getAssumedRoles()).as("precondition").containsExactly(assumedRoles.split(";"));
-    }
-
     void exactlyTheseRbacGrantsAreReturned(final List<RbacGrantEntity> actualResult, final String... expectedGrant) {
         assertThat(actualResult)
                 .filteredOn(g -> !g.getGranteeUserName().startsWith("test-user-")) // ignore test-users created by other tests
diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserRepositoryIntegrationTest.java
index 2a3ac1c9..c9042fcc 100644
--- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserRepositoryIntegrationTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserRepositoryIntegrationTest.java
@@ -1,6 +1,7 @@
 package net.hostsharing.hsadminng.rbac.rbacuser;
 
 import net.hostsharing.hsadminng.context.Context;
+import net.hostsharing.hsadminng.context.ContextBasedTest;
 import net.hostsharing.test.Array;
 import net.hostsharing.test.JpaAttempt;
 import org.junit.jupiter.api.Nested;
@@ -23,10 +24,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 @DataJpaTest
 @ComponentScan(basePackageClasses = { RbacUserRepository.class, Context.class, JpaAttempt.class })
 @DirtiesContext
-class RbacUserRepositoryIntegrationTest {
-
-    @Autowired
-    Context context;
+class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
 
     @Autowired
     RbacUserRepository rbacUserRepository;
@@ -43,6 +41,7 @@ class RbacUserRepositoryIntegrationTest {
         public void anyoneCanCreateTheirOwnUser() {
             // given
             final var givenNewUserName = "test-user-" + System.currentTimeMillis() + "@example.com";
+            context(givenNewUserName, null);
 
             // when
             final var result = rbacUserRepository.create(
@@ -52,7 +51,7 @@ class RbacUserRepositoryIntegrationTest {
             assertThat(result).isNotNull().extracting(RbacUserEntity::getName).isEqualTo(givenNewUserName);
 
             // and the new user entity can be fetched by the user itself
-            currentUser(givenNewUserName);
+            context(givenNewUserName);
             assertThat(em.find(RbacUserEntity.class, result.getUuid()))
                 .isNotNull().extracting(RbacUserEntity::getName).isEqualTo(givenNewUserName);
         }
@@ -67,7 +66,7 @@ class RbacUserRepositoryIntegrationTest {
 
             // when:
             final var result = jpaAttempt.transacted(() -> {
-                currentUser("admin@aaa.example.com");
+                context("admin@aaa.example.com");
                 return rbacUserRepository.create(new RbacUserEntity(givenUuid, newUserName));
             });
 
@@ -76,7 +75,7 @@ class RbacUserRepositoryIntegrationTest {
             assertThat(result.returnedValue()).isNotNull()
                 .extracting(RbacUserEntity::getUuid).isEqualTo(givenUuid);
             jpaAttempt.transacted(() -> {
-                currentUser(newUserName);
+                context(newUserName);
                 assertThat(em.find(RbacUserEntity.class, givenUuid))
                     .isNotNull().extracting(RbacUserEntity::getName).isEqualTo(newUserName);
             });
@@ -101,7 +100,7 @@ class RbacUserRepositoryIntegrationTest {
         @Test
         public void hostsharingAdmin_withoutAssumedRole_canViewAllRbacUsers() {
             // given
-            currentUser("mike@hostsharing.net");
+            context("mike@hostsharing.net");
 
             // when
             final var result = rbacUserRepository.findByOptionalNameLike(null);
@@ -113,8 +112,7 @@ class RbacUserRepositoryIntegrationTest {
         @Test
         public void hostsharingAdmin_withAssumedHostsharingAdminRole_canViewAllRbacUsers() {
             given:
-            currentUser("mike@hostsharing.net");
-            assumedRoles("global#hostsharing.admin");
+            context("mike@hostsharing.net", "global#hostsharing.admin");
 
             // when
             final var result = rbacUserRepository.findByOptionalNameLike(null);
@@ -126,8 +124,7 @@ class RbacUserRepositoryIntegrationTest {
         @Test
         public void hostsharingAdmin_withAssumedCustomerAdminRole_canViewOnlyUsersHavingRolesInThatCustomersRealm() {
             given:
-            currentUser("mike@hostsharing.net");
-            assumedRoles("customer#aaa.admin");
+            context("mike@hostsharing.net", "customer#aaa.admin");
 
             // when
             final var result = rbacUserRepository.findByOptionalNameLike(null);
@@ -143,7 +140,7 @@ class RbacUserRepositoryIntegrationTest {
         @Test
         public void customerAdmin_withoutAssumedRole_canViewOnlyUsersHavingRolesInThatCustomersRealm() {
             // given:
-            currentUser("admin@aaa.example.com");
+            context("admin@aaa.example.com");
 
             // when:
             final var result = rbacUserRepository.findByOptionalNameLike(null);
@@ -158,8 +155,7 @@ class RbacUserRepositoryIntegrationTest {
 
         @Test
         public void customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyUsersHavingRolesInThatPackage() {
-            currentUser("admin@aaa.example.com");
-            assumedRoles("package#aaa00.admin");
+            context("admin@aaa.example.com", "package#aaa00.admin");
 
             final var result = rbacUserRepository.findByOptionalNameLike(null);
 
@@ -168,7 +164,7 @@ class RbacUserRepositoryIntegrationTest {
 
         @Test
         public void packageAdmin_withoutAssumedRole_canViewOnlyUsersHavingRolesInThatPackage() {
-            currentUser("aaa00@aaa.example.com");
+            context("aaa00@aaa.example.com");
 
             final var result = rbacUserRepository.findByOptionalNameLike(null);
 
@@ -231,7 +227,7 @@ class RbacUserRepositoryIntegrationTest {
         @Test
         public void hostsharingAdmin_withoutAssumedRole_canViewTheirOwnPermissions() {
             // given
-            currentUser("mike@hostsharing.net");
+            context("mike@hostsharing.net");
 
             // when
             final var result = rbacUserRepository.findPermissionsOfUser("mike@hostsharing.net");
@@ -243,8 +239,7 @@ class RbacUserRepositoryIntegrationTest {
         @Test
         public void hostsharingAdmin_withAssumedHostmastersRole_willThrowException() {
             // given
-            currentUser("mike@hostsharing.net");
-            assumedRoles("global#hostsharing.admin");
+            context("mike@hostsharing.net", "global#hostsharing.admin");
 
             // when
             final var result = attempt(em, () ->
@@ -260,7 +255,7 @@ class RbacUserRepositoryIntegrationTest {
         @Test
         public void customerAdmin_withoutAssumedRole_canViewTheirOwnPermissions() {
             // given
-            currentUser("admin@aaa.example.com");
+            context("admin@aaa.example.com");
 
             // when
             final var result = rbacUserRepository.findPermissionsOfUser("admin@aaa.example.com");
@@ -302,7 +297,7 @@ class RbacUserRepositoryIntegrationTest {
         @Test
         public void customerAdmin_withoutAssumedRole_isNotAllowedToViewGlobalAdminsPermissions() {
             // given
-            currentUser("admin@aaa.example.com");
+            context("admin@aaa.example.com");
 
             // when
             final var result = attempt(em, () ->
@@ -318,7 +313,7 @@ class RbacUserRepositoryIntegrationTest {
         @Test
         public void customerAdmin_withoutAssumedRole_canViewAllPermissionsWithinThePacketsRealm() {
             // given
-            currentUser("admin@aaa.example.com");
+            context("admin@aaa.example.com");
 
             // when
             final var result = rbacUserRepository.findPermissionsOfUser("aaa00@aaa.example.com");
@@ -354,7 +349,7 @@ class RbacUserRepositoryIntegrationTest {
         @Test
         public void customerAdmin_withoutAssumedRole_canNotViewPermissionsOfUnrelatedUsers() {
             // given
-            currentUser("admin@aaa.example.com");
+            context("admin@aaa.example.com");
 
             // when
             final var result = rbacUserRepository.findPermissionsOfUser("aab00@aab.example.com");
@@ -366,7 +361,7 @@ class RbacUserRepositoryIntegrationTest {
         @Test
         public void packetAdmin_withoutAssumedRole_canViewAllPermissionsWithinThePacketsRealm() {
             // given
-            currentUser("aaa00@aaa.example.com");
+            context("aaa00@aaa.example.com");
 
             // when
             final var result = rbacUserRepository.findPermissionsOfUser("aaa00@aaa.example.com");
@@ -401,16 +396,6 @@ class RbacUserRepositoryIntegrationTest {
         }
     }
 
-    void currentUser(final String currentUser) {
-        context.setCurrentUser(currentUser);
-        assertThat(context.getCurrentUser()).as("precondition").isEqualTo(currentUser);
-    }
-
-    void assumedRoles(final String assumedRoles) {
-        context.assumeRoles(assumedRoles);
-        assertThat(context.getAssumedRoles()).as("precondition").containsExactly(assumedRoles.split(";"));
-    }
-
     void exactlyTheseRbacUsersAreReturned(final List<RbacUserEntity> actualResult, final String... expectedUserNames) {
         assertThat(actualResult)
             .filteredOn(u -> !u.getName().startsWith("test-user-"))
diff --git a/src/test/java/net/hostsharing/test/JpaAttempt.java b/src/test/java/net/hostsharing/test/JpaAttempt.java
index 83c9fe6e..4c66d7b3 100644
--- a/src/test/java/net/hostsharing/test/JpaAttempt.java
+++ b/src/test/java/net/hostsharing/test/JpaAttempt.java
@@ -132,8 +132,9 @@ public class JpaAttempt {
             }
         }
 
-        public void assertSuccessful() {
+        public JpaResult<T> assumeSuccessful() {
             assertThat(exception).isNull();;
+            return this;
         }
 
         private String firstRootCauseMessageLineOf(final RuntimeException exception) {