From 14572d328fc1030d16d7216696ea9e12ceb101e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Moreira?= Date: Wed, 9 Nov 2022 15:58:49 +0000 Subject: [PATCH] =?UTF-8?q?MNT-22485:=20audit=20query=20with=20createdAt?= =?UTF-8?q?=20criteria=20returns=20correct=20totalI=E2=80=A6=20(#1535)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * MNT-22485: audit query with createdAt criteria returns correct totalItems --- .../org/alfresco/rest/api/impl/AuditImpl.java | 28 +++- .../alfresco/rest/api/tests/AuditAppTest.java | 28 ++++ .../alfresco/repo/audit/AuditComponent.java | 12 ++ .../repo/audit/AuditComponentImpl.java | 7 + .../alfresco/repo/audit/AuditServiceImpl.java | 8 + .../domain/audit/AbstractAuditDAOImpl.java | 147 ++++++++++++------ .../alfresco/repo/domain/audit/AuditDAO.java | 12 ++ .../domain/audit/ibatis/AuditDAOImpl.java | 70 ++------- .../service/cmr/audit/AuditService.java | 12 ++ .../audit-common-SqlMap.xml | 17 ++ 10 files changed, 237 insertions(+), 104 deletions(-) diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/AuditImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/AuditImpl.java index 344bb73520..cf44a92f9c 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/impl/AuditImpl.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/AuditImpl.java @@ -295,7 +295,18 @@ public class AuditImpl implements Audit } else { - totalItems = hasMoreItems ? getAuditEntriesCountByApp(auditApplication) : totalRetrievedItems; + if (hasMoreItems) { + if (q != null) { + // filtering via "where" clause + AuditEntryQueryWalker propertyWalker = new AuditEntryQueryWalker(); + QueryHelper.walk(q, propertyWalker); + totalItems = getAuditEntriesCountByAppAndProperties(auditApplication, propertyWalker); + } else { + totalItems = getAuditEntriesCountByApp(auditApplication); + } + } else { + totalItems = totalRetrievedItems; + } } entriesAudit = (skipCount >= totalRetrievedItems) @@ -895,4 +906,19 @@ public class AuditImpl implements Audit final String applicationName = auditApplication.getKey().substring(1); return auditService.getAuditEntriesCountByApp(applicationName); } + + public int getAuditEntriesCountByAppAndProperties(AuditService.AuditApplication auditApplication, AuditEntryQueryWalker propertyWalker) + { + final String applicationName = auditApplication.getKey().substring(1); + + AuditQueryParameters parameters = new AuditQueryParameters(); + parameters.setApplicationName(applicationName); + parameters.setFromTime(propertyWalker.getFromTime()); + parameters.setToTime(propertyWalker.getToTime()); + parameters.setFromId(propertyWalker.getFromId()); + parameters.setToId(propertyWalker.getToId()); + parameters.setUser(propertyWalker.getCreatedByUser()); + + return auditService.getAuditEntriesCountByAppAndProperties(applicationName, parameters); + } } diff --git a/remote-api/src/test/java/org/alfresco/rest/api/tests/AuditAppTest.java b/remote-api/src/test/java/org/alfresco/rest/api/tests/AuditAppTest.java index a96d9b6db3..eb44c3b125 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/tests/AuditAppTest.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/AuditAppTest.java @@ -34,6 +34,9 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.net.URL; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -386,6 +389,7 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest AuditApp auditApp = auditAppsProxy.getAuditApp("alfresco-access"); testGetAuditEntries(auditAppsProxy, auditApp); + testGetAuditEntriesWhereCreatedAt(auditAppsProxy, auditApp); testAuditEntriesSorting(auditAppsProxy, auditApp); testAuditEntriesWhereDate(auditAppsProxy, auditApp); testAuditEntriesWhereId(auditAppsProxy, auditApp); @@ -396,6 +400,30 @@ public class AuditAppTest extends AbstractSingleNetworkSiteTest testDeleteAuditEntries(auditAppsProxy, auditApp); } + private void testGetAuditEntriesWhereCreatedAt(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception + { + // get "totalItems" for a specific time interval + Map params = new HashMap<>(); + + final ZonedDateTime beginDate = ZonedDateTime.now().minusHours(1).truncatedTo(ChronoUnit.MINUTES); + final ZonedDateTime endDate = ZonedDateTime.now().truncatedTo(ChronoUnit.MINUTES); + params.put("where","(createdAt BETWEEN ('"+beginDate.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)+"' , '"+endDate.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)+"'))"); + + ListResponse auditEntries = auditAppsProxy.getAuditAppEntries(auditApp.getId(), params, + HttpServletResponse.SC_OK); + int totalItemsWithDefaultMaxSize = auditEntries.getPaging().getTotalItems(); + assertTrue( totalItemsWithDefaultMaxSize > 1 ); + + // get "totalItems" for a specific time internal (with maxSize=1) + params.put("maxSize","1"); + auditEntries = auditAppsProxy.getAuditAppEntries(auditApp.getId(), params, + HttpServletResponse.SC_OK); + int totalItemsWithMaxSize1 = auditEntries.getPaging().getTotalItems(); + + // number of "totalItems" must be the same, regardless maxSize + assertEquals(totalItemsWithMaxSize1, totalItemsWithDefaultMaxSize); + } + private void testGetAuditEntries(AuditApps auditAppsProxy, AuditApp auditApp) throws Exception { // Positive tests diff --git a/repository/src/main/java/org/alfresco/repo/audit/AuditComponent.java b/repository/src/main/java/org/alfresco/repo/audit/AuditComponent.java index 49e400b582..821c0c4759 100644 --- a/repository/src/main/java/org/alfresco/repo/audit/AuditComponent.java +++ b/repository/src/main/java/org/alfresco/repo/audit/AuditComponent.java @@ -272,4 +272,16 @@ public interface AuditComponent { return -1; } + + /** + * Issue an audit query to retrieve count of records for a given application and properties + * + * @param applicationName the name of the application + * @param parameters audit parameters provided by the where clause on the ReST API + * @return a map containing min/max and the associated value + */ + default int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters) + { + return -1; + } } diff --git a/repository/src/main/java/org/alfresco/repo/audit/AuditComponentImpl.java b/repository/src/main/java/org/alfresco/repo/audit/AuditComponentImpl.java index 18b464c674..38fbd5ff69 100644 --- a/repository/src/main/java/org/alfresco/repo/audit/AuditComponentImpl.java +++ b/repository/src/main/java/org/alfresco/repo/audit/AuditComponentImpl.java @@ -955,4 +955,11 @@ public class AuditComponentImpl implements AuditComponent return auditDAO.getAuditEntriesCountByApp(applicationId); } + + @Override public int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters) + { + org.alfresco.repo.domain.audit.AuditQueryParameters dbParameters = new org.alfresco.repo.domain.audit.AuditQueryParameters(); + + return auditDAO.getAuditEntriesCountByAppAndProperties(applicationName, parameters); + } } diff --git a/repository/src/main/java/org/alfresco/repo/audit/AuditServiceImpl.java b/repository/src/main/java/org/alfresco/repo/audit/AuditServiceImpl.java index 0b96cc9304..7c92ec8e3f 100644 --- a/repository/src/main/java/org/alfresco/repo/audit/AuditServiceImpl.java +++ b/repository/src/main/java/org/alfresco/repo/audit/AuditServiceImpl.java @@ -186,4 +186,12 @@ public class AuditServiceImpl implements AuditService { return auditComponent.getAuditEntriesCountByApp(applicationName); } + + /** + * {@inheritDoc} + */ + @Override public int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters) + { + return auditComponent.getAuditEntriesCountByAppAndProperties(applicationName, parameters); + } } \ No newline at end of file diff --git a/repository/src/main/java/org/alfresco/repo/domain/audit/AbstractAuditDAOImpl.java b/repository/src/main/java/org/alfresco/repo/domain/audit/AbstractAuditDAOImpl.java index 224170f419..68d857bec2 100644 --- a/repository/src/main/java/org/alfresco/repo/domain/audit/AbstractAuditDAOImpl.java +++ b/repository/src/main/java/org/alfresco/repo/domain/audit/AbstractAuditDAOImpl.java @@ -1,28 +1,28 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited - * %% - * This file is part of the Alfresco software. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.domain.audit; import java.io.IOException; @@ -452,37 +452,86 @@ public abstract class AbstractAuditDAOImpl implements AuditDAO org.alfresco.service.cmr.audit.AuditQueryParameters parameters, int maxResults) { - String searchKey = null; - Serializable searchValue = null; - if (parameters.getSearchKeyValues().size() > 0) - { - // Only handle one pair for now - Pair searchKeyValue = parameters.getSearchKeyValues().get(0); - searchKey = searchKeyValue.getFirst(); - searchValue = searchKeyValue.getSecond(); - } - AuditQueryRowHandler rowHandler = new AuditQueryRowHandler(callback); findAuditEntries( rowHandler, - parameters.isForward(), - parameters.getApplicationName(), - parameters.getUser(), - parameters.getFromId(), - parameters.getToId(), - parameters.getFromTime(), - parameters.getToTime(), maxResults, - searchKey, - searchValue); + parameters); } protected abstract void findAuditEntries( AuditQueryRowHandler rowHandler, - boolean forward, - String applicationName, String user, - Long fromId, Long toId, - Long fromTime, Long toTime, int maxResults, - String searchKey, Serializable searchValue); + org.alfresco.service.cmr.audit.AuditQueryParameters restParameters); + + protected AuditQueryParameters convertFromRestAuditQueryParameters(org.alfresco.service.cmr.audit.AuditQueryParameters restParameters) + { + AuditQueryParameters dbParameters = new AuditQueryParameters(); + + String appName = restParameters.getApplicationName(); + if (appName != null) + { + // Look up the application's ID (this is unique) + Pair appNamePair = propertyValueDAO.getPropertyValue(appName); + if (appNamePair == null) + { + // No such value + return null; + } + dbParameters.setAuditAppNameId(appNamePair.getFirst()); + } + + String user = restParameters.getUser(); + if (user != null) + { + // Look up the application's ID (this is unique) + Pair userPair = propertyValueDAO.getPropertyValue(user); + if (userPair == null) + { + // No such value + return null; + } + dbParameters.setAuditUserId(userPair.getFirst()); + } + + dbParameters.setAuditFromId(restParameters.getFromId()); + dbParameters.setAuditToId(restParameters.getToId()); + dbParameters.setAuditFromTime(restParameters.getFromTime()); + dbParameters.setAuditToTime(restParameters.getToTime()); + + String searchKey = null; + Serializable searchValue = null; + if (restParameters.getSearchKeyValues().size() > 0) + { + // Only handle one pair for now + Pair searchKeyValue = restParameters.getSearchKeyValues().get(0); + searchKey = searchKeyValue.getFirst(); + searchValue = searchKeyValue.getSecond(); + } + if (searchKey != null) + { + // Look up the ID of the search key + Pair searchKeyPair = propertyValueDAO.getPropertyValue(searchKey); + if (searchKeyPair == null) + { + // No such value + return null; + } + dbParameters.setSearchKeyId(searchKeyPair.getFirst()); + } + if (searchValue != null) + { + // Look up the ID of the search key + Pair searchValuePair = propertyValueDAO.getPropertyValue(searchValue); + if (searchValuePair == null) + { + // No such value + return null; + } + dbParameters.setSearchValueId(searchValuePair.getFirst()); + } + dbParameters.setForward(restParameters.isForward()); + + return dbParameters; + } } diff --git a/repository/src/main/java/org/alfresco/repo/domain/audit/AuditDAO.java b/repository/src/main/java/org/alfresco/repo/domain/audit/AuditDAO.java index 22180ea78b..f8c61d0a8c 100644 --- a/repository/src/main/java/org/alfresco/repo/domain/audit/AuditDAO.java +++ b/repository/src/main/java/org/alfresco/repo/domain/audit/AuditDAO.java @@ -244,4 +244,16 @@ public interface AuditDAO { return -1; } + + /** + * Issue an audit query to retrieve count of records for a given application and properties + * + * @param applicationName name of the application to be queried + * @param parameters audit parameters provided by the where clause on the ReST API + * @return a map containing min/max and the associated value + */ + default int getAuditEntriesCountByAppAndProperties(String applicationName, org.alfresco.service.cmr.audit.AuditQueryParameters parameters) + { + return -1; + } } \ No newline at end of file diff --git a/repository/src/main/java/org/alfresco/repo/domain/audit/ibatis/AuditDAOImpl.java b/repository/src/main/java/org/alfresco/repo/domain/audit/ibatis/AuditDAOImpl.java index 58c97a9fa6..89f602dba5 100644 --- a/repository/src/main/java/org/alfresco/repo/domain/audit/ibatis/AuditDAOImpl.java +++ b/repository/src/main/java/org/alfresco/repo/domain/audit/ibatis/AuditDAOImpl.java @@ -66,6 +66,7 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl private static final String INSERT_ENTRY = "alfresco.audit.insert.insert_AuditEntry"; private static final String SELECT_MINMAX_ENTRY_FOR_APP = "alfresco.audit.select_MinMaxAuditEntryId"; private static final String SELECT_COUNT_ENTRIES_FOR_APP = "alfresco.audit.select_CountAuditEntryId"; + private static final String SELECT_COUNT_ENTRIES_FOR_APP_WITH_PROPERTIES = "select_CountAuditEntryIdWithWhereClause"; @SuppressWarnings("unused") private static final String SELECT_ENTRIES_SIMPLE = "alfresco.audit.select_AuditEntriesSimple"; @@ -235,68 +236,29 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl return result; } + @Override + public int getAuditEntriesCountByAppAndProperties(String applicationName, org.alfresco.service.cmr.audit.AuditQueryParameters parameters) + { + AuditQueryParameters dbParameters = convertFromRestAuditQueryParameters(parameters); + + int result = template.selectOne(SELECT_COUNT_ENTRIES_FOR_APP_WITH_PROPERTIES, dbParameters); + + return result; + } + @SuppressWarnings("unchecked") @Override protected void findAuditEntries( final AuditQueryRowHandler rowHandler, - boolean forward, - String appName, String user, - Long fromId, Long toId, - Long fromTime, Long toTime, int maxResults, - String searchKey, Serializable searchValue) + org.alfresco.service.cmr.audit.AuditQueryParameters restParameters) { - AuditQueryParameters params = new AuditQueryParameters(); - if (appName != null) + AuditQueryParameters params = convertFromRestAuditQueryParameters(restParameters); + if (params==null) { - // Look up the application's ID (this is unique) - Pair appNamePair = propertyValueDAO.getPropertyValue(appName); - if (appNamePair == null) - { - // No such value - return; - } - params.setAuditAppNameId(appNamePair.getFirst()); + return; } - if (user != null) - { - // Look up the application's ID (this is unique) - Pair userPair = propertyValueDAO.getPropertyValue(user); - if (userPair == null) - { - // No such value - return; - } - params.setAuditUserId(userPair.getFirst()); - } - params.setAuditFromId(fromId); - params.setAuditToId(toId); - params.setAuditFromTime(fromTime); - params.setAuditToTime(toTime); - if (searchKey != null) - { - // Look up the ID of the search key - Pair searchKeyPair = propertyValueDAO.getPropertyValue(searchKey); - if (searchKeyPair == null) - { - // No such value - return; - } - params.setSearchKeyId(searchKeyPair.getFirst()); - } - if (searchValue != null) - { - // Look up the ID of the search key - Pair searchValuePair = propertyValueDAO.getPropertyValue(searchValue); - if (searchValuePair == null) - { - // No such value - return; - } - params.setSearchValueId(searchValuePair.getFirst()); - } - params.setForward(forward); - + if (maxResults > 0) { // Query without getting the values. We gather all the results and batch-fetch the audited diff --git a/repository/src/main/java/org/alfresco/service/cmr/audit/AuditService.java b/repository/src/main/java/org/alfresco/service/cmr/audit/AuditService.java index 7f1e2ab264..4a7bcd0091 100644 --- a/repository/src/main/java/org/alfresco/service/cmr/audit/AuditService.java +++ b/repository/src/main/java/org/alfresco/service/cmr/audit/AuditService.java @@ -252,4 +252,16 @@ public interface AuditService { return -1; } + + /** + * Issue an audit query to retrieve min / max audit record id for a given application and properties + * + * @param applicationName the name of the application + * @param parameters audit parameters provided by the where clause on the ReST API + * @return a map containing min/max and the associated value + */ + default int getAuditEntriesCountByAppAndProperties(String applicationName, AuditQueryParameters parameters) + { + return -1; + } } diff --git a/repository/src/main/resources/alfresco/ibatis/org.alfresco.repo.domain.dialect.Dialect/audit-common-SqlMap.xml b/repository/src/main/resources/alfresco/ibatis/org.alfresco.repo.domain.dialect.Dialect/audit-common-SqlMap.xml index b9adc28823..eacfb1eb20 100644 --- a/repository/src/main/resources/alfresco/ibatis/org.alfresco.repo.domain.dialect.Dialect/audit-common-SqlMap.xml +++ b/repository/src/main/resources/alfresco/ibatis/org.alfresco.repo.domain.dialect.Dialect/audit-common-SqlMap.xml @@ -50,6 +50,15 @@ + + + + + + + + + @@ -291,6 +300,14 @@ alf_audit_entry.audit_app_id = #{auditAppId} + +