Fine grained repository permissions (#2562)

1. Introduce @PrreAuthorize check based on hasPermission - allowing custom processing (compared with non-modifiable hasAuthority/Role processing)
2. Dedicated permissions could be implemented on management api level. Check is made by plugged in PermissionEvaluator
3. Thus common XXX_REPOSITORY permissions could differ for extending services
4. Change create/update entity builder pattern - not via EntityFactory but via clean static lombok based builders (with fine fluent api).
5. Implement abstract repository management jpa class that handles the boilerplate code from extending classes in single place consistently -> AbsreactJpaRepositoryManagement
6. Register management api-s as **Sevice**-s instead of **Bean**-s in order to make easier maintainable and get away from heavy argument forwading
7. Simplify custom hawkbit repository registration + adding proxy to handle exception mapping at lower level - thus not depending on Aspects for converting exceptions
8. Implemented general purpose 'copy' utility (ObjectCopyUtil) that using getter/setter patterns is able to copy (e.g. Create/Update) objects to other objects (e.g. JPA entity objects)
This commit is contained in:
Avgustin Marinov
2025-07-28 14:57:33 +03:00
committed by GitHub
parent 8cdbe54cbe
commit 2b66449ff1
214 changed files with 3456 additions and 4416 deletions

View File

@@ -61,15 +61,13 @@ public class JpaConfiguration extends JpaBaseConfiguration {
}
/**
* {@link MultiTenantJpaTransactionManager} bean.
*
* @return a new {@link PlatformTransactionManager}
* @see org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration#transactionManager(ObjectProvider)
* {@link TransactionManager} bean. It mainly handles the tenancy but some other thins like conversion of dao / jpa exceptions to
* transaction exceptions
*/
@Override
@Bean
public PlatformTransactionManager transactionManager(final ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
return new MultiTenantJpaTransactionManager(tenantResolver);
return new TransactionManager(tenantResolver);
}
@Override

View File

@@ -16,32 +16,37 @@ import jakarta.persistence.EntityManager;
import jakarta.transaction.Transaction;
import org.eclipse.hawkbit.repository.jpa.model.EntityPropertyChangeListener;
import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorEventManager;
import org.eclipse.persistence.sessions.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.DefaultTransactionStatus;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* {@link JpaTransactionManager} that sets the {@link TenantAware#getCurrentTenant()} in the eclipselink session. This has
* {@link org.springframework.orm.jpa.JpaTransactionManager} that sets the {@link TenantAware#getCurrentTenant()} in the eclipselink session. This has
* to be done in eclipselink after a {@link Transaction} has been started.
* <p/>
* The class also handles setting the {@link EntityPropertyChangeListener} to the {@link DescriptorEventManager} of the
* The class also handles setting:
* <ul>
* <li>the {@link EntityPropertyChangeListener} to the {@link DescriptorEventManager}</li>
* <li>exception on doCommit mapping to management exceptions</li>
* </ul>
*/
class MultiTenantJpaTransactionManager extends JpaTransactionManager {
class TransactionManager extends JpaTransactionManager {
@Serial
private static final long serialVersionUID = 1L;
private static final Class<?> JPA_TARGET;
private transient TenantAware.TenantResolver tenantResolver;
private static final Class<?> JPA_TARGET;
static {
try {
JPA_TARGET = Class.forName("org.eclipse.hawkbit.repository.jpa.model.JpaTarget");
@@ -52,7 +57,7 @@ class MultiTenantJpaTransactionManager extends JpaTransactionManager {
}
}
MultiTenantJpaTransactionManager(final TenantAware.TenantResolver tenantResolver) {
TransactionManager(final TenantAware.TenantResolver tenantResolver) {
this.tenantResolver = tenantResolver;
}
@@ -86,6 +91,15 @@ class MultiTenantJpaTransactionManager extends JpaTransactionManager {
}
}
@Override
protected void doCommit(final DefaultTransactionStatus status) {
try {
super.doCommit(status);
} catch (final RuntimeException e) {
throw ExceptionMapper.mapRe(e);
}
}
private void cleanupTenant(final EntityManager em) {
if (em.isOpen() && em.getProperties().containsKey(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT)) {
em.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, "");