package gr.cite.notification.data; import gr.cite.notification.common.scope.tenant.TenantScope; import gr.cite.notification.common.scope.tenant.TenantScoped; import gr.cite.notification.data.tenant.TenantScopedBaseEntity; import gr.cite.notification.errorcode.ErrorThesaurusProperties; import gr.cite.tools.exception.MyForbiddenException; import jakarta.persistence.EntityManager; import jakarta.persistence.FlushModeType; import jakarta.persistence.PersistenceContext; import org.hibernate.Session; import org.springframework.stereotype.Service; import org.springframework.web.context.annotation.RequestScope; import javax.management.InvalidApplicationException; @Service @RequestScope public class TenantEntityManager { @PersistenceContext private EntityManager entityManager; private final TenantScope tenantScope; private final ErrorThesaurusProperties errors; public TenantEntityManager(TenantScope tenantScope, ErrorThesaurusProperties errors) { this.tenantScope = tenantScope; this.errors = errors; } public void persist(Object entity) { this.entityManager.persist(entity); } public T merge(T entity) throws InvalidApplicationException { if (tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) { if (!tenantScope.isDefaultTenant()) { if (tenantScopedEntity.getTenantId() == null || !tenantScopedEntity.getTenantId().equals(tenantScope.getTenant())) throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage()); } else if (tenantScopedEntity.getTenantId() != null) { throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage()); } } return this.entityManager.merge(entity); } public void remove(Object entity) throws InvalidApplicationException { if (tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) { if (!tenantScope.isDefaultTenant()) { if (tenantScopedEntity.getTenantId() == null || !tenantScopedEntity.getTenantId().equals(tenantScope.getTenant())) throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage()); } else if (tenantScopedEntity.getTenantId() != null) { throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage()); } } this.entityManager.remove(entity); } public T find(Class entityClass, Object primaryKey) throws InvalidApplicationException { T entity = this.entityManager.find(entityClass, primaryKey); if (tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) { if (tenantScopedEntity.getTenantId() != null && !tenantScopedEntity.getTenantId().equals(tenantScope.getTenant())) return null; } return entity; } public void flush() { this.entityManager.flush(); } public void setFlushMode(FlushModeType flushMode) { this.entityManager.setFlushMode(flushMode); } public FlushModeType getFlushMode() { return this.entityManager.getFlushMode(); } public void clear() { this.entityManager.clear(); } public void enableTenantFilters() throws InvalidApplicationException { if (!tenantScope.isSet()) return; if(!tenantScope.isDefaultTenant()) { this.entityManager .unwrap(Session.class) .enableFilter(TenantScopedBaseEntity.TENANT_FILTER) .setParameter(TenantScopedBaseEntity.TENANT_FILTER_TENANT_PARAM, tenantScope.getTenant().toString()); } else { this.entityManager .unwrap(Session.class) .enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER); } } public void disableTenantFilters(){ this.entityManager .unwrap(Session.class) .disableFilter(TenantScopedBaseEntity.TENANT_FILTER); this.entityManager .unwrap(Session.class) .disableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER); } public EntityManager getEntityManager() { return entityManager; } public void setEntityManager(EntityManager entityManager) { this.entityManager = entityManager; } }