Skip to content

Commit

Permalink
Feat/tenant (#4)
Browse files Browse the repository at this point in the history
* remove custom profiles from test

* fix: update external data

* feat: add tenantId to model and enable it

* legacy and external tenant test

* update test to have 100%

* feat: add tenant tests

* fix: remove code smell

---------

Co-authored-by: milan.horvath <[email protected]>
  • Loading branch information
milanhorvath and milan.horvath authored Dec 7, 2023
1 parent db40032 commit a103461
Show file tree
Hide file tree
Showing 55 changed files with 2,255 additions and 303 deletions.
16 changes: 15 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>io.github.onecx</groupId>
<artifactId>onecx-quarkus3-parent</artifactId>
<version>0.22.0</version>
<version>0.23.0</version>
</parent>

<artifactId>onecx-workspace-svc</artifactId>
Expand Down Expand Up @@ -40,6 +40,20 @@
<artifactId>tkit-quarkus-rest</artifactId>
</dependency>

<!-- TENANT -->
<dependency>
<groupId>io.github.onecx.quarkus</groupId>
<artifactId>onecx-tenant</artifactId>
</dependency>
<dependency>
<groupId>org.tkit.quarkus.lib</groupId>
<artifactId>tkit-quarkus-jpa-tenant</artifactId>
</dependency>
<dependency>
<groupId>org.tkit.quarkus.lib</groupId>
<artifactId>tkit-quarkus-rest-context</artifactId>
</dependency>

<!-- QUARKUS -->
<dependency>
<groupId>io.quarkus</groupId>
Expand Down
2 changes: 1 addition & 1 deletion src/main/helm/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
apiVersion: v1
apiVersion: v2
name: onecx-workspace-svc
version: 0.0.0
appVersion: 0.0.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,15 @@
import java.util.List;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.persistence.NoResultException;
import jakarta.persistence.criteria.Join;
import jakarta.transaction.Transactional;

import org.tkit.quarkus.jpa.daos.AbstractDAO;
import org.tkit.quarkus.jpa.exceptions.DAOException;
import org.tkit.quarkus.jpa.models.TraceableEntity_;

import io.github.onecx.workspace.domain.models.MenuItem;
import io.github.onecx.workspace.domain.models.MenuItem_;
import io.github.onecx.workspace.domain.models.Workspace;
import io.github.onecx.workspace.domain.models.Workspace_;
import io.github.onecx.workspace.domain.models.*;

@ApplicationScoped
public class MenuItemDAO extends AbstractDAO<MenuItem> {
Expand Down Expand Up @@ -168,7 +166,25 @@ public List<MenuItem> loadAllMenuItemsByWorkspaceId(String workspaceId) {
}
}

@Override
public MenuItem findById(Object id) throws DAOException {
try {
var cb = this.getEntityManager().getCriteriaBuilder();
var cq = cb.createQuery(MenuItem.class);
var root = cq.from(MenuItem.class);
cq.where(cb.equal(root.get(TraceableEntity_.ID), id));
return this.getEntityManager().createQuery(cq).getSingleResult();
} catch (NoResultException nre) {
return null;
} catch (Exception e) {
throw new DAOException(MenuItemDAO.ErrorKeys.FIND_ENTITY_BY_ID_FAILED, e, entityName, id);
}
}

public enum ErrorKeys {

FIND_ENTITY_BY_ID_FAILED,

ERROR_UPDATE_MENU_ITEMS,
ERROR_LOAD_ALL_MENU_ITEMS_BY_WORKSPACE_ID,
ERROR_DELETE_ALL_MENU_ITEMS_BY_WORKSPACE_ID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import java.util.List;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.persistence.NoResultException;
import jakarta.transaction.Transactional;

import org.tkit.quarkus.jpa.daos.AbstractDAO;
import org.tkit.quarkus.jpa.exceptions.DAOException;
import org.tkit.quarkus.jpa.models.TraceableEntity_;

import io.github.onecx.workspace.domain.models.MenuItem_;
import io.github.onecx.workspace.domain.models.Product;
import io.github.onecx.workspace.domain.models.Product_;

Expand All @@ -24,23 +26,60 @@ public List<Product> getProductsForWorkspaceId(String id) {
cq.where(cb.equal(root.get(Product_.WORKSPACE).get(TraceableEntity_.ID), id));
return this.getEntityManager().createQuery(cq).getResultList();
} catch (Exception ex) {
throw new DAOException(ProductDAO.ErrorKeys.ERROR_FIND_PRODUCTS_BY_WORKSPACE_ID, ex);
throw this.handleConstraint(ex, ProductDAO.ErrorKeys.ERROR_FIND_PRODUCTS_BY_WORKSPACE_ID);
}
}

@Transactional(value = Transactional.TxType.REQUIRED, rollbackOn = DAOException.class)
public void deleteProduct(String id) {
try {
var cb = this.getEntityManager().getCriteriaBuilder();
var cq = cb.createQuery(Product.class);
var root = cq.from(Product.class);

cq.where(cb.equal(root.get(TraceableEntity_.ID), id));
var product = this.getEntityManager().createQuery(cq).getSingleResult();
this.getEntityManager().remove(product);
} catch (NoResultException nre) {
// do nothing on No result
} catch (Exception ex) {
throw this.handleConstraint(ex, ProductDAO.ErrorKeys.ERROR_DELETE_PRODUCT_ID);
}
}

@Transactional(value = Transactional.TxType.REQUIRED, rollbackOn = DAOException.class)
public void deleteProductByWorkspaceId(String workspaceId) {
var cb = this.getEntityManager().getCriteriaBuilder();
var cq = cb.createQuery(Product.class);
var root = cq.from(Product.class);

cq.where(cb.equal(root.get(TraceableEntity_.ID), id));
var product = this.getEntityManager().createQuery(cq).getSingleResult();
this.getEntityManager().remove(product);
cq.where(cb.equal(root.get(MenuItem_.WORKSPACE).get(TraceableEntity_.ID), workspaceId));

var products = this.getEntityManager().createQuery(cq).getResultList();
delete(products);
}

@Override
public Product findById(Object id) throws DAOException {
try {
var cb = this.getEntityManager().getCriteriaBuilder();
var cq = cb.createQuery(Product.class);
var root = cq.from(Product.class);
cq.where(cb.equal(root.get(TraceableEntity_.ID), id));
return this.getEntityManager().createQuery(cq).getSingleResult();
} catch (NoResultException nre) {
return null;
} catch (Exception e) {
throw this.handleConstraint(e, ProductDAO.ErrorKeys.FIND_ENTITY_BY_ID_FAILED);
}
}

public enum ErrorKeys {

FIND_ENTITY_BY_ID_FAILED,

ERROR_DELETE_PRODUCT_ID,

ERROR_FIND_PRODUCTS_BY_WORKSPACE_ID,

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.tkit.quarkus.jpa.daos.Page;
import org.tkit.quarkus.jpa.daos.PageResult;
import org.tkit.quarkus.jpa.exceptions.DAOException;
import org.tkit.quarkus.jpa.models.TraceableEntity_;
import org.tkit.quarkus.jpa.utils.QueryCriteriaUtil;

import io.github.onecx.workspace.domain.criteria.WorkspaceSearchCriteria;
Expand All @@ -25,6 +26,22 @@
@ApplicationScoped
public class WorkspaceDAO extends AbstractDAO<Workspace> {

// https://hibernate.atlassian.net/browse/HHH-16830#icft=HHH-16830
@Override
public Workspace findById(Object id) throws DAOException {
try {
var cb = this.getEntityManager().getCriteriaBuilder();
var cq = cb.createQuery(Workspace.class);
var root = cq.from(Workspace.class);
cq.where(cb.equal(root.get(TraceableEntity_.ID), id));
return this.getEntityManager().createQuery(cq).getSingleResult();
} catch (NoResultException nre) {
return null;
} catch (Exception e) {
throw handleConstraint(e, ErrorKeys.FIND_ENTITY_BY_ID_FAILED);
}
}

/**
* This method fetches a workspace with
* workspaceName provided as a param and
Expand All @@ -45,7 +62,7 @@ public Workspace findByWorkspaceName(String workspaceName) {
} catch (NoResultException nre) {
return null;
} catch (Exception ex) {
throw new DAOException(ErrorKeys.ERROR_FIND_WORKSPACE_NAME, ex);
throw handleConstraint(ex, ErrorKeys.ERROR_FIND_WORKSPACE_NAME);
}
}

Expand Down Expand Up @@ -73,7 +90,7 @@ public Workspace loadByWorkspaceName(String workspaceName) {
} catch (NoResultException nre) {
return null;
} catch (Exception ex) {
throw new DAOException(ErrorKeys.ERROR_FIND_WORKSPACE_NAME, ex);
throw handleConstraint(ex, ErrorKeys.ERROR_FIND_WORKSPACE_NAME);
}
}

Expand Down Expand Up @@ -101,7 +118,7 @@ public PageResult<Workspace> findBySearchCriteria(WorkspaceSearchCriteria criter

return createPageQuery(cq, Page.of(criteria.getPageNumber(), criteria.getPageSize())).getPageResult();
} catch (Exception ex) {
throw new DAOException(ErrorKeys.ERROR_FIND_BY_CRITERIA, ex);
throw handleConstraint(ex, ErrorKeys.ERROR_FIND_BY_CRITERIA);
}
}

Expand All @@ -124,12 +141,13 @@ public Stream<WorkspaceInfo> findByThemeName(String themeName) {

return this.getEntityManager().createQuery(cq).getResultStream();
} catch (Exception ex) {
throw new DAOException(ErrorKeys.ERROR_FIND_BY_THEME_NAME, ex);
throw handleConstraint(ex, ErrorKeys.ERROR_FIND_BY_THEME_NAME);
}
}

public enum ErrorKeys {

FIND_ENTITY_BY_ID_FAILED,
ERROR_FIND_BY_BASE_URL,

ERROR_FIND_BY_CRITERIA,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package io.github.onecx.workspace.domain.di;

import java.util.LinkedList;
import java.util.List;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toCollection;

import java.util.ArrayList;

import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
Expand All @@ -13,32 +15,17 @@
import com.fasterxml.jackson.databind.ObjectMapper;

import gen.io.github.onecx.workspace.di.workspace.v1.model.ImportRequestDTOV1;
import gen.io.github.onecx.workspace.di.workspace.v1.model.MenuItemStructureDTOV1;
import gen.io.github.onecx.workspace.di.workspace.v1.model.WorkspaceDataImportDTOV1;
import io.github.onecx.workspace.domain.daos.MenuItemDAO;
import io.github.onecx.workspace.domain.daos.ProductDAO;
import io.github.onecx.workspace.domain.daos.WorkspaceDAO;
import io.github.onecx.workspace.domain.di.mappers.WorkspaceDataImportMapperV1;
import io.github.onecx.workspace.domain.models.MenuItem;
import io.github.onecx.workspace.domain.models.Workspace;
import gen.io.github.onecx.workspace.di.workspace.v1.model.WorkspaceImportDTOV1;

@DataImport("workspace")
public class WorkspaceDataImportService implements DataImportService {

@Inject
MenuItemDAO menuItemDAO;

@Inject
WorkspaceDAO workspaceDAO;

@Inject
ProductDAO productDAO;

@Inject
ObjectMapper objectMapper;

@Inject
WorkspaceDataImportMapperV1 mapper;
WorkspaceImportService importService;

@Override
@Transactional(Transactional.TxType.REQUIRES_NEW)
Expand All @@ -58,71 +45,34 @@ public void importData(DataImportConfig config) {
}

public void cleanInsert(WorkspaceDataImportDTOV1 data) {
if (data == null) {
if (data == null || data.getRequests() == null) {
return;
}
var tenantIds = data.getRequests().stream().map(ImportRequestDTOV1::getWorkspace)
.collect(groupingBy(WorkspaceImportDTOV1::getTenantId, toCollection(ArrayList::new))).keySet();

// clean data
productDAO.deleteAll();
menuItemDAO.deleteAll();
workspaceDAO.deleteAll();
for (var tenantId : tenantIds) {
try {
importService.deleteAll(tenantId);
} catch (Exception ex) {
throw new ImportException("Error deleting data from tenant " + tenantId, ex);
}
}

// import portals
importRequests(data);
}

public void importRequests(WorkspaceDataImportDTOV1 data) {
if (data.getRequests() == null) {
return;
}

for (var request : data.getRequests()) {
try {
importRequest(request);
importService.importRequest(request);
} catch (Exception ex) {
throw new ImportException("Error import portal " + request.getWorkspace().getWorkspaceName(), ex);
}
}
}

public void importRequest(ImportRequestDTOV1 importRequestDTO) {

var dto = importRequestDTO.getWorkspace();
var workspace = mapper.createWorkspace(dto);

workspace = workspaceDAO.create(workspace);

if (importRequestDTO.getMenuItems() != null && !importRequestDTO.getMenuItems().isEmpty()) {
menuItemDAO.deleteAllMenuItemsByWorkspaceId(workspace.getId());
List<MenuItem> menus = new LinkedList<>();
recursiveMappingTreeStructure(importRequestDTO.getMenuItems(), workspace, null, menus);
menuItemDAO.create(menus);
}

}

public void recursiveMappingTreeStructure(List<MenuItemStructureDTOV1> items, Workspace workspace, MenuItem parent,
List<MenuItem> mappedItems) {
int position = 0;
for (MenuItemStructureDTOV1 item : items) {
if (item != null) {
MenuItem menu = mapper.mapMenu(item);
menu.setWorkspace(workspace);
menu.setWorkspaceName(workspace.getWorkspaceName());
menu.setPosition(position);
menu.setParent(parent);
mappedItems.add(menu);
position++;

if (item.getChildren() == null || item.getChildren().isEmpty()) {
continue;
}

recursiveMappingTreeStructure(item.getChildren(), workspace, menu, mappedItems);
}
}
}

public static class ImportException extends RuntimeException {

public ImportException(String message, Throwable ex) {
Expand Down
Loading

0 comments on commit a103461

Please sign in to comment.