diff --git a/backend/src/main/java/com/redhat/cloud/notifications/db/repositories/ApplicationRepository.java b/backend/src/main/java/com/redhat/cloud/notifications/db/repositories/ApplicationRepository.java index 76f85c306c..856a510d9a 100644 --- a/backend/src/main/java/com/redhat/cloud/notifications/db/repositories/ApplicationRepository.java +++ b/backend/src/main/java/com/redhat/cloud/notifications/db/repositories/ApplicationRepository.java @@ -246,12 +246,12 @@ public boolean deleteEventTypeById(UUID id) { return rowCount > 0; } - public List getEventTypes(Query limiter, Set appIds, UUID bundleId, String eventTypeName) { + public List getEventTypes(Query limiter, Set appIds, UUID bundleId, String eventTypeName, boolean excludeMutedTypes) { if (limiter != null) { limiter.setSortFields(EventType.SORT_FIELDS); } - return getEventTypesQueryBuilder(appIds, bundleId, eventTypeName) + return getEventTypesQueryBuilder(appIds, bundleId, eventTypeName, excludeMutedTypes) .join(JoinBuilder.builder().leftJoinFetch("e.application")) .limit(limiter != null ? limiter.getLimit() : null) .sort(limiter != null ? limiter.getSort() : null) @@ -259,8 +259,8 @@ public List getEventTypes(Query limiter, Set appIds, UUID bundl .getResultList(); } - public Long getEventTypesCount(Set appIds, UUID bundleId, String eventTypeName) { - return getEventTypesQueryBuilder(appIds, bundleId, eventTypeName) + public Long getEventTypesCount(Set appIds, UUID bundleId, String eventTypeName, boolean excludeMutedTypes) { + return getEventTypesQueryBuilder(appIds, bundleId, eventTypeName, excludeMutedTypes) .buildCount(entityManager::createQuery) .getSingleResult(); } @@ -298,7 +298,9 @@ public boolean applicationBundleExists(final String applicationName, final Strin } } - private QueryBuilder getEventTypesQueryBuilder(Set appIds, UUID bundleId, String eventTypeName) { + private QueryBuilder getEventTypesQueryBuilder(Set appIds, UUID bundleId, String eventTypeName, boolean excludeMutedTypes) { + final String unmutedEventTypesQuery = "SELECT etb.eventType.id FROM EventTypeBehavior AS etb"; + return QueryBuilder .builder(EventType.class) .alias("e") @@ -308,6 +310,7 @@ private QueryBuilder getEventTypesQueryBuilder(Set appIds, UUID .ifAnd(appIds != null && appIds.size() > 0, "e.application.id IN (:appIds)", "appIds", appIds) .ifAnd(bundleId != null, "e.application.bundle.id = :bundleId", "bundleId", bundleId) .ifAnd(eventTypeName != null, "(LOWER(e.displayName) LIKE :eventTypeName OR LOWER(e.name) LIKE :eventTypeName)", "eventTypeName", (Supplier) () -> "%" + eventTypeName.toLowerCase() + "%") + .ifAnd(excludeMutedTypes, "e.id IN (" + unmutedEventTypesQuery + ")") .and("e.visible = true") ); } diff --git a/backend/src/main/java/com/redhat/cloud/notifications/routers/NotificationResource.java b/backend/src/main/java/com/redhat/cloud/notifications/routers/NotificationResource.java index 31ade27bb2..ad50c36afa 100644 --- a/backend/src/main/java/com/redhat/cloud/notifications/routers/NotificationResource.java +++ b/backend/src/main/java/com/redhat/cloud/notifications/routers/NotificationResource.java @@ -124,14 +124,14 @@ public Page getLinkedBehaviorGroups( @GET @Path("/eventTypes") @Produces(APPLICATION_JSON) - @Operation(summary = "List all event types", description = "Lists all event types. You can filter the returned list by bundle or application name.") + @Operation(summary = "List all event types", description = "Lists all event types. You can filter the returned list by bundle, application name, or unmuted types.") @RolesAllowed(ConsoleIdentityProvider.RBAC_READ_NOTIFICATIONS) public Page getEventTypes( @Context UriInfo uriInfo, @BeanParam @Valid Query query, @QueryParam("applicationIds") Set applicationIds, @QueryParam("bundleId") UUID bundleId, - @QueryParam("eventTypeName") String eventTypeName + @QueryParam("eventTypeName") String eventTypeName, @QueryParam("excludeMutedTypes") boolean excludeMutedTypes ) { - List eventTypes = applicationRepository.getEventTypes(query, applicationIds, bundleId, eventTypeName); - Long count = applicationRepository.getEventTypesCount(applicationIds, bundleId, eventTypeName); + List eventTypes = applicationRepository.getEventTypes(query, applicationIds, bundleId, eventTypeName, excludeMutedTypes); + Long count = applicationRepository.getEventTypesCount(applicationIds, bundleId, eventTypeName, excludeMutedTypes); return new Page<>( eventTypes, PageLinksBuilder.build(uriInfo.getPath(), count, query.getLimit().getLimit(), query.getLimit().getOffset()), diff --git a/backend/src/test/java/com/redhat/cloud/notifications/routers/NotificationResourceTest.java b/backend/src/test/java/com/redhat/cloud/notifications/routers/NotificationResourceTest.java index d4f35fdd36..58a3b07fca 100644 --- a/backend/src/test/java/com/redhat/cloud/notifications/routers/NotificationResourceTest.java +++ b/backend/src/test/java/com/redhat/cloud/notifications/routers/NotificationResourceTest.java @@ -58,6 +58,7 @@ import static io.restassured.RestAssured.given; import static io.restassured.http.ContentType.JSON; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -330,6 +331,107 @@ void testEventTypeFetchingByBundleApplicationAndEventTypeName() { assertEquals(1, eventTypes.size()); } + @Test + void testEventTypeFetchingAndExcludeMutedTypes() { + UUID bundleId = helpers.createTestAppAndEventTypes(); + List apps = applicationRepository.getApplications(TEST_BUNDLE_NAME); + Application app = apps.stream().filter(a -> a.getName().equals(TEST_APP_NAME_2)).findFirst().get(); + UUID appId = app.getId(); + Header identityHeader = initRbacMock(ACCOUNT_ID, ORG_ID, "user", FULL_ACCESS); + UUID behaviorGroupId1 = helpers.createBehaviorGroup(ACCOUNT_ID, ORG_ID, "behaviour-group-1", bundleId).getId(); + UUID behaviorGroupId2 = helpers.createBehaviorGroup(ACCOUNT_ID, ORG_ID, "behaviour-group-2", bundleId).getId(); + + List eventTypes = applicationRepository.getEventTypes(appId); + // bgroup1 assigned to ev0 and ev1, bgroup2 assigned to ev14, all other event types unassigned + List unmutedEventTypeNames = List.of(String.format(TEST_EVENT_TYPE_FORMAT, 0), String.format(TEST_EVENT_TYPE_FORMAT, 1), String.format(TEST_EVENT_TYPE_FORMAT, 14)); + behaviorGroupRepository.updateEventTypeBehaviors(ORG_ID, eventTypes.stream().filter(ev -> ev.getName().equals(unmutedEventTypeNames.getFirst())).findFirst().get().getId(), Set.of(behaviorGroupId1)); + behaviorGroupRepository.updateEventTypeBehaviors(ORG_ID, eventTypes.stream().filter(ev -> ev.getName().equals(unmutedEventTypeNames.get(1))).findFirst().get().getId(), Set.of(behaviorGroupId1)); + behaviorGroupRepository.updateEventTypeBehaviors(ORG_ID, eventTypes.stream().filter(ev -> ev.getName().equals(unmutedEventTypeNames.get(2))).findFirst().get().getId(), Set.of(behaviorGroupId2)); + + String response = given() + .when() + .header(identityHeader) + .queryParam("excludeMutedTypes", "true") + .get("/notifications/eventTypes") + .then() + .statusCode(200) + .contentType(JSON) + .extract().asString(); + + JsonObject page = new JsonObject(response); + JsonArray respEventTypes = page.getJsonArray("data"); + ArrayList respEventTypeNames = new ArrayList<>(); + for (int i = 0; i < respEventTypes.size(); i++) { + JsonObject ev = respEventTypes.getJsonObject(i); + respEventTypeNames.add(ev.getString("name")); + } + + assertTrue(unmutedEventTypeNames.containsAll(respEventTypeNames) && respEventTypeNames.containsAll(unmutedEventTypeNames)); + assertFalse(respEventTypeNames.contains(String.format(TEST_EVENT_TYPE_FORMAT, 2))); + assertEquals(3, page.getJsonObject("meta").getInteger("count")); + } + + @Test + void testEventTypeFetchingByBundleApplicationEventTypeNameAndExcludeMutedTypes() { + UUID bundleId = helpers.createTestAppAndEventTypes(); + List apps = applicationRepository.getApplications(TEST_BUNDLE_NAME); + Application app1 = apps.stream().filter(a -> a.getName().equals(TEST_APP_NAME)).findFirst().get(); + UUID appId1 = app1.getId(); + Application app2 = apps.stream().filter(a -> a.getName().equals(TEST_APP_NAME_2)).findFirst().get(); + UUID appId2 = app2.getId(); + Header identityHeader = initRbacMock(ACCOUNT_ID, ORG_ID, "user", FULL_ACCESS); + UUID behaviorGroupId1 = helpers.createBehaviorGroup(ACCOUNT_ID, ORG_ID, "behaviour-group-1", bundleId).getId(); + UUID behaviorGroupId2 = helpers.createBehaviorGroup(ACCOUNT_ID, ORG_ID, "behaviour-group-2", bundleId).getId(); + + // bgroup1 assigned to ev0 and ev1 on TEST_APP_NAME, bgroup2 assigned to ev1 on TEST_APP_NAME_2, all other event types unassigned + List eventTypesApp1 = applicationRepository.getEventTypes(appId1); + behaviorGroupRepository.updateEventTypeBehaviors(ORG_ID, eventTypesApp1.getFirst().getId(), Set.of(behaviorGroupId1)); + behaviorGroupRepository.updateEventTypeBehaviors(ORG_ID, eventTypesApp1.get(1).getId(), Set.of(behaviorGroupId1)); + List eventTypesApp2 = applicationRepository.getEventTypes(appId2); + behaviorGroupRepository.updateEventTypeBehaviors(ORG_ID, eventTypesApp2.get(1).getId(), Set.of(behaviorGroupId2)); + + Response unmutedResponse = given() + .when() + .header(identityHeader) + .queryParam("bundleId", bundleId) + .queryParam("applicationIds", appId1) + .queryParam("eventTypeName", "1") + .queryParam("excludeMutedTypes", "true") + .get("/notifications/eventTypes") + .then() + .statusCode(200) + .contentType(JSON) + .extract().response(); + + JsonObject unmutedPage = new JsonObject(unmutedResponse.getBody().asString()); + JsonArray unmutedEventTypes = unmutedPage.getJsonArray("data"); + for (int i = 0; i < unmutedEventTypes.size(); i++) { + JsonObject unmutedEv = unmutedEventTypes.getJsonObject(i); + unmutedEv.mapTo(EventType.class); + assertEquals(bundleId.toString(), unmutedEv.getJsonObject("application").getString("bundle_id")); + assertEquals(appId1.toString(), unmutedEv.getJsonObject("application").getString("id")); + assertTrue(unmutedEv.getString("display_name").contains("1") || unmutedEv.getString("name").contains("1")); + } + assertEquals(1, unmutedEventTypes.size()); + + Response mutedResponse = given() + .when() + .header(identityHeader) + .queryParam("bundleId", bundleId) + .queryParam("applicationIds", appId2) + .queryParam("eventTypeName", "50") + .queryParam("excludeMutedTypes", "true") + .get("notifications/eventTypes") + .then() + .statusCode(200) + .contentType(JSON) + .extract().response(); + + JsonObject mutedPage = new JsonObject(mutedResponse.getBody().asString()); + JsonArray mutedEventTypes = mutedPage.getJsonArray("data"); + assertTrue(mutedEventTypes.isEmpty()); + } + @Test void testGetEventTypesAffectedByEndpoint() { String accountId = "testGetEventTypesAffectedByEndpoint";