diff options
author | Lukasz Jarocki <lukasz.jarocki@sonarsource.com> | 2021-07-14 15:54:51 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2021-07-27 20:03:02 +0000 |
commit | 9519c05d2ca5d3df513ab322baa9a3f23e93d6b7 (patch) | |
tree | 724db6875c570ee6af6cd2e42e9a568efe58b03d /server | |
parent | 09d8569209aade0e3b4cbd21c6dee9da025b245b (diff) | |
download | sonarqube-9519c05d2ca5d3df513ab322baa9a3f23e93d6b7.tar.gz sonarqube-9519c05d2ca5d3df513ab322baa9a3f23e93d6b7.zip |
SONAR-15143 created api/audit_logs/download endpoint
Diffstat (limited to 'server')
7 files changed, 128 insertions, 101 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/AuditDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/AuditDao.java index 5279b63575b..7c2b2d67979 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/AuditDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/AuditDao.java @@ -19,12 +19,12 @@ */ package org.sonar.db.audit; +import java.util.List; import org.sonar.api.utils.System2; import org.sonar.core.util.UuidFactory; import org.sonar.db.Dao; import org.sonar.db.DbSession; - -import java.util.List; +import org.sonar.db.Pagination; import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.MAX_SIZE; @@ -45,23 +45,19 @@ public class AuditDao implements Dao { return dbSession.getMapper(AuditMapper.class); } - public List<AuditDto> selectAll(DbSession dbSession) { - return getMapper(dbSession).selectAll(); - } - - public List<AuditDto> selectByPeriod(DbSession dbSession, long beginning, long end) { - return getMapper(dbSession).selectByPeriod(beginning, end); - } - - public List<AuditDto> selectIfBeforeSelectedDate(DbSession dbSession, long end) { - return getMapper(dbSession).selectIfBeforeSelectedDate(end); + public List<AuditDto> selectByPeriodPaginated(DbSession dbSession, long start, long end, int page) { + return getMapper(dbSession).selectByPeriodPaginated(start, end, Pagination.forPage(page).andSize(DEFAULT_PAGE_SIZE)); } public void insert(DbSession dbSession, AuditDto auditDto) { - long now = system2.now(); - auditDto.setUuid(uuidFactory.create()); - auditDto.setCreatedAt(now); - if (auditDto.getNewValue().length() > MAX_SIZE) { + if (auditDto.getUuid() == null) { + auditDto.setUuid(uuidFactory.create()); + } + if (auditDto.getCreatedAt() == 0) { + long now = system2.now(); + auditDto.setCreatedAt(now); + } + if(auditDto.getNewValue().length() > MAX_SIZE) { auditDto.setNewValue(EXCEEDED_LENGTH); } getMapper(dbSession).insert(auditDto); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/AuditMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/AuditMapper.java index 22c7ea2ef53..f5a45d34ba6 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/AuditMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/AuditMapper.java @@ -20,21 +20,18 @@ package org.sonar.db.audit; import org.apache.ibatis.annotations.Param; +import org.sonar.db.Pagination; import java.util.List; public interface AuditMapper { - List<AuditDto> selectAll(); - - List<AuditDto> selectByPeriod(@Param("start") long start, @Param("end") long end); - - List<AuditDto> selectIfBeforeSelectedDate(@Param("end") long end); - void insert(@Param("dto") AuditDto auditDto); void delete(@Param("uuids") List<String> uuids); void deleteIfBeforeSelectedDate(@Param("timestamp") long timestamp); + List<AuditDto> selectByPeriodPaginated(@Param("start")long start, @Param("end") long end, @Param("pagination") Pagination pagination); + } diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/audit/AuditMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/audit/AuditMapper.xml index 31ab08d8a71..a2a6347c333 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/audit/AuditMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/audit/AuditMapper.xml @@ -13,27 +13,16 @@ a.created_at as "createdAt" </sql> - <select id="selectAll" resultType="org.sonar.db.audit.AuditDto"> - select <include refid="sqlColumns"/> - from - audits a - </select> - - <select id="selectByPeriod" parameterType="map" resultType="org.sonar.db.audit.AuditDto"> - select <include refid="sqlColumns"/> - from - audits a - where - a.created_at > #{start, jdbcType=BIGINT} AND - a.created_at < #{end, jdbcType=BIGINT} - </select> - - <select id="selectIfBeforeSelectedDate" parameterType="map" resultType="org.sonar.db.audit.AuditDto"> - select <include refid="sqlColumns"/> - from - audits a + <select id="selectByPeriodPaginated" parameterType="map" resultType="org.sonar.db.audit.AuditDto"> + select <include refid="sqlColumns"/> from ( + select + row_number() over(order by created_at, uuid) as row_number, * + from audits + where created_at >= #{start} and created_at < #{end} + ) as a where - a.created_at > #{end, jdbcType=BIGINT} + a.row_number between #{pagination.startRowNumber,jdbcType=INTEGER} and #{pagination.endRowNumber,jdbcType=INTEGER} + order by a.row_number asc </select> <insert id="insert" parameterType="Map" useGeneratedKeys="false"> diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/audit/AuditDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/audit/AuditDaoTest.java index fcde499416c..b338b23132d 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/audit/AuditDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/audit/AuditDaoTest.java @@ -23,110 +23,94 @@ import java.util.List; import org.junit.Rule; import org.junit.Test; import org.sonar.api.impl.utils.TestSystem2; -import org.sonar.core.util.UuidFactory; import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; import static org.sonar.db.audit.AuditDao.EXCEEDED_LENGTH; public class AuditDaoTest { private static final long NOW = 1000000L; - private static final String A_UUID = "SOME_UUID"; private final TestSystem2 system2 = new TestSystem2().setNow(NOW); @Rule public final DbTester db = DbTester.create(system2); private final DbSession dbSession = db.getSession(); - private final UuidFactory uuidFactory = mock(UuidFactory.class); private final AuditDao testAuditDao = new AuditDao(system2, UuidFactoryImpl.INSTANCE); @Test - public void selectAll_oneEntryInserted_returnThisEntry() { - AuditDao auditDaoDeterministicUUID = new AuditDao(system2, uuidFactory); - when(uuidFactory.create()).thenReturn(A_UUID); - AuditDto auditDto = AuditTesting.newAuditDto(); - auditDaoDeterministicUUID.insert(dbSession, auditDto); + public void selectByPeriodPaginated_10001EntriesInserted_defaultPageSizeEntriesReturned() { + prepareRowsWithDeterministicCreatedAt(10001); - List<AuditDto> auditDtos = auditDaoDeterministicUUID.selectAll(dbSession); + List<AuditDto> auditDtos = testAuditDao.selectByPeriodPaginated(dbSession, 1, 20000, 1); - assertThat(auditDtos.size()).isEqualTo(1); - assertThat(auditDtos.get(0)) - .extracting(AuditDto::getUuid, AuditDto::getUserLogin, - AuditDto::getUserUuid, AuditDto::getCategory, - AuditDto::getOperation, AuditDto::getNewValue, - AuditDto::getCreatedAt) - .containsExactly(A_UUID, auditDto.getUserLogin(), - auditDto.getUserUuid(), auditDto.getCategory(), - auditDto.getOperation(), auditDto.getNewValue(), - auditDto.getCreatedAt()); + assertThat(auditDtos.size()).isEqualTo(10000); } @Test - public void selectAll_100EntriesInserted_100EntriesReturned() { - AuditDao auditDao = new AuditDao(system2, UuidFactoryImpl.INSTANCE); - for(int i=0; i<100; i++) { - AuditDto auditDto = AuditTesting.newAuditDto(); - auditDto.setUuid(randomAlphanumeric(20)); - auditDao.insert(dbSession, auditDto); - } + public void selectByPeriodPaginated_10001EntriesInserted_querySecondPageReturns1Item() { + prepareRowsWithDeterministicCreatedAt(10001); - List<AuditDto> auditDtos = auditDao.selectAll(dbSession); + List<AuditDto> auditDtos = testAuditDao.selectByPeriodPaginated(dbSession, 1, 20000, 2); - assertThat(auditDtos.size()).isEqualTo(100); + assertThat(auditDtos.size()).isEqualTo(1); } @Test - public void selectByPeriod_selectOneRowFromTheMiddle() { - prepareThreeRowsWithDeterministicCreatedAt(); + public void deleteIfBeforeSelectedDate_deleteTwoRows() { + prepareRowsWithDeterministicCreatedAt(3); - List<AuditDto> auditDtos = testAuditDao.selectByPeriod(dbSession, 1, 3); + testAuditDao.deleteIfBeforeSelectedDate(dbSession, 2); + List<AuditDto> auditDtos = testAuditDao.selectByPeriodPaginated(dbSession, 1, 4, 1); assertThat(auditDtos.size()).isEqualTo(1); - assertThat(auditDtos.get(0).getCreatedAt()).isEqualTo(2); } @Test - public void selectByPeriod_selectOneRowFromTheEnd() { - prepareThreeRowsWithDeterministicCreatedAt(); + public void selectByPeriodPaginated_100EntriesInserted_100EntriesReturned() { + prepareRowsWithDeterministicCreatedAt(100); - List<AuditDto> auditDtos = testAuditDao.selectByPeriod(dbSession, 2, 4); + List<AuditDto> auditDtos = testAuditDao.selectByPeriodPaginated(dbSession, 1, 101, 1); - assertThat(auditDtos.size()).isEqualTo(1); - assertThat(auditDtos.get(0).getCreatedAt()).isEqualTo(3); + assertThat(auditDtos.size()).isEqualTo(100); } @Test - public void selectByPeriod_selectAllRows() { - prepareThreeRowsWithDeterministicCreatedAt(); + public void insert_doNotSetACreatedAtIfAlreadySet() { + AuditDto auditDto = AuditTesting.newAuditDto(); + auditDto.setCreatedAt(1041375600000L); - List<AuditDto> auditDtos = testAuditDao.selectByPeriod(dbSession, 0, 4); + testAuditDao.insert(dbSession, auditDto); - assertThat(auditDtos.size()).isEqualTo(3); + List<AuditDto> auditDtos = testAuditDao.selectByPeriodPaginated(dbSession, 1041375500000L, 1041375700000L, 1); + AuditDto storedAuditDto = auditDtos.get(0); + assertThat(storedAuditDto.getCreatedAt()).isEqualTo(auditDto.getCreatedAt()); } @Test - public void selectIfBeforeSelectedDate_select1Row() { - prepareThreeRowsWithDeterministicCreatedAt(); + public void insert_setACreatedAtIfAlreadySet() { + AuditDto auditDto = AuditTesting.newAuditDto(); + auditDto.setCreatedAt(0); - List<AuditDto> auditDtos = testAuditDao.selectIfBeforeSelectedDate(dbSession, 2); + testAuditDao.insert(dbSession, auditDto); - assertThat(auditDtos.size()).isEqualTo(1); + assertThat(auditDto.getCreatedAt()).isNotZero(); } @Test - public void deleteIfBeforeSelectedDate_deleteTwoRows() { - prepareThreeRowsWithDeterministicCreatedAt(); + public void insert_doNotSetAUUIDIfAlreadySet() { + AuditDto auditDto = AuditTesting.newAuditDto(); + auditDto.setUuid("myuuid"); + auditDto.setCreatedAt(1041375600000L); - testAuditDao.deleteIfBeforeSelectedDate(dbSession, 2); + testAuditDao.insert(dbSession, auditDto); - List<AuditDto> auditDtos = testAuditDao.selectAll(dbSession); - assertThat(auditDtos.size()).isEqualTo(1); + List<AuditDto> auditDtos = testAuditDao.selectByPeriodPaginated(dbSession, 1041375500000L, 1041375700000L, 1); + AuditDto storedAuditDto = auditDtos.get(0); + assertThat(storedAuditDto.getUuid()).isEqualTo(auditDto.getUuid()); } @Test @@ -140,10 +124,9 @@ public class AuditDaoTest { assertThat(auditDto.getNewValue()).isEqualTo(EXCEEDED_LENGTH); } - private void prepareThreeRowsWithDeterministicCreatedAt() { - for(int i=1; i<=3; i++) { - AuditDto auditDto = AuditTesting.newAuditDto(); - system2.setNow(i); + private void prepareRowsWithDeterministicCreatedAt(int size) { + for (int i = 1; i <= size; i++) { + AuditDto auditDto = AuditTesting.newAuditDto(i); testAuditDao.insert(dbSession, auditDto); } } diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java index 8d795b2411c..b4733ef57be 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java @@ -34,6 +34,7 @@ import org.sonar.core.util.SequenceUuidFactory; import org.sonar.core.util.UuidFactory; import org.sonar.db.alm.integration.pat.AlmPatsDbTester; import org.sonar.db.almsettings.AlmSettingsDbTester; +import org.sonar.db.audit.AuditDbTester; import org.sonar.db.audit.AuditPersister; import org.sonar.db.component.ComponentDbTester; import org.sonar.db.component.ProjectLinkDbTester; @@ -88,6 +89,7 @@ public class DbTester extends AbstractDbTester<TestDbImpl> { private final InternalComponentPropertyDbTester internalComponentPropertyTester; private final AlmSettingsDbTester almSettingsDbTester; private final AlmPatsDbTester almPatsDbtester; + private final AuditDbTester auditDbTester; private DbTester(System2 system2, @Nullable String schemaPath, AuditPersister auditPersister, MyBatisConfExtension... confExtensions) { super(TestDbImpl.create(schemaPath, confExtensions)); @@ -116,6 +118,7 @@ public class DbTester extends AbstractDbTester<TestDbImpl> { this.newCodePeriodTester = new NewCodePeriodDbTester(this); this.almSettingsDbTester = new AlmSettingsDbTester(this); this.almPatsDbtester = new AlmPatsDbTester(this); + this.auditDbTester = new AuditDbTester(this); } public static DbTester create() { @@ -244,6 +247,10 @@ public class DbTester extends AbstractDbTester<TestDbImpl> { return almPatsDbtester; } + public AuditDbTester audits() { + return auditDbTester; + } + @Override protected void after() { if (session != null) { diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/audit/AuditDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/audit/AuditDbTester.java new file mode 100644 index 00000000000..2d34d325108 --- /dev/null +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/audit/AuditDbTester.java @@ -0,0 +1,43 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.db.audit; + +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.DbTester; + +public class AuditDbTester { + + private final DbTester db; + private final DbClient dbClient; + private final DbSession dbSession; + + public AuditDbTester(DbTester db) { + this.db = db; + this.dbClient = db.getDbClient(); + this.dbSession = db.getSession(); + } + + public final void insertRandomAuditEntry(long createdAt) { + AuditDto auditDto = AuditTesting.newAuditDto(createdAt); + dbClient.auditDao().insert(dbSession, auditDto); + db.commit(); + } +} diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/audit/AuditTesting.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/audit/AuditTesting.java index 094ae46db49..1cc60162c32 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/audit/AuditTesting.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/audit/AuditTesting.java @@ -28,14 +28,26 @@ public class AuditTesting { private static final Random random = new Random(); public static AuditDto newAuditDto() { + return newAuditDto(random.nextLong(), "operation"); + } + + public static AuditDto newAuditDto(String operation) { + return newAuditDto(random.nextLong(), operation); + } + + public static AuditDto newAuditDto(long createdAt) { + return newAuditDto(createdAt, "operation"); + } + + public static AuditDto newAuditDto(long createdAt, String operation) { AuditDto auditDto = new AuditDto(); auditDto.setUuid(randomAlphanumeric(20)); auditDto.setUserUuid(randomAlphanumeric(40)); auditDto.setUserLogin(randomAlphanumeric(40)); - auditDto.setNewValue(randomAlphanumeric(2000)); - auditDto.setOperation("operation"); + auditDto.setNewValue("{ \"someKey\": \"someValue\" }"); + auditDto.setOperation(operation); auditDto.setCategory("category"); - auditDto.setCreatedAt(random.nextLong()); + auditDto.setCreatedAt(createdAt); return auditDto; } } |