split PersonEntity/Repo into Rbac and Real Entity/Repo and use in Relation for faster lazy loading #130

Merged
hsh-michaelhoennig merged 15 commits from feature/split-PersonEntity-and-Repo-into-Rbac-and-Real into master 2024-12-05 10:39:26 +01:00
17 changed files with 84 additions and 25 deletions
Showing only changes of commit 2adfc490ad - Show all commits

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.contact;
import io.micrometer.core.annotation.Timed;
import net.hostsharing.hsadminng.mapper.StandardMapper;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeContactsApi;
@ -33,7 +34,8 @@ public class HsOfficeContactController implements HsOfficeContactsApi {
@Override
@Transactional(readOnly = true)
public ResponseEntity<List<HsOfficeContactResource>> listContacts(
@Timed("app.contacts.api.getListOfContacts")
public ResponseEntity<List<HsOfficeContactResource>> getListOfContacts(
final String currentSubject,
final String assumedRoles,
final String caption) {
@ -47,7 +49,8 @@ public class HsOfficeContactController implements HsOfficeContactsApi {
@Override
@Transactional
public ResponseEntity<HsOfficeContactResource> addContact(
@Timed("app.contacts.api.postNewContact")
public ResponseEntity<HsOfficeContactResource> postNewContact(
final String currentSubject,
final String assumedRoles,
final HsOfficeContactInsertResource body) {
@ -69,7 +72,8 @@ public class HsOfficeContactController implements HsOfficeContactsApi {
@Override
@Transactional(readOnly = true)
public ResponseEntity<HsOfficeContactResource> getContactByUuid(
@Timed("app.contacts.api.getSingleContactByUuid")
public ResponseEntity<HsOfficeContactResource> getSingleContactByUuid(
final String currentSubject,
final String assumedRoles,
final UUID contactUuid) {
@ -85,6 +89,7 @@ public class HsOfficeContactController implements HsOfficeContactsApi {
@Override
@Transactional
@Timed("app.contacts.api.deleteContactByUuid")
public ResponseEntity<Void> deleteContactByUuid(
final String currentSubject,
final String assumedRoles,
@ -101,6 +106,7 @@ public class HsOfficeContactController implements HsOfficeContactsApi {
@Override
@Transactional
@Timed("app.contacts.api.patchContact")
public ResponseEntity<HsOfficeContactResource> patchContact(
final String currentSubject,
final String assumedRoles,

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.contact;
import io.micrometer.core.annotation.Timed;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
@ -9,6 +10,7 @@ import java.util.UUID;
public interface HsOfficeContactRbacRepository extends Repository<HsOfficeContactRbacEntity, UUID> {
@Timed("app.contacts.repo.findByUuid.rbac")
Optional<HsOfficeContactRbacEntity> findByUuid(UUID id);
@Query("""
@ -16,11 +18,15 @@ public interface HsOfficeContactRbacRepository extends Repository<HsOfficeContac
WHERE :caption is null
OR c.caption like concat(cast(:caption as text), '%')
""")
@Timed("app.contacts.repo.findContactByOptionalCaptionLike.rbac")
List<HsOfficeContactRbacEntity> findContactByOptionalCaptionLike(String caption);
@Timed("app.contacts.repo.save.rbac")
HsOfficeContactRbacEntity save(final HsOfficeContactRbacEntity entity);
@Timed("app.contacts.repo.deleteByUuid.rbac")
int deleteByUuid(final UUID uuid);
@Timed("app.contacts.repo.count.rbac")
long count();
}

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.contact;
import io.micrometer.core.annotation.Timed;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
@ -9,6 +10,7 @@ import java.util.UUID;
public interface HsOfficeContactRealRepository extends Repository<HsOfficeContactRealEntity, UUID> {
@Timed("app.repo.contacts.findByUuid.real")
Optional<HsOfficeContactRealEntity> findByUuid(UUID id);
@Query("""
@ -16,11 +18,15 @@ public interface HsOfficeContactRealRepository extends Repository<HsOfficeContac
WHERE :caption is null
OR c.caption like concat(cast(:caption as text), '%')
""")
@Timed("app.repo.contacts.findContactByOptionalCaptionLike.real")
List<HsOfficeContactRealEntity> findContactByOptionalCaptionLike(String caption);
@Timed("app.repo.contacts.save.real")
HsOfficeContactRealEntity save(final HsOfficeContactRealEntity entity);
@Timed("app.repo.contacts.deleteByUuid.real")
int deleteByUuid(final UUID uuid);
@Timed("app.repo.contacts.count.real")
long count();
}

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.person;
import io.micrometer.core.annotation.Timed;
import net.hostsharing.hsadminng.mapper.StandardMapper;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficePersonsApi;
@ -30,7 +31,8 @@ public class HsOfficePersonController implements HsOfficePersonsApi {
@Override
@Transactional(readOnly = true)
public ResponseEntity<List<HsOfficePersonResource>> listPersons(
@Timed("app.persons.api.getListOfPersons")
public ResponseEntity<List<HsOfficePersonResource>> getListOfPersons(
final String currentSubject,
final String assumedRoles,
final String caption) {
@ -44,7 +46,8 @@ public class HsOfficePersonController implements HsOfficePersonsApi {
@Override
@Transactional
public ResponseEntity<HsOfficePersonResource> addPerson(
@Timed("app.persons.api.postNewPerson")
public ResponseEntity<HsOfficePersonResource> postNewPerson(
final String currentSubject,
final String assumedRoles,
final HsOfficePersonInsertResource body) {
@ -66,7 +69,8 @@ public class HsOfficePersonController implements HsOfficePersonsApi {
@Override
@Transactional(readOnly = true)
public ResponseEntity<HsOfficePersonResource> getPersonByUuid(
@Timed("app.persons.api.getSinglePersonByUuid")
public ResponseEntity<HsOfficePersonResource> getSinglePersonByUuid(
final String currentSubject,
final String assumedRoles,
final UUID personUuid) {
@ -82,6 +86,7 @@ public class HsOfficePersonController implements HsOfficePersonsApi {
@Override
@Transactional
@Timed("app.persons.api.deletePersonByUuid")
public ResponseEntity<Void> deletePersonByUuid(
final String currentSubject,
final String assumedRoles,
@ -98,6 +103,7 @@ public class HsOfficePersonController implements HsOfficePersonsApi {
@Override
@Transactional
@Timed("app.persons.api.patchPerson")
public ResponseEntity<HsOfficePersonResource> patchPerson(
final String currentSubject,
final String assumedRoles,

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.person;
import io.micrometer.core.annotation.Timed;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
@ -9,6 +10,7 @@ import java.util.UUID;
public interface HsOfficePersonRepository extends Repository<HsOfficePersonEntity, UUID> {
@Timed("app.persons.repo.findByUuid.rbac")
Optional<HsOfficePersonEntity> findByUuid(UUID personUuid);
@Query("""
@ -18,11 +20,15 @@ public interface HsOfficePersonRepository extends Repository<HsOfficePersonEntit
OR p.givenName like concat(cast(:name as text), '%')
OR p.familyName like concat(cast(:name as text), '%')
""")
@Timed("app.persons.repo.findPersonByOptionalNameLike.rbac")
List<HsOfficePersonEntity> findPersonByOptionalNameLike(String name);
@Timed("app.persons.repo.save.rbac")
HsOfficePersonEntity save(final HsOfficePersonEntity entity);
@Timed("app.persons.repo.deleteByUuid.rbac")
int deleteByUuid(final UUID personUuid);
@Timed("app.persons.repo.count.rbac")
long count();
}

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.relation;
import io.micrometer.core.annotation.Timed;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealRepository;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeRelationsApi;
@ -21,7 +22,6 @@ import java.util.function.BiConsumer;
@RestController
public class HsOfficeRelationController implements HsOfficeRelationsApi {
@Autowired
@ -44,7 +44,8 @@ public class HsOfficeRelationController implements HsOfficeRelationsApi {
@Override
@Transactional(readOnly = true)
public ResponseEntity<List<HsOfficeRelationResource>> listRelations(
@Timed("app.relations.api.getListOfRelations")
public ResponseEntity<List<HsOfficeRelationResource>> getListOfRelations(
final String currentSubject,
final String assumedRoles,
final UUID personUuid,
@ -66,7 +67,8 @@ public class HsOfficeRelationController implements HsOfficeRelationsApi {
@Override
@Transactional
public ResponseEntity<HsOfficeRelationResource> addRelation(
@Timed("app.relations.api.postNewRelation")
public ResponseEntity<HsOfficeRelationResource> postNewRelation(
final String currentSubject,
final String assumedRoles,
final HsOfficeRelationInsertResource body) {
@ -100,7 +102,8 @@ public class HsOfficeRelationController implements HsOfficeRelationsApi {
@Override
@Transactional(readOnly = true)
public ResponseEntity<HsOfficeRelationResource> getRelationByUuid(
@Timed("app.relations.api.getSingleRelationByUuid")
public ResponseEntity<HsOfficeRelationResource> getSingleRelationByUuid(
final String currentSubject,
final String assumedRoles,
final UUID relationUuid) {
@ -116,6 +119,7 @@ public class HsOfficeRelationController implements HsOfficeRelationsApi {
@Override
@Transactional
@Timed("apprelations.api..deleteRelationByUuid")
public ResponseEntity<Void> deleteRelationByUuid(
final String currentSubject,
final String assumedRoles,
@ -132,6 +136,7 @@ public class HsOfficeRelationController implements HsOfficeRelationsApi {
@Override
@Transactional
@Timed("app.relations.api.patchRelation")
public ResponseEntity<HsOfficeRelationResource> patchRelation(
final String currentSubject,
final String assumedRoles,

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.relation;
import io.micrometer.core.annotation.Timed;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
@ -10,12 +11,14 @@ import java.util.UUID;
public interface HsOfficeRelationRbacRepository extends Repository<HsOfficeRelationRbacEntity, UUID> {
@Timed("app.relations.repo.findByUuid.rbac")
Optional<HsOfficeRelationRbacEntity> findByUuid(UUID id);
@Query(value = """
SELECT p.* FROM hs_office.relation_rv AS p
WHERE p.anchorUuid = :personUuid OR p.holderUuid = :personUuid
""", nativeQuery = true)
@Timed("app.relations.repo.findRelationRelatedToPersonUuid.rbac")
List<HsOfficeRelationRbacEntity> findRelationRelatedToPersonUuid(@NotNull UUID personUuid);
/**
@ -51,16 +54,20 @@ public interface HsOfficeRelationRbacRepository extends Repository<HsOfficeRelat
OR lower(CAST(rel.contact.emailAddresses AS String)) LIKE :contactData
OR lower(CAST(rel.contact.phoneNumbers AS String)) LIKE :contactData )
""")
@Timed("app.relations.repo.findRelationRelatedToPersonUuidRelationTypePersonAndContactDataImpl.rbac")
List<HsOfficeRelationRbacEntity> findRelationRelatedToPersonUuidRelationTypePersonAndContactDataImpl(
final UUID personUuid,
final String relationType,
final String personData,
final String contactData);
@Timed("app.relations.repo.save.rbac")
HsOfficeRelationRbacEntity save(final HsOfficeRelationRbacEntity entity);
@Timed("app.relations.repo.count.rbac")
long count();
@Timed("app.relations.repo.deleteByUuid.rbac")
int deleteByUuid(UUID uuid);
private static String toSqlLikeOperand(final String text) {

View File

@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.relation;
import io.micrometer.core.annotation.Timed;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
@ -10,6 +11,7 @@ import java.util.UUID;
public interface HsOfficeRelationRealRepository extends Repository<HsOfficeRelationRealEntity, UUID> {
@Timed("app.repo.relations.findByUuid.real")
Optional<HsOfficeRelationRealEntity> findByUuid(UUID id);
default List<HsOfficeRelationRealEntity> findRelationRelatedToPersonUuidAndRelationType(@NotNull UUID personUuid, HsOfficeRelationType relationType) {
@ -20,6 +22,7 @@ public interface HsOfficeRelationRealRepository extends Repository<HsOfficeRelat
SELECT p.* FROM hs_office.relation AS p
WHERE p.anchorUuid = :personUuid OR p.holderUuid = :personUuid
""", nativeQuery = true)
@Timed("app.repo.relations.findRelationRelatedToPersonUuid.real")
List<HsOfficeRelationRealEntity> findRelationRelatedToPersonUuid(@NotNull UUID personUuid);
@Query(value = """
@ -27,11 +30,15 @@ public interface HsOfficeRelationRealRepository extends Repository<HsOfficeRelat
WHERE (:relationType IS NULL OR p.type = cast(:relationType AS hs_office.RelationType))
AND ( p.anchorUuid = :personUuid OR p.holderUuid = :personUuid)
""", nativeQuery = true)
@Timed("app.repo.relations.findRelationRelatedToPersonUuidAndRelationTypeString.real")
List<HsOfficeRelationRealEntity> findRelationRelatedToPersonUuidAndRelationTypeString(@NotNull UUID personUuid, String relationType);
@Timed("app.repo.relations.save.real")
HsOfficeRelationRealEntity save(final HsOfficeRelationRealEntity entity);
@Timed("app.repo.relations.count.real")
long count();
@Timed("app.repo.relations.deleteByUuid.real")
int deleteByUuid(UUID uuid);
}

View File

@ -2,7 +2,7 @@ get:
tags:
- hs-office-contacts
description: 'Fetch a single business contact by its uuid, if visible for the current subject.'
operationId: getContactByUuid
operationId: getSingleContactByUuid
parameters:
- $ref: 'auth.yaml#/components/parameters/currentSubject'
- $ref: 'auth.yaml#/components/parameters/assumedRoles'

View File

@ -3,7 +3,7 @@ get:
description: Returns the list of (optionally filtered) contacts which are visible to the current subject or any of it's assumed roles.
tags:
- hs-office-contacts
operationId: listContacts
operationId: getListOfContacts
parameters:
- $ref: 'auth.yaml#/components/parameters/currentSubject'
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
@ -31,7 +31,7 @@ post:
summary: Adds a new contact.
tags:
- hs-office-contacts
operationId: addContact
operationId: postNewContact
parameters:
- $ref: 'auth.yaml#/components/parameters/currentSubject'
- $ref: 'auth.yaml#/components/parameters/assumedRoles'

View File

@ -2,7 +2,7 @@ get:
tags:
- hs-office-persons
description: 'Fetch a single business person by its uuid, if visible for the current subject.'
operationId: getPersonByUuid
operationId: getSinglePersonByUuid
parameters:
- $ref: 'auth.yaml#/components/parameters/currentSubject'
- $ref: 'auth.yaml#/components/parameters/assumedRoles'

View File

@ -3,7 +3,7 @@ get:
description: Returns the list of (optionally filtered) persons which are visible to the current subject or any of it's assumed roles.
tags:
- hs-office-persons
operationId: listPersons
operationId: getListOfPersons
parameters:
- $ref: 'auth.yaml#/components/parameters/currentSubject'
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
@ -31,7 +31,7 @@ post:
summary: Adds a new person.
tags:
- hs-office-persons
operationId: addPerson
operationId: postNewPerson
parameters:
- $ref: 'auth.yaml#/components/parameters/currentSubject'
- $ref: 'auth.yaml#/components/parameters/assumedRoles'

View File

@ -2,7 +2,7 @@ get:
tags:
- hs-office-relations
description: 'Fetch a single person relation by its uuid, if visible for the current subject.'
operationId: getRelationByUuid
operationId: getSingleRelationByUuid
parameters:
- $ref: 'auth.yaml#/components/parameters/currentSubject'
- $ref: 'auth.yaml#/components/parameters/assumedRoles'

View File

@ -5,7 +5,7 @@ get:
To match data, all given query parameters must be fulfilled ('and' / logical conjunction).
tags:
- hs-office-relations
operationId: listRelations
operationId: getListOfRelations
parameters:
- $ref: 'auth.yaml#/components/parameters/currentSubject'
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
@ -52,7 +52,7 @@ post:
summary: Adds a new person relation.
tags:
- hs-office-relations
operationId: addRelation
operationId: postNewRelation
parameters:
- $ref: 'auth.yaml#/components/parameters/currentSubject'
- $ref: 'auth.yaml#/components/parameters/assumedRoles'

View File

@ -9,9 +9,11 @@ management:
web:
exposure:
include: info, health, metrics
observations:
annotations:
enabled: true
spring:
datasource:
driver-class-name: org.postgresql.Driver
password: password
@ -33,3 +35,11 @@ liquibase:
hsadminng:
postgres:
leakproof:
metrics:
distribution:
percentiles-histogram:
http:
server:
requests: true

View File

@ -52,7 +52,7 @@ class HsOfficePersonControllerAcceptanceTest extends ContextBasedTestWithCleanup
EntityManager em;
@Nested
class ListPersons {
class GetListOfPersons {
@Test
void globalAdmin_withoutAssumedRoles_canViewAllPersons_ifNoCriteriaGiven() {

View File

@ -54,7 +54,7 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
JpaAttempt jpaAttempt;
@Nested
class ListRelations {
class GetListOfRelations {
@Test
void globalAdmin_withoutAssumedRoles_canViewAllRelationsOfGivenPersonAndType() {