real rbac-entities in booking+hosting #89

Merged
hsh-michaelhoennig merged 15 commits from real-and-rbac-entities-everywhere into master 2024-08-21 06:18:38 +02:00
4 changed files with 104 additions and 29 deletions
Showing only changes of commit f7c55ea3c8 - Show all commits

View File

@ -6,7 +6,8 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public interface HsBookingProjectRbacRepository extends Repository<HsBookingProjectRbacEntity, UUID> { public interface HsBookingProjectRbacRepository extends HsBookingProjectRepository<HsBookingProjectRbacEntity>,
Repository<HsBookingProjectRbacEntity, UUID> {
Optional<HsBookingProjectRbacEntity> findByUuid(final UUID bookingProjectUuid); Optional<HsBookingProjectRbacEntity> findByUuid(final UUID bookingProjectUuid);
List<HsBookingProjectRbacEntity> findByCaption(final String projectCaption); List<HsBookingProjectRbacEntity> findByCaption(final String projectCaption);

View File

@ -6,7 +6,8 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public interface HsBookingProjectRealRepository extends Repository<HsBookingProjectRealEntity, UUID> { public interface HsBookingProjectRealRepository extends HsBookingProjectRepository<HsBookingProjectRealEntity>,
Repository<HsBookingProjectRealEntity, UUID> {
Optional<HsBookingProjectRealEntity> findByUuid(final UUID bookingProjectUuid); Optional<HsBookingProjectRealEntity> findByUuid(final UUID bookingProjectUuid);
List<HsBookingProjectRealEntity> findByCaption(final String projectCaption); List<HsBookingProjectRealEntity> findByCaption(final String projectCaption);

View File

@ -0,0 +1,19 @@
package net.hostsharing.hsadminng.hs.booking.project;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
public interface HsBookingProjectRepository<E extends HsBookingProject> {
Optional<E> findByUuid(final UUID bookingProjectUuid);
List<E> findByCaption(final String projectCaption);
List<E> findAllByDebitorUuid(final UUID bookingProjectUuid);
E save(E current);
int deleteByUuid(final UUID uuid);
long count();
}

View File

@ -9,6 +9,8 @@ import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup;
import net.hostsharing.hsadminng.rbac.test.JpaAttempt; import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
@ -29,7 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest @DataJpaTest
@Import({ Context.class, JpaAttempt.class }) @Import({ Context.class, JpaAttempt.class })
class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWithCleanup { class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithCleanup {
@Autowired @Autowired
HsBookingProjectRealRepository realProjectRepo; HsBookingProjectRealRepository realProjectRepo;
@ -58,8 +60,9 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
@Nested @Nested
class CreateBookingProject { class CreateBookingProject {
@Test @ParameterizedTest
public void testHostsharingAdmin_withoutAssumedRole_canCreateNewBookingProject() { @EnumSource(TestCase.class)
public void testHostsharingAdmin_withoutAssumedRole_canCreateNewBookingProject(final TestCase testCase) {
// given // given
context("superuser-alex@hostsharing.net"); // TODO.test: remove once we have a realDebitorRepo context("superuser-alex@hostsharing.net"); // TODO.test: remove once we have a realDebitorRepo
final var count = realProjectRepo.count(); final var count = realProjectRepo.count();
@ -71,7 +74,7 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
.debitor(givenDebitor) .debitor(givenDebitor)
.caption("some new booking project") .caption("some new booking project")
.build(); .build();
return toCleanup(rbacProjectRepo.save(newBookingProject)); return toCleanup(repoUnderTest(testCase).save(newBookingProject));
}); });
// then // then
@ -81,8 +84,9 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
assertThat(realProjectRepo.count()).isEqualTo(count + 1); assertThat(realProjectRepo.count()).isEqualTo(count + 1);
} }
@Test @ParameterizedTest
public void createsAndGrantsRoles() { @EnumSource(TestCase.class)
public void createsAndGrantsRoles(final TestCase testCase) {
// given // given
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll()); final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll());
@ -97,7 +101,7 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
.debitor(givenDebitor) .debitor(givenDebitor)
.caption("some new booking project") .caption("some new booking project")
.build(); .build();
return toCleanup(rbacProjectRepo.save(newBookingProject)); return toCleanup(repoUnderTest(testCase).save(newBookingProject));
}); });
// then // then
@ -144,15 +148,16 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
@Nested @Nested
class FindByDebitorUuid { class FindByDebitorUuid {
@Test @ParameterizedTest
public void globalAdmin_withoutAssumedRole_canViewAllBookingProjectsOfArbitraryDebitor() { @EnumSource(TestCase.class)
public void globalAdmin_withoutAssumedRole_canViewAllBookingProjectsOfArbitraryDebitor(final TestCase testCase) {
// given // given
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
final var debitorUuid = debitorRepo.findByDebitorNumber(1000212).stream() final var debitorUuid = debitorRepo.findByDebitorNumber(1000212).stream()
.findAny().orElseThrow().getUuid(); .findAny().orElseThrow().getUuid();
// when // when
final var result = rbacProjectRepo.findAllByDebitorUuid(debitorUuid); final var result = repoUnderTest(testCase).findAllByDebitorUuid(debitorUuid);
// then // then
allTheseBookingProjectsAreReturned( allTheseBookingProjectsAreReturned(
@ -160,8 +165,9 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
"HsBookingProject(D-1000212, D-1000212 default project)"); "HsBookingProject(D-1000212, D-1000212 default project)");
} }
@Test @ParameterizedTest
public void packetAgent_canViewOnlyRelatedBookingProjects() { @EnumSource(TestCase.class)
public void packetAgent_canViewOnlyRelatedBookingProjects(final TestCase testCase) {
// given: // given:
context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT"); context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT");
@ -169,11 +175,10 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
.findAny().orElseThrow().getUuid(); .findAny().orElseThrow().getUuid();
// when: // when:
final var result = rbacProjectRepo.findAllByDebitorUuid(debitorUuid); final var result = repoUnderTest(testCase).findAllByDebitorUuid(debitorUuid);
// then: // then:
exactlyTheseBookingProjectsAreReturned( assertResult(testCase, result,
result,
"HsBookingProject(D-1000111, D-1000111 default project)"); "HsBookingProject(D-1000111, D-1000111 default project)");
} }
} }
@ -181,8 +186,9 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
@Nested @Nested
class UpdateBookingProject { class UpdateBookingProject {
@Test @ParameterizedTest
public void bookingProjectAdmin_canUpdateArbitraryBookingProject() { @EnumSource(TestCase.class)
public void bookingProjectAdmin_canUpdateArbitraryBookingProject(final TestCase testCase) {
// given // given
final var givenBookingProjectUuid = givenSomeTemporaryBookingProject(1000111).getUuid(); final var givenBookingProjectUuid = givenSomeTemporaryBookingProject(1000111).getUuid();
@ -191,7 +197,7 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
context("superuser-alex@hostsharing.net", "hs_booking_project#D-1000111-sometempproject:ADMIN"); context("superuser-alex@hostsharing.net", "hs_booking_project#D-1000111-sometempproject:ADMIN");
final var foundBookingProject = em.find(HsBookingProjectRbacEntity.class, givenBookingProjectUuid); final var foundBookingProject = em.find(HsBookingProjectRbacEntity.class, givenBookingProjectUuid);
foundBookingProject.setCaption("updated caption"); foundBookingProject.setCaption("updated caption");
return toCleanup(rbacProjectRepo.save(foundBookingProject)); return toCleanup(repoUnderTest(testCase).save(foundBookingProject));
}); });
// then // then
@ -212,8 +218,9 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
@Nested @Nested
class DeleteByUuid { class DeleteByUuid {
@Test @ParameterizedTest
public void globalAdmin_withoutAssumedRole_canDeleteAnyBookingProject() { @EnumSource(TestCase.class)
public void globalAdmin_withoutAssumedRole_canDeleteAnyBookingProject(final TestCase testCase) {
// given // given
context("superuser-alex@hostsharing.net", null); context("superuser-alex@hostsharing.net", null);
final var givenBookingProject = givenSomeTemporaryBookingProject(1000111); final var givenBookingProject = givenSomeTemporaryBookingProject(1000111);
@ -221,7 +228,7 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
rbacProjectRepo.deleteByUuid(givenBookingProject.getUuid()); repoUnderTest(testCase).deleteByUuid(givenBookingProject.getUuid());
}); });
// then // then
@ -242,7 +249,7 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-sometempproject:AGENT"); context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-sometempproject:AGENT");
assertThat(rbacProjectRepo.findByUuid(givenBookingProject.getUuid())).isPresent(); assertThat(rbacProjectRepo.findByUuid(givenBookingProject.getUuid())).isPresent();
rbacProjectRepo.deleteByUuid(givenBookingProject.getUuid()); repoUnderTest(TestCase.RBAC).deleteByUuid(givenBookingProject.getUuid());
}); });
// then // then
@ -255,8 +262,9 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
}).assertSuccessful().returnedValue()).isPresent(); // still there }).assertSuccessful().returnedValue()).isPresent(); // still there
} }
@Test @ParameterizedTest
public void deletingABookingProjectAlsoDeletesRelatedRolesAndGrants() { @EnumSource(TestCase.class)
public void deletingABookingProjectAlsoDeletesRelatedRolesAndGrants(final TestCase testCase) {
// given // given
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
final var initialRoleNames = Array.from(distinctRoleNamesOf(rawRoleRepo.findAll())); final var initialRoleNames = Array.from(distinctRoleNamesOf(rawRoleRepo.findAll()));
@ -266,7 +274,7 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
// when // when
final var result = jpaAttempt.transacted(() -> { final var result = jpaAttempt.transacted(() -> {
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
return rbacProjectRepo.deleteByUuid(givenBookingProject.getUuid()); return repoUnderTest(testCase).deleteByUuid(givenBookingProject.getUuid());
}); });
// then // then
@ -310,7 +318,7 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
} }
void exactlyTheseBookingProjectsAreReturned( void exactlyTheseBookingProjectsAreReturned(
final List<HsBookingProjectRbacEntity> actualResult, final List<? extends HsBookingProject> actualResult,
final String... bookingProjectNames) { final String... bookingProjectNames) {
assertThat(actualResult) assertThat(actualResult)
.extracting(HsBookingProject::toString) .extracting(HsBookingProject::toString)
@ -318,10 +326,56 @@ class HsBookingProjectRbacRepositoryIntegrationTest extends ContextBasedTestWith
} }
void allTheseBookingProjectsAreReturned( void allTheseBookingProjectsAreReturned(
final List<HsBookingProjectRbacEntity> actualResult, final List<? extends HsBookingProject> actualResult,
final String... bookingProjectNames) { final String... bookingProjectNames) {
assertThat(actualResult) assertThat(actualResult)
.extracting(HsBookingProject::toString) .extracting(HsBookingProject::toString)
.contains(bookingProjectNames); .contains(bookingProjectNames);
} }
private HsBookingProjectRepository repoUnderTest(final TestCase testCase) {
return testCase.repo(HsBookingProjectRepositoryIntegrationTest.this);
}
private void assertResult(
final TestCase testCase,
final List<? extends HsBookingProject> actualResult,
final String... expectedProjects) {
testCase.assertResult(HsBookingProjectRepositoryIntegrationTest.this, actualResult, expectedProjects);
}
enum TestCase {
REAL {
@Override
HsBookingProjectRepository repo(final HsBookingProjectRepositoryIntegrationTest test) {
return test.realProjectRepo;
}
@Override
void assertResult(
final HsBookingProjectRepositoryIntegrationTest test,
final List<? extends HsBookingProject> result,
final String... expectedProjects) {
test.allTheseBookingProjectsAreReturned(result, expectedProjects);
}
},
RBAC {
@Override
HsBookingProjectRepository repo(final HsBookingProjectRepositoryIntegrationTest test) {
return test.rbacProjectRepo;
}
@Override
void assertResult(
final HsBookingProjectRepositoryIntegrationTest test,
final List<? extends HsBookingProject> result,
final String... expectedProjects) {
test.exactlyTheseBookingProjectsAreReturned(result, expectedProjects);
}
};
abstract HsBookingProjectRepository repo(final HsBookingProjectRepositoryIntegrationTest test);
abstract void assertResult(final HsBookingProjectRepositoryIntegrationTest test, final List<? extends HsBookingProject> result, final String... expectedProjects);
}
} }