Skip to content

Commit d1e576d

Browse files
dev-marekphiz71
authored andcommitted
refactor: support portal pages when deleting environment
1 parent aadcfc9 commit d1e576d

File tree

2 files changed

+121
-1
lines changed

2 files changed

+121
-1
lines changed

gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/cockpit/command/handler/DeleteEnvironmentCommandHandler.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package io.gravitee.rest.api.service.cockpit.command.handler;
1717

18+
import com.fasterxml.jackson.databind.ObjectMapper;
1819
import io.gravitee.apim.core.access_point.crud_service.AccessPointCrudService;
1920
import io.gravitee.apim.core.access_point.model.AccessPoint;
2021
import io.gravitee.apim.core.scoring.model.ScoringRuleset;
@@ -53,7 +54,9 @@
5354
import io.gravitee.repository.management.api.ParameterRepository;
5455
import io.gravitee.repository.management.api.PlanRepository;
5556
import io.gravitee.repository.management.api.PortalMenuLinkRepository;
57+
import io.gravitee.repository.management.api.PortalNavigationItemRepository;
5658
import io.gravitee.repository.management.api.PortalNotificationConfigRepository;
59+
import io.gravitee.repository.management.api.PortalPageContentRepository;
5760
import io.gravitee.repository.management.api.PortalPageContextRepository;
5861
import io.gravitee.repository.management.api.PortalPageRepository;
5962
import io.gravitee.repository.management.api.PromotionRepository;
@@ -84,6 +87,7 @@
8487
import io.gravitee.repository.management.model.NotificationReferenceType;
8588
import io.gravitee.repository.management.model.PageReferenceType;
8689
import io.gravitee.repository.management.model.ParameterReferenceType;
90+
import io.gravitee.repository.management.model.PortalNavigationItem;
8791
import io.gravitee.repository.management.model.QualityRule;
8892
import io.gravitee.repository.management.model.RatingReferenceType;
8993
import io.gravitee.repository.management.model.RoleReferenceType;
@@ -114,6 +118,7 @@
114118
@Component
115119
public class DeleteEnvironmentCommandHandler implements CommandHandler<DeleteEnvironmentCommand, DeleteEnvironmentReply> {
116120

121+
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
117122
private final AccessPointCrudService accessPointService;
118123
private final AccessPointRepository accessPointRepository;
119124
private final AlertService alertService;
@@ -153,6 +158,8 @@ public class DeleteEnvironmentCommandHandler implements CommandHandler<DeleteEnv
153158
private final PortalNotificationConfigRepository portalNotificationConfigRepository;
154159
private final PortalPageRepository portalPageRepository;
155160
private final PortalPageContextRepository portalPageContextRepository;
161+
private final PortalNavigationItemRepository portalNavigationItemRepository;
162+
private final PortalPageContentRepository portalPageContentRepository;
156163
private final PromotionRepository promotionRepository;
157164
private final QualityRuleRepository qualityRuleRepository;
158165
private final RatingAnswerRepository ratingAnswerRepository;
@@ -204,6 +211,8 @@ public DeleteEnvironmentCommandHandler(
204211
@Lazy PortalNotificationConfigRepository portalNotificationConfigRepository,
205212
@Lazy PortalPageRepository portalPageRepository,
206213
@Lazy PortalPageContextRepository portalPageContextRepository,
214+
@Lazy PortalNavigationItemRepository portalNavigationItemRepository,
215+
@Lazy PortalPageContentRepository portalPageContentRepository,
207216
@Lazy PromotionRepository promotionRepository,
208217
@Lazy QualityRuleRepository qualityRuleRepository,
209218
@Lazy RatingAnswerRepository ratingAnswerRepository,
@@ -268,6 +277,8 @@ public DeleteEnvironmentCommandHandler(
268277
this.portalNotificationConfigRepository = portalNotificationConfigRepository;
269278
this.portalPageRepository = portalPageRepository;
270279
this.portalPageContextRepository = portalPageContextRepository;
280+
this.portalNavigationItemRepository = portalNavigationItemRepository;
281+
this.portalPageContentRepository = portalPageContentRepository;
271282
this.promotionRepository = promotionRepository;
272283
this.qualityRuleRepository = qualityRuleRepository;
273284
this.ratingAnswerRepository = ratingAnswerRepository;
@@ -367,7 +378,8 @@ private void deleteEnvironment(ExecutionContext executionContext, EnvironmentEnt
367378
parameterRepository.deleteByReferenceIdAndReferenceType(environment.getId(), ParameterReferenceType.ENVIRONMENT);
368379
portalMenuLinkRepository.deleteByEnvironmentId(environment.getId());
369380
portalPageRepository.deleteByEnvironmentId(environment.getId());
370-
portalPageContextRepository.deleteByEnvironmentId(environment.getId());
381+
deletePortalNavigationItems(environment);
382+
portalNavigationItemRepository.deleteByEnvironmentId(environment.getId());
371383
customUserFieldsRepository.deleteByReferenceIdAndReferenceType(environment.getId(), CustomUserFieldReferenceType.ENVIRONMENT);
372384
groupRepository
373385
.deleteByEnvironmentId(environment.getId())
@@ -410,6 +422,40 @@ private void deleteEnvironment(ExecutionContext executionContext, EnvironmentEnt
410422
clusterRepository.deleteByEnvironmentId(environment.getId());
411423
}
412424

425+
private void deletePortalNavigationItems(EnvironmentEntity environment) throws TechnicalException {
426+
portalNavigationItemRepository
427+
.findAllByOrganizationIdAndEnvironmentId(environment.getOrganizationId(), environment.getId())
428+
.stream()
429+
.filter(item -> item.getType() == PortalNavigationItem.Type.PAGE)
430+
.forEach(item -> {
431+
try {
432+
var pageContentId = extractPageContentId(item.getConfiguration());
433+
if (pageContentId == null) {
434+
return;
435+
}
436+
portalPageContentRepository.delete(pageContentId);
437+
} catch (TechnicalException e) {
438+
throw new TechnicalManagementException(e);
439+
}
440+
});
441+
portalPageContextRepository.deleteByEnvironmentId(environment.getId());
442+
}
443+
444+
private String extractPageContentId(String configuration) {
445+
if (configuration == null || configuration.isEmpty()) {
446+
return null;
447+
}
448+
try {
449+
var node = OBJECT_MAPPER.readTree(configuration);
450+
if (node.has("pageId")) {
451+
return node.get("pageId").asText();
452+
}
453+
} catch (Exception e) {
454+
log.error("Failed to extract pageId from configuration: {}", configuration, e);
455+
}
456+
return null;
457+
}
458+
413459
private void deleteApis(ExecutionContext executionContext) throws TechnicalException {
414460
apiRepository
415461
.deleteByEnvironmentId(executionContext.getEnvironmentId())

gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/test/java/io/gravitee/rest/api/service/cockpit/command/handler/DeleteEnvironmentCommandHandlerTest.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@
5757
import io.gravitee.repository.management.api.ParameterRepository;
5858
import io.gravitee.repository.management.api.PlanRepository;
5959
import io.gravitee.repository.management.api.PortalMenuLinkRepository;
60+
import io.gravitee.repository.management.api.PortalNavigationItemRepository;
6061
import io.gravitee.repository.management.api.PortalNotificationConfigRepository;
62+
import io.gravitee.repository.management.api.PortalPageContentRepository;
6163
import io.gravitee.repository.management.api.PortalPageContextRepository;
6264
import io.gravitee.repository.management.api.PortalPageRepository;
6365
import io.gravitee.repository.management.api.PromotionRepository;
@@ -89,6 +91,7 @@
8991
import io.gravitee.repository.management.model.NotificationReferenceType;
9092
import io.gravitee.repository.management.model.PageReferenceType;
9193
import io.gravitee.repository.management.model.ParameterReferenceType;
94+
import io.gravitee.repository.management.model.PortalNavigationItem;
9295
import io.gravitee.repository.management.model.QualityRule;
9396
import io.gravitee.repository.management.model.RatingReferenceType;
9497
import io.gravitee.repository.management.model.RoleReferenceType;
@@ -147,6 +150,7 @@ public class DeleteEnvironmentCommandHandlerTest {
147150
private static final String ERROR_ENV_ID = "error";
148151
private static final String SUBSCRIPTION_ID_1 = "subscription#1";
149152
private static final String SUBSCRIPTION_ID_2 = "subscription#2";
153+
private static final String PAGE_CONTENT_ID = "page-content-id";
150154

151155
@Mock
152156
private AccessPointRepository accessPointRepository;
@@ -283,6 +287,12 @@ public class DeleteEnvironmentCommandHandlerTest {
283287
@Mock
284288
private PortalPageContextRepository portalPageContextRepository;
285289

290+
@Mock
291+
private PortalPageContentRepository portalPageContentRepository;
292+
293+
@Mock
294+
private PortalNavigationItemRepository portalNavigationItemRepository;
295+
286296
@Mock
287297
private PromotionRepository promotionRepository;
288298

@@ -374,6 +384,22 @@ public void setUp() throws Exception {
374384
when(userRepository.findBySource(COCKPIT_SOURCE, COCKPIT_USER_ID, ORG_ID)).thenReturn(
375385
Optional.ofNullable(User.builder().id(RESOLVED_APIM_USER_ID).build())
376386
);
387+
when(portalNavigationItemRepository.findAllByOrganizationIdAndEnvironmentId(ORG_ID, ENV_ID)).thenReturn(
388+
List.of(
389+
new PortalNavigationItem(
390+
"portal-nav-item-id",
391+
ORG_ID,
392+
ENV_ID,
393+
"title",
394+
PortalNavigationItem.Type.PAGE,
395+
PortalNavigationItem.Area.HOMEPAGE,
396+
null,
397+
13,
398+
"{\"pageId\":\"" + PAGE_CONTENT_ID + "\"}"
399+
)
400+
)
401+
);
402+
377403
cut = new DeleteEnvironmentCommandHandler(
378404
accessPointRepository,
379405
apiCategoryOrderRepository,
@@ -407,6 +433,8 @@ public void setUp() throws Exception {
407433
portalNotificationConfigRepository,
408434
portalPageRepository,
409435
portalPageContextRepository,
436+
portalNavigationItemRepository,
437+
portalPageContentRepository,
410438
promotionRepository,
411439
qualityRuleRepository,
412440
ratingAnswerRepository,
@@ -514,6 +542,10 @@ public void should_delete_environment() throws TechnicalException {
514542
verify(portalMenuLinkRepository).deleteByEnvironmentId(ENV_ID);
515543
verify(portalPageRepository).deleteByEnvironmentId(ENV_ID);
516544
verify(portalPageContextRepository).deleteByEnvironmentId(ENV_ID);
545+
546+
verify(portalPageContentRepository).delete(PAGE_CONTENT_ID);
547+
verify(portalNavigationItemRepository).deleteByEnvironmentId(ENV_ID);
548+
517549
verify(metadataRepository).deleteByReferenceIdAndReferenceType(ENV_ID, MetadataReferenceType.ENVIRONMENT);
518550
verify(scoringRulesetRepository).deleteByReferenceId(ENV_ID, "ENVIRONMENT");
519551
verify(environmentService).delete(ENV_ID);
@@ -522,6 +554,48 @@ public void should_delete_environment() throws TechnicalException {
522554
verify(clusterRepository).deleteByEnvironmentId(ENV_ID);
523555
}
524556

557+
@Test
558+
public void should_fail_when_portal_page_content_delete_throws() throws Exception {
559+
org.mockito.Mockito.doThrow(new TechnicalException("delete failed")).when(portalPageContentRepository).delete(PAGE_CONTENT_ID);
560+
561+
DeleteEnvironmentReply reply = cut
562+
.handle(new DeleteEnvironmentCommand(new DeleteEnvironmentCommandPayload("delete-env", ENV_ID, COCKPIT_USER_ID)))
563+
.blockingGet();
564+
565+
assertEquals(CommandStatus.ERROR, reply.getCommandStatus());
566+
}
567+
568+
@Test
569+
public void should_skip_portal_page_content_delete_when_pageId_cannot_be_extracted() throws Exception {
570+
// override navigation items to provide an item without pageId in configuration
571+
when(portalNavigationItemRepository.findAllByOrganizationIdAndEnvironmentId(ORG_ID, ENV_ID)).thenReturn(
572+
List.of(
573+
new PortalNavigationItem(
574+
"portal-nav-item-id",
575+
ORG_ID,
576+
ENV_ID,
577+
"title",
578+
PortalNavigationItem.Type.PAGE,
579+
PortalNavigationItem.Area.HOMEPAGE,
580+
null,
581+
13,
582+
"{}"
583+
)
584+
)
585+
);
586+
587+
DeleteEnvironmentReply reply = cut
588+
.handle(new DeleteEnvironmentCommand(new DeleteEnvironmentCommandPayload("delete-env", ENV_ID, COCKPIT_USER_ID)))
589+
.blockingGet();
590+
591+
assertEquals(CommandStatus.SUCCEEDED, reply.getCommandStatus());
592+
593+
// page delete should not be invoked because no pageId could be extracted
594+
org.mockito.Mockito.verify(portalPageContentRepository, org.mockito.Mockito.never()).delete(org.mockito.Mockito.anyString());
595+
// navigation items should still be deleted
596+
verify(portalNavigationItemRepository).deleteByEnvironmentId(ENV_ID);
597+
}
598+
525599
private void verifyDeleteApplications(ExecutionContext executionContext) throws TechnicalException {
526600
verify(applicationRepository).deleteByEnvironmentId(executionContext.getEnvironmentId());
527601
verifyDeleteApplication(executionContext, APP_ID_1);

0 commit comments

Comments
 (0)